42#define DEBUG_TYPE "wasm-fastisel"
46class WebAssemblyFastISel final :
public FastISel {
50 enum BaseKind { RegBase, FrameIndexBase };
53 BaseKind Kind = RegBase;
60 bool IsBaseSet =
false;
69 void setKind(BaseKind K) {
70 assert(!isSet() &&
"Can't change kind with non-zero base");
73 BaseKind getKind()
const {
return Kind; }
74 bool isRegBase()
const {
return Kind == RegBase; }
75 bool isFIBase()
const {
return Kind == FrameIndexBase; }
76 void setReg(
unsigned Reg) {
77 assert(isRegBase() &&
"Invalid base register access!");
78 assert(!IsBaseSet &&
"Base cannot be reset");
83 assert(isRegBase() &&
"Invalid base register access!");
86 void setFI(
unsigned FI) {
87 assert(isFIBase() &&
"Invalid base frame index access!");
88 assert(!IsBaseSet &&
"Base cannot be reset");
92 unsigned getFI()
const {
93 assert(isFIBase() &&
"Invalid base frame index access!");
97 void setOffset(int64_t NewOffset) {
98 assert(NewOffset >= 0 &&
"Offsets must be non-negative");
103 const GlobalValue *getGlobalValue()
const {
return GV; }
104 bool isSet()
const {
return IsBaseSet; }
115 EVT VT = TLI.getValueType(
DL, Ty,
true);
155 bool computeAddress(
const Value *Obj, Address &Addr);
156 void materializeLoadStoreOperands(Address &Addr);
159 unsigned maskI1Value(
unsigned Reg,
const Value *V);
160 unsigned getRegForI1Value(
const Value *V,
const BasicBlock *BB,
bool &Not);
161 unsigned zeroExtendToI32(
unsigned Reg,
const Value *V,
163 unsigned signExtendToI32(
unsigned Reg,
const Value *V,
169 unsigned getRegForUnsignedValue(
const Value *V);
170 unsigned getRegForSignedValue(
const Value *V);
171 unsigned getRegForPromotedValue(
const Value *V,
bool IsSigned);
172 unsigned notValue(
unsigned Reg);
173 unsigned copyValue(
unsigned Reg);
178 bool fastLowerArguments()
override;
200 :
FastISel(FuncInfo, LibInfo, LibcallLowering,
206 bool fastSelectInstruction(
const Instruction *
I)
override;
208#include "WebAssemblyGenFastISel.inc"
213bool WebAssemblyFastISel::computeAddress(
const Value *Obj, Address &Addr) {
214 const User *
U =
nullptr;
215 unsigned Opcode = Instruction::UserOp1;
219 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(Obj)) ||
220 FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
221 Opcode =
I->getOpcode();
225 Opcode =
C->getOpcode();
230 if (Ty->getAddressSpace() > 255)
236 if (TLI.isPositionIndependent())
238 if (Addr.getGlobalValue())
240 if (GV->isThreadLocal())
242 Addr.setGlobalValue(GV);
249 case Instruction::BitCast: {
251 return computeAddress(
U->getOperand(0), Addr);
253 case Instruction::IntToPtr: {
255 if (TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
256 TLI.getPointerTy(
DL))
257 return computeAddress(
U->getOperand(0), Addr);
260 case Instruction::PtrToInt: {
262 if (TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
263 return computeAddress(
U->getOperand(0), Addr);
266 case Instruction::GetElementPtr: {
268 uint64_t TmpOffset = Addr.getOffset();
271 goto unsupported_gep;
276 const Value *
Op = GTI.getOperand();
277 if (StructType *STy = GTI.getStructTypeOrNull()) {
278 const StructLayout *SL =
DL.getStructLayout(STy);
282 uint64_t S = GTI.getSequentialElementStride(
DL);
286 TmpOffset += CI->getSExtValue() * S;
289 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
297 if (canFoldAddIntoGEP(U,
Op)) {
300 TmpOffset += CI->getSExtValue() * S;
306 goto unsupported_gep;
311 if (int64_t(TmpOffset) >= 0) {
313 Addr.setOffset(TmpOffset);
314 if (computeAddress(
U->getOperand(0), Addr))
322 case Instruction::Alloca: {
324 DenseMap<const AllocaInst *, int>::iterator
SI =
325 FuncInfo.StaticAllocaMap.find(AI);
326 if (SI != FuncInfo.StaticAllocaMap.end()) {
330 Addr.setKind(Address::FrameIndexBase);
331 Addr.setFI(
SI->second);
336 case Instruction::Add: {
340 if (!OFBinOp->hasNoUnsignedWrap())
351 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
352 if (int64_t(TmpOffset) >= 0) {
353 Addr.setOffset(TmpOffset);
354 return computeAddress(
LHS, Addr);
359 if (computeAddress(
LHS, Addr) && computeAddress(
RHS, Addr))
365 case Instruction::Sub: {
369 if (!OFBinOp->hasNoUnsignedWrap())
377 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
378 if (TmpOffset >= 0) {
379 Addr.setOffset(TmpOffset);
380 return computeAddress(
LHS, Addr);
393 return Addr.getReg() != 0;
396void WebAssemblyFastISel::materializeLoadStoreOperands(
Address &Addr) {
397 if (Addr.isRegBase()) {
398 unsigned Reg = Addr.getReg();
400 Reg = createResultReg(Subtarget->
hasAddr64() ? &WebAssembly::I64RegClass
401 : &WebAssembly::I32RegClass);
402 unsigned Opc = Subtarget->
hasAddr64() ? WebAssembly::CONST_I64
403 : WebAssembly::CONST_I32;
411void WebAssemblyFastISel::addLoadStoreOperands(
const Address &Addr,
412 const MachineInstrBuilder &MIB,
413 MachineMemOperand *MMO) {
418 if (
const GlobalValue *GV = Addr.getGlobalValue())
421 MIB.
addImm(Addr.getOffset());
423 if (Addr.isRegBase())
424 MIB.
addReg(Addr.getReg());
431unsigned WebAssemblyFastISel::maskI1Value(
unsigned Reg,
const Value *V) {
432 return zeroExtendToI32(
Reg, V, MVT::i1);
435unsigned WebAssemblyFastISel::getRegForI1Value(
const Value *V,
436 const BasicBlock *BB,
440 if (ICmp->isEquality() &&
C->isZero() &&
C->getType()->isIntegerTy(32) &&
441 ICmp->getParent() == BB) {
442 Not = ICmp->isTrueWhenEqual();
443 return getRegForValue(ICmp->getOperand(0));
450 return maskI1Value(
Reg, V);
453unsigned WebAssemblyFastISel::zeroExtendToI32(
unsigned Reg,
const Value *V,
464 return copyValue(
Reg);
470 return copyValue(
Reg);
475 Register Imm = createResultReg(&WebAssembly::I32RegClass);
476 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
477 TII.get(WebAssembly::CONST_I32), Imm)
478 .
addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
481 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
482 TII.get(WebAssembly::AND_I32), Result)
489unsigned WebAssemblyFastISel::signExtendToI32(
unsigned Reg,
const Value *V,
500 return copyValue(
Reg);
505 Register Imm = createResultReg(&WebAssembly::I32RegClass);
506 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
507 TII.get(WebAssembly::CONST_I32), Imm)
508 .
addImm(32 - MVT(From).getSizeInBits());
510 Register Left = createResultReg(&WebAssembly::I32RegClass);
511 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
512 TII.get(WebAssembly::SHL_I32),
Left)
517 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
518 TII.get(WebAssembly::SHR_S_I32),
Right)
525unsigned WebAssemblyFastISel::zeroExtend(
unsigned Reg,
const Value *V,
528 if (To == MVT::i64) {
529 if (From == MVT::i64)
530 return copyValue(
Reg);
532 Reg = zeroExtendToI32(
Reg, V, From);
535 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
536 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
542 return zeroExtendToI32(
Reg, V, From);
547unsigned WebAssemblyFastISel::signExtend(
unsigned Reg,
const Value *V,
550 if (To == MVT::i64) {
551 if (From == MVT::i64)
552 return copyValue(
Reg);
554 Reg = signExtendToI32(
Reg, V, From);
557 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
558 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
564 return signExtendToI32(
Reg, V, From);
569unsigned WebAssemblyFastISel::getRegForUnsignedValue(
const Value *V) {
577 return zeroExtend(VReg, V, From, To);
580unsigned WebAssemblyFastISel::getRegForSignedValue(
const Value *V) {
588 return signExtend(VReg, V, From, To);
591unsigned WebAssemblyFastISel::getRegForPromotedValue(
const Value *V,
593 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(
V);
596unsigned WebAssemblyFastISel::notValue(
unsigned Reg) {
597 assert(
MRI.getRegClass(
Reg) == &WebAssembly::I32RegClass);
599 Register NotReg = createResultReg(&WebAssembly::I32RegClass);
600 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
601 TII.get(WebAssembly::EQZ_I32), NotReg)
606unsigned WebAssemblyFastISel::copyValue(
unsigned Reg) {
608 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::COPY),
614Register WebAssemblyFastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
615 DenseMap<const AllocaInst *, int>::iterator
SI =
616 FuncInfo.StaticAllocaMap.find(AI);
618 if (SI != FuncInfo.StaticAllocaMap.end()) {
620 createResultReg(Subtarget->
hasAddr64() ? &WebAssembly::I64RegClass
621 : &WebAssembly::I32RegClass);
623 Subtarget->
hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
624 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
632Register WebAssemblyFastISel::fastMaterializeConstant(
const Constant *
C) {
634 if (TLI.isPositionIndependent())
636 if (GV->isThreadLocal())
639 createResultReg(Subtarget->
hasAddr64() ? &WebAssembly::I64RegClass
640 : &WebAssembly::I32RegClass);
641 unsigned Opc = Subtarget->
hasAddr64() ? WebAssembly::CONST_I64
642 : WebAssembly::CONST_I32;
643 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
652bool WebAssemblyFastISel::fastLowerArguments() {
653 if (!FuncInfo.CanLowerReturn)
660 if (FuncInfo.Fn->getCallingConv() == CallingConv::Swift)
664 for (
auto const &Arg :
F->args()) {
665 const AttributeList &
Attrs =
F->getAttributes();
666 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
667 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
668 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
669 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
670 Attrs.hasParamAttr(
I, Attribute::Nest))
673 Type *ArgTy = Arg.getType();
680 const TargetRegisterClass *RC;
681 switch (getSimpleType(ArgTy)) {
686 Opc = WebAssembly::ARGUMENT_i32;
687 RC = &WebAssembly::I32RegClass;
690 Opc = WebAssembly::ARGUMENT_i64;
691 RC = &WebAssembly::I64RegClass;
694 Opc = WebAssembly::ARGUMENT_f32;
695 RC = &WebAssembly::F32RegClass;
698 Opc = WebAssembly::ARGUMENT_f64;
699 RC = &WebAssembly::F64RegClass;
702 Opc = WebAssembly::ARGUMENT_v16i8;
703 RC = &WebAssembly::V128RegClass;
706 Opc = WebAssembly::ARGUMENT_v8i16;
707 RC = &WebAssembly::V128RegClass;
710 Opc = WebAssembly::ARGUMENT_v4i32;
711 RC = &WebAssembly::V128RegClass;
714 Opc = WebAssembly::ARGUMENT_v2i64;
715 RC = &WebAssembly::V128RegClass;
718 Opc = WebAssembly::ARGUMENT_v4f32;
719 RC = &WebAssembly::V128RegClass;
722 Opc = WebAssembly::ARGUMENT_v2f64;
723 RC = &WebAssembly::V128RegClass;
726 Opc = WebAssembly::ARGUMENT_funcref;
727 RC = &WebAssembly::FUNCREFRegClass;
730 Opc = WebAssembly::ARGUMENT_externref;
731 RC = &WebAssembly::EXTERNREFRegClass;
734 Opc = WebAssembly::ARGUMENT_exnref;
735 RC = &WebAssembly::EXNREFRegClass;
740 Register ResultReg = createResultReg(RC);
741 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
743 updateValueMap(&Arg, ResultReg);
748 MRI.addLiveIn(WebAssembly::ARGUMENTS);
750 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
751 for (
auto const &Arg :
F->args()) {
754 MFI->clearParamsAndResults();
757 MFI->addParam(ArgTy);
760 if (!
F->getReturnType()->isVoidTy()) {
762 getLegalType(getSimpleType(
F->getReturnType()));
764 MFI->clearParamsAndResults();
767 MFI->addResult(RetTy);
773bool WebAssemblyFastISel::selectCall(
const Instruction *
I) {
778 WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_DEFAULT)
787 if (Func &&
Func->isIntrinsic())
793 bool IsDirect =
Func !=
nullptr;
798 unsigned Opc = IsDirect ? WebAssembly::CALL : WebAssembly::CALL_INDIRECT;
799 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
811 ResultReg = createResultReg(&WebAssembly::I32RegClass);
814 ResultReg = createResultReg(&WebAssembly::I64RegClass);
817 ResultReg = createResultReg(&WebAssembly::F32RegClass);
820 ResultReg = createResultReg(&WebAssembly::F64RegClass);
823 ResultReg = createResultReg(&WebAssembly::V128RegClass);
826 ResultReg = createResultReg(&WebAssembly::V128RegClass);
829 ResultReg = createResultReg(&WebAssembly::V128RegClass);
832 ResultReg = createResultReg(&WebAssembly::V128RegClass);
835 ResultReg = createResultReg(&WebAssembly::V128RegClass);
838 ResultReg = createResultReg(&WebAssembly::V128RegClass);
841 ResultReg = createResultReg(&WebAssembly::FUNCREFRegClass);
844 ResultReg = createResultReg(&WebAssembly::EXTERNREFRegClass);
847 ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);
854 SmallVector<unsigned, 8>
Args;
862 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
863 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
864 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
865 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
866 Attrs.hasParamAttr(
I, Attribute::Nest))
872 Reg = getRegForSignedValue(V);
874 Reg = getRegForUnsignedValue(V);
876 Reg = getRegForValue(V);
884 unsigned CalleeReg = 0;
891 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc));
894 MIB.
addReg(ResultReg, RegState::Define);
903 MF->getContext(), Subtarget);
915 for (
unsigned ArgReg : Args)
922 updateValueMap(
Call, ResultReg);
928bool WebAssemblyFastISel::selectSelect(
const Instruction *
I) {
933 getRegForI1Value(
Select->getCondition(),
I->getParent(), Not);
949 const TargetRegisterClass *RC;
950 switch (getSimpleType(
Select->getType())) {
955 Opc = WebAssembly::SELECT_I32;
956 RC = &WebAssembly::I32RegClass;
959 Opc = WebAssembly::SELECT_I64;
960 RC = &WebAssembly::I64RegClass;
963 Opc = WebAssembly::SELECT_F32;
964 RC = &WebAssembly::F32RegClass;
967 Opc = WebAssembly::SELECT_F64;
968 RC = &WebAssembly::F64RegClass;
971 Opc = WebAssembly::SELECT_FUNCREF;
972 RC = &WebAssembly::FUNCREFRegClass;
975 Opc = WebAssembly::SELECT_EXTERNREF;
976 RC = &WebAssembly::EXTERNREFRegClass;
979 Opc = WebAssembly::SELECT_EXNREF;
980 RC = &WebAssembly::EXNREFRegClass;
986 Register ResultReg = createResultReg(RC);
987 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
992 updateValueMap(
Select, ResultReg);
996bool WebAssemblyFastISel::selectTrunc(
const Instruction *
I) {
999 const Value *
Op = Trunc->getOperand(0);
1007 if (From == MVT::i64) {
1009 return copyValue(
Reg);
1011 if (To == MVT::i1 || To == MVT::i8 || To == MVT::i16 || To == MVT::i32) {
1013 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1014 TII.get(WebAssembly::I32_WRAP_I64), Result)
1020 if (From == MVT::i32)
1021 return copyValue(
Reg);
1026 unsigned Reg = Truncate(In);
1030 updateValueMap(Trunc,
Reg);
1034bool WebAssemblyFastISel::selectZExt(
const Instruction *
I) {
1037 const Value *
Op = ZExt->getOperand(0);
1043 unsigned Reg = zeroExtend(In,
Op, From, To);
1047 updateValueMap(ZExt,
Reg);
1051bool WebAssemblyFastISel::selectSExt(
const Instruction *
I) {
1054 const Value *
Op = SExt->getOperand(0);
1060 unsigned Reg = signExtend(In,
Op, From, To);
1064 updateValueMap(SExt,
Reg);
1068bool WebAssemblyFastISel::selectICmp(
const Instruction *
I) {
1071 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
1073 bool IsSigned =
false;
1074 switch (ICmp->getPredicate()) {
1075 case ICmpInst::ICMP_EQ:
1076 Opc =
I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
1078 case ICmpInst::ICMP_NE:
1079 Opc =
I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1081 case ICmpInst::ICMP_UGT:
1082 Opc =
I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1084 case ICmpInst::ICMP_UGE:
1085 Opc =
I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1087 case ICmpInst::ICMP_ULT:
1088 Opc =
I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1090 case ICmpInst::ICMP_ULE:
1091 Opc =
I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1093 case ICmpInst::ICMP_SGT:
1094 Opc =
I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1097 case ICmpInst::ICMP_SGE:
1098 Opc =
I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1101 case ICmpInst::ICMP_SLT:
1102 Opc =
I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1105 case ICmpInst::ICMP_SLE:
1106 Opc =
I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1113 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
1117 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
1121 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1122 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1125 updateValueMap(ICmp, ResultReg);
1129bool WebAssemblyFastISel::selectFCmp(
const Instruction *
I) {
1132 Register LHS = getRegForValue(FCmp->getOperand(0));
1136 Register RHS = getRegForValue(FCmp->getOperand(1));
1140 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1143 switch (FCmp->getPredicate()) {
1144 case FCmpInst::FCMP_OEQ:
1145 Opc =
F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1147 case FCmpInst::FCMP_UNE:
1148 Opc =
F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1150 case FCmpInst::FCMP_OGT:
1151 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1153 case FCmpInst::FCMP_OGE:
1154 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1156 case FCmpInst::FCMP_OLT:
1157 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1159 case FCmpInst::FCMP_OLE:
1160 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1162 case FCmpInst::FCMP_UGT:
1163 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1166 case FCmpInst::FCMP_UGE:
1167 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1170 case FCmpInst::FCMP_ULT:
1171 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1174 case FCmpInst::FCMP_ULE:
1175 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1182 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1183 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1188 ResultReg = notValue(ResultReg);
1190 updateValueMap(FCmp, ResultReg);
1194bool WebAssemblyFastISel::selectBitCast(
const Instruction *
I) {
1198 EVT VT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
1199 EVT RetVT = TLI.getValueType(
DL,
I->getType());
1209 updateValueMap(
I, In);
1219 assert(Iter->isBitcast());
1221 updateValueMap(
I,
Reg);
1225bool WebAssemblyFastISel::selectLoad(
const Instruction *
I) {
1227 if (
Load->isAtomic())
1235 if (!computeAddress(
Load->getPointerOperand(), Addr))
1241 const TargetRegisterClass *RC;
1243 switch (getSimpleType(
Load->getType())) {
1246 Opc = A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
1247 RC = &WebAssembly::I32RegClass;
1250 Opc = A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;
1251 RC = &WebAssembly::I32RegClass;
1254 Opc = A64 ? WebAssembly::LOAD_I32_A64 : WebAssembly::LOAD_I32_A32;
1255 RC = &WebAssembly::I32RegClass;
1258 Opc = A64 ? WebAssembly::LOAD_I64_A64 : WebAssembly::LOAD_I64_A32;
1259 RC = &WebAssembly::I64RegClass;
1262 Opc = A64 ? WebAssembly::LOAD_F32_A64 : WebAssembly::LOAD_F32_A32;
1263 RC = &WebAssembly::F32RegClass;
1266 Opc = A64 ? WebAssembly::LOAD_F64_A64 : WebAssembly::LOAD_F64_A32;
1267 RC = &WebAssembly::F64RegClass;
1273 materializeLoadStoreOperands(Addr);
1275 Register ResultReg = createResultReg(RC);
1276 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc),
1279 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1281 updateValueMap(Load, ResultReg);
1285bool WebAssemblyFastISel::selectStore(
const Instruction *
I) {
1287 if (
Store->isAtomic())
1292 Store->getValueOperand()->getType()->isVectorTy())
1296 if (!computeAddress(
Store->getPointerOperand(), Addr))
1300 bool VTIsi1 =
false;
1302 switch (getSimpleType(
Store->getValueOperand()->getType())) {
1307 Opc = A64 ? WebAssembly::STORE8_I32_A64 : WebAssembly::STORE8_I32_A32;
1310 Opc = A64 ? WebAssembly::STORE16_I32_A64 : WebAssembly::STORE16_I32_A32;
1313 Opc = A64 ? WebAssembly::STORE_I32_A64 : WebAssembly::STORE_I32_A32;
1316 Opc = A64 ? WebAssembly::STORE_I64_A64 : WebAssembly::STORE_I64_A32;
1319 Opc = A64 ? WebAssembly::STORE_F32_A64 : WebAssembly::STORE_F32_A32;
1322 Opc = A64 ? WebAssembly::STORE_F64_A64 : WebAssembly::STORE_F64_A32;
1328 materializeLoadStoreOperands(Addr);
1330 Register ValueReg = getRegForValue(
Store->getValueOperand());
1334 ValueReg = maskI1Value(ValueReg,
Store->getValueOperand());
1336 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc));
1338 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1344bool WebAssemblyFastISel::selectBr(
const Instruction *
I) {
1346 if (Br->isUnconditional()) {
1347 MachineBasicBlock *MSucc = FuncInfo.getMBB(Br->getSuccessor(0));
1348 fastEmitBranch(MSucc, Br->getDebugLoc());
1352 MachineBasicBlock *
TBB = FuncInfo.getMBB(Br->getSuccessor(0));
1353 MachineBasicBlock *FBB = FuncInfo.getMBB(Br->getSuccessor(1));
1356 unsigned CondReg = getRegForI1Value(Br->getCondition(), Br->getParent(), Not);
1360 unsigned Opc = WebAssembly::BR_IF;
1362 Opc = WebAssembly::BR_UNLESS;
1364 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1368 finishCondBranch(Br->getParent(),
TBB, FBB);
1372bool WebAssemblyFastISel::selectRet(
const Instruction *
I) {
1373 if (!FuncInfo.CanLowerReturn)
1378 if (Ret->getNumOperands() == 0) {
1379 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1380 TII.get(WebAssembly::RETURN));
1385 if (Ret->getNumOperands() > 1)
1388 Value *RV = Ret->getOperand(0);
1392 switch (getSimpleType(RV->
getType())) {
1407 case MVT::externref:
1415 if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::SExt))
1416 Reg = getRegForSignedValue(RV);
1417 else if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::ZExt))
1418 Reg = getRegForUnsignedValue(RV);
1420 Reg = getRegForValue(RV);
1425 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1426 TII.get(WebAssembly::RETURN))
1431bool WebAssemblyFastISel::selectUnreachable(
const Instruction *
I) {
1432 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1433 TII.get(WebAssembly::UNREACHABLE));
1437bool WebAssemblyFastISel::fastSelectInstruction(
const Instruction *
I) {
1438 switch (
I->getOpcode()) {
1439 case Instruction::Call:
1443 case Instruction::Select:
1444 return selectSelect(
I);
1445 case Instruction::Trunc:
1446 return selectTrunc(
I);
1447 case Instruction::ZExt:
1448 return selectZExt(
I);
1449 case Instruction::SExt:
1450 return selectSExt(
I);
1451 case Instruction::ICmp:
1452 return selectICmp(
I);
1453 case Instruction::FCmp:
1454 return selectFCmp(
I);
1455 case Instruction::BitCast:
1456 return selectBitCast(
I);
1457 case Instruction::Load:
1458 return selectLoad(
I);
1459 case Instruction::Store:
1460 return selectStore(
I);
1461 case Instruction::Br:
1463 case Instruction::Ret:
1464 return selectRet(
I);
1465 case Instruction::Unreachable:
1466 return selectUnreachable(
I);
1472 return selectOperator(
I,
I->getOpcode());
1479 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 & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
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 & 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.
LLVM_ABI unsigned getPointerAddressSpace() const
Get the address space of this pointer or pointer vector type.
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.
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.