45 #define DEBUG_TYPE "wasm-fastisel" 49 class WebAssemblyFastISel final :
public FastISel {
53 typedef enum { RegBase, FrameIndexBase } BaseKind;
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(
Base.Reg == 0 &&
"Overwriting non-zero register");
82 assert(isRegBase() &&
"Invalid base register access!");
85 void setFI(
unsigned FI) {
86 assert(isFIBase() &&
"Invalid base frame index access!");
87 assert(
Base.FI == 0 &&
"Overwriting non-zero frame index");
90 unsigned getFI()
const {
91 assert(isFIBase() &&
"Invalid base frame index access!");
95 void setOffset(int64_t Offset_) {
96 assert(Offset_ >= 0 &&
"Offsets must be non-negative");
101 const GlobalValue *getGlobalValue()
const {
return GV; }
104 return Base.Reg != 0;
119 EVT VT = TLI.getValueType(DL, Ty,
true);
155 void materializeLoadStoreOperands(
Address &Addr);
158 unsigned maskI1Value(
unsigned Reg,
const Value *V);
159 unsigned getRegForI1Value(
const Value *V,
bool &Not);
160 unsigned zeroExtendToI32(
unsigned Reg,
const Value *V,
162 unsigned signExtendToI32(
unsigned Reg,
const Value *V,
168 unsigned getRegForUnsignedValue(
const Value *V);
169 unsigned getRegForSignedValue(
const Value *V);
170 unsigned getRegForPromotedValue(
const Value *V,
bool IsSigned);
171 unsigned notValue(
unsigned Reg);
172 unsigned copyValue(
unsigned Reg);
175 unsigned fastMaterializeAlloca(
const AllocaInst *AI)
override;
176 unsigned fastMaterializeConstant(
const Constant *
C)
override;
177 bool fastLowerArguments()
override;
198 :
FastISel(FuncInfo, LibInfo,
true) {
203 bool fastSelectInstruction(
const Instruction *I)
override;
205 #include "WebAssemblyGenFastISel.inc" 210 bool WebAssemblyFastISel::computeAddress(
const Value *Obj,
Address &Addr) {
212 const User *U =
nullptr;
213 unsigned Opcode = Instruction::UserOp1;
214 if (
const Instruction *
I = dyn_cast<Instruction>(Obj)) {
217 if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
218 FuncInfo.MBBMap[
I->getParent()] == FuncInfo.MBB) {
219 Opcode =
I->getOpcode();
222 }
else if (
const ConstantExpr *
C = dyn_cast<ConstantExpr>(Obj)) {
227 if (
auto *Ty = dyn_cast<PointerType>(Obj->
getType()))
228 if (Ty->getAddressSpace() > 255)
233 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(Obj)) {
234 if (Addr.getGlobalValue())
236 Addr.setGlobalValue(GV);
243 case Instruction::BitCast: {
245 return computeAddress(U->
getOperand(0), Addr);
247 case Instruction::IntToPtr: {
250 TLI.getPointerTy(DL))
251 return computeAddress(U->
getOperand(0), Addr);
254 case Instruction::PtrToInt: {
256 if (TLI.getValueType(DL, U->
getType()) == TLI.getPointerTy(DL))
257 return computeAddress(U->
getOperand(0), Addr);
260 case Instruction::GetElementPtr: {
262 uint64_t TmpOffset = Addr.getOffset();
264 if (!cast<GEPOperator>(U)->isInBounds())
265 goto unsupported_gep;
270 const Value *
Op = GTI.getOperand();
271 if (
StructType *STy = GTI.getStructTypeOrNull()) {
273 unsigned Idx = cast<ConstantInt>(
Op)->getZExtValue();
276 uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
278 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
280 TmpOffset += CI->getSExtValue() * S;
283 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
285 unsigned Reg = getRegForValue(Op);
291 if (canFoldAddIntoGEP(U, Op)) {
294 cast<ConstantInt>(cast<AddOperator>(
Op)->getOperand(1));
297 Op = cast<AddOperator>(
Op)->getOperand(0);
301 goto unsupported_gep;
306 if (int64_t(TmpOffset) >= 0) {
308 Addr.setOffset(TmpOffset);
317 case Instruction::Alloca: {
320 FuncInfo.StaticAllocaMap.find(AI);
321 if (SI != FuncInfo.StaticAllocaMap.end()) {
325 Addr.setKind(Address::FrameIndexBase);
326 Addr.setFI(SI->second);
336 if (isa<ConstantInt>(LHS))
339 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
340 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
341 if (int64_t(TmpOffset) >= 0) {
342 Addr.setOffset(TmpOffset);
343 return computeAddress(LHS, Addr);
348 if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
354 case Instruction::Sub: {
359 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
360 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
361 if (TmpOffset >= 0) {
362 Addr.setOffset(TmpOffset);
363 return computeAddress(LHS, Addr);
372 unsigned Reg = getRegForValue(Obj);
376 return Addr.getReg() != 0;
379 void WebAssemblyFastISel::materializeLoadStoreOperands(
Address &Addr) {
380 if (Addr.isRegBase()) {
381 unsigned Reg = Addr.getReg();
383 Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
384 : &WebAssembly::I32RegClass);
385 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
386 : WebAssembly::CONST_I32;
387 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc),
Reg)
394 void WebAssemblyFastISel::addLoadStoreOperands(
const Address &Addr,
404 MIB.
addImm(Addr.getOffset());
406 if (Addr.isRegBase())
407 MIB.
addReg(Addr.getReg());
414 unsigned WebAssemblyFastISel::maskI1Value(
unsigned Reg,
const Value *V) {
415 return zeroExtendToI32(Reg, V,
MVT::i1);
418 unsigned WebAssemblyFastISel::getRegForI1Value(
const Value *V,
bool &Not) {
419 if (
const ICmpInst *ICmp = dyn_cast<ICmpInst>(V))
420 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
422 Not = ICmp->isTrueWhenEqual();
423 return getRegForValue(ICmp->getOperand(0));
429 return getRegForValue(NotV);
433 unsigned Reg = getRegForValue(V);
436 return maskI1Value(Reg, V);
439 unsigned WebAssemblyFastISel::zeroExtendToI32(
unsigned Reg,
const Value *V,
449 if (V !=
nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr())
450 return copyValue(Reg);
456 return copyValue(Reg);
461 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
462 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
463 TII.get(WebAssembly::CONST_I32), Imm)
466 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
467 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
468 TII.get(WebAssembly::AND_I32), Result)
475 unsigned WebAssemblyFastISel::signExtendToI32(
unsigned Reg,
const Value *V,
486 return copyValue(Reg);
491 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
492 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
493 TII.get(WebAssembly::CONST_I32), Imm)
496 unsigned Left = createResultReg(&WebAssembly::I32RegClass);
497 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
498 TII.get(WebAssembly::SHL_I32), Left)
502 unsigned Right = createResultReg(&WebAssembly::I32RegClass);
503 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
504 TII.get(WebAssembly::SHR_S_I32), Right)
511 unsigned WebAssemblyFastISel::zeroExtend(
unsigned Reg,
const Value *V,
516 return copyValue(Reg);
518 Reg = zeroExtendToI32(Reg, V,
From);
520 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
521 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
522 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
527 return zeroExtendToI32(Reg, V,
From);
530 unsigned WebAssemblyFastISel::signExtend(
unsigned Reg,
const Value *V,
535 return copyValue(Reg);
537 Reg = signExtendToI32(Reg, V,
From);
539 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
540 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
541 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
546 return signExtendToI32(Reg, V,
From);
549 unsigned WebAssemblyFastISel::getRegForUnsignedValue(
const Value *V) {
552 unsigned VReg = getRegForValue(V);
555 return zeroExtend(VReg, V, From, To);
558 unsigned WebAssemblyFastISel::getRegForSignedValue(
const Value *V) {
561 unsigned VReg = getRegForValue(V);
564 return signExtend(VReg, V, From, To);
567 unsigned WebAssemblyFastISel::getRegForPromotedValue(
const Value *V,
569 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
572 unsigned WebAssemblyFastISel::notValue(
unsigned Reg) {
573 assert(
MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
575 unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
576 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
577 TII.get(WebAssembly::EQZ_I32), NotReg)
582 unsigned WebAssemblyFastISel::copyValue(
unsigned Reg) {
583 unsigned ResultReg = createResultReg(
MRI.getRegClass(Reg));
584 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(WebAssembly::COPY),
590 unsigned WebAssemblyFastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
592 FuncInfo.StaticAllocaMap.find(AI);
594 if (SI != FuncInfo.StaticAllocaMap.
end()) {
596 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
597 : &WebAssembly::I32RegClass);
599 Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
600 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
601 .addFrameIndex(SI->second);
608 unsigned WebAssemblyFastISel::fastMaterializeConstant(
const Constant *
C) {
609 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
611 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
612 : &WebAssembly::I32RegClass);
613 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
614 : WebAssembly::CONST_I32;
615 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
616 .addGlobalAddress(GV);
624 bool WebAssemblyFastISel::fastLowerArguments() {
625 if (!FuncInfo.CanLowerReturn)
633 for (
auto const &
Arg : F->
args()) {
645 if (!Subtarget->hasSIMD128() && ArgTy->
isVectorTy())
650 switch (getSimpleType(ArgTy)) {
655 Opc = WebAssembly::ARGUMENT_i32;
656 RC = &WebAssembly::I32RegClass;
659 Opc = WebAssembly::ARGUMENT_i64;
660 RC = &WebAssembly::I64RegClass;
663 Opc = WebAssembly::ARGUMENT_f32;
664 RC = &WebAssembly::F32RegClass;
667 Opc = WebAssembly::ARGUMENT_f64;
668 RC = &WebAssembly::F64RegClass;
671 Opc = WebAssembly::ARGUMENT_v16i8;
672 RC = &WebAssembly::V128RegClass;
675 Opc = WebAssembly::ARGUMENT_v8i16;
676 RC = &WebAssembly::V128RegClass;
679 Opc = WebAssembly::ARGUMENT_v4i32;
680 RC = &WebAssembly::V128RegClass;
683 Opc = WebAssembly::ARGUMENT_v2i64;
684 RC = &WebAssembly::V128RegClass;
687 Opc = WebAssembly::ARGUMENT_v4f32;
688 RC = &WebAssembly::V128RegClass;
691 Opc = WebAssembly::ARGUMENT_v2f64;
692 RC = &WebAssembly::V128RegClass;
695 Opc = WebAssembly::ARGUMENT_ExceptRef;
696 RC = &WebAssembly::EXCEPT_REFRegClass;
701 unsigned ResultReg = createResultReg(RC);
702 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
704 updateValueMap(&
Arg, ResultReg);
709 MRI.addLiveIn(WebAssembly::ARGUMENTS);
712 for (
auto const &
Arg : F->
args()) {
715 MFI->clearParamsAndResults();
718 MFI->addParam(ArgTy);
725 MFI->clearParamsAndResults();
728 MFI->addResult(RetTy);
734 bool WebAssemblyFastISel::selectCall(
const Instruction *
I) {
735 const CallInst *Call = cast<CallInst>(
I);
745 bool IsDirect = Func !=
nullptr;
754 Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
765 Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::PCALL_INDIRECT_I32;
766 ResultReg = createResultReg(&WebAssembly::I32RegClass);
769 Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::PCALL_INDIRECT_I64;
770 ResultReg = createResultReg(&WebAssembly::I64RegClass);
773 Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::PCALL_INDIRECT_F32;
774 ResultReg = createResultReg(&WebAssembly::F32RegClass);
777 Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::PCALL_INDIRECT_F64;
778 ResultReg = createResultReg(&WebAssembly::F64RegClass);
781 Opc = IsDirect ? WebAssembly::CALL_v16i8
782 : WebAssembly::PCALL_INDIRECT_v16i8;
783 ResultReg = createResultReg(&WebAssembly::V128RegClass);
786 Opc = IsDirect ? WebAssembly::CALL_v8i16
787 : WebAssembly::PCALL_INDIRECT_v8i16;
788 ResultReg = createResultReg(&WebAssembly::V128RegClass);
791 Opc = IsDirect ? WebAssembly::CALL_v4i32
792 : WebAssembly::PCALL_INDIRECT_v4i32;
793 ResultReg = createResultReg(&WebAssembly::V128RegClass);
796 Opc = IsDirect ? WebAssembly::CALL_v2i64
797 : WebAssembly::PCALL_INDIRECT_v2i64;
798 ResultReg = createResultReg(&WebAssembly::V128RegClass);
801 Opc = IsDirect ? WebAssembly::CALL_v4f32
802 : WebAssembly::PCALL_INDIRECT_v4f32;
803 ResultReg = createResultReg(&WebAssembly::V128RegClass);
806 Opc = IsDirect ? WebAssembly::CALL_v2f64
807 : WebAssembly::PCALL_INDIRECT_v2f64;
808 ResultReg = createResultReg(&WebAssembly::V128RegClass);
811 Opc = IsDirect ? WebAssembly::CALL_EXCEPT_REF
812 : WebAssembly::PCALL_INDIRECT_EXCEPT_REF;
813 ResultReg = createResultReg(&WebAssembly::EXCEPT_REFRegClass);
838 Reg = getRegForSignedValue(V);
840 Reg = getRegForUnsignedValue(V);
842 Reg = getRegForValue(V);
850 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc));
864 for (
unsigned ArgReg : Args)
868 updateValueMap(Call, ResultReg);
872 bool WebAssemblyFastISel::selectSelect(
const Instruction *I) {
876 unsigned CondReg = getRegForI1Value(Select->
getCondition(), Not);
880 unsigned TrueReg = getRegForValue(Select->
getTrueValue());
893 switch (getSimpleType(Select->
getType())) {
898 Opc = WebAssembly::SELECT_I32;
899 RC = &WebAssembly::I32RegClass;
902 Opc = WebAssembly::SELECT_I64;
903 RC = &WebAssembly::I64RegClass;
906 Opc = WebAssembly::SELECT_F32;
907 RC = &WebAssembly::F32RegClass;
910 Opc = WebAssembly::SELECT_F64;
911 RC = &WebAssembly::F64RegClass;
914 Opc = WebAssembly::SELECT_EXCEPT_REF;
915 RC = &WebAssembly::EXCEPT_REFRegClass;
921 unsigned ResultReg = createResultReg(RC);
922 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
927 updateValueMap(Select, ResultReg);
931 bool WebAssemblyFastISel::selectTrunc(
const Instruction *I) {
934 unsigned Reg = getRegForValue(Trunc->
getOperand(0));
939 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
940 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
941 TII.get(WebAssembly::I32_WRAP_I64), Result)
946 updateValueMap(Trunc, Reg);
950 bool WebAssemblyFastISel::selectZExt(
const Instruction *I) {
951 const ZExtInst *ZExt = cast<ZExtInst>(
I);
956 unsigned In = getRegForValue(Op);
959 unsigned Reg = zeroExtend(In, Op, From, To);
963 updateValueMap(ZExt, Reg);
967 bool WebAssemblyFastISel::selectSExt(
const Instruction *I) {
968 const SExtInst *SExt = cast<SExtInst>(
I);
973 unsigned In = getRegForValue(Op);
976 unsigned Reg = signExtend(In, Op, From, To);
980 updateValueMap(SExt, Reg);
984 bool WebAssemblyFastISel::selectICmp(
const Instruction *I) {
985 const ICmpInst *ICmp = cast<ICmpInst>(
I);
989 bool isSigned =
false;
992 Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
995 Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
998 Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1001 Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1004 Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1007 Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1010 Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1014 Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1018 Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1022 Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1029 unsigned LHS = getRegForPromotedValue(ICmp->
getOperand(0), isSigned);
1033 unsigned RHS = getRegForPromotedValue(ICmp->
getOperand(1), isSigned);
1037 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1038 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
1041 updateValueMap(ICmp, ResultReg);
1045 bool WebAssemblyFastISel::selectFCmp(
const Instruction *I) {
1046 const FCmpInst *FCmp = cast<FCmpInst>(
I);
1048 unsigned LHS = getRegForValue(FCmp->
getOperand(0));
1052 unsigned RHS = getRegForValue(FCmp->
getOperand(1));
1061 Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1064 Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1067 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1070 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1073 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1076 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1079 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1083 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1087 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1091 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1098 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1099 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
1104 ResultReg = notValue(ResultReg);
1106 updateValueMap(FCmp, ResultReg);
1110 bool WebAssemblyFastISel::selectBitCast(
const Instruction *I) {
1115 EVT RetVT = TLI.getValueType(DL, I->
getType());
1125 updateValueMap(I, In);
1135 assert(Iter->isBitcast());
1137 updateValueMap(I, Reg);
1141 bool WebAssemblyFastISel::selectLoad(
const Instruction *I) {
1156 switch (getSimpleType(Load->
getType())) {
1159 Opc = WebAssembly::LOAD8_U_I32;
1160 RC = &WebAssembly::I32RegClass;
1163 Opc = WebAssembly::LOAD16_U_I32;
1164 RC = &WebAssembly::I32RegClass;
1167 Opc = WebAssembly::LOAD_I32;
1168 RC = &WebAssembly::I32RegClass;
1171 Opc = WebAssembly::LOAD_I64;
1172 RC = &WebAssembly::I64RegClass;
1175 Opc = WebAssembly::LOAD_F32;
1176 RC = &WebAssembly::F32RegClass;
1179 Opc = WebAssembly::LOAD_F64;
1180 RC = &WebAssembly::F64RegClass;
1186 materializeLoadStoreOperands(Addr);
1188 unsigned ResultReg = createResultReg(RC);
1189 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc),
1192 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1194 updateValueMap(Load, ResultReg);
1198 bool WebAssemblyFastISel::selectStore(
const Instruction *I) {
1202 if (!Subtarget->hasSIMD128() &&
1211 bool VTIsi1 =
false;
1217 Opc = WebAssembly::STORE8_I32;
1220 Opc = WebAssembly::STORE16_I32;
1223 Opc = WebAssembly::STORE_I32;
1226 Opc = WebAssembly::STORE_I64;
1229 Opc = WebAssembly::STORE_F32;
1232 Opc = WebAssembly::STORE_F64;
1238 materializeLoadStoreOperands(Addr);
1246 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc));
1248 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1250 MIB.addReg(ValueReg);
1254 bool WebAssemblyFastISel::selectBr(
const Instruction *I) {
1266 unsigned CondReg = getRegForI1Value(Br->
getCondition(), Not);
1270 unsigned Opc = WebAssembly::BR_IF;
1272 Opc = WebAssembly::BR_UNLESS;
1274 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc))
1278 finishCondBranch(Br->
getParent(), TBB, FBB);
1282 bool WebAssemblyFastISel::selectRet(
const Instruction *I) {
1283 if (!FuncInfo.CanLowerReturn)
1289 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1290 TII.get(WebAssembly::RETURN_VOID));
1299 switch (getSimpleType(RV->
getType())) {
1304 Opc = WebAssembly::RETURN_I32;
1307 Opc = WebAssembly::RETURN_I64;
1310 Opc = WebAssembly::RETURN_F32;
1313 Opc = WebAssembly::RETURN_F64;
1316 Opc = WebAssembly::RETURN_v16i8;
1319 Opc = WebAssembly::RETURN_v8i16;
1322 Opc = WebAssembly::RETURN_v4i32;
1325 Opc = WebAssembly::RETURN_v2i64;
1328 Opc = WebAssembly::RETURN_v4f32;
1331 Opc = WebAssembly::RETURN_v2f64;
1334 Opc = WebAssembly::RETURN_EXCEPT_REF;
1342 Reg = getRegForSignedValue(RV);
1343 else if (FuncInfo.Fn->getAttributes().hasAttribute(0,
Attribute::ZExt))
1344 Reg = getRegForUnsignedValue(RV);
1346 Reg = getRegForValue(RV);
1351 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc)).addReg(Reg);
1355 bool WebAssemblyFastISel::selectUnreachable(
const Instruction *I) {
1356 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1357 TII.get(WebAssembly::UNREACHABLE));
1361 bool WebAssemblyFastISel::fastSelectInstruction(
const Instruction *I) {
1368 return selectSelect(I);
1369 case Instruction::Trunc:
1370 return selectTrunc(I);
1371 case Instruction::ZExt:
1372 return selectZExt(I);
1373 case Instruction::SExt:
1374 return selectSExt(I);
1375 case Instruction::ICmp:
1376 return selectICmp(I);
1377 case Instruction::FCmp:
1378 return selectFCmp(I);
1379 case Instruction::BitCast:
1380 return selectBitCast(I);
1382 return selectLoad(I);
1384 return selectStore(I);
1385 case Instruction::Br:
1388 return selectRet(I);
1389 case Instruction::Unreachable:
1390 return selectUnreachable(I);
1396 return selectOperator(I, I->
getOpcode());
1401 return new WebAssemblyFastISel(FuncInfo, LibInfo);
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Return a value (possibly void), from a function.
Value * getValueOperand()
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
This class represents lattice values for constants.
bool isAtomic() const
Return true if this instruction has an AtomicOrdering of unordered or higher.
This class represents zero extension of integer types.
void push_back(const T &Elt)
This class represents a function call, abstracting a target machine's calling convention.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
gep_type_iterator gep_type_end(const User *GEP)
const Value * getTrueValue() const
0 1 0 0 True if ordered and less than
1 1 1 0 True if unordered or not equal
BasicBlock * getSuccessor(unsigned i) const
unsigned const TargetRegisterInfo * TRI
This class represents a sign extension of integer types.
An instruction for reading from memory.
Value * getCondition() const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
bool isVectorTy() const
True if this is an instance of VectorType.
bool isMustTailCall() const
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
Value * getArgOperand(unsigned i) const
bool match(Val *V, const Pattern &P)
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
A description of a memory reference used in the backend.
This class represents the LLVM 'select' instruction.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
const HexagonInstrInfo * TII
Class to represent struct types.
bool isIntegerTy() const
True if this is an instance of IntegerType.
0 1 0 1 True if ordered and less than or equal
bool hasUnimplementedSIMD128() const
unsigned getSizeInBits() const
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Class to represent function types.
A constant value that is initialized with an expression using other constant values.
This file declares the WebAssembly-specific subclass of TargetMachine.
Type * getType() const
All values are typed, get the type of this value.
This instruction compares its operands according to the predicate given to the constructor.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
AttributeList getAttributes() const
Return the attribute list for this Function.
An instruction for storing to memory.
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
This class represents a truncation of integer types.
Value * getOperand(unsigned i) const
bool isVoidTy() const
Return true if this is 'void'.
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Type * getReturnType() const
Returns the type of the ret val.
unsigned const MachineRegisterInfo * MRI
Value * getCalledValue() const
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
Conditional or Unconditional Branch instruction.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
FunctionType * getFunctionType() const
This file provides WebAssembly-specific target descriptions.
This instruction compares its operands according to the predicate given to the constructor.
Value * getPointerOperand()
const MachineInstrBuilder & addFrameIndex(int Idx) const
const Value * getCondition() const
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
1 1 0 1 True if unordered, less than, or equal
0 0 1 0 True if ordered and greater than
This file declares the WebAssembly-specific subclass of TargetSubtarget.
unsigned getNumOperands() const
bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const
Equivalent to hasAttribute(ArgNo + FirstArgIndex, Kind).
This is the shared class of boolean and integer constants.
BlockVerifier::State From
1 1 0 0 True if unordered or less than
Provides information about what library functions are available for the current target.
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Type * getReturnType() const
AttributeList getAttributes() const
Return the parameter attributes for this call.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
This file defines the FastISel class.
const Value * getFalseValue() const
amdgpu Simplify well known AMD library false Value Value * Arg
Predicate getPredicate() const
Return the predicate for this instruction.
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
unsigned getNumArgOperands() const
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
bool isInlineAsm() const
Check if this call is an inline asm statement.
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
uint64_t getElementOffset(unsigned Idx) const
unsigned greater or equal
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation.
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
This file declares WebAssembly-specific per-machine-function information.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool isUnconditional() const
1 0 1 0 True if unordered or greater than
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
0 0 0 1 True if ordered and equal
LLVM Value Representation.
unsigned getSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
1 0 1 1 True if unordered, greater than, or equal
bool hasOneUse() const
Return true if there is exactly one user of this value.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
0 0 1 1 True if ordered and greater than or equal
Value * getPointerOperand()
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
BinaryOp_match< ValTy, cst_pred_ty< is_all_ones >, Instruction::Xor, true > m_Not(const ValTy &V)
Matches a 'Not' as 'xor V, -1' or 'xor -1, V'.
iterator_range< arg_iterator > args()
bool isStructTy() const
True if this is an instance of StructType.
bool isArrayTy() const
True if this is an instance of ArrayType.
const BasicBlock * getParent() const
an instruction to allocate memory on the stack
gep_type_iterator gep_type_begin(const User *GEP)