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);
156 bool computeAddress(
const Value *Obj, Address &
Addr);
157 void materializeLoadStoreOperands(Address &
Addr);
160 unsigned maskI1Value(
unsigned Reg,
const Value *V);
161 unsigned getRegForI1Value(
const Value *V,
const BasicBlock *BB,
bool &Not);
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);
207#include "WebAssemblyGenFastISel.inc"
212bool 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)) {
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: {
250 return computeAddress(
U->getOperand(0),
Addr);
252 case Instruction::IntToPtr: {
254 if (TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
255 TLI.getPointerTy(
DL))
256 return computeAddress(
U->getOperand(0),
Addr);
259 case Instruction::PtrToInt: {
261 if (TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
262 return computeAddress(
U->getOperand(0),
Addr);
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);
313 if (computeAddress(
U->getOperand(0),
Addr))
321 case Instruction::Alloca: {
322 const auto *AI = cast<AllocaInst>(Obj);
325 if (SI !=
FuncInfo.StaticAllocaMap.end()) {
329 Addr.setKind(Address::FrameIndexBase);
335 case Instruction::Add: {
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);
352 if (computeAddress(LHS,
Addr) && computeAddress(RHS,
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;
383void 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;
398void WebAssemblyFastISel::addLoadStoreOperands(
const Address &
Addr,
410 if (
Addr.isRegBase())
418unsigned WebAssemblyFastISel::maskI1Value(
unsigned Reg,
const Value *V) {
419 return zeroExtendToI32(Reg, V, MVT::i1);
422unsigned 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);
440unsigned 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);
464 TII.get(WebAssembly::CONST_I32), Imm)
469 TII.get(WebAssembly::AND_I32), Result)
476unsigned WebAssemblyFastISel::signExtendToI32(
unsigned Reg,
const Value *V,
487 return copyValue(Reg);
492 Register Imm = createResultReg(&WebAssembly::I32RegClass);
494 TII.get(WebAssembly::CONST_I32), Imm)
497 Register Left = createResultReg(&WebAssembly::I32RegClass);
499 TII.get(WebAssembly::SHL_I32),
Left)
505 TII.get(WebAssembly::SHR_S_I32),
Right)
512unsigned WebAssemblyFastISel::zeroExtend(
unsigned Reg,
const Value *V,
515 if (To == MVT::i64) {
516 if (
From == MVT::i64)
517 return copyValue(Reg);
519 Reg = zeroExtendToI32(Reg, V,
From);
523 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
529 return zeroExtendToI32(Reg, V,
From);
534unsigned WebAssemblyFastISel::signExtend(
unsigned Reg,
const Value *V,
537 if (To == MVT::i64) {
538 if (
From == MVT::i64)
539 return copyValue(Reg);
541 Reg = signExtendToI32(Reg, V,
From);
545 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
551 return signExtendToI32(Reg, V,
From);
556unsigned WebAssemblyFastISel::getRegForUnsignedValue(
const Value *V) {
562 return zeroExtend(VReg, V,
From, To);
565unsigned WebAssemblyFastISel::getRegForSignedValue(
const Value *V) {
571 return signExtend(VReg, V,
From, To);
574unsigned WebAssemblyFastISel::getRegForPromotedValue(
const Value *V,
576 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(
V);
579unsigned WebAssemblyFastISel::notValue(
unsigned Reg) {
580 assert(
MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
582 Register NotReg = createResultReg(&WebAssembly::I32RegClass);
584 TII.get(WebAssembly::EQZ_I32), NotReg)
589unsigned WebAssemblyFastISel::copyValue(
unsigned Reg) {
590 Register ResultReg = createResultReg(
MRI.getRegClass(Reg));
597unsigned WebAssemblyFastISel::fastMaterializeAlloca(
const AllocaInst *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;
615unsigned 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;
635bool WebAssemblyFastISel::fastLowerArguments() {
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);
722 updateValueMap(&
Arg, ResultReg);
727 MRI.addLiveIn(WebAssembly::ARGUMENTS);
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);
752bool 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()))
772 unsigned Opc = IsDirect ? WebAssembly::CALL : WebAssembly::CALL_INDIRECT;
773 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
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());
874 MF->getMMI().getContext(), Subtarget);
875 if (Subtarget->hasReferenceTypes()) {
888 if (Subtarget->hasAddr64()) {
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);
909bool 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);
969 updateValueMap(
Select, ResultReg);
973bool 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)) {
983 TII.get(WebAssembly::I32_WRAP_I64), Result)
988 updateValueMap(Trunc, Reg);
992bool WebAssemblyFastISel::selectZExt(
const Instruction *
I) {
993 const auto *ZExt = cast<ZExtInst>(
I);
995 const Value *
Op = ZExt->getOperand(0);
1001 unsigned Reg = zeroExtend(In, Op,
From, To);
1005 updateValueMap(ZExt, Reg);
1009bool WebAssemblyFastISel::selectSExt(
const Instruction *
I) {
1010 const auto *SExt = cast<SExtInst>(
I);
1012 const Value *
Op = SExt->getOperand(0);
1018 unsigned Reg = signExtend(In, Op,
From, To);
1022 updateValueMap(SExt, Reg);
1026bool 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()) {
1033 case ICmpInst::ICMP_EQ:
1034 Opc =
I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
1036 case ICmpInst::ICMP_NE:
1037 Opc =
I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1039 case ICmpInst::ICMP_UGT:
1040 Opc =
I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1042 case ICmpInst::ICMP_UGE:
1043 Opc =
I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1045 case ICmpInst::ICMP_ULT:
1046 Opc =
I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1048 case ICmpInst::ICMP_ULE:
1049 Opc =
I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1051 case ICmpInst::ICMP_SGT:
1052 Opc =
I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1055 case ICmpInst::ICMP_SGE:
1056 Opc =
I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1059 case ICmpInst::ICMP_SLT:
1060 Opc =
I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1063 case ICmpInst::ICMP_SLE:
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);
1083 updateValueMap(ICmp, ResultReg);
1087bool 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()) {
1102 case FCmpInst::FCMP_OEQ:
1103 Opc =
F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1105 case FCmpInst::FCMP_UNE:
1106 Opc =
F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1108 case FCmpInst::FCMP_OGT:
1109 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1111 case FCmpInst::FCMP_OGE:
1112 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1114 case FCmpInst::FCMP_OLT:
1115 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1117 case FCmpInst::FCMP_OLE:
1118 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1120 case FCmpInst::FCMP_UGT:
1121 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1124 case FCmpInst::FCMP_UGE:
1125 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1128 case FCmpInst::FCMP_ULT:
1129 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1132 case FCmpInst::FCMP_ULE:
1133 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1140 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1146 ResultReg = notValue(ResultReg);
1148 updateValueMap(FCmp, ResultReg);
1152bool 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);
1183bool 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);
1237 addLoadStoreOperands(
Addr, MIB, createMachineMemOperandFor(Load));
1239 updateValueMap(Load, ResultReg);
1243bool 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());
1296 addLoadStoreOperands(
Addr, MIB, createMachineMemOperandFor(Store));
1302bool 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;
1326 finishCondBranch(Br->getParent(),
TBB, FBB);
1330bool WebAssemblyFastISel::selectRet(
const Instruction *
I) {
1334 const auto *
Ret = cast<ReturnInst>(
I);
1336 if (
Ret->getNumOperands() == 0) {
1338 TII.get(WebAssembly::RETURN));
1343 if (
Ret->getNumOperands() > 1)
1350 switch (getSimpleType(RV->
getType())) {
1365 case MVT::externref:
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);
1383 TII.get(WebAssembly::RETURN))
1388bool WebAssemblyFastISel::selectUnreachable(
const Instruction *
I) {
1390 TII.get(WebAssembly::UNREACHABLE));
1394bool WebAssemblyFastISel::fastSelectInstruction(
const Instruction *
I) {
1395 switch (
I->getOpcode()) {
1396 case Instruction::Call:
1400 case Instruction::Select:
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);
1414 case Instruction::Load:
1415 return selectLoad(
I);
1416 case Instruction::Store:
1417 return selectStore(
I);
1418 case Instruction::Br:
1420 case Instruction::Ret:
1421 return selectRet(
I);
1422 case Instruction::Unreachable:
1423 return selectUnreachable(
I);
1429 return selectOperator(
I,
I->getOpcode());
1434 return new WebAssemblyFastISel(
FuncInfo, LibInfo);
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
amdgpu AMDGPU Register Bank Select
BlockVerifier::State From
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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
typename CallsiteContextGraph< DerivedCCG, FuncTy, CallTy >::FuncInfo FuncInfo
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 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...
This is an important class for using LLVM in a threaded context.
@ INVALID_SIMPLE_VALUE_TYPE
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
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.
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.
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.