37#include "llvm/IR/IntrinsicsWebAssembly.h"
42#define DEBUG_TYPE "wasm-fastisel"
46class WebAssemblyFastISel final :
public FastISel {
50 enum BaseKind { RegBase, FrameIndexBase };
53 BaseKind Kind = RegBase;
60 bool IsBaseSet =
false;
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(!IsBaseSet &&
"Base cannot be reset");
83 assert(isRegBase() &&
"Invalid base register access!");
86 void setFI(
unsigned FI) {
87 assert(isFIBase() &&
"Invalid base frame index access!");
88 assert(!IsBaseSet &&
"Base cannot be reset");
92 unsigned getFI()
const {
93 assert(isFIBase() &&
"Invalid base frame index access!");
97 void setOffset(int64_t NewOffset) {
98 assert(NewOffset >= 0 &&
"Offsets must be non-negative");
103 const GlobalValue *getGlobalValue()
const {
return GV; }
104 bool isSet()
const {
return IsBaseSet; }
115 EVT VT =
TLI.getValueType(
DL, Ty,
true);
155 bool computeAddress(
const Value *Obj, Address &Addr);
156 void materializeLoadStoreOperands(Address &Addr);
160 unsigned maskI1Value(
unsigned Reg,
const Value *
V);
162 unsigned zeroExtendToI32(
unsigned Reg,
const Value *
V,
164 unsigned signExtendToI32(
unsigned Reg,
const Value *
V,
170 unsigned getRegForUnsignedValue(
const Value *
V);
171 unsigned getRegForSignedValue(
const Value *
V);
172 unsigned getRegForPromotedValue(
const Value *
V,
bool IsSigned);
173 unsigned notValue(
unsigned Reg);
174 unsigned copyValue(
unsigned Reg);
179 bool fastLowerArguments()
override;
201 :
FastISel(FuncInfo, LibInfo, LibcallLowering,
207 bool fastSelectInstruction(
const Instruction *
I)
override;
211#include "WebAssemblyGenFastISel.inc"
216bool WebAssemblyFastISel::computeAddress(
const Value *Obj, Address &Addr) {
217 const User *
U =
nullptr;
218 unsigned Opcode = Instruction::UserOp1;
222 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(Obj)) ||
223 FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
224 Opcode =
I->getOpcode();
228 Opcode =
C->getOpcode();
233 if (Ty->getAddressSpace() > 255)
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: {
260 return computeAddress(
U->getOperand(0), Addr);
263 case Instruction::PtrToInt: {
266 return computeAddress(
U->getOperand(0), Addr);
269 case Instruction::GetElementPtr: {
271 uint64_t TmpOffset = Addr.getOffset();
274 goto unsupported_gep;
279 const Value *
Op = GTI.getOperand();
280 if (StructType *STy = GTI.getStructTypeOrNull()) {
281 const StructLayout *SL =
DL.getStructLayout(STy);
285 uint64_t S = GTI.getSequentialElementStride(
DL);
289 TmpOffset += CI->getSExtValue() * S;
292 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
300 if (canFoldAddIntoGEP(U,
Op)) {
303 TmpOffset += CI->getSExtValue() * S;
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: {
327 auto SI = FuncInfo.StaticAllocaMap.find(AI);
328 if (SI != FuncInfo.StaticAllocaMap.end()) {
332 Addr.setKind(Address::FrameIndexBase);
333 Addr.setFI(
SI->second);
338 case Instruction::Add: {
342 if (!OFBinOp->hasNoUnsignedWrap())
353 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
354 if (int64_t(TmpOffset) >= 0) {
355 Addr.setOffset(TmpOffset);
356 return computeAddress(
LHS, Addr);
361 if (computeAddress(
LHS, Addr) && computeAddress(
RHS, Addr))
367 case Instruction::Sub: {
371 if (!OFBinOp->hasNoUnsignedWrap())
379 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
380 if (TmpOffset >= 0) {
381 Addr.setOffset(TmpOffset);
382 return computeAddress(
LHS, Addr);
395 return Addr.getReg() != 0;
398void WebAssemblyFastISel::materializeLoadStoreOperands(
Address &Addr) {
399 if (Addr.isRegBase()) {
400 unsigned Reg = Addr.getReg();
402 Reg = createResultReg(
Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
403 : &WebAssembly::I32RegClass);
404 unsigned Opc =
Subtarget->hasAddr64() ? WebAssembly::CONST_I64
405 : WebAssembly::CONST_I32;
413void WebAssemblyFastISel::addLoadStoreOperands(
const Address &Addr,
414 const MachineInstrBuilder &MIB,
415 MachineMemOperand *MMO) {
420 if (
const GlobalValue *GV = Addr.getGlobalValue())
423 MIB.
addImm(Addr.getOffset());
425 if (Addr.isRegBase())
426 MIB.
addReg(Addr.getReg());
433bool WebAssemblyFastISel::emitLoad(
Register ResultReg,
unsigned Opc,
434 const LoadInst *
Load) {
436 if (!computeAddress(
Load->getPointerOperand(), Addr))
439 materializeLoadStoreOperands(Addr);
441 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg);
442 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(
Load));
447unsigned WebAssemblyFastISel::maskI1Value(
unsigned Reg,
const Value *
V) {
448 return zeroExtendToI32(
Reg,
V, MVT::i1);
451unsigned WebAssemblyFastISel::getRegForI1Value(
const Value *
V,
452 const BasicBlock *BB,
456 if (ICmp->isEquality() &&
C->isZero() &&
C->getType()->isIntegerTy(32) &&
457 ICmp->getParent() == BB) {
458 Not = ICmp->isTrueWhenEqual();
459 return getRegForValue(ICmp->getOperand(0));
466 return maskI1Value(
Reg,
V);
469unsigned WebAssemblyFastISel::zeroExtendToI32(
unsigned Reg,
const Value *
V,
480 return copyValue(
Reg);
486 return copyValue(
Reg);
491 Register Imm = createResultReg(&WebAssembly::I32RegClass);
492 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
493 TII.get(WebAssembly::CONST_I32),
Imm)
497 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::AND_I32),
505unsigned WebAssemblyFastISel::signExtendToI32(
unsigned Reg,
const Value *
V,
516 return copyValue(
Reg);
522 if (From == MVT::i8 || From == MVT::i16) {
524 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
525 TII.get(From == MVT::i16 ? WebAssembly::I32_EXTEND16_S_I32
526 : WebAssembly::I32_EXTEND8_S_I32),
533 Register Imm = createResultReg(&WebAssembly::I32RegClass);
534 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
535 TII.get(WebAssembly::CONST_I32),
Imm)
536 .
addImm(32 - MVT(From).getSizeInBits());
538 Register Left = createResultReg(&WebAssembly::I32RegClass);
539 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::SHL_I32),
545 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
546 TII.get(WebAssembly::SHR_S_I32),
Right)
553unsigned WebAssemblyFastISel::zeroExtend(
unsigned Reg,
const Value *
V,
556 if (To == MVT::i64) {
557 if (From == MVT::i64)
558 return copyValue(
Reg);
560 Reg = zeroExtendToI32(
Reg,
V, From);
563 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
564 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
570 return zeroExtendToI32(
Reg,
V, From);
575unsigned WebAssemblyFastISel::signExtend(
unsigned Reg,
const Value *
V,
578 if (To == MVT::i64) {
579 if (From == MVT::i64)
580 return copyValue(
Reg);
588 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
589 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
593 Result = createResultReg(&WebAssembly::I64RegClass);
595 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
596 TII.get(From == MVT::i8 ? WebAssembly::I64_EXTEND8_S_I64
597 : WebAssembly::I64_EXTEND16_S_I64),
603 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
604 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
612 Reg = signExtendToI32(
Reg,
V, From);
616 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
617 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
623 return signExtendToI32(
Reg,
V, From);
628unsigned WebAssemblyFastISel::getRegForUnsignedValue(
const Value *
V) {
636 return zeroExtend(VReg,
V, From, To);
639unsigned WebAssemblyFastISel::getRegForSignedValue(
const Value *
V) {
647 return signExtend(VReg,
V, From, To);
650unsigned WebAssemblyFastISel::getRegForPromotedValue(
const Value *
V,
652 return IsSigned ? getRegForSignedValue(
V) : getRegForUnsignedValue(
V);
655unsigned WebAssemblyFastISel::notValue(
unsigned Reg) {
658 Register NotReg = createResultReg(&WebAssembly::I32RegClass);
659 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::EQZ_I32),
665unsigned WebAssemblyFastISel::copyValue(
unsigned Reg) {
667 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::COPY),
673Register WebAssemblyFastISel::fastMaterializeAlloca(
const AllocaInst *AI) {
674 auto SI = FuncInfo.StaticAllocaMap.find(AI);
676 if (SI != FuncInfo.StaticAllocaMap.end()) {
678 createResultReg(
Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
679 : &WebAssembly::I32RegClass);
681 Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
682 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
690Register WebAssemblyFastISel::fastMaterializeConstant(
const Constant *
C) {
694 if (GV->isThreadLocal())
697 createResultReg(
Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
698 : &WebAssembly::I32RegClass);
699 unsigned Opc =
Subtarget->hasAddr64() ? WebAssembly::CONST_I64
700 : WebAssembly::CONST_I32;
701 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
710bool WebAssemblyFastISel::fastLowerArguments() {
711 if (!FuncInfo.CanLowerReturn)
718 if (FuncInfo.Fn->getCallingConv() == CallingConv::Swift ||
719 FuncInfo.Fn->getCallingConv() == CallingConv::SwiftTail)
723 for (
auto const &Arg :
F->args()) {
724 const AttributeList &
Attrs =
F->getAttributes();
725 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
726 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
727 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
728 Attrs.hasParamAttr(
I, Attribute::SwiftAsync) ||
729 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
730 Attrs.hasParamAttr(
I, Attribute::Nest))
733 Type *ArgTy = Arg.getType();
741 switch (getSimpleType(ArgTy)) {
746 Opc = WebAssembly::ARGUMENT_i32;
747 RC = &WebAssembly::I32RegClass;
750 Opc = WebAssembly::ARGUMENT_i64;
751 RC = &WebAssembly::I64RegClass;
754 Opc = WebAssembly::ARGUMENT_f32;
755 RC = &WebAssembly::F32RegClass;
758 Opc = WebAssembly::ARGUMENT_f64;
759 RC = &WebAssembly::F64RegClass;
762 Opc = WebAssembly::ARGUMENT_v16i8;
763 RC = &WebAssembly::V128RegClass;
766 Opc = WebAssembly::ARGUMENT_v8i16;
767 RC = &WebAssembly::V128RegClass;
770 Opc = WebAssembly::ARGUMENT_v4i32;
771 RC = &WebAssembly::V128RegClass;
774 Opc = WebAssembly::ARGUMENT_v2i64;
775 RC = &WebAssembly::V128RegClass;
778 Opc = WebAssembly::ARGUMENT_v4f32;
779 RC = &WebAssembly::V128RegClass;
782 Opc = WebAssembly::ARGUMENT_v2f64;
783 RC = &WebAssembly::V128RegClass;
786 Opc = WebAssembly::ARGUMENT_funcref;
787 RC = &WebAssembly::FUNCREFRegClass;
790 Opc = WebAssembly::ARGUMENT_externref;
791 RC = &WebAssembly::EXTERNREFRegClass;
794 Opc = WebAssembly::ARGUMENT_exnref;
795 RC = &WebAssembly::EXNREFRegClass;
800 Register ResultReg = createResultReg(RC);
801 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
803 updateValueMap(&Arg, ResultReg);
810 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
811 for (
auto const &Arg :
F->args()) {
814 MFI->clearParamsAndResults();
817 MFI->addParam(ArgTy);
820 if (!
F->getReturnType()->isVoidTy()) {
822 getLegalType(getSimpleType(
F->getReturnType()));
824 MFI->clearParamsAndResults();
827 MFI->addResult(RetTy);
833bool WebAssemblyFastISel::selectCall(
const Instruction *
I) {
842 if (Func &&
Func->isIntrinsic())
849 bool IsDirect =
Func !=
nullptr;
854 unsigned Opc = IsDirect ? WebAssembly::CALL : WebAssembly::CALL_INDIRECT;
855 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
867 ResultReg = createResultReg(&WebAssembly::I32RegClass);
870 ResultReg = createResultReg(&WebAssembly::I64RegClass);
873 ResultReg = createResultReg(&WebAssembly::F32RegClass);
876 ResultReg = createResultReg(&WebAssembly::F64RegClass);
879 ResultReg = createResultReg(&WebAssembly::V128RegClass);
882 ResultReg = createResultReg(&WebAssembly::V128RegClass);
885 ResultReg = createResultReg(&WebAssembly::V128RegClass);
888 ResultReg = createResultReg(&WebAssembly::V128RegClass);
891 ResultReg = createResultReg(&WebAssembly::V128RegClass);
894 ResultReg = createResultReg(&WebAssembly::V128RegClass);
897 ResultReg = createResultReg(&WebAssembly::FUNCREFRegClass);
900 ResultReg = createResultReg(&WebAssembly::EXTERNREFRegClass);
903 ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);
910 SmallVector<unsigned, 8>
Args;
919 if (
Attrs.hasParamAttr(
I, Attribute::ByVal) ||
920 Attrs.hasParamAttr(
I, Attribute::SwiftSelf) ||
921 Attrs.hasParamAttr(
I, Attribute::SwiftError) ||
923 Attrs.hasParamAttr(
I, Attribute::InAlloca) ||
924 Attrs.hasParamAttr(
I, Attribute::Nest))
930 Reg = getRegForSignedValue(
V);
932 Reg = getRegForUnsignedValue(
V);
934 Reg = getRegForValue(
V);
942 unsigned CalleeReg = 0;
949 const Value *FuncrefArg =
nullptr;
951 if (Conv->getIntrinsicID() == Intrinsic::wasm_funcref_to_ptr)
952 FuncrefArg = Conv->getArgOperand(0);
954 const bool IsFuncrefCall = FuncrefArg !=
nullptr;
955 MCSymbolWasm *
Table =
nullptr;
958 if (!IsFuncrefCall) {
960 Table = WebAssembly::getOrCreateFunctionTableSymbol(MF->getContext(),
967 Table = WebAssembly::getOrCreateFuncrefCallTableSymbol(MF->getContext(),
969 CalleeReg = getRegForValue(FuncrefArg);
971 unsigned ZeroReg = createResultReg(&WebAssembly::I32RegClass);
972 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
973 TII.get(WebAssembly::CONST_I32), ZeroReg)
975 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
976 TII.get(WebAssembly::TABLE_SET_FUNCREF))
981 CalleeReg = createResultReg(&WebAssembly::I32RegClass);
982 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
983 TII.get(WebAssembly::CONST_I32), CalleeReg)
988 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc));
991 MIB.
addReg(ResultReg, RegState::Define);
998 if (
Subtarget->hasCallIndirectOverlong()) {
1004 Table->setNoStrip();
1009 for (
unsigned ArgReg : Args)
1015 if (IsFuncrefCall) {
1017 unsigned ZeroReg = createResultReg(&WebAssembly::I32RegClass);
1018 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1019 TII.get(WebAssembly::CONST_I32), ZeroReg)
1021 unsigned NullReg = createResultReg(&WebAssembly::FUNCREFRegClass);
1022 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1023 TII.get(WebAssembly::REF_NULL_FUNCREF), NullReg);
1024 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1025 TII.get(WebAssembly::TABLE_SET_FUNCREF))
1032 updateValueMap(
Call, ResultReg);
1038bool WebAssemblyFastISel::selectSelect(
const Instruction *
I) {
1043 getRegForI1Value(
Select->getCondition(),
I->getParent(), Not);
1060 switch (getSimpleType(
Select->getType())) {
1065 Opc = WebAssembly::SELECT_I32;
1066 RC = &WebAssembly::I32RegClass;
1069 Opc = WebAssembly::SELECT_I64;
1070 RC = &WebAssembly::I64RegClass;
1073 Opc = WebAssembly::SELECT_F32;
1074 RC = &WebAssembly::F32RegClass;
1077 Opc = WebAssembly::SELECT_F64;
1078 RC = &WebAssembly::F64RegClass;
1081 Opc = WebAssembly::SELECT_FUNCREF;
1082 RC = &WebAssembly::FUNCREFRegClass;
1084 case MVT::externref:
1085 Opc = WebAssembly::SELECT_EXTERNREF;
1086 RC = &WebAssembly::EXTERNREFRegClass;
1089 Opc = WebAssembly::SELECT_EXNREF;
1090 RC = &WebAssembly::EXNREFRegClass;
1096 Register ResultReg = createResultReg(RC);
1097 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1102 updateValueMap(
Select, ResultReg);
1106bool WebAssemblyFastISel::selectTrunc(
const Instruction *
I) {
1109 const Value *
Op = Trunc->getOperand(0);
1117 if (From == MVT::i64) {
1119 return copyValue(
Reg);
1121 if (To == MVT::i1 || To == MVT::i8 || To == MVT::i16 || To == MVT::i32) {
1123 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1124 TII.get(WebAssembly::I32_WRAP_I64), Result)
1130 if (From == MVT::i32)
1131 return copyValue(
Reg);
1136 unsigned Reg = Truncate(In);
1140 updateValueMap(Trunc,
Reg);
1144bool WebAssemblyFastISel::selectZExt(
const Instruction *
I) {
1147 const Value *
Op = ZExt->getOperand(0);
1153 unsigned Reg = zeroExtend(In,
Op, From, To);
1157 updateValueMap(ZExt,
Reg);
1161bool WebAssemblyFastISel::selectSExt(
const Instruction *
I) {
1164 const Value *
Op = SExt->getOperand(0);
1170 unsigned Reg = signExtend(In,
Op, From, To);
1174 updateValueMap(SExt,
Reg);
1178bool WebAssemblyFastISel::selectICmp(
const Instruction *
I) {
1185 if (ICmp->getOperand(0)->getType()->isVectorTy())
1188 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
1190 bool IsSigned =
false;
1191 switch (ICmp->getPredicate()) {
1192 case ICmpInst::ICMP_EQ:
1193 Opc =
I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
1195 case ICmpInst::ICMP_NE:
1196 Opc =
I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1198 case ICmpInst::ICMP_UGT:
1199 Opc =
I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1201 case ICmpInst::ICMP_UGE:
1202 Opc =
I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1204 case ICmpInst::ICMP_ULT:
1205 Opc =
I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1207 case ICmpInst::ICMP_ULE:
1208 Opc =
I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1210 case ICmpInst::ICMP_SGT:
1211 Opc =
I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1214 case ICmpInst::ICMP_SGE:
1215 Opc =
I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1218 case ICmpInst::ICMP_SLT:
1219 Opc =
I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1222 case ICmpInst::ICMP_SLE:
1223 Opc =
I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1230 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
1234 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
1238 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1239 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1242 updateValueMap(ICmp, ResultReg);
1246bool WebAssemblyFastISel::selectFCmp(
const Instruction *
I) {
1253 if (FCmp->getOperand(0)->getType()->isVectorTy())
1256 Register LHS = getRegForValue(FCmp->getOperand(0));
1260 Register RHS = getRegForValue(FCmp->getOperand(1));
1264 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1267 switch (FCmp->getPredicate()) {
1268 case FCmpInst::FCMP_OEQ:
1269 Opc =
F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1271 case FCmpInst::FCMP_UNE:
1272 Opc =
F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1274 case FCmpInst::FCMP_OGT:
1275 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1277 case FCmpInst::FCMP_OGE:
1278 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1280 case FCmpInst::FCMP_OLT:
1281 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1283 case FCmpInst::FCMP_OLE:
1284 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1286 case FCmpInst::FCMP_UGT:
1287 Opc =
F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1290 case FCmpInst::FCMP_UGE:
1291 Opc =
F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1294 case FCmpInst::FCMP_ULT:
1295 Opc =
F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1298 case FCmpInst::FCMP_ULE:
1299 Opc =
F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1306 Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
1307 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
1312 ResultReg = notValue(ResultReg);
1314 updateValueMap(FCmp, ResultReg);
1318bool WebAssemblyFastISel::selectBitCast(
const Instruction *
I) {
1333 updateValueMap(
I, In);
1343 assert(Iter->isBitcast());
1344 Iter->setImplicitPhysRegDefsDead();
1345 updateValueMap(
I,
Reg);
1353 return WebAssembly::INSTRUCTION_LIST_END;
1355 return A64 ? WebAssembly::LOAD8_S_I64_A64 : WebAssembly::LOAD8_S_I64_A32;
1357 return A64 ? WebAssembly::LOAD16_S_I64_A64
1358 : WebAssembly::LOAD16_S_I64_A32;
1360 return A64 ? WebAssembly::LOAD32_S_I64_A64
1361 : WebAssembly::LOAD32_S_I64_A32;
1367 return WebAssembly::INSTRUCTION_LIST_END;
1369 return A64 ? WebAssembly::LOAD8_S_I32_A64 : WebAssembly::LOAD8_S_I32_A32;
1371 return A64 ? WebAssembly::LOAD16_S_I32_A64 : WebAssembly::LOAD16_S_I32_A32;
1379 return WebAssembly::INSTRUCTION_LIST_END;
1381 return A64 ? WebAssembly::LOAD8_U_I64_A64 : WebAssembly::LOAD8_U_I64_A32;
1383 return A64 ? WebAssembly::LOAD16_U_I64_A64
1384 : WebAssembly::LOAD16_U_I64_A32;
1386 return A64 ? WebAssembly::LOAD32_U_I64_A64
1387 : WebAssembly::LOAD32_U_I64_A32;
1393 return WebAssembly::INSTRUCTION_LIST_END;
1395 return A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
1397 return A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;
1405 case WebAssembly::I32_EXTEND8_S_I32:
1406 case WebAssembly::I32_EXTEND16_S_I32:
1407 case WebAssembly::I64_EXTEND8_S_I64:
1408 case WebAssembly::I64_EXTEND16_S_I64:
1409 case WebAssembly::I64_EXTEND32_S_I64:
1410 case WebAssembly::I64_EXTEND_S_I32:
1419 case WebAssembly::I32_EXTEND8_S_I32:
1420 case WebAssembly::I32_EXTEND16_S_I32:
1422 case WebAssembly::I64_EXTEND8_S_I64:
1423 case WebAssembly::I64_EXTEND16_S_I64:
1424 case WebAssembly::I64_EXTEND32_S_I64:
1425 case WebAssembly::I64_EXTEND_S_I32:
1432 unsigned Opc =
MI->getOpcode();
1439 return WebAssembly::INSTRUCTION_LIST_END;
1445 unsigned NarrowOpc) {
1446 if (!
MRI.hasOneNonDBGUse(DestReg))
1452 case WebAssembly::I64_EXTEND_U_I32:
1453 OuterUserMI = UserMI;
1455 case WebAssembly::I64_EXTEND_S_I32:
1456 OuterUserMI = UserMI;
1474 unsigned Opc =
MI->getOpcode();
1475 unsigned NewOpc = WebAssembly::INSTRUCTION_LIST_END;
1476 if (
Opc != WebAssembly::SHL_I32)
1479 Register DestReg =
MI->getOperand(0).getReg();
1480 if (!
MRI.hasOneNonDBGUse(DestReg))
1483 UserMI = &*
MRI.use_instr_nodbg_begin(DestReg);
1485 if (UserOpc != WebAssembly::SHR_S_I32)
1493 Register ShlAmtReg =
MI->getOperand(2).getReg();
1498 return MI &&
MI->getOpcode() == WebAssembly::CONST_I32 &&
1499 MI->getOperand(1).getImm() == ExpectedShiftAmt;
1501 if (!IsExpectedConst(ShlAmtDef) || !IsExpectedConst(ShrAmtDef))
1506 if (NarrowOpc == WebAssembly::INSTRUCTION_LIST_END)
1507 return WebAssembly::INSTRUCTION_LIST_END;
1510 OuterUserMI, NarrowOpc);
1518 if (
MI->getOpcode() != WebAssembly::I64_EXTEND_U_I32)
1519 return WebAssembly::INSTRUCTION_LIST_END;
1522 Register DestReg =
MI->getOperand(0).getReg();
1523 if (!
MRI.hasOneNonDBGUse(DestReg))
1524 return WebAssembly::INSTRUCTION_LIST_END;
1526 UserMI = &*
MRI.use_instr_nodbg_begin(DestReg);
1529 return WebAssembly::INSTRUCTION_LIST_END;
1530 case WebAssembly::I64_EXTEND8_S_I64:
1532 return WebAssembly::INSTRUCTION_LIST_END;
1534 case WebAssembly::I64_EXTEND16_S_I64:
1536 return WebAssembly::INSTRUCTION_LIST_END;
1544 if (
MI->getOpcode() != WebAssembly::COPY)
1545 return WebAssembly::INSTRUCTION_LIST_END;
1549 return WebAssembly::INSTRUCTION_LIST_END;
1551 Register CopyDst =
MI->getOperand(0).getReg();
1552 if (!
MRI.hasOneNonDBGUse(CopyDst))
1553 return WebAssembly::INSTRUCTION_LIST_END;
1555 OuterUserMI = &*
MRI.use_instr_nodbg_begin(CopyDst);
1558 return WebAssembly::INSTRUCTION_LIST_END;
1559 case WebAssembly::I64_EXTEND_U_I32:
1561 case WebAssembly::I64_EXTEND_S_I32:
1569 if (
MI->getOpcode() != WebAssembly::AND_I32 &&
1570 MI->getOpcode() != WebAssembly::AND_I64)
1571 return WebAssembly::INSTRUCTION_LIST_END;
1574 bool IsConstant =
false;
1575 for (
unsigned I = 1;
I <= 2; ++
I) {
1578 if (
DefMI && (
DefMI->getOpcode() == WebAssembly::CONST_I32 ||
1579 DefMI->getOpcode() == WebAssembly::CONST_I64)) {
1580 Mask =
DefMI->getOperand(1).getImm();
1587 return WebAssembly::INSTRUCTION_LIST_END;
1591 return WebAssembly::INSTRUCTION_LIST_END;
1593 if (
MI->getOpcode() == WebAssembly::AND_I64)
1597 if (NarrowOpc == WebAssembly::INSTRUCTION_LIST_END)
1598 return WebAssembly::INSTRUCTION_LIST_END;
1601 OuterUserMI, NarrowOpc);
1604bool WebAssemblyFastISel::tryToFoldLoadIntoMI(MachineInstr *
MI,
unsigned OpNo,
1605 const LoadInst *LI) {
1609 MachineInstr *UserMI =
nullptr;
1610 MachineInstr *OuterUserMI =
nullptr;
1611 unsigned NewOpc = WebAssembly::INSTRUCTION_LIST_END;
1613 WebAssembly::INSTRUCTION_LIST_END) {
1615 }
else if ((NewOpc =
1617 WebAssembly::INSTRUCTION_LIST_END) {
1620 WebAssembly::INSTRUCTION_LIST_END) {
1622 :
MI->getOperand(0).getReg();
1624 WebAssembly::INSTRUCTION_LIST_END) {
1625 ResultReg =
MI->getOperand(0).getReg();
1626 }
else if ((NewOpc =
1628 WebAssembly::INSTRUCTION_LIST_END) {
1635 if (!
emitLoad(ResultReg, NewOpc, LI))
1640 removeDeadCode(OuterIter, std::next(OuterIter));
1645 removeDeadCode(UserIter, std::next(UserIter));
1649 removeDeadCode(Iter, std::next(Iter));
1653bool WebAssemblyFastISel::selectLoad(
const Instruction *
I) {
1655 if (
Load->isAtomic())
1657 if (!WebAssembly::isDefaultAddressSpace(
Load->getPointerAddressSpace()))
1659 if (!
Subtarget->hasSIMD128() &&
Load->getType()->isVectorTy())
1667 switch (getSimpleType(
Load->getType())) {
1670 Opc = A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
1671 RC = &WebAssembly::I32RegClass;
1674 Opc = A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;
1675 RC = &WebAssembly::I32RegClass;
1678 Opc = A64 ? WebAssembly::LOAD_I32_A64 : WebAssembly::LOAD_I32_A32;
1679 RC = &WebAssembly::I32RegClass;
1682 Opc = A64 ? WebAssembly::LOAD_I64_A64 : WebAssembly::LOAD_I64_A32;
1683 RC = &WebAssembly::I64RegClass;
1686 Opc = A64 ? WebAssembly::LOAD_F32_A64 : WebAssembly::LOAD_F32_A32;
1687 RC = &WebAssembly::F32RegClass;
1690 Opc = A64 ? WebAssembly::LOAD_F64_A64 : WebAssembly::LOAD_F64_A32;
1691 RC = &WebAssembly::F64RegClass;
1697 Register ResultReg = createResultReg(RC);
1701 updateValueMap(
Load, ResultReg);
1705bool WebAssemblyFastISel::selectStore(
const Instruction *
I) {
1707 if (
Store->isAtomic())
1709 if (!WebAssembly::isDefaultAddressSpace(
Store->getPointerAddressSpace()))
1712 Store->getValueOperand()->getType()->isVectorTy())
1716 if (!computeAddress(
Store->getPointerOperand(), Addr))
1720 bool VTIsi1 =
false;
1722 switch (getSimpleType(
Store->getValueOperand()->getType())) {
1727 Opc = A64 ? WebAssembly::STORE8_I32_A64 : WebAssembly::STORE8_I32_A32;
1730 Opc = A64 ? WebAssembly::STORE16_I32_A64 : WebAssembly::STORE16_I32_A32;
1733 Opc = A64 ? WebAssembly::STORE_I32_A64 : WebAssembly::STORE_I32_A32;
1736 Opc = A64 ? WebAssembly::STORE_I64_A64 : WebAssembly::STORE_I64_A32;
1739 Opc = A64 ? WebAssembly::STORE_F32_A64 : WebAssembly::STORE_F32_A32;
1742 Opc = A64 ? WebAssembly::STORE_F64_A64 : WebAssembly::STORE_F64_A32;
1748 materializeLoadStoreOperands(Addr);
1750 Register ValueReg = getRegForValue(
Store->getValueOperand());
1754 ValueReg = maskI1Value(ValueReg,
Store->getValueOperand());
1756 auto MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc));
1758 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(
Store));
1764bool WebAssemblyFastISel::selectCondBr(
const Instruction *
I) {
1767 MachineBasicBlock *
TBB = FuncInfo.getMBB(Br->getSuccessor(0));
1768 MachineBasicBlock *FBB = FuncInfo.getMBB(Br->getSuccessor(1));
1771 unsigned CondReg = getRegForI1Value(Br->getCondition(), Br->getParent(), Not);
1775 unsigned Opc = WebAssembly::BR_IF;
1777 Opc = WebAssembly::BR_UNLESS;
1779 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc))
1783 finishCondBranch(Br->getParent(),
TBB, FBB);
1787bool WebAssemblyFastISel::selectRet(
const Instruction *
I) {
1788 if (!FuncInfo.CanLowerReturn)
1793 if (Ret->getNumOperands() == 0) {
1794 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1795 TII.get(WebAssembly::RETURN));
1800 if (Ret->getNumOperands() > 1)
1803 Value *RV = Ret->getOperand(0);
1807 switch (getSimpleType(RV->
getType())) {
1822 case MVT::externref:
1830 if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::SExt))
1831 Reg = getRegForSignedValue(RV);
1832 else if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::ZExt))
1833 Reg = getRegForUnsignedValue(RV);
1835 Reg = getRegForValue(RV);
1840 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(WebAssembly::RETURN))
1845bool WebAssemblyFastISel::selectUnreachable(
const Instruction *
I) {
1846 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1847 TII.get(WebAssembly::UNREACHABLE));
1851bool WebAssemblyFastISel::fastSelectInstruction(
const Instruction *
I) {
1852 switch (
I->getOpcode()) {
1853 case Instruction::Call:
1857 case Instruction::Select:
1858 return selectSelect(
I);
1859 case Instruction::Trunc:
1860 return selectTrunc(
I);
1861 case Instruction::ZExt:
1862 return selectZExt(
I);
1863 case Instruction::SExt:
1864 return selectSExt(
I);
1865 case Instruction::ICmp:
1866 return selectICmp(
I);
1867 case Instruction::FCmp:
1868 return selectFCmp(
I);
1869 case Instruction::BitCast:
1870 return selectBitCast(
I);
1871 case Instruction::Load:
1872 return selectLoad(
I);
1873 case Instruction::Store:
1874 return selectStore(
I);
1875 case Instruction::CondBr:
1876 return selectCondBr(
I);
1877 case Instruction::Ret:
1878 return selectRet(
I);
1879 case Instruction::Unreachable:
1880 return selectUnreachable(
I);
1886 return selectOperator(
I,
I->getOpcode());
1893 return new WebAssemblyFastISel(FuncInfo, LibInfo, LibcallLowering);
MachineInstrBuilder MachineInstrBuilder & DefMI
const AArch64Subtarget & Subtarget
const TargetLowering & TLI
static void emitLoad(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator Pos, const TargetInstrInfo &TII, unsigned Reg1, unsigned Reg2, int Offset, bool IsPostDec)
Emit a load-pair instruction for frame-destroy.
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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 ...
Promote Memory to Register
static MCRegister getReg(const MCDisassembler *D, unsigned RC, unsigned RegNo)
MachineRegisterInfo & MRI
const SmallVectorImpl< MachineOperand > MachineBasicBlock * TBB
static bool isFoldableSExtOpcode(unsigned Opc)
static unsigned getSExtLoadOpcode(unsigned LoadSize, bool I64Result, bool A64)
static bool isI64SExtResult(unsigned Opc)
static unsigned matchFoldableCopyToI64Ext(MachineInstr *MI, const LoadInst *LI, MachineRegisterInfo &MRI, bool A64, MachineInstr *&OuterUserMI)
static unsigned matchFoldableSExtFromPromotedI32(MachineInstr *MI, const LoadInst *LI, MachineRegisterInfo &MRI, bool A64, MachineInstr *&UserMI)
static unsigned getZExtLoadOpcode(unsigned LoadSize, bool I64Result, bool A64)
static unsigned matchFoldableShift(MachineInstr *MI, const LoadInst *LI, MachineRegisterInfo &MRI, bool A64, MachineInstr *&UserMI, MachineInstr *&OuterUserMI)
Matches a sign-extension pattern (shl + shr_s) to fold it into a signed load.
static unsigned getFoldedI64LoadOpcode(Register DestReg, const LoadInst *LI, MachineRegisterInfo &MRI, bool A64, MachineInstr *&OuterUserMI, unsigned NarrowOpc)
static unsigned getFoldedLoadOpcode(MachineInstr *MI, MachineRegisterInfo &MRI, const LoadInst *LI, bool A64)
static unsigned matchFoldableAnd(MachineInstr *MI, const LoadInst *LI, MachineRegisterInfo &MRI, bool A64, MachineInstr *&OuterUserMI)
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 contains the declaration of the WebAssembly-specific utility functions.
an instruction to allocate memory on the stack
LLVM Basic Block Representation.
bool isInlineAsm() const
Check if this call is an inline asm statement.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
CallingConv::ID getCallingConv() const
LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
Value * getCalledOperand() const
Value * getArgOperand(unsigned i) const
FunctionType * getFunctionType() const
unsigned arg_size() const
AttributeList getAttributes() const
Return the attributes for this call.
bool isMustTailCall() const
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 ...
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.
Tracks which library functions to use for a particular subtarget or function.
An instruction for reading from memory.
@ INVALID_SIMPLE_VALUE_TYPE
MachineInstrBundleIterator< MachineInstr > iterator
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
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 & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
A description of a memory reference used in the backend.
Register getReg() const
getReg - Returns the register number.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
void addLiveIn(MCRegister Reg, Register vreg=Register())
addLiveIn - Add the specified register as a live-in.
Wrapper class representing virtual and physical registers.
TypeSize getElementOffset(unsigned Idx) const
Provides information about what library functions are available for the current target.
EVT getValueType(const DataLayout &DL, Type *Ty, bool AllowUnknown=false) const
Return the EVT corresponding to this LLVM type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
bool isPositionIndependent() const
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM_ABI unsigned getIntegerBitWidth() const
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_ABI TypeSize getPrimitiveSizeInBits() const LLVM_READONLY
Return the basic size of this type if it is a primitive type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
Not(const Pred &P) -> Not< Pred >
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering)
@ User
could "use" a pointer
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.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI void diagnoseDontCall(const CallInst &CI)
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
gep_type_iterator gep_type_end(const User *GEP)
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
generic_gep_type_iterator<> gep_type_iterator
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
gep_type_iterator gep_type_begin(const User *GEP)
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
MCRegisterClass TargetRegisterClass
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.