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;
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 const Value *
Op = Trunc->getOperand(0);
999 if (From == MVT::i64) {
1001 return copyValue(
Reg);
1003 if (To == MVT::i1 || To == MVT::i8 || To == MVT::i16 || To == MVT::i32) {
1005 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1006 TII.get(WebAssembly::I32_WRAP_I64), Result)
1012 if (From == MVT::i32)
1013 return copyValue(
Reg);
1018 unsigned Reg = Truncate(In);
1022 updateValueMap(Trunc,
Reg);
1026bool WebAssemblyFastISel::selectZExt(
const Instruction *
I) {
1029 const Value *
Op = ZExt->getOperand(0);
1035 unsigned Reg = zeroExtend(In,
Op, From, To);
1039 updateValueMap(ZExt,
Reg);
1043bool WebAssemblyFastISel::selectSExt(
const Instruction *
I) {
1046 const Value *
Op = SExt->getOperand(0);
1052 unsigned Reg = signExtend(In,
Op, From, To);
1056 updateValueMap(SExt,
Reg);
1060bool WebAssemblyFastISel::selectICmp(
const Instruction *
I) {
1063 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
1065 bool IsSigned =
false;
1066 switch (ICmp->getPredicate()) {
1067 case ICmpInst::ICMP_EQ:
1068 Opc =
I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
1070 case ICmpInst::ICMP_NE:
1071 Opc =
I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1073 case ICmpInst::ICMP_UGT:
1074 Opc =
I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1076 case ICmpInst::ICMP_UGE:
1077 Opc =
I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1079 case ICmpInst::ICMP_ULT:
1080 Opc =
I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1082 case ICmpInst::ICMP_ULE:
1083 Opc =
I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1085 case ICmpInst::ICMP_SGT:
1086 Opc =
I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1089 case ICmpInst::ICMP_SGE:
1090 Opc =
I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1093 case ICmpInst::ICMP_SLT:
1094 Opc =
I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1097 case ICmpInst::ICMP_SLE:
1098 Opc =
I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1105 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
1109 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
1113 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1114 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1117 updateValueMap(ICmp, ResultReg);
1121bool WebAssemblyFastISel::selectFCmp(
const Instruction *
I) {
1124 Register LHS = getRegForValue(FCmp->getOperand(0));
1128 Register RHS = getRegForValue(FCmp->getOperand(1));
1132 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1135 switch (FCmp->getPredicate()) {
1136 case FCmpInst::FCMP_OEQ:
1137 Opc =
F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1139 case FCmpInst::FCMP_UNE:
1140 Opc =
F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1142 case FCmpInst::FCMP_OGT:
1143 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1145 case FCmpInst::FCMP_OGE:
1146 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1148 case FCmpInst::FCMP_OLT:
1149 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1151 case FCmpInst::FCMP_OLE:
1152 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1154 case FCmpInst::FCMP_UGT:
1155 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1158 case FCmpInst::FCMP_UGE:
1159 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1162 case FCmpInst::FCMP_ULT:
1163 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1166 case FCmpInst::FCMP_ULE:
1167 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1174 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1175 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1180 ResultReg = notValue(ResultReg);
1182 updateValueMap(FCmp, ResultReg);
1186bool WebAssemblyFastISel::selectBitCast(
const Instruction *
I) {
1190 EVT VT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
1191 EVT RetVT = TLI.getValueType(
DL,
I->getType());
1201 updateValueMap(
I, In);
1211 assert(Iter->isBitcast());
1213 updateValueMap(
I,
Reg);
1217bool WebAssemblyFastISel::selectLoad(
const Instruction *
I) {
1219 if (
Load->isAtomic())
1227 if (!computeAddress(
Load->getPointerOperand(), Addr))
1233 const TargetRegisterClass *RC;
1235 switch (getSimpleType(
Load->getType())) {
1238 Opc = A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
1239 RC = &WebAssembly::I32RegClass;
1242 Opc = A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;
1243 RC = &WebAssembly::I32RegClass;
1246 Opc = A64 ? WebAssembly::LOAD_I32_A64 : WebAssembly::LOAD_I32_A32;
1247 RC = &WebAssembly::I32RegClass;
1250 Opc = A64 ? WebAssembly::LOAD_I64_A64 : WebAssembly::LOAD_I64_A32;
1251 RC = &WebAssembly::I64RegClass;
1254 Opc = A64 ? WebAssembly::LOAD_F32_A64 : WebAssembly::LOAD_F32_A32;
1255 RC = &WebAssembly::F32RegClass;
1258 Opc = A64 ? WebAssembly::LOAD_F64_A64 : WebAssembly::LOAD_F64_A32;
1259 RC = &WebAssembly::F64RegClass;
1265 materializeLoadStoreOperands(Addr);
1267 Register ResultReg = createResultReg(RC);
1268 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc),
1271 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1273 updateValueMap(Load, ResultReg);
1277bool WebAssemblyFastISel::selectStore(
const Instruction *
I) {
1279 if (
Store->isAtomic())
1284 Store->getValueOperand()->getType()->isVectorTy())
1288 if (!computeAddress(
Store->getPointerOperand(), Addr))
1292 bool VTIsi1 =
false;
1294 switch (getSimpleType(
Store->getValueOperand()->getType())) {
1299 Opc = A64 ? WebAssembly::STORE8_I32_A64 : WebAssembly::STORE8_I32_A32;
1302 Opc = A64 ? WebAssembly::STORE16_I32_A64 : WebAssembly::STORE16_I32_A32;
1305 Opc = A64 ? WebAssembly::STORE_I32_A64 : WebAssembly::STORE_I32_A32;
1308 Opc = A64 ? WebAssembly::STORE_I64_A64 : WebAssembly::STORE_I64_A32;
1311 Opc = A64 ? WebAssembly::STORE_F32_A64 : WebAssembly::STORE_F32_A32;
1314 Opc = A64 ? WebAssembly::STORE_F64_A64 : WebAssembly::STORE_F64_A32;
1320 materializeLoadStoreOperands(Addr);
1322 Register ValueReg = getRegForValue(
Store->getValueOperand());
1326 ValueReg = maskI1Value(ValueReg,
Store->getValueOperand());
1328 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc));
1330 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1336bool WebAssemblyFastISel::selectBr(
const Instruction *
I) {
1338 if (Br->isUnconditional()) {
1339 MachineBasicBlock *MSucc = FuncInfo.getMBB(Br->getSuccessor(0));
1340 fastEmitBranch(MSucc, Br->getDebugLoc());
1344 MachineBasicBlock *
TBB = FuncInfo.getMBB(Br->getSuccessor(0));
1345 MachineBasicBlock *FBB = FuncInfo.getMBB(Br->getSuccessor(1));
1348 unsigned CondReg = getRegForI1Value(Br->getCondition(), Br->getParent(), Not);
1352 unsigned Opc = WebAssembly::BR_IF;
1354 Opc = WebAssembly::BR_UNLESS;
1356 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1360 finishCondBranch(Br->getParent(),
TBB, FBB);
1364bool WebAssemblyFastISel::selectRet(
const Instruction *
I) {
1365 if (!FuncInfo.CanLowerReturn)
1370 if (
Ret->getNumOperands() == 0) {
1371 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1372 TII.get(WebAssembly::RETURN));
1377 if (
Ret->getNumOperands() > 1)
1384 switch (getSimpleType(RV->
getType())) {
1399 case MVT::externref:
1407 if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::SExt))
1408 Reg = getRegForSignedValue(RV);
1409 else if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::ZExt))
1410 Reg = getRegForUnsignedValue(RV);
1412 Reg = getRegForValue(RV);
1417 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1418 TII.get(WebAssembly::RETURN))
1423bool WebAssemblyFastISel::selectUnreachable(
const Instruction *
I) {
1424 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1425 TII.get(WebAssembly::UNREACHABLE));
1429bool WebAssemblyFastISel::fastSelectInstruction(
const Instruction *
I) {
1430 switch (
I->getOpcode()) {
1431 case Instruction::Call:
1435 case Instruction::Select:
1436 return selectSelect(
I);
1437 case Instruction::Trunc:
1438 return selectTrunc(
I);
1439 case Instruction::ZExt:
1440 return selectZExt(
I);
1441 case Instruction::SExt:
1442 return selectSExt(
I);
1443 case Instruction::ICmp:
1444 return selectICmp(
I);
1445 case Instruction::FCmp:
1446 return selectFCmp(
I);
1447 case Instruction::BitCast:
1448 return selectBitCast(
I);
1449 case Instruction::Load:
1450 return selectLoad(
I);
1451 case Instruction::Store:
1452 return selectStore(
I);
1453 case Instruction::Br:
1455 case Instruction::Ret:
1456 return selectRet(
I);
1457 case Instruction::Unreachable:
1458 return selectUnreachable(
I);
1464 return selectOperator(
I,
I->getOpcode());
1469 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 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.
@ 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.