41#define DEBUG_TYPE "wasm-fastisel"
45class WebAssemblyFastISel final :
public FastISel {
49 enum BaseKind { 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;
199 :
FastISel(FuncInfo, LibInfo, LibcallLowering,
205 bool fastSelectInstruction(
const Instruction *
I)
override;
207#include "WebAssemblyGenFastISel.inc"
212bool WebAssemblyFastISel::computeAddress(
const Value *Obj, Address &Addr) {
213 const User *
U =
nullptr;
214 unsigned Opcode = Instruction::UserOp1;
218 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(Obj)) ||
219 FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
220 Opcode =
I->getOpcode();
224 Opcode =
C->getOpcode();
229 if (Ty->getAddressSpace() > 255)
235 if (TLI.isPositionIndependent())
237 if (Addr.getGlobalValue())
239 if (GV->isThreadLocal())
241 Addr.setGlobalValue(GV);
248 case Instruction::BitCast: {
250 return computeAddress(
U->getOperand(0), Addr);
252 case Instruction::IntToPtr: {
254 if (TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
255 TLI.getPointerTy(
DL))
256 return computeAddress(
U->getOperand(0), Addr);
259 case Instruction::PtrToInt: {
261 if (TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
262 return computeAddress(
U->getOperand(0), Addr);
265 case Instruction::GetElementPtr: {
267 uint64_t TmpOffset = Addr.getOffset();
270 goto unsupported_gep;
275 const Value *
Op = GTI.getOperand();
276 if (StructType *STy = GTI.getStructTypeOrNull()) {
277 const StructLayout *SL =
DL.getStructLayout(STy);
281 uint64_t S = GTI.getSequentialElementStride(
DL);
285 TmpOffset += CI->getSExtValue() * S;
288 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
296 if (canFoldAddIntoGEP(U,
Op)) {
299 TmpOffset += CI->getSExtValue() * S;
305 goto unsupported_gep;
310 if (int64_t(TmpOffset) >= 0) {
312 Addr.setOffset(TmpOffset);
313 if (computeAddress(
U->getOperand(0), Addr))
321 case Instruction::Alloca: {
323 DenseMap<const AllocaInst *, int>::iterator
SI =
324 FuncInfo.StaticAllocaMap.find(AI);
325 if (SI != FuncInfo.StaticAllocaMap.end()) {
329 Addr.setKind(Address::FrameIndexBase);
330 Addr.setFI(
SI->second);
335 case Instruction::Add: {
339 if (!OFBinOp->hasNoUnsignedWrap())
350 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
351 if (int64_t(TmpOffset) >= 0) {
352 Addr.setOffset(TmpOffset);
353 return computeAddress(
LHS, Addr);
358 if (computeAddress(
LHS, Addr) && computeAddress(
RHS, Addr))
364 case Instruction::Sub: {
368 if (!OFBinOp->hasNoUnsignedWrap())
376 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
377 if (TmpOffset >= 0) {
378 Addr.setOffset(TmpOffset);
379 return computeAddress(
LHS, Addr);
392 return Addr.getReg() != 0;
395void WebAssemblyFastISel::materializeLoadStoreOperands(
Address &Addr) {
396 if (Addr.isRegBase()) {
397 unsigned Reg = Addr.getReg();
399 Reg = createResultReg(Subtarget->
hasAddr64() ? &WebAssembly::I64RegClass
400 : &WebAssembly::I32RegClass);
401 unsigned Opc = Subtarget->
hasAddr64() ? WebAssembly::CONST_I64
402 : WebAssembly::CONST_I32;
410void WebAssemblyFastISel::addLoadStoreOperands(
const Address &Addr,
411 const MachineInstrBuilder &MIB,
412 MachineMemOperand *MMO) {
417 if (
const GlobalValue *GV = Addr.getGlobalValue())
420 MIB.
addImm(Addr.getOffset());
422 if (Addr.isRegBase())
423 MIB.
addReg(Addr.getReg());
430unsigned WebAssemblyFastISel::maskI1Value(
unsigned Reg,
const Value *V) {
431 return zeroExtendToI32(
Reg, V, MVT::i1);
434unsigned WebAssemblyFastISel::getRegForI1Value(
const Value *V,
435 const BasicBlock *BB,
439 if (ICmp->isEquality() &&
C->isZero() &&
C->getType()->isIntegerTy(32) &&
440 ICmp->getParent() == BB) {
441 Not = ICmp->isTrueWhenEqual();
442 return getRegForValue(ICmp->getOperand(0));
449 return maskI1Value(
Reg, V);
452unsigned WebAssemblyFastISel::zeroExtendToI32(
unsigned Reg,
const Value *V,
463 return copyValue(
Reg);
469 return copyValue(
Reg);
474 Register Imm = createResultReg(&WebAssembly::I32RegClass);
475 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
476 TII.get(WebAssembly::CONST_I32), Imm)
477 .
addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
480 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
481 TII.get(WebAssembly::AND_I32), Result)
488unsigned WebAssemblyFastISel::signExtendToI32(
unsigned Reg,
const Value *V,
499 return copyValue(
Reg);
504 Register Imm = createResultReg(&WebAssembly::I32RegClass);
505 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
506 TII.get(WebAssembly::CONST_I32), Imm)
507 .
addImm(32 - MVT(From).getSizeInBits());
509 Register Left = createResultReg(&WebAssembly::I32RegClass);
510 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
511 TII.get(WebAssembly::SHL_I32),
Left)
516 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
517 TII.get(WebAssembly::SHR_S_I32),
Right)
524unsigned WebAssemblyFastISel::zeroExtend(
unsigned Reg,
const Value *V,
527 if (To == MVT::i64) {
528 if (From == MVT::i64)
529 return copyValue(
Reg);
531 Reg = zeroExtendToI32(
Reg, V, From);
534 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
535 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
541 return zeroExtendToI32(
Reg, V, From);
546unsigned WebAssemblyFastISel::signExtend(
unsigned Reg,
const Value *V,
549 if (To == MVT::i64) {
550 if (From == MVT::i64)
551 return copyValue(
Reg);
553 Reg = signExtendToI32(
Reg, V, From);
556 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
557 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
563 return signExtendToI32(
Reg, V, From);
568unsigned WebAssemblyFastISel::getRegForUnsignedValue(
const Value *V) {
576 return zeroExtend(VReg, V, From, To);
579unsigned WebAssemblyFastISel::getRegForSignedValue(
const Value *V) {
587 return signExtend(VReg, V, From, To);
590unsigned WebAssemblyFastISel::getRegForPromotedValue(
const Value *V,
592 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(
V);
595unsigned WebAssemblyFastISel::notValue(
unsigned Reg) {
596 assert(
MRI.getRegClass(
Reg) == &WebAssembly::I32RegClass);
598 Register NotReg = createResultReg(&WebAssembly::I32RegClass);
599 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
600 TII.get(WebAssembly::EQZ_I32), NotReg)
605unsigned WebAssemblyFastISel::copyValue(
unsigned Reg) {
607 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::COPY),
613Register WebAssemblyFastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
614 DenseMap<const AllocaInst *, int>::iterator
SI =
615 FuncInfo.StaticAllocaMap.find(AI);
617 if (SI != FuncInfo.StaticAllocaMap.end()) {
619 createResultReg(Subtarget->
hasAddr64() ? &WebAssembly::I64RegClass
620 : &WebAssembly::I32RegClass);
622 Subtarget->
hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
623 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
631Register WebAssemblyFastISel::fastMaterializeConstant(
const Constant *
C) {
633 if (TLI.isPositionIndependent())
635 if (GV->isThreadLocal())
638 createResultReg(Subtarget->
hasAddr64() ? &WebAssembly::I64RegClass
639 : &WebAssembly::I32RegClass);
640 unsigned Opc = Subtarget->
hasAddr64() ? WebAssembly::CONST_I64
641 : WebAssembly::CONST_I32;
642 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
651bool WebAssemblyFastISel::fastLowerArguments() {
652 if (!FuncInfo.CanLowerReturn)
659 if (FuncInfo.Fn->getCallingConv() == CallingConv::Swift)
663 for (
auto const &Arg :
F->args()) {
664 const AttributeList &
Attrs =
F->getAttributes();
665 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
666 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
667 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
668 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
669 Attrs.hasParamAttr(
I, Attribute::Nest))
672 Type *ArgTy = Arg.getType();
679 const TargetRegisterClass *RC;
680 switch (getSimpleType(ArgTy)) {
685 Opc = WebAssembly::ARGUMENT_i32;
686 RC = &WebAssembly::I32RegClass;
689 Opc = WebAssembly::ARGUMENT_i64;
690 RC = &WebAssembly::I64RegClass;
693 Opc = WebAssembly::ARGUMENT_f32;
694 RC = &WebAssembly::F32RegClass;
697 Opc = WebAssembly::ARGUMENT_f64;
698 RC = &WebAssembly::F64RegClass;
701 Opc = WebAssembly::ARGUMENT_v16i8;
702 RC = &WebAssembly::V128RegClass;
705 Opc = WebAssembly::ARGUMENT_v8i16;
706 RC = &WebAssembly::V128RegClass;
709 Opc = WebAssembly::ARGUMENT_v4i32;
710 RC = &WebAssembly::V128RegClass;
713 Opc = WebAssembly::ARGUMENT_v2i64;
714 RC = &WebAssembly::V128RegClass;
717 Opc = WebAssembly::ARGUMENT_v4f32;
718 RC = &WebAssembly::V128RegClass;
721 Opc = WebAssembly::ARGUMENT_v2f64;
722 RC = &WebAssembly::V128RegClass;
725 Opc = WebAssembly::ARGUMENT_funcref;
726 RC = &WebAssembly::FUNCREFRegClass;
729 Opc = WebAssembly::ARGUMENT_externref;
730 RC = &WebAssembly::EXTERNREFRegClass;
733 Opc = WebAssembly::ARGUMENT_exnref;
734 RC = &WebAssembly::EXNREFRegClass;
739 Register ResultReg = createResultReg(RC);
740 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
742 updateValueMap(&Arg, ResultReg);
747 MRI.addLiveIn(WebAssembly::ARGUMENTS);
749 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
750 for (
auto const &Arg :
F->args()) {
753 MFI->clearParamsAndResults();
756 MFI->addParam(ArgTy);
759 if (!
F->getReturnType()->isVoidTy()) {
761 getLegalType(getSimpleType(
F->getReturnType()));
763 MFI->clearParamsAndResults();
766 MFI->addResult(RetTy);
772bool WebAssemblyFastISel::selectCall(
const Instruction *
I) {
781 if (Func &&
Func->isIntrinsic())
787 bool IsDirect =
Func !=
nullptr;
792 unsigned Opc = IsDirect ? WebAssembly::CALL : WebAssembly::CALL_INDIRECT;
793 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
805 ResultReg = createResultReg(&WebAssembly::I32RegClass);
808 ResultReg = createResultReg(&WebAssembly::I64RegClass);
811 ResultReg = createResultReg(&WebAssembly::F32RegClass);
814 ResultReg = createResultReg(&WebAssembly::F64RegClass);
817 ResultReg = createResultReg(&WebAssembly::V128RegClass);
820 ResultReg = createResultReg(&WebAssembly::V128RegClass);
823 ResultReg = createResultReg(&WebAssembly::V128RegClass);
826 ResultReg = createResultReg(&WebAssembly::V128RegClass);
829 ResultReg = createResultReg(&WebAssembly::V128RegClass);
832 ResultReg = createResultReg(&WebAssembly::V128RegClass);
835 ResultReg = createResultReg(&WebAssembly::FUNCREFRegClass);
838 ResultReg = createResultReg(&WebAssembly::EXTERNREFRegClass);
841 ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);
848 SmallVector<unsigned, 8>
Args;
856 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
857 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
858 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
859 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
860 Attrs.hasParamAttr(
I, Attribute::Nest))
866 Reg = getRegForSignedValue(V);
868 Reg = getRegForUnsignedValue(V);
870 Reg = getRegForValue(V);
878 unsigned CalleeReg = 0;
885 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc));
897 MF->getContext(), Subtarget);
909 for (
unsigned ArgReg : Args)
916 updateValueMap(
Call, ResultReg);
922bool WebAssemblyFastISel::selectSelect(
const Instruction *
I) {
927 getRegForI1Value(
Select->getCondition(),
I->getParent(), Not);
943 const TargetRegisterClass *RC;
944 switch (getSimpleType(
Select->getType())) {
949 Opc = WebAssembly::SELECT_I32;
950 RC = &WebAssembly::I32RegClass;
953 Opc = WebAssembly::SELECT_I64;
954 RC = &WebAssembly::I64RegClass;
957 Opc = WebAssembly::SELECT_F32;
958 RC = &WebAssembly::F32RegClass;
961 Opc = WebAssembly::SELECT_F64;
962 RC = &WebAssembly::F64RegClass;
965 Opc = WebAssembly::SELECT_FUNCREF;
966 RC = &WebAssembly::FUNCREFRegClass;
969 Opc = WebAssembly::SELECT_EXTERNREF;
970 RC = &WebAssembly::EXTERNREFRegClass;
973 Opc = WebAssembly::SELECT_EXNREF;
974 RC = &WebAssembly::EXNREFRegClass;
980 Register ResultReg = createResultReg(RC);
981 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
986 updateValueMap(
Select, ResultReg);
990bool WebAssemblyFastISel::selectTrunc(
const Instruction *
I) {
993 const Value *
Op = Trunc->getOperand(0);
1001 if (From == MVT::i64) {
1003 return copyValue(
Reg);
1005 if (To == MVT::i1 || To == MVT::i8 || To == MVT::i16 || To == MVT::i32) {
1007 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1008 TII.get(WebAssembly::I32_WRAP_I64), Result)
1014 if (From == MVT::i32)
1015 return copyValue(
Reg);
1020 unsigned Reg = Truncate(In);
1024 updateValueMap(Trunc,
Reg);
1028bool WebAssemblyFastISel::selectZExt(
const Instruction *
I) {
1031 const Value *
Op = ZExt->getOperand(0);
1037 unsigned Reg = zeroExtend(In,
Op, From, To);
1041 updateValueMap(ZExt,
Reg);
1045bool WebAssemblyFastISel::selectSExt(
const Instruction *
I) {
1048 const Value *
Op = SExt->getOperand(0);
1054 unsigned Reg = signExtend(In,
Op, From, To);
1058 updateValueMap(SExt,
Reg);
1062bool WebAssemblyFastISel::selectICmp(
const Instruction *
I) {
1065 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
1067 bool IsSigned =
false;
1068 switch (ICmp->getPredicate()) {
1069 case ICmpInst::ICMP_EQ:
1070 Opc =
I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
1072 case ICmpInst::ICMP_NE:
1073 Opc =
I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1075 case ICmpInst::ICMP_UGT:
1076 Opc =
I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1078 case ICmpInst::ICMP_UGE:
1079 Opc =
I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1081 case ICmpInst::ICMP_ULT:
1082 Opc =
I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1084 case ICmpInst::ICMP_ULE:
1085 Opc =
I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1087 case ICmpInst::ICMP_SGT:
1088 Opc =
I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1091 case ICmpInst::ICMP_SGE:
1092 Opc =
I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1095 case ICmpInst::ICMP_SLT:
1096 Opc =
I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1099 case ICmpInst::ICMP_SLE:
1100 Opc =
I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1107 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
1111 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
1115 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1116 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1119 updateValueMap(ICmp, ResultReg);
1123bool WebAssemblyFastISel::selectFCmp(
const Instruction *
I) {
1126 Register LHS = getRegForValue(FCmp->getOperand(0));
1130 Register RHS = getRegForValue(FCmp->getOperand(1));
1134 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1137 switch (FCmp->getPredicate()) {
1138 case FCmpInst::FCMP_OEQ:
1139 Opc =
F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1141 case FCmpInst::FCMP_UNE:
1142 Opc =
F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1144 case FCmpInst::FCMP_OGT:
1145 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1147 case FCmpInst::FCMP_OGE:
1148 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1150 case FCmpInst::FCMP_OLT:
1151 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1153 case FCmpInst::FCMP_OLE:
1154 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1156 case FCmpInst::FCMP_UGT:
1157 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1160 case FCmpInst::FCMP_UGE:
1161 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1164 case FCmpInst::FCMP_ULT:
1165 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1168 case FCmpInst::FCMP_ULE:
1169 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1176 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1177 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1182 ResultReg = notValue(ResultReg);
1184 updateValueMap(FCmp, ResultReg);
1188bool WebAssemblyFastISel::selectBitCast(
const Instruction *
I) {
1192 EVT VT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
1193 EVT RetVT = TLI.getValueType(
DL,
I->getType());
1203 updateValueMap(
I, In);
1213 assert(Iter->isBitcast());
1215 updateValueMap(
I,
Reg);
1219bool WebAssemblyFastISel::selectLoad(
const Instruction *
I) {
1221 if (
Load->isAtomic())
1229 if (!computeAddress(
Load->getPointerOperand(), Addr))
1235 const TargetRegisterClass *RC;
1237 switch (getSimpleType(
Load->getType())) {
1240 Opc = A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
1241 RC = &WebAssembly::I32RegClass;
1244 Opc = A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;
1245 RC = &WebAssembly::I32RegClass;
1248 Opc = A64 ? WebAssembly::LOAD_I32_A64 : WebAssembly::LOAD_I32_A32;
1249 RC = &WebAssembly::I32RegClass;
1252 Opc = A64 ? WebAssembly::LOAD_I64_A64 : WebAssembly::LOAD_I64_A32;
1253 RC = &WebAssembly::I64RegClass;
1256 Opc = A64 ? WebAssembly::LOAD_F32_A64 : WebAssembly::LOAD_F32_A32;
1257 RC = &WebAssembly::F32RegClass;
1260 Opc = A64 ? WebAssembly::LOAD_F64_A64 : WebAssembly::LOAD_F64_A32;
1261 RC = &WebAssembly::F64RegClass;
1267 materializeLoadStoreOperands(Addr);
1269 Register ResultReg = createResultReg(RC);
1270 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc),
1273 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1275 updateValueMap(Load, ResultReg);
1279bool WebAssemblyFastISel::selectStore(
const Instruction *
I) {
1281 if (
Store->isAtomic())
1286 Store->getValueOperand()->getType()->isVectorTy())
1290 if (!computeAddress(
Store->getPointerOperand(), Addr))
1294 bool VTIsi1 =
false;
1296 switch (getSimpleType(
Store->getValueOperand()->getType())) {
1301 Opc = A64 ? WebAssembly::STORE8_I32_A64 : WebAssembly::STORE8_I32_A32;
1304 Opc = A64 ? WebAssembly::STORE16_I32_A64 : WebAssembly::STORE16_I32_A32;
1307 Opc = A64 ? WebAssembly::STORE_I32_A64 : WebAssembly::STORE_I32_A32;
1310 Opc = A64 ? WebAssembly::STORE_I64_A64 : WebAssembly::STORE_I64_A32;
1313 Opc = A64 ? WebAssembly::STORE_F32_A64 : WebAssembly::STORE_F32_A32;
1316 Opc = A64 ? WebAssembly::STORE_F64_A64 : WebAssembly::STORE_F64_A32;
1322 materializeLoadStoreOperands(Addr);
1324 Register ValueReg = getRegForValue(
Store->getValueOperand());
1328 ValueReg = maskI1Value(ValueReg,
Store->getValueOperand());
1330 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc));
1332 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1338bool WebAssemblyFastISel::selectBr(
const Instruction *
I) {
1340 if (Br->isUnconditional()) {
1341 MachineBasicBlock *MSucc = FuncInfo.getMBB(Br->getSuccessor(0));
1342 fastEmitBranch(MSucc, Br->getDebugLoc());
1346 MachineBasicBlock *
TBB = FuncInfo.getMBB(Br->getSuccessor(0));
1347 MachineBasicBlock *FBB = FuncInfo.getMBB(Br->getSuccessor(1));
1350 unsigned CondReg = getRegForI1Value(Br->getCondition(), Br->getParent(), Not);
1354 unsigned Opc = WebAssembly::BR_IF;
1356 Opc = WebAssembly::BR_UNLESS;
1358 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1362 finishCondBranch(Br->getParent(),
TBB, FBB);
1366bool WebAssemblyFastISel::selectRet(
const Instruction *
I) {
1367 if (!FuncInfo.CanLowerReturn)
1372 if (Ret->getNumOperands() == 0) {
1373 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1374 TII.get(WebAssembly::RETURN));
1379 if (Ret->getNumOperands() > 1)
1382 Value *RV = Ret->getOperand(0);
1386 switch (getSimpleType(RV->
getType())) {
1401 case MVT::externref:
1409 if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::SExt))
1410 Reg = getRegForSignedValue(RV);
1411 else if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::ZExt))
1412 Reg = getRegForUnsignedValue(RV);
1414 Reg = getRegForValue(RV);
1419 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1420 TII.get(WebAssembly::RETURN))
1425bool WebAssemblyFastISel::selectUnreachable(
const Instruction *
I) {
1426 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1427 TII.get(WebAssembly::UNREACHABLE));
1431bool WebAssemblyFastISel::fastSelectInstruction(
const Instruction *
I) {
1432 switch (
I->getOpcode()) {
1433 case Instruction::Call:
1437 case Instruction::Select:
1438 return selectSelect(
I);
1439 case Instruction::Trunc:
1440 return selectTrunc(
I);
1441 case Instruction::ZExt:
1442 return selectZExt(
I);
1443 case Instruction::SExt:
1444 return selectSExt(
I);
1445 case Instruction::ICmp:
1446 return selectICmp(
I);
1447 case Instruction::FCmp:
1448 return selectFCmp(
I);
1449 case Instruction::BitCast:
1450 return selectBitCast(
I);
1451 case Instruction::Load:
1452 return selectLoad(
I);
1453 case Instruction::Store:
1454 return selectStore(
I);
1455 case Instruction::Br:
1457 case Instruction::Ret:
1458 return selectRet(
I);
1459 case Instruction::Unreachable:
1460 return selectUnreachable(
I);
1466 return selectOperator(
I,
I->getOpcode());
1473 return new WebAssemblyFastISel(FuncInfo, LibInfo, LibcallLowering);
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 MCRegister 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.
Tracks which library functions to use for a particular subtarget.
@ 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, const LibcallLoweringInfo *libcallLowering)
@ 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.