45using namespace PatternMatch;
47#define DEBUG_TYPE "wasm-fastisel"
51class 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);
160 bool computeAddress(
const Value *Obj, Address &
Addr);
161 void materializeLoadStoreOperands(Address &
Addr);
164 unsigned maskI1Value(
unsigned Reg,
const Value *V);
165 unsigned getRegForI1Value(
const Value *V,
const BasicBlock *BB,
bool &Not);
166 unsigned zeroExtendToI32(
unsigned Reg,
const Value *V,
168 unsigned signExtendToI32(
unsigned Reg,
const Value *V,
174 unsigned getRegForUnsignedValue(
const Value *V);
175 unsigned getRegForSignedValue(
const Value *V);
176 unsigned getRegForPromotedValue(
const Value *V,
bool IsSigned);
177 unsigned notValue(
unsigned Reg);
178 unsigned copyValue(
unsigned Reg);
204 :
FastISel(FuncInfo, LibInfo,
true) {
211#include "WebAssemblyGenFastISel.inc"
216bool WebAssemblyFastISel::computeAddress(
const Value *Obj, Address &
Addr) {
217 const User *
U =
nullptr;
218 unsigned Opcode = Instruction::UserOp1;
219 if (
const auto *
I = dyn_cast<Instruction>(Obj)) {
222 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(Obj)) ||
223 FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
224 Opcode =
I->getOpcode();
227 }
else if (
const auto *
C = dyn_cast<ConstantExpr>(Obj)) {
228 Opcode =
C->getOpcode();
232 if (
auto *Ty = dyn_cast<PointerType>(Obj->
getType()))
233 if (Ty->getAddressSpace() > 255)
238 if (
const auto *GV = dyn_cast<GlobalValue>(Obj)) {
239 if (TLI.isPositionIndependent())
241 if (
Addr.getGlobalValue())
243 if (GV->isThreadLocal())
245 Addr.setGlobalValue(GV);
252 case Instruction::BitCast: {
254 return computeAddress(
U->getOperand(0),
Addr);
256 case Instruction::IntToPtr: {
258 if (TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
259 TLI.getPointerTy(
DL))
260 return computeAddress(
U->getOperand(0),
Addr);
263 case Instruction::PtrToInt: {
265 if (TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
266 return computeAddress(
U->getOperand(0),
Addr);
269 case Instruction::GetElementPtr: {
273 if (!cast<GEPOperator>(U)->isInBounds())
274 goto unsupported_gep;
279 const Value *
Op = GTI.getOperand();
280 if (
StructType *STy = GTI.getStructTypeOrNull()) {
282 unsigned Idx = cast<ConstantInt>(
Op)->getZExtValue();
285 uint64_t S = GTI.getSequentialElementStride(
DL);
287 if (
const auto *CI = dyn_cast<ConstantInt>(
Op)) {
289 TmpOffset += CI->getSExtValue() * S;
292 if (S == 1 &&
Addr.isRegBase() &&
Addr.getReg() == 0) {
300 if (canFoldAddIntoGEP(U,
Op)) {
302 auto *CI = cast<ConstantInt>(cast<AddOperator>(
Op)->getOperand(1));
303 TmpOffset += CI->getSExtValue() * S;
305 Op = cast<AddOperator>(
Op)->getOperand(0);
309 goto unsupported_gep;
314 if (int64_t(TmpOffset) >= 0) {
316 Addr.setOffset(TmpOffset);
317 if (computeAddress(
U->getOperand(0),
Addr))
325 case Instruction::Alloca: {
326 const auto *AI = cast<AllocaInst>(Obj);
328 FuncInfo.StaticAllocaMap.find(AI);
329 if (SI != FuncInfo.StaticAllocaMap.end()) {
333 Addr.setKind(Address::FrameIndexBase);
339 case Instruction::Add: {
344 if (isa<ConstantInt>(LHS))
347 if (
const auto *CI = dyn_cast<ConstantInt>(RHS)) {
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: {
367 if (
const auto *CI = dyn_cast<ConstantInt>(RHS)) {
368 int64_t TmpOffset =
Addr.getOffset() - CI->getSExtValue();
369 if (TmpOffset >= 0) {
370 Addr.setOffset(TmpOffset);
371 return computeAddress(LHS,
Addr);
384 return Addr.getReg() != 0;
387void WebAssemblyFastISel::materializeLoadStoreOperands(Address &
Addr) {
388 if (
Addr.isRegBase()) {
391 Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
392 : &WebAssembly::I32RegClass);
393 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
394 : WebAssembly::CONST_I32;
395 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), Reg)
402void WebAssemblyFastISel::addLoadStoreOperands(
const Address &
Addr,
414 if (
Addr.isRegBase())
422unsigned WebAssemblyFastISel::maskI1Value(
unsigned Reg,
const Value *V) {
423 return zeroExtendToI32(Reg, V, MVT::i1);
426unsigned WebAssemblyFastISel::getRegForI1Value(
const Value *V,
429 if (
const auto *ICmp = dyn_cast<ICmpInst>(V))
430 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
431 if (ICmp->isEquality() &&
C->isZero() &&
C->getType()->isIntegerTy(32) &&
432 ICmp->getParent() == BB) {
433 Not = ICmp->isTrueWhenEqual();
434 return getRegForValue(ICmp->getOperand(0));
441 return maskI1Value(Reg, V);
444unsigned WebAssemblyFastISel::zeroExtendToI32(
unsigned Reg,
const Value *V,
454 if (V !=
nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr())
455 return copyValue(Reg);
461 return copyValue(Reg);
466 Register Imm = createResultReg(&WebAssembly::I32RegClass);
467 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
468 TII.get(WebAssembly::CONST_I32), Imm)
472 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
473 TII.get(WebAssembly::AND_I32), Result)
480unsigned WebAssemblyFastISel::signExtendToI32(
unsigned Reg,
const Value *V,
491 return copyValue(Reg);
496 Register Imm = createResultReg(&WebAssembly::I32RegClass);
497 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
498 TII.get(WebAssembly::CONST_I32), Imm)
501 Register Left = createResultReg(&WebAssembly::I32RegClass);
502 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
503 TII.get(WebAssembly::SHL_I32),
Left)
508 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
509 TII.get(WebAssembly::SHR_S_I32),
Right)
516unsigned WebAssemblyFastISel::zeroExtend(
unsigned Reg,
const Value *V,
519 if (To == MVT::i64) {
520 if (
From == MVT::i64)
521 return copyValue(Reg);
523 Reg = zeroExtendToI32(Reg, V,
From);
526 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
527 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
533 return zeroExtendToI32(Reg, V,
From);
538unsigned WebAssemblyFastISel::signExtend(
unsigned Reg,
const Value *V,
541 if (To == MVT::i64) {
542 if (
From == MVT::i64)
543 return copyValue(Reg);
545 Reg = signExtendToI32(Reg, V,
From);
548 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
549 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
555 return signExtendToI32(Reg, V,
From);
560unsigned WebAssemblyFastISel::getRegForUnsignedValue(
const Value *V) {
568 return zeroExtend(VReg, V,
From, To);
571unsigned WebAssemblyFastISel::getRegForSignedValue(
const Value *V) {
579 return signExtend(VReg, V,
From, To);
582unsigned WebAssemblyFastISel::getRegForPromotedValue(
const Value *V,
584 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(
V);
587unsigned WebAssemblyFastISel::notValue(
unsigned Reg) {
588 assert(
MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
590 Register NotReg = createResultReg(&WebAssembly::I32RegClass);
591 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
592 TII.get(WebAssembly::EQZ_I32), NotReg)
597unsigned WebAssemblyFastISel::copyValue(
unsigned Reg) {
598 Register ResultReg = createResultReg(
MRI.getRegClass(Reg));
599 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::COPY),
605unsigned WebAssemblyFastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
607 FuncInfo.StaticAllocaMap.find(AI);
609 if (SI != FuncInfo.StaticAllocaMap.end()) {
611 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
612 : &WebAssembly::I32RegClass);
614 Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
615 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg)
623unsigned WebAssemblyFastISel::fastMaterializeConstant(
const Constant *
C) {
625 if (TLI.isPositionIndependent())
627 if (GV->isThreadLocal())
630 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
631 : &WebAssembly::I32RegClass);
632 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
633 : WebAssembly::CONST_I32;
634 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg)
643bool WebAssemblyFastISel::fastLowerArguments() {
644 if (!FuncInfo.CanLowerReturn)
655 for (
auto const &Arg :
F->args()) {
657 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
658 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
659 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
660 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
661 Attrs.hasParamAttr(
I, Attribute::Nest))
664 Type *ArgTy = Arg.getType();
667 if (!Subtarget->hasSIMD128() && ArgTy->
isVectorTy())
672 switch (getSimpleType(ArgTy)) {
677 Opc = WebAssembly::ARGUMENT_i32;
678 RC = &WebAssembly::I32RegClass;
681 Opc = WebAssembly::ARGUMENT_i64;
682 RC = &WebAssembly::I64RegClass;
685 Opc = WebAssembly::ARGUMENT_f32;
686 RC = &WebAssembly::F32RegClass;
689 Opc = WebAssembly::ARGUMENT_f64;
690 RC = &WebAssembly::F64RegClass;
693 Opc = WebAssembly::ARGUMENT_v16i8;
694 RC = &WebAssembly::V128RegClass;
697 Opc = WebAssembly::ARGUMENT_v8i16;
698 RC = &WebAssembly::V128RegClass;
701 Opc = WebAssembly::ARGUMENT_v4i32;
702 RC = &WebAssembly::V128RegClass;
705 Opc = WebAssembly::ARGUMENT_v2i64;
706 RC = &WebAssembly::V128RegClass;
709 Opc = WebAssembly::ARGUMENT_v4f32;
710 RC = &WebAssembly::V128RegClass;
713 Opc = WebAssembly::ARGUMENT_v2f64;
714 RC = &WebAssembly::V128RegClass;
717 Opc = WebAssembly::ARGUMENT_funcref;
718 RC = &WebAssembly::FUNCREFRegClass;
721 Opc = WebAssembly::ARGUMENT_externref;
722 RC = &WebAssembly::EXTERNREFRegClass;
725 Opc = WebAssembly::ARGUMENT_exnref;
726 RC = &WebAssembly::EXNREFRegClass;
731 Register ResultReg = createResultReg(RC);
732 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg)
734 updateValueMap(&Arg, ResultReg);
739 MRI.addLiveIn(WebAssembly::ARGUMENTS);
742 for (
auto const &Arg :
F->args()) {
745 MFI->clearParamsAndResults();
748 MFI->addParam(ArgTy);
751 if (!
F->getReturnType()->isVoidTy()) {
753 getLegalType(getSimpleType(
F->getReturnType()));
755 MFI->clearParamsAndResults();
758 MFI->addResult(
RetTy);
764bool WebAssemblyFastISel::selectCall(
const Instruction *
I) {
765 const auto *
Call = cast<CallInst>(
I);
768 if (
Call->isMustTailCall() ||
Call->isInlineAsm() ||
769 Call->getFunctionType()->isVarArg())
773 if (Func &&
Func->isIntrinsic())
779 bool IsDirect =
Func !=
nullptr;
780 if (!IsDirect && isa<ConstantExpr>(
Call->getCalledOperand()))
784 unsigned Opc = IsDirect ? WebAssembly::CALL : WebAssembly::CALL_INDIRECT;
785 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
788 if (!Subtarget->hasSIMD128() &&
Call->getType()->isVectorTy())
797 ResultReg = createResultReg(&WebAssembly::I32RegClass);
800 ResultReg = createResultReg(&WebAssembly::I64RegClass);
803 ResultReg = createResultReg(&WebAssembly::F32RegClass);
806 ResultReg = createResultReg(&WebAssembly::F64RegClass);
809 ResultReg = createResultReg(&WebAssembly::V128RegClass);
812 ResultReg = createResultReg(&WebAssembly::V128RegClass);
815 ResultReg = createResultReg(&WebAssembly::V128RegClass);
818 ResultReg = createResultReg(&WebAssembly::V128RegClass);
821 ResultReg = createResultReg(&WebAssembly::V128RegClass);
824 ResultReg = createResultReg(&WebAssembly::V128RegClass);
827 ResultReg = createResultReg(&WebAssembly::FUNCREFRegClass);
830 ResultReg = createResultReg(&WebAssembly::EXTERNREFRegClass);
833 ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);
841 for (
unsigned I = 0, E =
Call->arg_size();
I < E; ++
I) {
848 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
849 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
850 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
851 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
852 Attrs.hasParamAttr(
I, Attribute::Nest))
857 if (
Call->paramHasAttr(
I, Attribute::SExt))
858 Reg = getRegForSignedValue(V);
859 else if (
Call->paramHasAttr(
I, Attribute::ZExt))
860 Reg = getRegForUnsignedValue(V);
862 Reg = getRegForValue(V);
870 unsigned CalleeReg = 0;
872 CalleeReg = getRegForValue(
Call->getCalledOperand());
877 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc));
889 MF->getContext(), Subtarget);
890 if (Subtarget->hasReferenceTypes()) {
901 for (
unsigned ArgReg : Args)
908 updateValueMap(Call, ResultReg);
912bool WebAssemblyFastISel::selectSelect(
const Instruction *
I) {
913 const auto *
Select = cast<SelectInst>(
I);
917 getRegForI1Value(
Select->getCondition(),
I->getParent(), Not);
934 switch (getSimpleType(
Select->getType())) {
939 Opc = WebAssembly::SELECT_I32;
940 RC = &WebAssembly::I32RegClass;
943 Opc = WebAssembly::SELECT_I64;
944 RC = &WebAssembly::I64RegClass;
947 Opc = WebAssembly::SELECT_F32;
948 RC = &WebAssembly::F32RegClass;
951 Opc = WebAssembly::SELECT_F64;
952 RC = &WebAssembly::F64RegClass;
955 Opc = WebAssembly::SELECT_FUNCREF;
956 RC = &WebAssembly::FUNCREFRegClass;
959 Opc = WebAssembly::SELECT_EXTERNREF;
960 RC = &WebAssembly::EXTERNREFRegClass;
963 Opc = WebAssembly::SELECT_EXNREF;
964 RC = &WebAssembly::EXNREFRegClass;
970 Register ResultReg = createResultReg(RC);
971 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg)
976 updateValueMap(
Select, ResultReg);
980bool WebAssemblyFastISel::selectTrunc(
const Instruction *
I) {
981 const auto *Trunc = cast<TruncInst>(
I);
983 Register Reg = getRegForValue(Trunc->getOperand(0));
987 if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
989 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
990 TII.get(WebAssembly::I32_WRAP_I64), Result)
995 updateValueMap(Trunc, Reg);
999bool WebAssemblyFastISel::selectZExt(
const Instruction *
I) {
1000 const auto *ZExt = cast<ZExtInst>(
I);
1002 const Value *
Op = ZExt->getOperand(0);
1008 unsigned Reg = zeroExtend(In,
Op,
From, To);
1012 updateValueMap(ZExt, Reg);
1016bool WebAssemblyFastISel::selectSExt(
const Instruction *
I) {
1017 const auto *SExt = cast<SExtInst>(
I);
1019 const Value *
Op = SExt->getOperand(0);
1025 unsigned Reg = signExtend(In,
Op,
From, To);
1029 updateValueMap(SExt, Reg);
1033bool WebAssemblyFastISel::selectICmp(
const Instruction *
I) {
1034 const auto *ICmp = cast<ICmpInst>(
I);
1036 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
1038 bool IsSigned =
false;
1039 switch (ICmp->getPredicate()) {
1040 case ICmpInst::ICMP_EQ:
1041 Opc =
I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
1043 case ICmpInst::ICMP_NE:
1044 Opc =
I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1046 case ICmpInst::ICMP_UGT:
1047 Opc =
I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1049 case ICmpInst::ICMP_UGE:
1050 Opc =
I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1052 case ICmpInst::ICMP_ULT:
1053 Opc =
I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1055 case ICmpInst::ICMP_ULE:
1056 Opc =
I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1058 case ICmpInst::ICMP_SGT:
1059 Opc =
I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1062 case ICmpInst::ICMP_SGE:
1063 Opc =
I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1066 case ICmpInst::ICMP_SLT:
1067 Opc =
I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1070 case ICmpInst::ICMP_SLE:
1071 Opc =
I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1078 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
1082 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
1086 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1087 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg)
1090 updateValueMap(ICmp, ResultReg);
1094bool WebAssemblyFastISel::selectFCmp(
const Instruction *
I) {
1095 const auto *FCmp = cast<FCmpInst>(
I);
1097 Register LHS = getRegForValue(FCmp->getOperand(0));
1101 Register RHS = getRegForValue(FCmp->getOperand(1));
1105 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1108 switch (FCmp->getPredicate()) {
1109 case FCmpInst::FCMP_OEQ:
1110 Opc =
F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1112 case FCmpInst::FCMP_UNE:
1113 Opc =
F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1115 case FCmpInst::FCMP_OGT:
1116 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1118 case FCmpInst::FCMP_OGE:
1119 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1121 case FCmpInst::FCMP_OLT:
1122 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1124 case FCmpInst::FCMP_OLE:
1125 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1127 case FCmpInst::FCMP_UGT:
1128 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1131 case FCmpInst::FCMP_UGE:
1132 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1135 case FCmpInst::FCMP_ULT:
1136 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1139 case FCmpInst::FCMP_ULE:
1140 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1147 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1148 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg)
1153 ResultReg = notValue(ResultReg);
1155 updateValueMap(FCmp, ResultReg);
1159bool WebAssemblyFastISel::selectBitCast(
const Instruction *
I) {
1163 EVT VT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
1164 EVT RetVT = TLI.getValueType(
DL,
I->getType());
1174 updateValueMap(
I, In);
1184 assert(Iter->isBitcast());
1186 updateValueMap(
I, Reg);
1190bool WebAssemblyFastISel::selectLoad(
const Instruction *
I) {
1191 const auto *
Load = cast<LoadInst>(
I);
1192 if (
Load->isAtomic())
1196 if (!Subtarget->hasSIMD128() &&
Load->getType()->isVectorTy())
1200 if (!computeAddress(
Load->getPointerOperand(),
Addr))
1207 bool A64 = Subtarget->hasAddr64();
1208 switch (getSimpleType(
Load->getType())) {
1211 Opc = A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
1212 RC = &WebAssembly::I32RegClass;
1215 Opc = A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;
1216 RC = &WebAssembly::I32RegClass;
1219 Opc = A64 ? WebAssembly::LOAD_I32_A64 : WebAssembly::LOAD_I32_A32;
1220 RC = &WebAssembly::I32RegClass;
1223 Opc = A64 ? WebAssembly::LOAD_I64_A64 : WebAssembly::LOAD_I64_A32;
1224 RC = &WebAssembly::I64RegClass;
1227 Opc = A64 ? WebAssembly::LOAD_F32_A64 : WebAssembly::LOAD_F32_A32;
1228 RC = &WebAssembly::F32RegClass;
1231 Opc = A64 ? WebAssembly::LOAD_F64_A64 : WebAssembly::LOAD_F64_A32;
1232 RC = &WebAssembly::F64RegClass;
1238 materializeLoadStoreOperands(
Addr);
1240 Register ResultReg = createResultReg(RC);
1241 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc),
1244 addLoadStoreOperands(
Addr, MIB, createMachineMemOperandFor(Load));
1246 updateValueMap(Load, ResultReg);
1250bool WebAssemblyFastISel::selectStore(
const Instruction *
I) {
1251 const auto *
Store = cast<StoreInst>(
I);
1252 if (
Store->isAtomic())
1256 if (!Subtarget->hasSIMD128() &&
1257 Store->getValueOperand()->getType()->isVectorTy())
1261 if (!computeAddress(
Store->getPointerOperand(),
Addr))
1265 bool VTIsi1 =
false;
1266 bool A64 = Subtarget->hasAddr64();
1267 switch (getSimpleType(
Store->getValueOperand()->getType())) {
1272 Opc = A64 ? WebAssembly::STORE8_I32_A64 : WebAssembly::STORE8_I32_A32;
1275 Opc = A64 ? WebAssembly::STORE16_I32_A64 : WebAssembly::STORE16_I32_A32;
1278 Opc = A64 ? WebAssembly::STORE_I32_A64 : WebAssembly::STORE_I32_A32;
1281 Opc = A64 ? WebAssembly::STORE_I64_A64 : WebAssembly::STORE_I64_A32;
1284 Opc = A64 ? WebAssembly::STORE_F32_A64 : WebAssembly::STORE_F32_A32;
1287 Opc = A64 ? WebAssembly::STORE_F64_A64 : WebAssembly::STORE_F64_A32;
1293 materializeLoadStoreOperands(
Addr);
1295 Register ValueReg = getRegForValue(
Store->getValueOperand());
1299 ValueReg = maskI1Value(ValueReg,
Store->getValueOperand());
1301 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc));
1303 addLoadStoreOperands(
Addr, MIB, createMachineMemOperandFor(Store));
1309bool WebAssemblyFastISel::selectBr(
const Instruction *
I) {
1310 const auto *Br = cast<BranchInst>(
I);
1311 if (Br->isUnconditional()) {
1313 fastEmitBranch(MSucc, Br->getDebugLoc());
1321 unsigned CondReg = getRegForI1Value(Br->getCondition(), Br->getParent(), Not);
1325 unsigned Opc = WebAssembly::BR_IF;
1327 Opc = WebAssembly::BR_UNLESS;
1329 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc))
1333 finishCondBranch(Br->getParent(),
TBB, FBB);
1337bool WebAssemblyFastISel::selectRet(
const Instruction *
I) {
1338 if (!FuncInfo.CanLowerReturn)
1341 const auto *
Ret = cast<ReturnInst>(
I);
1343 if (
Ret->getNumOperands() == 0) {
1344 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1345 TII.get(WebAssembly::RETURN));
1350 if (
Ret->getNumOperands() > 1)
1357 switch (getSimpleType(RV->
getType())) {
1372 case MVT::externref:
1380 if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::SExt))
1381 Reg = getRegForSignedValue(RV);
1382 else if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::ZExt))
1383 Reg = getRegForUnsignedValue(RV);
1385 Reg = getRegForValue(RV);
1390 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1391 TII.get(WebAssembly::RETURN))
1396bool WebAssemblyFastISel::selectUnreachable(
const Instruction *
I) {
1397 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1398 TII.get(WebAssembly::UNREACHABLE));
1402bool WebAssemblyFastISel::fastSelectInstruction(
const Instruction *
I) {
1403 switch (
I->getOpcode()) {
1404 case Instruction::Call:
1408 case Instruction::Select:
1409 return selectSelect(
I);
1410 case Instruction::Trunc:
1411 return selectTrunc(
I);
1412 case Instruction::ZExt:
1413 return selectZExt(
I);
1414 case Instruction::SExt:
1415 return selectSExt(
I);
1416 case Instruction::ICmp:
1417 return selectICmp(
I);
1418 case Instruction::FCmp:
1419 return selectFCmp(
I);
1420 case Instruction::BitCast:
1421 return selectBitCast(
I);
1422 case Instruction::Load:
1423 return selectLoad(
I);
1424 case Instruction::Store:
1425 return selectStore(
I);
1426 case Instruction::Br:
1428 case Instruction::Ret:
1429 return selectRet(
I);
1430 case Instruction::Unreachable:
1431 return selectUnreachable(
I);
1437 return selectOperator(
I,
I->getOpcode());
1442 return new WebAssemblyFastISel(FuncInfo, LibInfo);
unsigned const MachineRegisterInfo * MRI
amdgpu AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
BlockVerifier::State From
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
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 ...
unsigned const TargetRegisterInfo * TRI
static unsigned getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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 declares the WebAssembly-specific subclass of TargetMachine.
This file contains the declaration of the WebAssembly-specific type parsing utility functions.
This file contains the declaration of the WebAssembly-specific utility functions.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end.
an instruction to allocate memory on the stack
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
LLVM Basic Block Representation.
This is the shared class of boolean and integer constants.
This is an important base class in LLVM.
This class represents an Operation in the Expression.
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
virtual unsigned fastMaterializeConstant(const Constant *C)
Emit a constant in a register using target-specific logic, such as constant pool loads.
virtual bool fastLowerArguments()
This method is called by target-independent code to do target- specific argument lowering.
bool selectCall(const User *I)
virtual bool fastSelectInstruction(const Instruction *I)=0
This method is called by target-independent code when the normal FastISel process fails to select an ...
bool selectBitCast(const User *I)
virtual unsigned fastMaterializeAlloca(const AllocaInst *C)
Emit an alloca address in a register using target-specific logic.
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
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.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getElementOffset(unsigned Idx) const
Class to represent struct types.
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.
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
bool hasReferenceTypes() const
bool hasExceptionHandling() const
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
@ Swift
Calling convention for Swift.
@ 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)
Reg
All possible values of the reg field in the ModR/M byte.
NodeAddr< FuncNode * > Func
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
gep_type_iterator gep_type_end(const User *GEP)
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
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.