45 using namespace PatternMatch;
47 #define DEBUG_TYPE "wasm-fastisel"
51 class WebAssemblyFastISel final :
public FastISel {
55 using BaseKind =
enum { RegBase, FrameIndexBase };
58 BaseKind
Kind = RegBase;
65 bool IsBaseSet =
false;
73 Address() {
Base.Reg = 0; }
74 void setKind(BaseKind K) {
75 assert(!isSet() &&
"Can't change kind with non-zero base");
78 BaseKind getKind()
const {
return Kind; }
79 bool isRegBase()
const {
return Kind == RegBase; }
80 bool isFIBase()
const {
return Kind == FrameIndexBase; }
81 void setReg(
unsigned Reg) {
82 assert(isRegBase() &&
"Invalid base register access!");
83 assert(!IsBaseSet &&
"Base cannot be reset");
88 assert(isRegBase() &&
"Invalid base register access!");
91 void setFI(
unsigned FI) {
92 assert(isFIBase() &&
"Invalid base frame index access!");
93 assert(!IsBaseSet &&
"Base cannot be reset");
97 unsigned getFI()
const {
98 assert(isFIBase() &&
"Invalid base frame index access!");
102 void setOffset(int64_t NewOffset) {
103 assert(NewOffset >= 0 &&
"Offsets must be non-negative");
106 int64_t
getOffset()
const {
return Offset; }
108 const GlobalValue *getGlobalValue()
const {
return GV; }
109 bool isSet()
const {
return IsBaseSet; }
120 EVT VT = TLI.getValueType(
DL, Ty,
true);
156 bool computeAddress(
const Value *Obj, Address &
Addr);
157 void materializeLoadStoreOperands(Address &
Addr);
160 unsigned maskI1Value(
unsigned Reg,
const Value *V);
162 unsigned zeroExtendToI32(
unsigned Reg,
const Value *V,
164 unsigned signExtendToI32(
unsigned Reg,
const Value *V,
170 unsigned getRegForUnsignedValue(
const Value *V);
171 unsigned getRegForSignedValue(
const Value *V);
172 unsigned getRegForPromotedValue(
const Value *V,
bool IsSigned);
173 unsigned notValue(
unsigned Reg);
174 unsigned copyValue(
unsigned Reg);
177 unsigned fastMaterializeAlloca(
const AllocaInst *AI)
override;
178 unsigned fastMaterializeConstant(
const Constant *
C)
override;
179 bool fastLowerArguments()
override;
200 :
FastISel(FuncInfo, LibInfo,
true) {
205 bool fastSelectInstruction(
const Instruction *
I)
override;
207 #include "WebAssemblyGenFastISel.inc"
212 bool WebAssemblyFastISel::computeAddress(
const Value *Obj, Address &
Addr) {
213 const User *U =
nullptr;
214 unsigned Opcode = Instruction::UserOp1;
215 if (
const auto *
I = dyn_cast<Instruction>(Obj)) {
218 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(Obj)) ||
219 FuncInfo.MBBMap[
I->getParent()] == FuncInfo.MBB) {
220 Opcode =
I->getOpcode();
223 }
else if (
const auto *
C = dyn_cast<ConstantExpr>(Obj)) {
224 Opcode =
C->getOpcode();
228 if (
auto *Ty = dyn_cast<PointerType>(Obj->
getType()))
229 if (Ty->getAddressSpace() > 255)
234 if (
const auto *GV = dyn_cast<GlobalValue>(Obj)) {
235 if (TLI.isPositionIndependent())
237 if (
Addr.getGlobalValue())
239 if (GV->isThreadLocal())
241 Addr.setGlobalValue(GV);
248 case Instruction::BitCast: {
252 case Instruction::IntToPtr: {
255 TLI.getPointerTy(
DL))
259 case Instruction::PtrToInt: {
261 if (TLI.getValueType(
DL, U->
getType()) == TLI.getPointerTy(
DL))
265 case Instruction::GetElementPtr: {
269 if (!cast<GEPOperator>(U)->isInBounds())
270 goto unsupported_gep;
275 const Value *
Op = GTI.getOperand();
276 if (
StructType *STy = GTI.getStructTypeOrNull()) {
278 unsigned Idx = cast<ConstantInt>(
Op)->getZExtValue();
281 uint64_t S =
DL.getTypeAllocSize(GTI.getIndexedType());
283 if (
const auto *CI = dyn_cast<ConstantInt>(
Op)) {
285 TmpOffset += CI->getSExtValue() *
S;
288 if (
S == 1 &&
Addr.isRegBase() &&
Addr.getReg() == 0) {
296 if (canFoldAddIntoGEP(U,
Op)) {
298 auto *CI = cast<ConstantInt>(cast<AddOperator>(
Op)->getOperand(1));
299 TmpOffset += CI->getSExtValue() *
S;
301 Op = cast<AddOperator>(
Op)->getOperand(0);
305 goto unsupported_gep;
310 if (int64_t(TmpOffset) >= 0) {
312 Addr.setOffset(TmpOffset);
321 case Instruction::Alloca: {
322 const auto *AI = cast<AllocaInst>(Obj);
324 FuncInfo.StaticAllocaMap.find(AI);
325 if (
SI != FuncInfo.StaticAllocaMap.end()) {
329 Addr.setKind(Address::FrameIndexBase);
340 if (isa<ConstantInt>(
LHS))
343 if (
const auto *CI = dyn_cast<ConstantInt>(
RHS)) {
344 uint64_t TmpOffset =
Addr.getOffset() + CI->getSExtValue();
345 if (int64_t(TmpOffset) >= 0) {
346 Addr.setOffset(TmpOffset);
347 return computeAddress(
LHS,
Addr);
358 case Instruction::Sub: {
363 if (
const auto *CI = dyn_cast<ConstantInt>(
RHS)) {
364 int64_t TmpOffset =
Addr.getOffset() - CI->getSExtValue();
365 if (TmpOffset >= 0) {
366 Addr.setOffset(TmpOffset);
367 return computeAddress(
LHS,
Addr);
380 return Addr.getReg() != 0;
383 void WebAssemblyFastISel::materializeLoadStoreOperands(Address &
Addr) {
384 if (
Addr.isRegBase()) {
387 Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
388 : &WebAssembly::I32RegClass);
389 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
390 : WebAssembly::CONST_I32;
391 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc),
Reg)
398 void WebAssemblyFastISel::addLoadStoreOperands(
const Address &
Addr,
410 if (
Addr.isRegBase())
418 unsigned WebAssemblyFastISel::maskI1Value(
unsigned Reg,
const Value *V) {
422 unsigned WebAssemblyFastISel::getRegForI1Value(
const Value *V,
425 if (
const auto *ICmp = dyn_cast<ICmpInst>(V))
426 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
427 if (ICmp->isEquality() &&
C->isZero() &&
C->getType()->isIntegerTy(32) &&
428 ICmp->getParent() ==
BB) {
429 Not = ICmp->isTrueWhenEqual();
430 return getRegForValue(ICmp->getOperand(0));
437 return maskI1Value(
Reg, V);
440 unsigned WebAssemblyFastISel::zeroExtendToI32(
unsigned Reg,
const Value *V,
450 if (V !=
nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr())
451 return copyValue(
Reg);
457 return copyValue(
Reg);
462 Register Imm = createResultReg(&WebAssembly::I32RegClass);
463 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
464 TII.get(WebAssembly::CONST_I32),
Imm)
468 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
469 TII.get(WebAssembly::AND_I32), Result)
476 unsigned WebAssemblyFastISel::signExtendToI32(
unsigned Reg,
const Value *V,
487 return copyValue(
Reg);
492 Register Imm = createResultReg(&WebAssembly::I32RegClass);
493 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
494 TII.get(WebAssembly::CONST_I32),
Imm)
497 Register Left = createResultReg(&WebAssembly::I32RegClass);
498 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
499 TII.get(WebAssembly::SHL_I32), Left)
504 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
505 TII.get(WebAssembly::SHR_S_I32), Right)
512 unsigned WebAssemblyFastISel::zeroExtend(
unsigned Reg,
const Value *V,
517 return copyValue(
Reg);
522 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
523 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
529 return zeroExtendToI32(
Reg, V,
From);
534 unsigned WebAssemblyFastISel::signExtend(
unsigned Reg,
const Value *V,
539 return copyValue(
Reg);
544 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
545 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
551 return signExtendToI32(
Reg, V,
From);
556 unsigned WebAssemblyFastISel::getRegForUnsignedValue(
const Value *V) {
562 return zeroExtend(VReg, V,
From, To);
565 unsigned WebAssemblyFastISel::getRegForSignedValue(
const Value *V) {
571 return signExtend(VReg, V,
From, To);
574 unsigned WebAssemblyFastISel::getRegForPromotedValue(
const Value *V,
576 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
579 unsigned WebAssemblyFastISel::notValue(
unsigned Reg) {
582 Register NotReg = createResultReg(&WebAssembly::I32RegClass);
583 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
584 TII.get(WebAssembly::EQZ_I32), NotReg)
589 unsigned WebAssemblyFastISel::copyValue(
unsigned Reg) {
591 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(WebAssembly::COPY),
597 unsigned WebAssemblyFastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
599 FuncInfo.StaticAllocaMap.find(AI);
601 if (
SI != FuncInfo.StaticAllocaMap.end()) {
603 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
604 : &WebAssembly::I32RegClass);
606 Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
607 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
615 unsigned WebAssemblyFastISel::fastMaterializeConstant(
const Constant *
C) {
617 if (TLI.isPositionIndependent())
619 if (GV->isThreadLocal())
622 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
623 : &WebAssembly::I32RegClass);
624 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
625 : WebAssembly::CONST_I32;
626 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
635 bool WebAssemblyFastISel::fastLowerArguments() {
636 if (!FuncInfo.CanLowerReturn)
647 for (
auto const &
Arg :
F->args()) {
649 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
650 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
651 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
652 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
653 Attrs.hasParamAttr(
I, Attribute::Nest))
659 if (!Subtarget->hasSIMD128() && ArgTy->
isVectorTy())
664 switch (getSimpleType(ArgTy)) {
669 Opc = WebAssembly::ARGUMENT_i32;
670 RC = &WebAssembly::I32RegClass;
673 Opc = WebAssembly::ARGUMENT_i64;
674 RC = &WebAssembly::I64RegClass;
677 Opc = WebAssembly::ARGUMENT_f32;
678 RC = &WebAssembly::F32RegClass;
681 Opc = WebAssembly::ARGUMENT_f64;
682 RC = &WebAssembly::F64RegClass;
685 Opc = WebAssembly::ARGUMENT_v16i8;
686 RC = &WebAssembly::V128RegClass;
689 Opc = WebAssembly::ARGUMENT_v8i16;
690 RC = &WebAssembly::V128RegClass;
693 Opc = WebAssembly::ARGUMENT_v4i32;
694 RC = &WebAssembly::V128RegClass;
697 Opc = WebAssembly::ARGUMENT_v2i64;
698 RC = &WebAssembly::V128RegClass;
701 Opc = WebAssembly::ARGUMENT_v4f32;
702 RC = &WebAssembly::V128RegClass;
705 Opc = WebAssembly::ARGUMENT_v2f64;
706 RC = &WebAssembly::V128RegClass;
709 Opc = WebAssembly::ARGUMENT_funcref;
710 RC = &WebAssembly::FUNCREFRegClass;
713 Opc = WebAssembly::ARGUMENT_externref;
714 RC = &WebAssembly::EXTERNREFRegClass;
719 Register ResultReg = createResultReg(RC);
720 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
722 updateValueMap(&
Arg, ResultReg);
730 for (
auto const &
Arg :
F->args()) {
733 MFI->clearParamsAndResults();
736 MFI->addParam(ArgTy);
739 if (!
F->getReturnType()->isVoidTy()) {
741 getLegalType(getSimpleType(
F->getReturnType()));
743 MFI->clearParamsAndResults();
746 MFI->addResult(RetTy);
752 bool WebAssemblyFastISel::selectCall(
const Instruction *
I) {
753 const auto *
Call = cast<CallInst>(
I);
756 if (
Call->isMustTailCall() ||
Call->isInlineAsm() ||
757 Call->getFunctionType()->isVarArg())
761 if (Func &&
Func->isIntrinsic())
767 bool IsDirect =
Func !=
nullptr;
768 if (!IsDirect && isa<ConstantExpr>(
Call->getCalledOperand()))
776 if (!Subtarget->hasSIMD128() &&
Call->getType()->isVectorTy())
785 ResultReg = createResultReg(&WebAssembly::I32RegClass);
788 ResultReg = createResultReg(&WebAssembly::I64RegClass);
791 ResultReg = createResultReg(&WebAssembly::F32RegClass);
794 ResultReg = createResultReg(&WebAssembly::F64RegClass);
797 ResultReg = createResultReg(&WebAssembly::V128RegClass);
800 ResultReg = createResultReg(&WebAssembly::V128RegClass);
803 ResultReg = createResultReg(&WebAssembly::V128RegClass);
806 ResultReg = createResultReg(&WebAssembly::V128RegClass);
809 ResultReg = createResultReg(&WebAssembly::V128RegClass);
812 ResultReg = createResultReg(&WebAssembly::V128RegClass);
815 ResultReg = createResultReg(&WebAssembly::FUNCREFRegClass);
818 ResultReg = createResultReg(&WebAssembly::EXTERNREFRegClass);
826 for (
unsigned I = 0,
E =
Call->arg_size();
I <
E; ++
I) {
833 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
834 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
835 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
836 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
837 Attrs.hasParamAttr(
I, Attribute::Nest))
842 if (
Attrs.hasParamAttr(
I, Attribute::SExt))
843 Reg = getRegForSignedValue(V);
844 else if (
Attrs.hasParamAttr(
I, Attribute::ZExt))
845 Reg = getRegForUnsignedValue(V);
847 Reg = getRegForValue(V);
855 unsigned CalleeReg = 0;
857 CalleeReg = getRegForValue(
Call->getCalledOperand());
862 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc));
874 MF->getMMI().getContext(), Subtarget);
875 if (Subtarget->hasReferenceTypes()) {
888 if (Subtarget->hasAddr64()) {
889 auto Wrap =
BuildMI(*FuncInfo.MBB, std::prev(FuncInfo.InsertPt), DbgLoc,
890 TII.get(WebAssembly::I32_WRAP_I64));
891 Register Reg32 = createResultReg(&WebAssembly::I32RegClass);
893 Wrap.addReg(CalleeReg);
898 for (
unsigned ArgReg :
Args)
905 updateValueMap(Call, ResultReg);
909 bool WebAssemblyFastISel::selectSelect(
const Instruction *
I) {
910 const auto *
Select = cast<SelectInst>(
I);
914 getRegForI1Value(
Select->getCondition(),
I->getParent(), Not);
931 switch (getSimpleType(
Select->getType())) {
936 Opc = WebAssembly::SELECT_I32;
937 RC = &WebAssembly::I32RegClass;
940 Opc = WebAssembly::SELECT_I64;
941 RC = &WebAssembly::I64RegClass;
944 Opc = WebAssembly::SELECT_F32;
945 RC = &WebAssembly::F32RegClass;
948 Opc = WebAssembly::SELECT_F64;
949 RC = &WebAssembly::F64RegClass;
952 Opc = WebAssembly::SELECT_FUNCREF;
953 RC = &WebAssembly::FUNCREFRegClass;
956 Opc = WebAssembly::SELECT_EXTERNREF;
957 RC = &WebAssembly::EXTERNREFRegClass;
963 Register ResultReg = createResultReg(RC);
964 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
969 updateValueMap(
Select, ResultReg);
973 bool WebAssemblyFastISel::selectTrunc(
const Instruction *
I) {
974 const auto *Trunc = cast<TruncInst>(
I);
976 Register Reg = getRegForValue(Trunc->getOperand(0));
980 if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
982 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
983 TII.get(WebAssembly::I32_WRAP_I64), Result)
988 updateValueMap(Trunc,
Reg);
992 bool WebAssemblyFastISel::selectZExt(
const Instruction *
I) {
993 const auto *ZExt = cast<ZExtInst>(
I);
995 const Value *
Op = ZExt->getOperand(0);
1005 updateValueMap(ZExt,
Reg);
1009 bool WebAssemblyFastISel::selectSExt(
const Instruction *
I) {
1010 const auto *SExt = cast<SExtInst>(
I);
1012 const Value *
Op = SExt->getOperand(0);
1022 updateValueMap(SExt,
Reg);
1026 bool WebAssemblyFastISel::selectICmp(
const Instruction *
I) {
1027 const auto *ICmp = cast<ICmpInst>(
I);
1029 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) !=
MVT::i64;
1031 bool IsSigned =
false;
1032 switch (ICmp->getPredicate()) {
1034 Opc =
I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
1037 Opc =
I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1040 Opc =
I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1043 Opc =
I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1046 Opc =
I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1049 Opc =
I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1052 Opc =
I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1056 Opc =
I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1060 Opc =
I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1064 Opc =
I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1071 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
1075 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
1079 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1080 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
1083 updateValueMap(ICmp, ResultReg);
1087 bool WebAssemblyFastISel::selectFCmp(
const Instruction *
I) {
1088 const auto *FCmp = cast<FCmpInst>(
I);
1090 Register LHS = getRegForValue(FCmp->getOperand(0));
1094 Register RHS = getRegForValue(FCmp->getOperand(1));
1098 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) !=
MVT::f64;
1101 switch (FCmp->getPredicate()) {
1103 Opc =
F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1106 Opc =
F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1109 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1112 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1115 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1118 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1121 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1125 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1129 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1133 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1140 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1141 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
1146 ResultReg = notValue(ResultReg);
1148 updateValueMap(FCmp, ResultReg);
1152 bool WebAssemblyFastISel::selectBitCast(
const Instruction *
I) {
1156 EVT VT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
1157 EVT RetVT = TLI.getValueType(
DL,
I->getType());
1167 updateValueMap(
I,
In);
1177 assert(Iter->isBitcast());
1179 updateValueMap(
I,
Reg);
1183 bool WebAssemblyFastISel::selectLoad(
const Instruction *
I) {
1184 const auto *
Load = cast<LoadInst>(
I);
1185 if (
Load->isAtomic())
1189 if (!Subtarget->hasSIMD128() &&
Load->getType()->isVectorTy())
1193 if (!computeAddress(
Load->getPointerOperand(),
Addr))
1200 bool A64 = Subtarget->hasAddr64();
1201 switch (getSimpleType(
Load->getType())) {
1204 Opc = A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
1205 RC = &WebAssembly::I32RegClass;
1208 Opc = A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;
1209 RC = &WebAssembly::I32RegClass;
1212 Opc = A64 ? WebAssembly::LOAD_I32_A64 : WebAssembly::LOAD_I32_A32;
1213 RC = &WebAssembly::I32RegClass;
1216 Opc = A64 ? WebAssembly::LOAD_I64_A64 : WebAssembly::LOAD_I64_A32;
1217 RC = &WebAssembly::I64RegClass;
1220 Opc = A64 ? WebAssembly::LOAD_F32_A64 : WebAssembly::LOAD_F32_A32;
1221 RC = &WebAssembly::F32RegClass;
1224 Opc = A64 ? WebAssembly::LOAD_F64_A64 : WebAssembly::LOAD_F64_A32;
1225 RC = &WebAssembly::F64RegClass;
1231 materializeLoadStoreOperands(
Addr);
1233 Register ResultReg = createResultReg(RC);
1234 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc),
1237 addLoadStoreOperands(
Addr, MIB, createMachineMemOperandFor(
Load));
1239 updateValueMap(
Load, ResultReg);
1243 bool WebAssemblyFastISel::selectStore(
const Instruction *
I) {
1244 const auto *
Store = cast<StoreInst>(
I);
1245 if (
Store->isAtomic())
1249 if (!Subtarget->hasSIMD128() &&
1250 Store->getValueOperand()->getType()->isVectorTy())
1254 if (!computeAddress(
Store->getPointerOperand(),
Addr))
1258 bool VTIsi1 =
false;
1259 bool A64 = Subtarget->hasAddr64();
1260 switch (getSimpleType(
Store->getValueOperand()->getType())) {
1265 Opc = A64 ? WebAssembly::STORE8_I32_A64 : WebAssembly::STORE8_I32_A32;
1268 Opc = A64 ? WebAssembly::STORE16_I32_A64 : WebAssembly::STORE16_I32_A32;
1271 Opc = A64 ? WebAssembly::STORE_I32_A64 : WebAssembly::STORE_I32_A32;
1274 Opc = A64 ? WebAssembly::STORE_I64_A64 : WebAssembly::STORE_I64_A32;
1277 Opc = A64 ? WebAssembly::STORE_F32_A64 : WebAssembly::STORE_F32_A32;
1280 Opc = A64 ? WebAssembly::STORE_F64_A64 : WebAssembly::STORE_F64_A32;
1286 materializeLoadStoreOperands(
Addr);
1288 Register ValueReg = getRegForValue(
Store->getValueOperand());
1292 ValueReg = maskI1Value(ValueReg,
Store->getValueOperand());
1294 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc));
1296 addLoadStoreOperands(
Addr, MIB, createMachineMemOperandFor(
Store));
1302 bool WebAssemblyFastISel::selectBr(
const Instruction *
I) {
1303 const auto *Br = cast<BranchInst>(
I);
1304 if (Br->isUnconditional()) {
1306 fastEmitBranch(MSucc, Br->getDebugLoc());
1314 unsigned CondReg = getRegForI1Value(Br->getCondition(), Br->getParent(), Not);
1318 unsigned Opc = WebAssembly::BR_IF;
1320 Opc = WebAssembly::BR_UNLESS;
1322 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc))
1326 finishCondBranch(Br->getParent(), TBB, FBB);
1330 bool WebAssemblyFastISel::selectRet(
const Instruction *
I) {
1331 if (!FuncInfo.CanLowerReturn)
1334 const auto *
Ret = cast<ReturnInst>(
I);
1336 if (
Ret->getNumOperands() == 0) {
1337 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1343 if (
Ret->getNumOperands() > 1)
1350 switch (getSimpleType(RV->
getType())) {
1372 if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::SExt))
1373 Reg = getRegForSignedValue(RV);
1374 else if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::ZExt))
1375 Reg = getRegForUnsignedValue(RV);
1377 Reg = getRegForValue(RV);
1382 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1388 bool WebAssemblyFastISel::selectUnreachable(
const Instruction *
I) {
1389 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1390 TII.get(WebAssembly::UNREACHABLE));
1394 bool WebAssemblyFastISel::fastSelectInstruction(
const Instruction *
I) {
1395 switch (
I->getOpcode()) {
1401 return selectSelect(
I);
1402 case Instruction::Trunc:
1403 return selectTrunc(
I);
1404 case Instruction::ZExt:
1405 return selectZExt(
I);
1406 case Instruction::SExt:
1407 return selectSExt(
I);
1408 case Instruction::ICmp:
1409 return selectICmp(
I);
1410 case Instruction::FCmp:
1411 return selectFCmp(
I);
1412 case Instruction::BitCast:
1413 return selectBitCast(
I);
1415 return selectLoad(
I);
1417 return selectStore(
I);
1418 case Instruction::Br:
1421 return selectRet(
I);
1422 case Instruction::Unreachable:
1423 return selectUnreachable(
I);
1429 return selectOperator(
I,
I->getOpcode());
1434 return new WebAssemblyFastISel(FuncInfo, LibInfo);