41#define DEBUG_TYPE "wasm-fastisel"
45class WebAssemblyFastISel final :
public FastISel {
49 using BaseKind =
enum { RegBase, FrameIndexBase };
52 BaseKind Kind = RegBase;
59 bool IsBaseSet =
false;
68 void setKind(BaseKind K) {
69 assert(!isSet() &&
"Can't change kind with non-zero base");
72 BaseKind getKind()
const {
return Kind; }
73 bool isRegBase()
const {
return Kind == RegBase; }
74 bool isFIBase()
const {
return Kind == FrameIndexBase; }
75 void setReg(
unsigned Reg) {
76 assert(isRegBase() &&
"Invalid base register access!");
77 assert(!IsBaseSet &&
"Base cannot be reset");
82 assert(isRegBase() &&
"Invalid base register access!");
85 void setFI(
unsigned FI) {
86 assert(isFIBase() &&
"Invalid base frame index access!");
87 assert(!IsBaseSet &&
"Base cannot be reset");
91 unsigned getFI()
const {
92 assert(isFIBase() &&
"Invalid base frame index access!");
96 void setOffset(int64_t NewOffset) {
97 assert(NewOffset >= 0 &&
"Offsets must be non-negative");
102 const GlobalValue *getGlobalValue()
const {
return GV; }
103 bool isSet()
const {
return IsBaseSet; }
114 EVT VT = TLI.getValueType(
DL, Ty,
true);
154 bool computeAddress(
const Value *Obj, Address &Addr);
155 void materializeLoadStoreOperands(Address &Addr);
158 unsigned maskI1Value(
unsigned Reg,
const Value *V);
159 unsigned getRegForI1Value(
const Value *V,
const BasicBlock *BB,
bool &Not);
160 unsigned zeroExtendToI32(
unsigned Reg,
const Value *V,
162 unsigned signExtendToI32(
unsigned Reg,
const Value *V,
168 unsigned getRegForUnsignedValue(
const Value *V);
169 unsigned getRegForSignedValue(
const Value *V);
170 unsigned getRegForPromotedValue(
const Value *V,
bool IsSigned);
171 unsigned notValue(
unsigned Reg);
172 unsigned copyValue(
unsigned Reg);
177 bool fastLowerArguments()
override;
198 :
FastISel(FuncInfo, LibInfo,
true) {
203 bool fastSelectInstruction(
const Instruction *
I)
override;
205#include "WebAssemblyGenFastISel.inc"
210bool WebAssemblyFastISel::computeAddress(
const Value *Obj, Address &Addr) {
211 const User *
U =
nullptr;
212 unsigned Opcode = Instruction::UserOp1;
216 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(Obj)) ||
217 FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
218 Opcode =
I->getOpcode();
222 Opcode =
C->getOpcode();
227 if (Ty->getAddressSpace() > 255)
233 if (TLI.isPositionIndependent())
235 if (Addr.getGlobalValue())
237 if (GV->isThreadLocal())
239 Addr.setGlobalValue(GV);
246 case Instruction::BitCast: {
248 return computeAddress(
U->getOperand(0), Addr);
250 case Instruction::IntToPtr: {
252 if (TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
253 TLI.getPointerTy(
DL))
254 return computeAddress(
U->getOperand(0), Addr);
257 case Instruction::PtrToInt: {
259 if (TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
260 return computeAddress(
U->getOperand(0), Addr);
263 case Instruction::GetElementPtr: {
265 uint64_t TmpOffset = Addr.getOffset();
268 goto unsupported_gep;
273 const Value *
Op = GTI.getOperand();
274 if (StructType *STy = GTI.getStructTypeOrNull()) {
275 const StructLayout *SL =
DL.getStructLayout(STy);
279 uint64_t S = GTI.getSequentialElementStride(
DL);
283 TmpOffset += CI->getSExtValue() * S;
286 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
294 if (canFoldAddIntoGEP(U,
Op)) {
297 TmpOffset += CI->getSExtValue() * S;
303 goto unsupported_gep;
308 if (int64_t(TmpOffset) >= 0) {
310 Addr.setOffset(TmpOffset);
311 if (computeAddress(
U->getOperand(0), Addr))
319 case Instruction::Alloca: {
321 DenseMap<const AllocaInst *, int>::iterator
SI =
322 FuncInfo.StaticAllocaMap.find(AI);
323 if (SI != FuncInfo.StaticAllocaMap.end()) {
327 Addr.setKind(Address::FrameIndexBase);
328 Addr.setFI(
SI->second);
333 case Instruction::Add: {
337 if (!OFBinOp->hasNoUnsignedWrap())
348 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
349 if (int64_t(TmpOffset) >= 0) {
350 Addr.setOffset(TmpOffset);
351 return computeAddress(
LHS, Addr);
356 if (computeAddress(
LHS, Addr) && computeAddress(
RHS, Addr))
362 case Instruction::Sub: {
366 if (!OFBinOp->hasNoUnsignedWrap())
374 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
375 if (TmpOffset >= 0) {
376 Addr.setOffset(TmpOffset);
377 return computeAddress(
LHS, Addr);
390 return Addr.getReg() != 0;
393void WebAssemblyFastISel::materializeLoadStoreOperands(
Address &Addr) {
394 if (Addr.isRegBase()) {
395 unsigned Reg = Addr.getReg();
397 Reg = createResultReg(Subtarget->
hasAddr64() ? &WebAssembly::I64RegClass
398 : &WebAssembly::I32RegClass);
399 unsigned Opc = Subtarget->
hasAddr64() ? WebAssembly::CONST_I64
400 : WebAssembly::CONST_I32;
408void WebAssemblyFastISel::addLoadStoreOperands(
const Address &Addr,
409 const MachineInstrBuilder &MIB,
410 MachineMemOperand *MMO) {
415 if (
const GlobalValue *GV = Addr.getGlobalValue())
418 MIB.
addImm(Addr.getOffset());
420 if (Addr.isRegBase())
421 MIB.
addReg(Addr.getReg());
428unsigned WebAssemblyFastISel::maskI1Value(
unsigned Reg,
const Value *V) {
429 return zeroExtendToI32(
Reg, V, MVT::i1);
432unsigned WebAssemblyFastISel::getRegForI1Value(
const Value *V,
433 const BasicBlock *BB,
437 if (ICmp->isEquality() &&
C->isZero() &&
C->getType()->isIntegerTy(32) &&
438 ICmp->getParent() == BB) {
439 Not = ICmp->isTrueWhenEqual();
440 return getRegForValue(ICmp->getOperand(0));
447 return maskI1Value(
Reg, V);
450unsigned WebAssemblyFastISel::zeroExtendToI32(
unsigned Reg,
const Value *V,
461 return copyValue(
Reg);
467 return copyValue(
Reg);
472 Register Imm = createResultReg(&WebAssembly::I32RegClass);
473 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
474 TII.get(WebAssembly::CONST_I32), Imm)
475 .
addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
478 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
479 TII.get(WebAssembly::AND_I32), Result)
486unsigned WebAssemblyFastISel::signExtendToI32(
unsigned Reg,
const Value *V,
497 return copyValue(
Reg);
502 Register Imm = createResultReg(&WebAssembly::I32RegClass);
503 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
504 TII.get(WebAssembly::CONST_I32), Imm)
505 .
addImm(32 - MVT(From).getSizeInBits());
507 Register Left = createResultReg(&WebAssembly::I32RegClass);
508 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
509 TII.get(WebAssembly::SHL_I32),
Left)
514 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
515 TII.get(WebAssembly::SHR_S_I32),
Right)
522unsigned WebAssemblyFastISel::zeroExtend(
unsigned Reg,
const Value *V,
525 if (To == MVT::i64) {
526 if (From == MVT::i64)
527 return copyValue(
Reg);
529 Reg = zeroExtendToI32(
Reg, V, From);
532 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
533 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
539 return zeroExtendToI32(
Reg, V, From);
544unsigned WebAssemblyFastISel::signExtend(
unsigned Reg,
const Value *V,
547 if (To == MVT::i64) {
548 if (From == MVT::i64)
549 return copyValue(
Reg);
551 Reg = signExtendToI32(
Reg, V, From);
554 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
555 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
561 return signExtendToI32(
Reg, V, From);
566unsigned WebAssemblyFastISel::getRegForUnsignedValue(
const Value *V) {
574 return zeroExtend(VReg, V, From, To);
577unsigned WebAssemblyFastISel::getRegForSignedValue(
const Value *V) {
585 return signExtend(VReg, V, From, To);
588unsigned WebAssemblyFastISel::getRegForPromotedValue(
const Value *V,
590 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(
V);
593unsigned WebAssemblyFastISel::notValue(
unsigned Reg) {
594 assert(
MRI.getRegClass(
Reg) == &WebAssembly::I32RegClass);
596 Register NotReg = createResultReg(&WebAssembly::I32RegClass);
597 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
598 TII.get(WebAssembly::EQZ_I32), NotReg)
603unsigned WebAssemblyFastISel::copyValue(
unsigned Reg) {
605 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::COPY),
611Register WebAssemblyFastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
612 DenseMap<const AllocaInst *, int>::iterator
SI =
613 FuncInfo.StaticAllocaMap.find(AI);
615 if (SI != FuncInfo.StaticAllocaMap.end()) {
617 createResultReg(Subtarget->
hasAddr64() ? &WebAssembly::I64RegClass
618 : &WebAssembly::I32RegClass);
620 Subtarget->
hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
621 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
629Register WebAssemblyFastISel::fastMaterializeConstant(
const Constant *
C) {
631 if (TLI.isPositionIndependent())
633 if (GV->isThreadLocal())
636 createResultReg(Subtarget->
hasAddr64() ? &WebAssembly::I64RegClass
637 : &WebAssembly::I32RegClass);
638 unsigned Opc = Subtarget->
hasAddr64() ? WebAssembly::CONST_I64
639 : WebAssembly::CONST_I32;
640 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
649bool WebAssemblyFastISel::fastLowerArguments() {
650 if (!FuncInfo.CanLowerReturn)
657 if (FuncInfo.Fn->getCallingConv() == CallingConv::Swift)
661 for (
auto const &Arg :
F->args()) {
662 const AttributeList &
Attrs =
F->getAttributes();
663 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
664 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
665 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
666 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
667 Attrs.hasParamAttr(
I, Attribute::Nest))
670 Type *ArgTy = Arg.getType();
677 const TargetRegisterClass *RC;
678 switch (getSimpleType(ArgTy)) {
683 Opc = WebAssembly::ARGUMENT_i32;
684 RC = &WebAssembly::I32RegClass;
687 Opc = WebAssembly::ARGUMENT_i64;
688 RC = &WebAssembly::I64RegClass;
691 Opc = WebAssembly::ARGUMENT_f32;
692 RC = &WebAssembly::F32RegClass;
695 Opc = WebAssembly::ARGUMENT_f64;
696 RC = &WebAssembly::F64RegClass;
699 Opc = WebAssembly::ARGUMENT_v16i8;
700 RC = &WebAssembly::V128RegClass;
703 Opc = WebAssembly::ARGUMENT_v8i16;
704 RC = &WebAssembly::V128RegClass;
707 Opc = WebAssembly::ARGUMENT_v4i32;
708 RC = &WebAssembly::V128RegClass;
711 Opc = WebAssembly::ARGUMENT_v2i64;
712 RC = &WebAssembly::V128RegClass;
715 Opc = WebAssembly::ARGUMENT_v4f32;
716 RC = &WebAssembly::V128RegClass;
719 Opc = WebAssembly::ARGUMENT_v2f64;
720 RC = &WebAssembly::V128RegClass;
723 Opc = WebAssembly::ARGUMENT_funcref;
724 RC = &WebAssembly::FUNCREFRegClass;
727 Opc = WebAssembly::ARGUMENT_externref;
728 RC = &WebAssembly::EXTERNREFRegClass;
731 Opc = WebAssembly::ARGUMENT_exnref;
732 RC = &WebAssembly::EXNREFRegClass;
737 Register ResultReg = createResultReg(RC);
738 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
740 updateValueMap(&Arg, ResultReg);
745 MRI.addLiveIn(WebAssembly::ARGUMENTS);
747 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
748 for (
auto const &Arg :
F->args()) {
751 MFI->clearParamsAndResults();
754 MFI->addParam(ArgTy);
757 if (!
F->getReturnType()->isVoidTy()) {
759 getLegalType(getSimpleType(
F->getReturnType()));
761 MFI->clearParamsAndResults();
764 MFI->addResult(RetTy);
770bool WebAssemblyFastISel::selectCall(
const Instruction *
I) {
779 if (Func &&
Func->isIntrinsic())
785 bool IsDirect =
Func !=
nullptr;
790 unsigned Opc = IsDirect ? WebAssembly::CALL : WebAssembly::CALL_INDIRECT;
791 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
803 ResultReg = createResultReg(&WebAssembly::I32RegClass);
806 ResultReg = createResultReg(&WebAssembly::I64RegClass);
809 ResultReg = createResultReg(&WebAssembly::F32RegClass);
812 ResultReg = createResultReg(&WebAssembly::F64RegClass);
815 ResultReg = createResultReg(&WebAssembly::V128RegClass);
818 ResultReg = createResultReg(&WebAssembly::V128RegClass);
821 ResultReg = createResultReg(&WebAssembly::V128RegClass);
824 ResultReg = createResultReg(&WebAssembly::V128RegClass);
827 ResultReg = createResultReg(&WebAssembly::V128RegClass);
830 ResultReg = createResultReg(&WebAssembly::V128RegClass);
833 ResultReg = createResultReg(&WebAssembly::FUNCREFRegClass);
836 ResultReg = createResultReg(&WebAssembly::EXTERNREFRegClass);
839 ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);
846 SmallVector<unsigned, 8>
Args;
854 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
855 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
856 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
857 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
858 Attrs.hasParamAttr(
I, Attribute::Nest))
864 Reg = getRegForSignedValue(V);
866 Reg = getRegForUnsignedValue(V);
868 Reg = getRegForValue(V);
876 unsigned CalleeReg = 0;
883 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc));
895 MF->getContext(), Subtarget);
907 for (
unsigned ArgReg : Args)
914 updateValueMap(
Call, ResultReg);
920bool WebAssemblyFastISel::selectSelect(
const Instruction *
I) {
925 getRegForI1Value(
Select->getCondition(),
I->getParent(), Not);
941 const TargetRegisterClass *RC;
942 switch (getSimpleType(
Select->getType())) {
947 Opc = WebAssembly::SELECT_I32;
948 RC = &WebAssembly::I32RegClass;
951 Opc = WebAssembly::SELECT_I64;
952 RC = &WebAssembly::I64RegClass;
955 Opc = WebAssembly::SELECT_F32;
956 RC = &WebAssembly::F32RegClass;
959 Opc = WebAssembly::SELECT_F64;
960 RC = &WebAssembly::F64RegClass;
963 Opc = WebAssembly::SELECT_FUNCREF;
964 RC = &WebAssembly::FUNCREFRegClass;
967 Opc = WebAssembly::SELECT_EXTERNREF;
968 RC = &WebAssembly::EXTERNREFRegClass;
971 Opc = WebAssembly::SELECT_EXNREF;
972 RC = &WebAssembly::EXNREFRegClass;
978 Register ResultReg = createResultReg(RC);
979 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
984 updateValueMap(
Select, ResultReg);
988bool WebAssemblyFastISel::selectTrunc(
const Instruction *
I) {
991 Register Reg = getRegForValue(Trunc->getOperand(0));
995 unsigned FromBitWidth = Trunc->getOperand(0)->getType()->getIntegerBitWidth();
996 unsigned ToBitWidth = Trunc->getType()->getIntegerBitWidth();
998 if (ToBitWidth <= 32 && (32 < FromBitWidth && FromBitWidth <= 64)) {
1000 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1001 TII.get(WebAssembly::I32_WRAP_I64), Result)
1006 updateValueMap(Trunc,
Reg);
1010bool WebAssemblyFastISel::selectZExt(
const Instruction *
I) {
1013 const Value *
Op = ZExt->getOperand(0);
1019 unsigned Reg = zeroExtend(In,
Op, From, To);
1023 updateValueMap(ZExt,
Reg);
1027bool WebAssemblyFastISel::selectSExt(
const Instruction *
I) {
1030 const Value *
Op = SExt->getOperand(0);
1036 unsigned Reg = signExtend(In,
Op, From, To);
1040 updateValueMap(SExt,
Reg);
1044bool WebAssemblyFastISel::selectICmp(
const Instruction *
I) {
1047 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
1049 bool IsSigned =
false;
1050 switch (ICmp->getPredicate()) {
1051 case ICmpInst::ICMP_EQ:
1052 Opc =
I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
1054 case ICmpInst::ICMP_NE:
1055 Opc =
I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1057 case ICmpInst::ICMP_UGT:
1058 Opc =
I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1060 case ICmpInst::ICMP_UGE:
1061 Opc =
I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1063 case ICmpInst::ICMP_ULT:
1064 Opc =
I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1066 case ICmpInst::ICMP_ULE:
1067 Opc =
I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1069 case ICmpInst::ICMP_SGT:
1070 Opc =
I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1073 case ICmpInst::ICMP_SGE:
1074 Opc =
I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1077 case ICmpInst::ICMP_SLT:
1078 Opc =
I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1081 case ICmpInst::ICMP_SLE:
1082 Opc =
I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1089 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
1093 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
1097 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1098 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1101 updateValueMap(ICmp, ResultReg);
1105bool WebAssemblyFastISel::selectFCmp(
const Instruction *
I) {
1108 Register LHS = getRegForValue(FCmp->getOperand(0));
1112 Register RHS = getRegForValue(FCmp->getOperand(1));
1116 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1119 switch (FCmp->getPredicate()) {
1120 case FCmpInst::FCMP_OEQ:
1121 Opc =
F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1123 case FCmpInst::FCMP_UNE:
1124 Opc =
F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1126 case FCmpInst::FCMP_OGT:
1127 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1129 case FCmpInst::FCMP_OGE:
1130 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1132 case FCmpInst::FCMP_OLT:
1133 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1135 case FCmpInst::FCMP_OLE:
1136 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1138 case FCmpInst::FCMP_UGT:
1139 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1142 case FCmpInst::FCMP_UGE:
1143 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1146 case FCmpInst::FCMP_ULT:
1147 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1150 case FCmpInst::FCMP_ULE:
1151 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1158 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1159 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1164 ResultReg = notValue(ResultReg);
1166 updateValueMap(FCmp, ResultReg);
1170bool WebAssemblyFastISel::selectBitCast(
const Instruction *
I) {
1174 EVT VT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
1175 EVT RetVT = TLI.getValueType(
DL,
I->getType());
1185 updateValueMap(
I, In);
1195 assert(Iter->isBitcast());
1197 updateValueMap(
I,
Reg);
1201bool WebAssemblyFastISel::selectLoad(
const Instruction *
I) {
1203 if (
Load->isAtomic())
1211 if (!computeAddress(
Load->getPointerOperand(), Addr))
1217 const TargetRegisterClass *RC;
1219 switch (getSimpleType(
Load->getType())) {
1222 Opc = A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
1223 RC = &WebAssembly::I32RegClass;
1226 Opc = A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;
1227 RC = &WebAssembly::I32RegClass;
1230 Opc = A64 ? WebAssembly::LOAD_I32_A64 : WebAssembly::LOAD_I32_A32;
1231 RC = &WebAssembly::I32RegClass;
1234 Opc = A64 ? WebAssembly::LOAD_I64_A64 : WebAssembly::LOAD_I64_A32;
1235 RC = &WebAssembly::I64RegClass;
1238 Opc = A64 ? WebAssembly::LOAD_F32_A64 : WebAssembly::LOAD_F32_A32;
1239 RC = &WebAssembly::F32RegClass;
1242 Opc = A64 ? WebAssembly::LOAD_F64_A64 : WebAssembly::LOAD_F64_A32;
1243 RC = &WebAssembly::F64RegClass;
1249 materializeLoadStoreOperands(Addr);
1251 Register ResultReg = createResultReg(RC);
1252 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc),
1255 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1257 updateValueMap(Load, ResultReg);
1261bool WebAssemblyFastISel::selectStore(
const Instruction *
I) {
1263 if (
Store->isAtomic())
1268 Store->getValueOperand()->getType()->isVectorTy())
1272 if (!computeAddress(
Store->getPointerOperand(), Addr))
1276 bool VTIsi1 =
false;
1278 switch (getSimpleType(
Store->getValueOperand()->getType())) {
1283 Opc = A64 ? WebAssembly::STORE8_I32_A64 : WebAssembly::STORE8_I32_A32;
1286 Opc = A64 ? WebAssembly::STORE16_I32_A64 : WebAssembly::STORE16_I32_A32;
1289 Opc = A64 ? WebAssembly::STORE_I32_A64 : WebAssembly::STORE_I32_A32;
1292 Opc = A64 ? WebAssembly::STORE_I64_A64 : WebAssembly::STORE_I64_A32;
1295 Opc = A64 ? WebAssembly::STORE_F32_A64 : WebAssembly::STORE_F32_A32;
1298 Opc = A64 ? WebAssembly::STORE_F64_A64 : WebAssembly::STORE_F64_A32;
1304 materializeLoadStoreOperands(Addr);
1306 Register ValueReg = getRegForValue(
Store->getValueOperand());
1310 ValueReg = maskI1Value(ValueReg,
Store->getValueOperand());
1312 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc));
1314 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1320bool WebAssemblyFastISel::selectBr(
const Instruction *
I) {
1322 if (Br->isUnconditional()) {
1323 MachineBasicBlock *MSucc = FuncInfo.getMBB(Br->getSuccessor(0));
1324 fastEmitBranch(MSucc, Br->getDebugLoc());
1328 MachineBasicBlock *
TBB = FuncInfo.getMBB(Br->getSuccessor(0));
1329 MachineBasicBlock *FBB = FuncInfo.getMBB(Br->getSuccessor(1));
1332 unsigned CondReg = getRegForI1Value(Br->getCondition(), Br->getParent(), Not);
1336 unsigned Opc = WebAssembly::BR_IF;
1338 Opc = WebAssembly::BR_UNLESS;
1340 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1344 finishCondBranch(Br->getParent(),
TBB, FBB);
1348bool WebAssemblyFastISel::selectRet(
const Instruction *
I) {
1349 if (!FuncInfo.CanLowerReturn)
1354 if (
Ret->getNumOperands() == 0) {
1355 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1356 TII.get(WebAssembly::RETURN));
1361 if (
Ret->getNumOperands() > 1)
1368 switch (getSimpleType(RV->
getType())) {
1383 case MVT::externref:
1391 if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::SExt))
1392 Reg = getRegForSignedValue(RV);
1393 else if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::ZExt))
1394 Reg = getRegForUnsignedValue(RV);
1396 Reg = getRegForValue(RV);
1401 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1402 TII.get(WebAssembly::RETURN))
1407bool WebAssemblyFastISel::selectUnreachable(
const Instruction *
I) {
1408 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1409 TII.get(WebAssembly::UNREACHABLE));
1413bool WebAssemblyFastISel::fastSelectInstruction(
const Instruction *
I) {
1414 switch (
I->getOpcode()) {
1415 case Instruction::Call:
1419 case Instruction::Select:
1420 return selectSelect(
I);
1421 case Instruction::Trunc:
1422 return selectTrunc(
I);
1423 case Instruction::ZExt:
1424 return selectZExt(
I);
1425 case Instruction::SExt:
1426 return selectSExt(
I);
1427 case Instruction::ICmp:
1428 return selectICmp(
I);
1429 case Instruction::FCmp:
1430 return selectFCmp(
I);
1431 case Instruction::BitCast:
1432 return selectBitCast(
I);
1433 case Instruction::Load:
1434 return selectLoad(
I);
1435 case Instruction::Store:
1436 return selectStore(
I);
1437 case Instruction::Br:
1439 case Instruction::Ret:
1440 return selectRet(
I);
1441 case Instruction::Unreachable:
1442 return selectUnreachable(
I);
1448 return selectOperator(
I,
I->getOpcode());
1453 return new WebAssemblyFastISel(FuncInfo, LibInfo);
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the FastISel class.
const HexagonInstrInfo * TII
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
This file provides WebAssembly-specific target descriptions.
This file declares WebAssembly-specific per-machine-function information.
This file declares the WebAssembly-specific subclass of TargetSubtarget.
This file contains the declaration of the WebAssembly-specific type parsing utility functions.
This file contains the declaration of the WebAssembly-specific utility functions.
an instruction to allocate memory on the stack
LLVM Basic Block Representation.
bool isInlineAsm() const
Check if this call is an inline asm statement.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
CallingConv::ID getCallingConv() const
LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
Value * getCalledOperand() const
Value * getArgOperand(unsigned i) const
FunctionType * getFunctionType() const
unsigned arg_size() const
AttributeList getAttributes() const
Return the attributes for this call.
bool isMustTailCall() const
This is an important base class in LLVM.
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
This is an important class for using LLVM in a threaded context.
@ INVALID_SIMPLE_VALUE_TYPE
MachineInstrBundleIterator< MachineInstr > iterator
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addFrameIndex(int Idx) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
A description of a memory reference used in the backend.
Wrapper class representing virtual and physical registers.
TypeSize getElementOffset(unsigned Idx) const
Provides information about what library functions are available for the current target.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isArrayTy() const
True if this is an instance of ArrayType.
bool isStructTy() const
True if this is an instance of StructType.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasCallIndirectOverlong() const
bool hasReferenceTypes() const
bool hasExceptionHandling() const
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ C
The default llvm calling convention, compatible with C.
@ Define
Register definition.
Not(const Pred &P) -> Not< Pred >
bool isDefaultAddressSpace(unsigned AS)
MCSymbolWasm * getOrCreateFunctionTableSymbol(MCContext &Ctx, const WebAssemblySubtarget *Subtarget)
Returns the __indirect_function_table, for use in call_indirect and in function bitcasts.
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
@ User
could "use" a pointer
NodeAddr< FuncNode * > Func
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void diagnoseDontCall(const CallInst &CI)
gep_type_iterator gep_type_end(const User *GEP)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
generic_gep_type_iterator<> gep_type_iterator
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
DWARFExpression::Operation Op
ArrayRef(const T &OneElt) -> ArrayRef< T >
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
gep_type_iterator gep_type_begin(const User *GEP)
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.