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,
TII.get(WebAssembly::AND_I32),
489unsigned WebAssemblyFastISel::signExtendToI32(
unsigned Reg,
const Value *V,
500 return copyValue(
Reg);
506 if (From == MVT::i8 || From == MVT::i16) {
508 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
509 TII.get(From == MVT::i16 ? WebAssembly::I32_EXTEND16_S_I32
510 : WebAssembly::I32_EXTEND8_S_I32),
517 Register Imm = createResultReg(&WebAssembly::I32RegClass);
518 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
519 TII.get(WebAssembly::CONST_I32), Imm)
520 .
addImm(32 - MVT(From).getSizeInBits());
522 Register Left = createResultReg(&WebAssembly::I32RegClass);
523 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::SHL_I32),
529 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
530 TII.get(WebAssembly::SHR_S_I32),
Right)
537unsigned WebAssemblyFastISel::zeroExtend(
unsigned Reg,
const Value *V,
540 if (To == MVT::i64) {
541 if (From == MVT::i64)
542 return copyValue(
Reg);
544 Reg = zeroExtendToI32(
Reg, V, From);
547 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
548 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
554 return zeroExtendToI32(
Reg, V, From);
559unsigned WebAssemblyFastISel::signExtend(
unsigned Reg,
const Value *V,
562 if (To == MVT::i64) {
563 if (From == MVT::i64)
564 return copyValue(
Reg);
569 if (From != MVT::i32) {
570 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
571 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
575 Result = createResultReg(&WebAssembly::I64RegClass);
580 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
581 TII.get(WebAssembly::I64_EXTEND8_S_I64), Result)
585 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
586 TII.get(WebAssembly::I64_EXTEND16_S_I64), Result)
590 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
591 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
598 Reg = signExtendToI32(
Reg, V, From);
600 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
601 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
609 return signExtendToI32(
Reg, V, From);
614unsigned WebAssemblyFastISel::getRegForUnsignedValue(
const Value *V) {
622 return zeroExtend(VReg, V, From, To);
625unsigned WebAssemblyFastISel::getRegForSignedValue(
const Value *V) {
633 return signExtend(VReg, V, From, To);
636unsigned WebAssemblyFastISel::getRegForPromotedValue(
const Value *V,
638 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(
V);
641unsigned WebAssemblyFastISel::notValue(
unsigned Reg) {
642 assert(
MRI.getRegClass(
Reg) == &WebAssembly::I32RegClass);
644 Register NotReg = createResultReg(&WebAssembly::I32RegClass);
645 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::EQZ_I32),
651unsigned WebAssemblyFastISel::copyValue(
unsigned Reg) {
653 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::COPY),
659Register WebAssemblyFastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
660 DenseMap<const AllocaInst *, int>::iterator
SI =
661 FuncInfo.StaticAllocaMap.find(AI);
663 if (SI != FuncInfo.StaticAllocaMap.end()) {
665 createResultReg(Subtarget->
hasAddr64() ? &WebAssembly::I64RegClass
666 : &WebAssembly::I32RegClass);
668 Subtarget->
hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
669 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
677Register WebAssemblyFastISel::fastMaterializeConstant(
const Constant *
C) {
679 if (TLI.isPositionIndependent())
681 if (GV->isThreadLocal())
684 createResultReg(Subtarget->
hasAddr64() ? &WebAssembly::I64RegClass
685 : &WebAssembly::I32RegClass);
686 unsigned Opc = Subtarget->
hasAddr64() ? WebAssembly::CONST_I64
687 : WebAssembly::CONST_I32;
688 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
697bool WebAssemblyFastISel::fastLowerArguments() {
698 if (!FuncInfo.CanLowerReturn)
705 if (FuncInfo.Fn->getCallingConv() == CallingConv::Swift)
709 for (
auto const &Arg :
F->args()) {
710 const AttributeList &
Attrs =
F->getAttributes();
711 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
712 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
713 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
714 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
715 Attrs.hasParamAttr(
I, Attribute::Nest))
718 Type *ArgTy = Arg.getType();
725 const TargetRegisterClass *RC;
726 switch (getSimpleType(ArgTy)) {
731 Opc = WebAssembly::ARGUMENT_i32;
732 RC = &WebAssembly::I32RegClass;
735 Opc = WebAssembly::ARGUMENT_i64;
736 RC = &WebAssembly::I64RegClass;
739 Opc = WebAssembly::ARGUMENT_f32;
740 RC = &WebAssembly::F32RegClass;
743 Opc = WebAssembly::ARGUMENT_f64;
744 RC = &WebAssembly::F64RegClass;
747 Opc = WebAssembly::ARGUMENT_v16i8;
748 RC = &WebAssembly::V128RegClass;
751 Opc = WebAssembly::ARGUMENT_v8i16;
752 RC = &WebAssembly::V128RegClass;
755 Opc = WebAssembly::ARGUMENT_v4i32;
756 RC = &WebAssembly::V128RegClass;
759 Opc = WebAssembly::ARGUMENT_v2i64;
760 RC = &WebAssembly::V128RegClass;
763 Opc = WebAssembly::ARGUMENT_v4f32;
764 RC = &WebAssembly::V128RegClass;
767 Opc = WebAssembly::ARGUMENT_v2f64;
768 RC = &WebAssembly::V128RegClass;
771 Opc = WebAssembly::ARGUMENT_funcref;
772 RC = &WebAssembly::FUNCREFRegClass;
775 Opc = WebAssembly::ARGUMENT_externref;
776 RC = &WebAssembly::EXTERNREFRegClass;
779 Opc = WebAssembly::ARGUMENT_exnref;
780 RC = &WebAssembly::EXNREFRegClass;
785 Register ResultReg = createResultReg(RC);
786 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
788 updateValueMap(&Arg, ResultReg);
793 MRI.addLiveIn(WebAssembly::ARGUMENTS);
795 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
796 for (
auto const &Arg :
F->args()) {
799 MFI->clearParamsAndResults();
802 MFI->addParam(ArgTy);
805 if (!
F->getReturnType()->isVoidTy()) {
807 getLegalType(getSimpleType(
F->getReturnType()));
809 MFI->clearParamsAndResults();
812 MFI->addResult(RetTy);
818bool WebAssemblyFastISel::selectCall(
const Instruction *
I) {
823 WebAssembly::WasmAddressSpace::WASM_ADDRESS_SPACE_DEFAULT)
832 if (Func &&
Func->isIntrinsic())
838 bool IsDirect =
Func !=
nullptr;
843 unsigned Opc = IsDirect ? WebAssembly::CALL : WebAssembly::CALL_INDIRECT;
844 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
856 ResultReg = createResultReg(&WebAssembly::I32RegClass);
859 ResultReg = createResultReg(&WebAssembly::I64RegClass);
862 ResultReg = createResultReg(&WebAssembly::F32RegClass);
865 ResultReg = createResultReg(&WebAssembly::F64RegClass);
868 ResultReg = createResultReg(&WebAssembly::V128RegClass);
871 ResultReg = createResultReg(&WebAssembly::V128RegClass);
874 ResultReg = createResultReg(&WebAssembly::V128RegClass);
877 ResultReg = createResultReg(&WebAssembly::V128RegClass);
880 ResultReg = createResultReg(&WebAssembly::V128RegClass);
883 ResultReg = createResultReg(&WebAssembly::V128RegClass);
886 ResultReg = createResultReg(&WebAssembly::FUNCREFRegClass);
889 ResultReg = createResultReg(&WebAssembly::EXTERNREFRegClass);
892 ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);
899 SmallVector<unsigned, 8>
Args;
907 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
908 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
909 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
910 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
911 Attrs.hasParamAttr(
I, Attribute::Nest))
917 Reg = getRegForSignedValue(V);
919 Reg = getRegForUnsignedValue(V);
921 Reg = getRegForValue(V);
929 unsigned CalleeReg = 0;
936 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc));
939 MIB.
addReg(ResultReg, RegState::Define);
948 MF->getContext(), Subtarget);
960 for (
unsigned ArgReg : Args)
967 updateValueMap(
Call, ResultReg);
973bool WebAssemblyFastISel::selectSelect(
const Instruction *
I) {
978 getRegForI1Value(
Select->getCondition(),
I->getParent(), Not);
994 const TargetRegisterClass *RC;
995 switch (getSimpleType(
Select->getType())) {
1000 Opc = WebAssembly::SELECT_I32;
1001 RC = &WebAssembly::I32RegClass;
1004 Opc = WebAssembly::SELECT_I64;
1005 RC = &WebAssembly::I64RegClass;
1008 Opc = WebAssembly::SELECT_F32;
1009 RC = &WebAssembly::F32RegClass;
1012 Opc = WebAssembly::SELECT_F64;
1013 RC = &WebAssembly::F64RegClass;
1016 Opc = WebAssembly::SELECT_FUNCREF;
1017 RC = &WebAssembly::FUNCREFRegClass;
1019 case MVT::externref:
1020 Opc = WebAssembly::SELECT_EXTERNREF;
1021 RC = &WebAssembly::EXTERNREFRegClass;
1024 Opc = WebAssembly::SELECT_EXNREF;
1025 RC = &WebAssembly::EXNREFRegClass;
1031 Register ResultReg = createResultReg(RC);
1032 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1037 updateValueMap(
Select, ResultReg);
1041bool WebAssemblyFastISel::selectTrunc(
const Instruction *
I) {
1044 const Value *
Op = Trunc->getOperand(0);
1052 if (From == MVT::i64) {
1054 return copyValue(
Reg);
1056 if (To == MVT::i1 || To == MVT::i8 || To == MVT::i16 || To == MVT::i32) {
1058 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1059 TII.get(WebAssembly::I32_WRAP_I64), Result)
1065 if (From == MVT::i32)
1066 return copyValue(
Reg);
1071 unsigned Reg = Truncate(In);
1075 updateValueMap(Trunc,
Reg);
1079bool WebAssemblyFastISel::selectZExt(
const Instruction *
I) {
1082 const Value *
Op = ZExt->getOperand(0);
1088 unsigned Reg = zeroExtend(In,
Op, From, To);
1092 updateValueMap(ZExt,
Reg);
1096bool WebAssemblyFastISel::selectSExt(
const Instruction *
I) {
1099 const Value *
Op = SExt->getOperand(0);
1105 unsigned Reg = signExtend(In,
Op, From, To);
1109 updateValueMap(SExt,
Reg);
1113bool WebAssemblyFastISel::selectICmp(
const Instruction *
I) {
1116 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
1118 bool IsSigned =
false;
1119 switch (ICmp->getPredicate()) {
1120 case ICmpInst::ICMP_EQ:
1121 Opc =
I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
1123 case ICmpInst::ICMP_NE:
1124 Opc =
I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1126 case ICmpInst::ICMP_UGT:
1127 Opc =
I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1129 case ICmpInst::ICMP_UGE:
1130 Opc =
I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1132 case ICmpInst::ICMP_ULT:
1133 Opc =
I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1135 case ICmpInst::ICMP_ULE:
1136 Opc =
I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1138 case ICmpInst::ICMP_SGT:
1139 Opc =
I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1142 case ICmpInst::ICMP_SGE:
1143 Opc =
I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1146 case ICmpInst::ICMP_SLT:
1147 Opc =
I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1150 case ICmpInst::ICMP_SLE:
1151 Opc =
I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1158 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
1162 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
1166 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1167 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1170 updateValueMap(ICmp, ResultReg);
1174bool WebAssemblyFastISel::selectFCmp(
const Instruction *
I) {
1177 Register LHS = getRegForValue(FCmp->getOperand(0));
1181 Register RHS = getRegForValue(FCmp->getOperand(1));
1185 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1188 switch (FCmp->getPredicate()) {
1189 case FCmpInst::FCMP_OEQ:
1190 Opc =
F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1192 case FCmpInst::FCMP_UNE:
1193 Opc =
F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1195 case FCmpInst::FCMP_OGT:
1196 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1198 case FCmpInst::FCMP_OGE:
1199 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1201 case FCmpInst::FCMP_OLT:
1202 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1204 case FCmpInst::FCMP_OLE:
1205 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1207 case FCmpInst::FCMP_UGT:
1208 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1211 case FCmpInst::FCMP_UGE:
1212 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1215 case FCmpInst::FCMP_ULT:
1216 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1219 case FCmpInst::FCMP_ULE:
1220 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1227 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1228 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1233 ResultReg = notValue(ResultReg);
1235 updateValueMap(FCmp, ResultReg);
1239bool WebAssemblyFastISel::selectBitCast(
const Instruction *
I) {
1243 EVT VT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
1244 EVT RetVT = TLI.getValueType(
DL,
I->getType());
1254 updateValueMap(
I, In);
1264 assert(Iter->isBitcast());
1266 updateValueMap(
I,
Reg);
1270bool WebAssemblyFastISel::selectLoad(
const Instruction *
I) {
1272 if (
Load->isAtomic())
1280 if (!computeAddress(
Load->getPointerOperand(), Addr))
1286 const TargetRegisterClass *RC;
1288 switch (getSimpleType(
Load->getType())) {
1291 Opc = A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
1292 RC = &WebAssembly::I32RegClass;
1295 Opc = A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;
1296 RC = &WebAssembly::I32RegClass;
1299 Opc = A64 ? WebAssembly::LOAD_I32_A64 : WebAssembly::LOAD_I32_A32;
1300 RC = &WebAssembly::I32RegClass;
1303 Opc = A64 ? WebAssembly::LOAD_I64_A64 : WebAssembly::LOAD_I64_A32;
1304 RC = &WebAssembly::I64RegClass;
1307 Opc = A64 ? WebAssembly::LOAD_F32_A64 : WebAssembly::LOAD_F32_A32;
1308 RC = &WebAssembly::F32RegClass;
1311 Opc = A64 ? WebAssembly::LOAD_F64_A64 : WebAssembly::LOAD_F64_A32;
1312 RC = &WebAssembly::F64RegClass;
1318 materializeLoadStoreOperands(Addr);
1320 Register ResultReg = createResultReg(RC);
1322 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg);
1324 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1326 updateValueMap(Load, ResultReg);
1330bool WebAssemblyFastISel::selectStore(
const Instruction *
I) {
1332 if (
Store->isAtomic())
1337 Store->getValueOperand()->getType()->isVectorTy())
1341 if (!computeAddress(
Store->getPointerOperand(), Addr))
1345 bool VTIsi1 =
false;
1347 switch (getSimpleType(
Store->getValueOperand()->getType())) {
1352 Opc = A64 ? WebAssembly::STORE8_I32_A64 : WebAssembly::STORE8_I32_A32;
1355 Opc = A64 ? WebAssembly::STORE16_I32_A64 : WebAssembly::STORE16_I32_A32;
1358 Opc = A64 ? WebAssembly::STORE_I32_A64 : WebAssembly::STORE_I32_A32;
1361 Opc = A64 ? WebAssembly::STORE_I64_A64 : WebAssembly::STORE_I64_A32;
1364 Opc = A64 ? WebAssembly::STORE_F32_A64 : WebAssembly::STORE_F32_A32;
1367 Opc = A64 ? WebAssembly::STORE_F64_A64 : WebAssembly::STORE_F64_A32;
1373 materializeLoadStoreOperands(Addr);
1375 Register ValueReg = getRegForValue(
Store->getValueOperand());
1379 ValueReg = maskI1Value(ValueReg,
Store->getValueOperand());
1381 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc));
1383 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1389bool WebAssemblyFastISel::selectBr(
const Instruction *
I) {
1391 if (Br->isUnconditional()) {
1392 MachineBasicBlock *MSucc = FuncInfo.getMBB(Br->getSuccessor(0));
1393 fastEmitBranch(MSucc, Br->getDebugLoc());
1397 MachineBasicBlock *
TBB = FuncInfo.getMBB(Br->getSuccessor(0));
1398 MachineBasicBlock *FBB = FuncInfo.getMBB(Br->getSuccessor(1));
1401 unsigned CondReg = getRegForI1Value(Br->getCondition(), Br->getParent(), Not);
1405 unsigned Opc = WebAssembly::BR_IF;
1407 Opc = WebAssembly::BR_UNLESS;
1409 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1413 finishCondBranch(Br->getParent(),
TBB, FBB);
1417bool WebAssemblyFastISel::selectRet(
const Instruction *
I) {
1418 if (!FuncInfo.CanLowerReturn)
1423 if (Ret->getNumOperands() == 0) {
1424 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1425 TII.get(WebAssembly::RETURN));
1430 if (Ret->getNumOperands() > 1)
1433 Value *RV = Ret->getOperand(0);
1437 switch (getSimpleType(RV->
getType())) {
1452 case MVT::externref:
1460 if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::SExt))
1461 Reg = getRegForSignedValue(RV);
1462 else if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::ZExt))
1463 Reg = getRegForUnsignedValue(RV);
1465 Reg = getRegForValue(RV);
1470 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::RETURN))
1475bool WebAssemblyFastISel::selectUnreachable(
const Instruction *
I) {
1476 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1477 TII.get(WebAssembly::UNREACHABLE));
1481bool WebAssemblyFastISel::fastSelectInstruction(
const Instruction *
I) {
1482 switch (
I->getOpcode()) {
1483 case Instruction::Call:
1487 case Instruction::Select:
1488 return selectSelect(
I);
1489 case Instruction::Trunc:
1490 return selectTrunc(
I);
1491 case Instruction::ZExt:
1492 return selectZExt(
I);
1493 case Instruction::SExt:
1494 return selectSExt(
I);
1495 case Instruction::ICmp:
1496 return selectICmp(
I);
1497 case Instruction::FCmp:
1498 return selectFCmp(
I);
1499 case Instruction::BitCast:
1500 return selectBitCast(
I);
1501 case Instruction::Load:
1502 return selectLoad(
I);
1503 case Instruction::Store:
1504 return selectStore(
I);
1505 case Instruction::Br:
1507 case Instruction::Ret:
1508 return selectRet(
I);
1509 case Instruction::Unreachable:
1510 return selectUnreachable(
I);
1516 return selectOperator(
I,
I->getOpcode());
1523 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.