42 #define DEBUG_TYPE "wasm-fastisel"
46 class WebAssemblyFastISel final :
public FastISel {
50 typedef enum { RegBase, FrameIndexBase } BaseKind;
66 void setKind(BaseKind K) {
Kind = K; }
67 BaseKind getKind()
const {
return Kind; }
68 bool isRegBase()
const {
return Kind == RegBase; }
69 bool isFIBase()
const {
return Kind == FrameIndexBase; }
70 void setReg(
unsigned Reg) {
71 assert(isRegBase() &&
"Invalid base register access!");
75 assert(isRegBase() &&
"Invalid base register access!");
78 void setFI(
unsigned FI) {
79 assert(isFIBase() &&
"Invalid base frame index access!");
82 unsigned getFI()
const {
83 assert(isFIBase() &&
"Invalid base frame index access!");
87 void setOffset(int64_t Offset_) {
88 assert(Offset_ >= 0 &&
"Offsets must be non-negative");
93 const GlobalValue *getGlobalValue()
const {
return GV; }
104 EVT VT = TLI.getValueType(DL, Ty,
true);
123 if (Subtarget->hasSIMD128())
132 void materializeLoadStoreOperands(
Address &Addr);
135 unsigned maskI1Value(
unsigned Reg,
const Value *V);
136 unsigned getRegForI1Value(
const Value *V,
bool &
Not);
137 unsigned zeroExtendToI32(
unsigned Reg,
const Value *V,
139 unsigned signExtendToI32(
unsigned Reg,
const Value *V,
141 unsigned zeroExtend(
unsigned Reg,
const Value *V,
144 unsigned signExtend(
unsigned Reg,
const Value *V,
147 unsigned getRegForUnsignedValue(
const Value *V);
148 unsigned getRegForSignedValue(
const Value *V);
149 unsigned getRegForPromotedValue(
const Value *V,
bool IsSigned);
150 unsigned notValue(
unsigned Reg);
151 unsigned copyValue(
unsigned Reg);
154 unsigned fastMaterializeAlloca(
const AllocaInst *AI)
override;
155 unsigned fastMaterializeConstant(
const Constant *
C)
override;
156 bool fastLowerArguments()
override;
177 :
FastISel(FuncInfo, LibInfo,
true) {
182 bool fastSelectInstruction(
const Instruction *I)
override;
184 #include "WebAssemblyGenFastISel.inc"
189 bool WebAssemblyFastISel::computeAddress(
const Value *Obj,
Address &Addr) {
191 const User *U =
nullptr;
192 unsigned Opcode = Instruction::UserOp1;
193 if (
const Instruction *
I = dyn_cast<Instruction>(Obj)) {
196 if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
197 FuncInfo.MBBMap[
I->getParent()] == FuncInfo.MBB) {
198 Opcode =
I->getOpcode();
201 }
else if (
const ConstantExpr *
C = dyn_cast<ConstantExpr>(Obj)) {
202 Opcode =
C->getOpcode();
206 if (
auto *Ty = dyn_cast<PointerType>(Obj->
getType()))
207 if (Ty->getAddressSpace() > 255)
212 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(Obj)) {
213 if (Addr.getGlobalValue())
215 Addr.setGlobalValue(GV);
222 case Instruction::BitCast: {
224 return computeAddress(U->
getOperand(0), Addr);
226 case Instruction::IntToPtr: {
229 TLI.getPointerTy(DL))
230 return computeAddress(U->
getOperand(0), Addr);
233 case Instruction::PtrToInt: {
235 if (TLI.getValueType(DL, U->
getType()) == TLI.getPointerTy(DL))
236 return computeAddress(U->
getOperand(0), Addr);
239 case Instruction::GetElementPtr: {
241 uint64_t TmpOffset = Addr.getOffset();
243 if (!cast<GEPOperator>(U)->isInBounds())
244 goto unsupported_gep;
249 const Value *
Op = GTI.getOperand();
250 if (
StructType *STy = GTI.getStructTypeOrNull()) {
252 unsigned Idx = cast<ConstantInt>(
Op)->getZExtValue();
255 uint64_t S =
DL.getTypeAllocSize(GTI.getIndexedType());
257 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
259 TmpOffset += CI->getSExtValue() * S;
262 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
264 Addr.setReg(getRegForValue(Op));
267 if (canFoldAddIntoGEP(U, Op)) {
270 cast<ConstantInt>(cast<AddOperator>(
Op)->getOperand(1));
273 Op = cast<AddOperator>(
Op)->getOperand(0);
277 goto unsupported_gep;
282 if (int64_t(TmpOffset) >= 0) {
284 Addr.setOffset(TmpOffset);
293 case Instruction::Alloca: {
296 FuncInfo.StaticAllocaMap.find(AI);
297 if (SI != FuncInfo.StaticAllocaMap.end()) {
298 Addr.setKind(Address::FrameIndexBase);
299 Addr.setFI(SI->second);
309 if (isa<ConstantInt>(LHS))
312 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
313 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
314 if (int64_t(TmpOffset) >= 0) {
315 Addr.setOffset(TmpOffset);
316 return computeAddress(LHS, Addr);
321 if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
327 case Instruction::Sub: {
332 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
333 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
334 if (TmpOffset >= 0) {
335 Addr.setOffset(TmpOffset);
336 return computeAddress(LHS, Addr);
342 Addr.setReg(getRegForValue(Obj));
343 return Addr.getReg() != 0;
346 void WebAssemblyFastISel::materializeLoadStoreOperands(
Address &Addr) {
347 if (Addr.isRegBase()) {
348 unsigned Reg = Addr.getReg();
350 Reg = createResultReg(Subtarget->hasAddr64() ?
351 &WebAssembly::I64RegClass :
352 &WebAssembly::I32RegClass);
353 unsigned Opc = Subtarget->hasAddr64() ?
354 WebAssembly::CONST_I64 :
355 WebAssembly::CONST_I32;
356 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc),
Reg)
363 void WebAssemblyFastISel::addLoadStoreOperands(
const Address &Addr,
373 MIB.
addImm(Addr.getOffset());
375 if (Addr.isRegBase())
376 MIB.
addReg(Addr.getReg());
383 unsigned WebAssemblyFastISel::maskI1Value(
unsigned Reg,
const Value *V) {
384 return zeroExtendToI32(Reg, V,
MVT::i1);
387 unsigned WebAssemblyFastISel::getRegForI1Value(
const Value *V,
bool &
Not) {
388 if (
const ICmpInst *ICmp = dyn_cast<ICmpInst>(V))
389 if (
const ConstantInt *
C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
390 if (ICmp->isEquality() &&
C->isZero() &&
C->getType()->isIntegerTy(32)) {
391 Not = ICmp->isTrueWhenEqual();
392 return getRegForValue(ICmp->getOperand(0));
401 return maskI1Value(getRegForValue(V), V);
404 unsigned WebAssemblyFastISel::zeroExtendToI32(
unsigned Reg,
const Value *V,
413 if (From ==
MVT::i1 && V !=
nullptr) {
414 if (isa<CmpInst>(V) ||
415 (isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr()))
416 return copyValue(Reg);
422 return copyValue(Reg);
427 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
428 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
429 TII.get(WebAssembly::CONST_I32), Imm)
432 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
433 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
434 TII.get(WebAssembly::AND_I32), Result)
441 unsigned WebAssemblyFastISel::signExtendToI32(
unsigned Reg,
const Value *V,
452 return copyValue(Reg);
457 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
458 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
459 TII.get(WebAssembly::CONST_I32), Imm)
462 unsigned Left = createResultReg(&WebAssembly::I32RegClass);
463 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
468 unsigned Right = createResultReg(&WebAssembly::I32RegClass);
469 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
470 TII.get(WebAssembly::SHR_S_I32), Right)
477 unsigned WebAssemblyFastISel::zeroExtend(
unsigned Reg,
const Value *V,
482 return copyValue(Reg);
484 Reg = zeroExtendToI32(Reg, V, From);
486 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
487 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
488 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
493 return zeroExtendToI32(Reg, V, From);
496 unsigned WebAssemblyFastISel::signExtend(
unsigned Reg,
const Value *V,
501 return copyValue(Reg);
503 Reg = signExtendToI32(Reg, V, From);
505 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
506 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
507 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
512 return signExtendToI32(Reg, V, From);
515 unsigned WebAssemblyFastISel::getRegForUnsignedValue(
const Value *V) {
518 return zeroExtend(getRegForValue(V), V, From, To);
521 unsigned WebAssemblyFastISel::getRegForSignedValue(
const Value *V) {
524 return zeroExtend(getRegForValue(V), V, From, To);
527 unsigned WebAssemblyFastISel::getRegForPromotedValue(
const Value *V,
529 return IsSigned ? getRegForSignedValue(V) :
530 getRegForUnsignedValue(V);
533 unsigned WebAssemblyFastISel::notValue(
unsigned Reg) {
534 assert(
MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
536 unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
537 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
538 TII.get(WebAssembly::EQZ_I32), NotReg)
543 unsigned WebAssemblyFastISel::copyValue(
unsigned Reg) {
544 unsigned ResultReg = createResultReg(
MRI.getRegClass(Reg));
545 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
546 TII.get(WebAssembly::COPY), ResultReg)
551 unsigned WebAssemblyFastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
553 FuncInfo.StaticAllocaMap.
find(AI);
555 if (SI != FuncInfo.StaticAllocaMap.
end()) {
556 unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ?
557 &WebAssembly::I64RegClass :
558 &WebAssembly::I32RegClass);
559 unsigned Opc = Subtarget->hasAddr64() ?
560 WebAssembly::COPY_I64 :
561 WebAssembly::COPY_I32;
562 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
563 .addFrameIndex(SI->second);
570 unsigned WebAssemblyFastISel::fastMaterializeConstant(
const Constant *
C) {
571 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
572 unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ?
573 &WebAssembly::I64RegClass :
574 &WebAssembly::I32RegClass);
575 unsigned Opc = Subtarget->hasAddr64() ?
576 WebAssembly::CONST_I64 :
577 WebAssembly::CONST_I32;
578 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
579 .addGlobalAddress(GV);
587 bool WebAssemblyFastISel::fastLowerArguments() {
588 if (!FuncInfo.CanLowerReturn)
596 for (
auto const &Arg : F->
args()) {
605 Type *ArgTy = Arg.getType();
608 if (!Subtarget->hasSIMD128() && ArgTy->
isVectorTy())
613 switch (getSimpleType(ArgTy)) {
618 Opc = WebAssembly::ARGUMENT_I32;
619 RC = &WebAssembly::I32RegClass;
622 Opc = WebAssembly::ARGUMENT_I64;
623 RC = &WebAssembly::I64RegClass;
626 Opc = WebAssembly::ARGUMENT_F32;
627 RC = &WebAssembly::F32RegClass;
630 Opc = WebAssembly::ARGUMENT_F64;
631 RC = &WebAssembly::F64RegClass;
634 Opc = WebAssembly::ARGUMENT_v16i8;
635 RC = &WebAssembly::V128RegClass;
638 Opc = WebAssembly::ARGUMENT_v8i16;
639 RC = &WebAssembly::V128RegClass;
642 Opc = WebAssembly::ARGUMENT_v4i32;
643 RC = &WebAssembly::V128RegClass;
646 Opc = WebAssembly::ARGUMENT_v4f32;
647 RC = &WebAssembly::V128RegClass;
652 unsigned ResultReg = createResultReg(RC);
653 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
655 updateValueMap(&Arg, ResultReg);
660 MRI.addLiveIn(WebAssembly::ARGUMENTS);
663 for (
auto const &Arg : F->
args())
664 MFI->
addParam(getLegalType(getSimpleType(Arg.getType())));
667 MFI->addResult(getLegalType(getSimpleType(F->
getReturnType())));
672 bool WebAssemblyFastISel::selectCall(
const Instruction *
I) {
685 bool IsDirect = Func !=
nullptr;
689 Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
700 Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::PCALL_INDIRECT_I32;
701 ResultReg = createResultReg(&WebAssembly::I32RegClass);
704 Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::PCALL_INDIRECT_I64;
705 ResultReg = createResultReg(&WebAssembly::I64RegClass);
708 Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::PCALL_INDIRECT_F32;
709 ResultReg = createResultReg(&WebAssembly::F32RegClass);
712 Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::PCALL_INDIRECT_F64;
713 ResultReg = createResultReg(&WebAssembly::F64RegClass);
717 IsDirect ? WebAssembly::CALL_v16i8 : WebAssembly::PCALL_INDIRECT_v16i8;
718 ResultReg = createResultReg(&WebAssembly::V128RegClass);
722 IsDirect ? WebAssembly::CALL_v8i16 : WebAssembly::PCALL_INDIRECT_v8i16;
723 ResultReg = createResultReg(&WebAssembly::V128RegClass);
727 IsDirect ? WebAssembly::CALL_v4i32 : WebAssembly::PCALL_INDIRECT_v4i32;
728 ResultReg = createResultReg(&WebAssembly::V128RegClass);
732 IsDirect ? WebAssembly::CALL_v4f32 : WebAssembly::PCALL_INDIRECT_v4f32;
733 ResultReg = createResultReg(&WebAssembly::V128RegClass);
758 Reg = getRegForSignedValue(V);
760 Reg = getRegForUnsignedValue(V);
762 Reg = getRegForValue(V);
770 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc));
780 for (
unsigned ArgReg : Args)
784 updateValueMap(Call, ResultReg);
788 bool WebAssemblyFastISel::selectSelect(
const Instruction *I) {
796 unsigned TrueReg = getRegForValue(Select->
getTrueValue());
809 switch (getSimpleType(Select->
getType())) {
814 Opc = WebAssembly::SELECT_I32;
815 RC = &WebAssembly::I32RegClass;
818 Opc = WebAssembly::SELECT_I64;
819 RC = &WebAssembly::I64RegClass;
822 Opc = WebAssembly::SELECT_F32;
823 RC = &WebAssembly::F32RegClass;
826 Opc = WebAssembly::SELECT_F64;
827 RC = &WebAssembly::F64RegClass;
833 unsigned ResultReg = createResultReg(RC);
834 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
839 updateValueMap(Select, ResultReg);
843 bool WebAssemblyFastISel::selectTrunc(
const Instruction *I) {
846 unsigned Reg = getRegForValue(Trunc->
getOperand(0));
851 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
852 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
853 TII.get(WebAssembly::I32_WRAP_I64), Result)
858 updateValueMap(Trunc, Reg);
862 bool WebAssemblyFastISel::selectZExt(
const Instruction *I) {
863 const ZExtInst *ZExt = cast<ZExtInst>(
I);
868 unsigned Reg = zeroExtend(getRegForValue(Op), Op, From, To);
872 updateValueMap(ZExt, Reg);
876 bool WebAssemblyFastISel::selectSExt(
const Instruction *I) {
877 const SExtInst *SExt = cast<SExtInst>(
I);
882 unsigned Reg = signExtend(getRegForValue(Op), Op, From, To);
886 updateValueMap(SExt, Reg);
890 bool WebAssemblyFastISel::selectICmp(
const Instruction *I) {
891 const ICmpInst *ICmp = cast<ICmpInst>(
I);
895 bool isSigned =
false;
898 Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
901 Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
904 Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
907 Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
910 Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
913 Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
916 Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
920 Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
924 Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
928 Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
931 default:
return false;
934 unsigned LHS = getRegForPromotedValue(ICmp->
getOperand(0), isSigned);
938 unsigned RHS = getRegForPromotedValue(ICmp->
getOperand(1), isSigned);
942 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
943 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
946 updateValueMap(ICmp, ResultReg);
950 bool WebAssemblyFastISel::selectFCmp(
const Instruction *I) {
951 const FCmpInst *FCmp = cast<FCmpInst>(
I);
953 unsigned LHS = getRegForValue(FCmp->
getOperand(0));
957 unsigned RHS = getRegForValue(FCmp->
getOperand(1));
966 Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
969 Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
972 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
975 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
978 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
981 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
984 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
988 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
992 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
996 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1003 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1004 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc), ResultReg)
1009 ResultReg = notValue(ResultReg);
1011 updateValueMap(FCmp, ResultReg);
1015 bool WebAssemblyFastISel::selectBitCast(
const Instruction *I) {
1020 EVT RetVT = TLI.getValueType(DL, I->
getType());
1026 updateValueMap(I, getRegForValue(I->
getOperand(0)));
1037 assert(Iter->isBitcast());
1039 updateValueMap(I, Reg);
1043 bool WebAssemblyFastISel::selectLoad(
const Instruction *I) {
1058 switch (getSimpleType(Load->
getType())) {
1061 Opc = WebAssembly::LOAD8_U_I32;
1062 RC = &WebAssembly::I32RegClass;
1065 Opc = WebAssembly::LOAD16_U_I32;
1066 RC = &WebAssembly::I32RegClass;
1069 Opc = WebAssembly::LOAD_I32;
1070 RC = &WebAssembly::I32RegClass;
1073 Opc = WebAssembly::LOAD_I64;
1074 RC = &WebAssembly::I64RegClass;
1077 Opc = WebAssembly::LOAD_F32;
1078 RC = &WebAssembly::F32RegClass;
1081 Opc = WebAssembly::LOAD_F64;
1082 RC = &WebAssembly::F64RegClass;
1088 materializeLoadStoreOperands(Addr);
1090 unsigned ResultReg = createResultReg(RC);
1091 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc),
1094 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1096 updateValueMap(Load, ResultReg);
1100 bool WebAssemblyFastISel::selectStore(
const Instruction *I) {
1104 if (!Subtarget->hasSIMD128() &&
1113 bool VTIsi1 =
false;
1118 Opc = WebAssembly::STORE8_I32;
1121 Opc = WebAssembly::STORE16_I32;
1124 Opc = WebAssembly::STORE_I32;
1127 Opc = WebAssembly::STORE_I64;
1130 Opc = WebAssembly::STORE_F32;
1133 Opc = WebAssembly::STORE_F64;
1135 default:
return false;
1138 materializeLoadStoreOperands(Addr);
1146 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc));
1148 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1150 MIB.addReg(ValueReg);
1154 bool WebAssemblyFastISel::selectBr(
const Instruction *I) {
1170 unsigned Opc = WebAssembly::BR_IF;
1172 Opc = WebAssembly::BR_UNLESS;
1174 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc))
1178 finishCondBranch(Br->
getParent(), TBB, FBB);
1182 bool WebAssemblyFastISel::selectRet(
const Instruction *I) {
1183 if (!FuncInfo.CanLowerReturn)
1189 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1190 TII.get(WebAssembly::RETURN_VOID));
1199 switch (getSimpleType(RV->
getType())) {
1202 Opc = WebAssembly::RETURN_I32;
1205 Opc = WebAssembly::RETURN_I64;
1208 Opc = WebAssembly::RETURN_F32;
1211 Opc = WebAssembly::RETURN_F64;
1214 Opc = WebAssembly::RETURN_v16i8;
1217 Opc = WebAssembly::RETURN_v8i16;
1220 Opc = WebAssembly::RETURN_v4i32;
1223 Opc = WebAssembly::RETURN_v4f32;
1225 default:
return false;
1229 if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
1230 Reg = getRegForSignedValue(RV);
1231 else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
1232 Reg = getRegForUnsignedValue(RV);
1234 Reg = getRegForValue(RV);
1239 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
TII.get(Opc)).addReg(Reg);
1243 bool WebAssemblyFastISel::selectUnreachable(
const Instruction *I) {
1244 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1245 TII.get(WebAssembly::UNREACHABLE));
1249 bool WebAssemblyFastISel::fastSelectInstruction(
const Instruction *I) {
1256 case Instruction::Trunc:
return selectTrunc(I);
1257 case Instruction::ZExt:
return selectZExt(I);
1258 case Instruction::SExt:
return selectSExt(I);
1259 case Instruction::ICmp:
return selectICmp(I);
1260 case Instruction::FCmp:
return selectFCmp(I);
1261 case Instruction::BitCast:
return selectBitCast(I);
1264 case Instruction::Br:
return selectBr(I);
1266 case Instruction::Unreachable:
return selectUnreachable(I);
1271 return selectOperator(I, I->
getOpcode());
1276 return new WebAssemblyFastISel(FuncInfo, LibInfo);
AttributeSet getAttributes() const
Return the parameter attributes for this call.
Return a value (possibly void), from a function.
Value * getValueOperand()
const Value * getCalledValue() const
Get a pointer to the function that is invoked by this instruction.
void push_back(const T &Elt)
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
This class represents zero extension of integer types.
unsigned getNumOperands() const
This class represents a function call, abstracting a target machine's calling convention.
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
gep_type_iterator gep_type_end(const User *GEP)
0 1 0 0 True if ordered and less than
unsigned getSizeInBits() const
1 1 1 0 True if unordered or not equal
Type * getReturnType() const
Returns the type of the ret val.
This class represents a sign extension of integer types.
An instruction for reading from memory.
bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const
Return true if the attribute exists at the given index.
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
APInt Not(const APInt &APIVal)
Bitwise complement function.
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
bool isUnconditional() const
A description of a memory reference used in the backend.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
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.
unsigned getNumArgOperands() const
Return the number of call arguments.
Reg
All possible values of the reg field in the ModR/M byte.
0 1 0 1 True if ordered and less than or equal
bool isMustTailCall() const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
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.
This instruction compares its operands according to the predicate given to the constructor.
BasicBlock * getSuccessor(unsigned i) const
An instruction for storing to memory.
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
bool isArrayTy() const
True if this is an instance of ArrayType.
This class represents a truncation of integer types.
bool isAtomic() const
Return true if this instruction has an AtomicOrdering of unordered or higher.
static const Value * getNotArgument(const Value *BinOp)
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
uint64_t getElementOffset(unsigned Idx) const
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned const MachineRegisterInfo * MRI
MVT - Machine Value Type.
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.
bool isVectorTy() const
True if this is an instance of VectorType.
static unsigned getSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI)
Get the size in bits of Reg.
This is an important base class in LLVM.
const Value * getCondition() const
This file provides WebAssembly-specific target descriptions.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
This instruction compares its operands according to the predicate given to the constructor.
Value * getOperand(unsigned i) const
Value * getPointerOperand()
static bool isNot(const Value *V)
Predicate getPredicate() const
Return the predicate for this instruction.
EVT - Extended Value Type.
const Value * getTrueValue() const
1 1 0 1 True if unordered, less than, or equal
FunctionType * getFunctionType() const
0 0 1 0 True if ordered and greater than
This file declares the WebAssembly-specific subclass of TargetSubtarget.
This is the shared class of boolean and integer constants.
1 1 0 0 True if unordered or less than
Type * getType() const
All values are typed, get the type of this value.
Provides information about what library functions are available for the current target.
Function * getCalledFunction() const
Return the function called, or null if this is an indirect function invocation.
const MachineInstrBuilder & addFrameIndex(int Idx) const
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
AttributeSet getAttributes() const
Return the attribute list for this Function.
Value * getArgOperand(unsigned i) const
getArgOperand/setArgOperand - Return/set the i-th call argument.
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
bool isIntegerTy() const
True if this is an instance of IntegerType.
This file defines the FastISel class.
bool isInlineAsm() const
Check if this call is an inline asm statement.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
bool isStructTy() const
True if this is an instance of StructType.
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
Value * getCondition() const
unsigned greater or equal
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
bool hasOneUse() const
Return true if there is exactly one user of this value.
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
This file declares WebAssembly-specific per-machine-function information.
iterator find(const KeyT &Val)
1 0 1 0 True if unordered or greater than
Type * getReturnType() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isSimple() const
isSimple - Test if the given EVT is simple (as opposed to being extended).
0 0 0 1 True if ordered and equal
LLVM Value Representation.
1 0 1 1 True if unordered, greater than, or equal
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
const Value * getFalseValue() const
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
0 0 1 1 True if ordered and greater than or equal
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Value * getPointerOperand()
const BasicBlock * getParent() const
MVT getSimpleVT() const
getSimpleVT - Return the SimpleValueType held in the specified simple EVT.
iterator_range< arg_iterator > args()
bool isVoidTy() const
Return true if this is 'void'.
an instruction to allocate memory on the stack
gep_type_iterator gep_type_begin(const User *GEP)