37#include "llvm/IR/IntrinsicsX86.h"
48class X86FastISel final :
public FastISel {
51 const X86Subtarget *Subtarget;
54 explicit X86FastISel(FunctionLoweringInfo &funcInfo,
55 const TargetLibraryInfo *libInfo,
56 const LibcallLoweringInfo *libcallLowering)
57 : FastISel(funcInfo, libInfo, libcallLowering) {
61 bool fastSelectInstruction(
const Instruction *
I)
override;
67 bool tryToFoldLoadIntoMI(MachineInstr *
MI,
unsigned OpNo,
68 const LoadInst *LI)
override;
70 bool fastLowerArguments()
override;
71 bool fastLowerCall(CallLoweringInfo &CLI)
override;
72 bool fastLowerIntrinsicCall(
const IntrinsicInst *
II)
override;
74#include "X86GenFastISel.inc"
80 bool X86FastEmitLoad(MVT VT, X86AddressMode &AM, MachineMemOperand *MMO,
81 Register &ResultReg,
unsigned Alignment = 1);
83 bool X86FastEmitStore(EVT VT,
const Value *Val, X86AddressMode &AM,
84 MachineMemOperand *MMO =
nullptr,
bool Aligned =
false);
85 bool X86FastEmitStore(EVT VT,
Register ValReg, X86AddressMode &AM,
86 MachineMemOperand *MMO =
nullptr,
bool Aligned =
false);
92 bool X86SelectCallAddress(
const Value *V, X86AddressMode &AM);
94 bool X86SelectLoad(
const Instruction *
I);
96 bool X86SelectStore(
const Instruction *
I);
98 bool X86SelectRet(
const Instruction *
I);
100 bool X86SelectCmp(
const Instruction *
I);
102 bool X86SelectZExt(
const Instruction *
I);
104 bool X86SelectSExt(
const Instruction *
I);
106 bool X86SelectBranch(
const Instruction *
I);
108 bool X86SelectShift(
const Instruction *
I);
110 bool X86SelectDivRem(
const Instruction *
I);
112 bool X86FastEmitCMoveSelect(MVT RetVT,
const Instruction *
I);
114 bool X86FastEmitSSESelect(MVT RetVT,
const Instruction *
I);
116 bool X86FastEmitPseudoSelect(MVT RetVT,
const Instruction *
I);
118 bool X86SelectSelect(
const Instruction *
I);
120 bool X86SelectTrunc(
const Instruction *
I);
122 bool X86SelectFPExtOrFPTrunc(
const Instruction *
I,
unsigned Opc,
123 const TargetRegisterClass *RC);
125 bool X86SelectFPExt(
const Instruction *
I);
126 bool X86SelectFPTrunc(
const Instruction *
I);
127 bool X86SelectSIToFP(
const Instruction *
I);
128 bool X86SelectUIToFP(
const Instruction *
I);
129 bool X86SelectIntToFP(
const Instruction *
I,
bool IsSigned);
130 bool X86SelectBitCast(
const Instruction *
I);
132 const X86InstrInfo *getInstrInfo()
const {
133 return Subtarget->getInstrInfo();
135 const X86TargetMachine *getTargetMachine()
const {
136 return static_cast<const X86TargetMachine *
>(&TM);
139 bool handleConstantAddresses(
const Value *V, X86AddressMode &AM);
141 Register X86MaterializeInt(
const ConstantInt *CI, MVT VT);
142 Register X86MaterializeFP(
const ConstantFP *CFP, MVT VT);
143 Register X86MaterializeGV(
const GlobalValue *GV, MVT VT);
144 Register fastMaterializeConstant(
const Constant *
C)
override;
146 Register fastMaterializeAlloca(
const AllocaInst *
C)
override;
148 Register fastMaterializeFloatZero(
const ConstantFP *CF)
override;
152 bool isScalarFPTypeInSSEReg(EVT VT)
const {
153 return (VT == MVT::f64 && Subtarget->hasSSE2()) ||
154 (VT == MVT::f32 && Subtarget->hasSSE1()) || VT == MVT::f16;
157 bool isTypeLegal(
Type *Ty, MVT &VT,
bool AllowI1 =
false);
159 bool IsMemcpySmall(uint64_t Len);
161 bool TryEmitSmallMemcpy(X86AddressMode DestAM,
162 X86AddressMode SrcAM, uint64_t Len);
164 bool foldX86XALUIntrinsic(
X86::CondCode &CC,
const Instruction *
I,
167 const MachineInstrBuilder &
addFullAddress(
const MachineInstrBuilder &MIB,
170 Register fastEmitInst_rrrr(
unsigned MachineInstOpcode,
171 const TargetRegisterClass *RC,
Register Op0,
177static std::pair<unsigned, bool>
180 bool NeedSwap =
false;
209 return std::make_pair(CC, NeedSwap);
223 return ::addFullAddress(MIB, AM);
228bool X86FastISel::foldX86XALUIntrinsic(
X86::CondCode &CC,
const Instruction *
I,
242 if (!isTypeLegal(RetTy, RetVT))
245 if (RetVT != MVT::i32 && RetVT != MVT::i64)
249 switch (
II->getIntrinsicID()) {
250 default:
return false;
251 case Intrinsic::sadd_with_overflow:
252 case Intrinsic::ssub_with_overflow:
253 case Intrinsic::smul_with_overflow:
254 case Intrinsic::umul_with_overflow: TmpCC =
X86::COND_O;
break;
255 case Intrinsic::uadd_with_overflow:
256 case Intrinsic::usub_with_overflow: TmpCC =
X86::COND_B;
break;
260 if (
II->getParent() !=
I->getParent())
266 for (
auto Itr = std::prev(Start); Itr != End; --Itr) {
274 if (EVI->getAggregateOperand() !=
II)
280 auto HasPhis = [](
const BasicBlock *Succ) {
return !Succ->phis().empty(); };
293bool X86FastISel::isTypeLegal(
Type *Ty, MVT &VT,
bool AllowI1) {
294 EVT evt = TLI.getValueType(
DL, Ty,
true);
295 if (evt == MVT::Other || !evt.
isSimple())
302 if (VT == MVT::f64 && !Subtarget->hasSSE2())
304 if (VT == MVT::f32 && !Subtarget->hasSSE1())
313 return (AllowI1 && VT == MVT::i1) || TLI.isTypeLegal(VT);
319bool X86FastISel::X86FastEmitLoad(MVT VT, X86AddressMode &AM,
320 MachineMemOperand *MMO,
Register &ResultReg,
321 unsigned Alignment) {
322 bool HasSSE1 = Subtarget->hasSSE1();
323 bool HasSSE2 = Subtarget->hasSSE2();
324 bool HasSSE41 = Subtarget->hasSSE41();
325 bool HasAVX = Subtarget->hasAVX();
326 bool HasAVX2 = Subtarget->hasAVX2();
327 bool HasAVX512 = Subtarget->hasAVX512();
328 bool HasVLX = Subtarget->hasVLX();
338 default:
return false;
353 Opc = HasAVX512 ? X86::VMOVSSZrm_alt
354 : HasAVX ? X86::VMOVSSrm_alt
355 : HasSSE1 ? X86::MOVSSrm_alt
359 Opc = HasAVX512 ? X86::VMOVSDZrm_alt
360 : HasAVX ? X86::VMOVSDrm_alt
361 : HasSSE2 ? X86::MOVSDrm_alt
368 if (IsNonTemporal && Alignment >= 16 && HasSSE41)
369 Opc = HasVLX ? X86::VMOVNTDQAZ128rm :
370 HasAVX ? X86::VMOVNTDQArm : X86::MOVNTDQArm;
371 else if (Alignment >= 16)
372 Opc = HasVLX ? X86::VMOVAPSZ128rm :
373 HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm;
375 Opc = HasVLX ? X86::VMOVUPSZ128rm :
376 HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm;
379 if (IsNonTemporal && Alignment >= 16 && HasSSE41)
380 Opc = HasVLX ? X86::VMOVNTDQAZ128rm :
381 HasAVX ? X86::VMOVNTDQArm : X86::MOVNTDQArm;
382 else if (Alignment >= 16)
383 Opc = HasVLX ? X86::VMOVAPDZ128rm :
384 HasAVX ? X86::VMOVAPDrm : X86::MOVAPDrm;
386 Opc = HasVLX ? X86::VMOVUPDZ128rm :
387 HasAVX ? X86::VMOVUPDrm : X86::MOVUPDrm;
393 if (IsNonTemporal && Alignment >= 16 && HasSSE41)
394 Opc = HasVLX ? X86::VMOVNTDQAZ128rm :
395 HasAVX ? X86::VMOVNTDQArm : X86::MOVNTDQArm;
396 else if (Alignment >= 16)
397 Opc = HasVLX ? X86::VMOVDQA64Z128rm :
398 HasAVX ? X86::VMOVDQArm : X86::MOVDQArm;
400 Opc = HasVLX ? X86::VMOVDQU64Z128rm :
401 HasAVX ? X86::VMOVDQUrm : X86::MOVDQUrm;
405 if (IsNonTemporal && Alignment >= 32 && HasAVX2)
406 Opc = HasVLX ? X86::VMOVNTDQAZ256rm : X86::VMOVNTDQAYrm;
407 else if (IsNonTemporal && Alignment >= 16)
409 else if (Alignment >= 32)
410 Opc = HasVLX ? X86::VMOVAPSZ256rm : X86::VMOVAPSYrm;
412 Opc = HasVLX ? X86::VMOVUPSZ256rm : X86::VMOVUPSYrm;
416 if (IsNonTemporal && Alignment >= 32 && HasAVX2)
417 Opc = HasVLX ? X86::VMOVNTDQAZ256rm : X86::VMOVNTDQAYrm;
418 else if (IsNonTemporal && Alignment >= 16)
420 else if (Alignment >= 32)
421 Opc = HasVLX ? X86::VMOVAPDZ256rm : X86::VMOVAPDYrm;
423 Opc = HasVLX ? X86::VMOVUPDZ256rm : X86::VMOVUPDYrm;
430 if (IsNonTemporal && Alignment >= 32 && HasAVX2)
431 Opc = HasVLX ? X86::VMOVNTDQAZ256rm : X86::VMOVNTDQAYrm;
432 else if (IsNonTemporal && Alignment >= 16)
434 else if (Alignment >= 32)
435 Opc = HasVLX ? X86::VMOVDQA64Z256rm : X86::VMOVDQAYrm;
437 Opc = HasVLX ? X86::VMOVDQU64Z256rm : X86::VMOVDQUYrm;
441 if (IsNonTemporal && Alignment >= 64)
442 Opc = X86::VMOVNTDQAZrm;
444 Opc = (Alignment >= 64) ? X86::VMOVAPSZrm :
X86::VMOVUPSZrm;
448 if (IsNonTemporal && Alignment >= 64)
449 Opc = X86::VMOVNTDQAZrm;
451 Opc = (Alignment >= 64) ? X86::VMOVAPDZrm :
X86::VMOVUPDZrm;
460 if (IsNonTemporal && Alignment >= 64)
461 Opc = X86::VMOVNTDQAZrm;
463 Opc = (Alignment >= 64) ? X86::VMOVDQA64Zrm :
X86::VMOVDQU64Zrm;
467 const TargetRegisterClass *RC = TLI.getRegClassFor(VT);
469 ResultReg = createResultReg(RC);
470 MachineInstrBuilder MIB =
471 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg);
482bool X86FastISel::X86FastEmitStore(EVT VT,
Register ValReg, X86AddressMode &AM,
483 MachineMemOperand *MMO,
bool Aligned) {
484 bool HasSSE1 = Subtarget->hasSSE1();
485 bool HasSSE2 = Subtarget->hasSSE2();
486 bool HasSSE4A = Subtarget->hasSSE4A();
487 bool HasAVX = Subtarget->hasAVX();
488 bool HasAVX512 = Subtarget->hasAVX512();
489 bool HasVLX = Subtarget->hasVLX();
496 default:
return false;
499 Register AndResult = createResultReg(&X86::GR8RegClass);
500 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
501 TII.get(X86::AND8ri), AndResult)
506 case MVT::i8:
Opc = X86::MOV8mr;
break;
507 case MVT::i16:
Opc = X86::MOV16mr;
break;
509 Opc = (IsNonTemporal && HasSSE2) ? X86::MOVNTImr :
X86::MOV32mr;
513 Opc = (IsNonTemporal && HasSSE2) ? X86::MOVNTI_64mr :
X86::MOV64mr;
517 if (IsNonTemporal && HasSSE4A)
520 Opc = HasAVX512 ? X86::VMOVSSZmr :
521 HasAVX ? X86::VMOVSSmr : X86::MOVSSmr;
527 if (IsNonTemporal && HasSSE4A)
530 Opc = HasAVX512 ? X86::VMOVSDZmr :
531 HasAVX ? X86::VMOVSDmr : X86::MOVSDmr;
536 Opc = (IsNonTemporal && HasSSE1) ? X86::MMX_MOVNTQmr :
X86::MMX_MOVQ64mr;
541 Opc = HasVLX ? X86::VMOVNTPSZ128mr :
542 HasAVX ? X86::VMOVNTPSmr : X86::MOVNTPSmr;
544 Opc = HasVLX ? X86::VMOVAPSZ128mr :
545 HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr;
547 Opc = HasVLX ? X86::VMOVUPSZ128mr :
548 HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr;
553 Opc = HasVLX ? X86::VMOVNTPDZ128mr :
554 HasAVX ? X86::VMOVNTPDmr : X86::MOVNTPDmr;
556 Opc = HasVLX ? X86::VMOVAPDZ128mr :
557 HasAVX ? X86::VMOVAPDmr : X86::MOVAPDmr;
559 Opc = HasVLX ? X86::VMOVUPDZ128mr :
560 HasAVX ? X86::VMOVUPDmr : X86::MOVUPDmr;
568 Opc = HasVLX ? X86::VMOVNTDQZ128mr :
569 HasAVX ? X86::VMOVNTDQmr : X86::MOVNTDQmr;
571 Opc = HasVLX ? X86::VMOVDQA64Z128mr :
572 HasAVX ? X86::VMOVDQAmr : X86::MOVDQAmr;
574 Opc = HasVLX ? X86::VMOVDQU64Z128mr :
575 HasAVX ? X86::VMOVDQUmr : X86::MOVDQUmr;
581 Opc = HasVLX ? X86::VMOVNTPSZ256mr : X86::VMOVNTPSYmr;
583 Opc = HasVLX ? X86::VMOVAPSZ256mr : X86::VMOVAPSYmr;
585 Opc = HasVLX ? X86::VMOVUPSZ256mr : X86::VMOVUPSYmr;
591 Opc = HasVLX ? X86::VMOVNTPDZ256mr : X86::VMOVNTPDYmr;
593 Opc = HasVLX ? X86::VMOVAPDZ256mr : X86::VMOVAPDYmr;
595 Opc = HasVLX ? X86::VMOVUPDZ256mr : X86::VMOVUPDYmr;
604 Opc = HasVLX ? X86::VMOVNTDQZ256mr : X86::VMOVNTDQYmr;
606 Opc = HasVLX ? X86::VMOVDQA64Z256mr : X86::VMOVDQAYmr;
608 Opc = HasVLX ? X86::VMOVDQU64Z256mr : X86::VMOVDQUYmr;
613 Opc = IsNonTemporal ? X86::VMOVNTPSZmr : X86::VMOVAPSZmr;
615 Opc = X86::VMOVUPSZmr;
620 Opc = IsNonTemporal ? X86::VMOVNTPDZmr : X86::VMOVAPDZmr;
622 Opc = X86::VMOVUPDZmr;
632 Opc = IsNonTemporal ? X86::VMOVNTDQZmr : X86::VMOVDQA64Zmr;
634 Opc = X86::VMOVDQU64Zmr;
646 MachineInstrBuilder MIB =
647 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
Desc);
655bool X86FastISel::X86FastEmitStore(EVT VT,
const Value *Val,
657 MachineMemOperand *MMO,
bool Aligned) {
671 case MVT::i8:
Opc = X86::MOV8mi;
break;
672 case MVT::i16:
Opc = X86::MOV16mi;
break;
673 case MVT::i32:
Opc = X86::MOV32mi;
break;
677 Opc = X86::MOV64mi32;
682 MachineInstrBuilder MIB =
683 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc));
685 : CI->getZExtValue());
692 Register ValReg = getRegForValue(Val);
696 return X86FastEmitStore(VT, ValReg, AM, MMO,
Aligned);
712bool X86FastISel::handleConstantAddresses(
const Value *V, X86AddressMode &AM) {
721 if (TM.isLargeGlobalValue(GV))
725 if (GV->isThreadLocal())
729 if (GV->isAbsoluteSymbolRef())
735 if (!Subtarget->isPICStyleRIPRel() ||
741 unsigned char GVFlags = Subtarget->classifyGlobalReference(GV);
746 AM.
Base.
Reg = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
752 if (Subtarget->isPICStyleRIPRel()) {
764 auto I = LocalValueMap.find(V);
766 if (
I != LocalValueMap.end() &&
I->second) {
771 const TargetRegisterClass *RC =
nullptr;
772 X86AddressMode StubAM;
778 SavePoint SaveInsertPt = enterLocalValueArea();
780 if (TLI.getPointerTy(
DL) == MVT::i64) {
782 RC = &X86::GR64RegClass;
785 RC = &X86::GR32RegClass;
792 LoadReg = createResultReg(RC);
793 MachineInstrBuilder LoadMI =
794 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), LoadReg);
798 leaveLocalValueArea(SaveInsertPt);
801 LocalValueMap[
V] = LoadReg;
813 if (!AM.
GV || !Subtarget->isPICStyleRIPRel()) {
815 AM.
Base.
Reg = getRegForValue(V);
830bool X86FastISel::X86SelectAddress(
const Value *V, X86AddressMode &AM) {
833 const User *
U =
nullptr;
834 unsigned Opcode = Instruction::UserOp1;
839 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(V)) ||
840 FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
841 Opcode =
I->getOpcode();
845 Opcode =
C->getOpcode();
850 if (Ty->getAddressSpace() > 255)
857 case Instruction::BitCast:
861 case Instruction::IntToPtr:
863 if (TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
864 TLI.getPointerTy(
DL))
868 case Instruction::PtrToInt:
870 if (TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
874 case Instruction::Alloca: {
877 auto SI = FuncInfo.StaticAllocaMap.find(
A);
878 if (SI != FuncInfo.StaticAllocaMap.end()) {
886 case Instruction::Add: {
889 uint64_t Disp = (int32_t)AM.
Disp + (uint64_t)CI->getSExtValue();
892 AM.
Disp = (uint32_t)Disp;
899 case Instruction::GetElementPtr: {
900 X86AddressMode SavedAM = AM;
903 uint64_t Disp = (int32_t)AM.
Disp;
905 unsigned Scale = AM.
Scale;
906 MVT PtrVT = TLI.getValueType(
DL,
U->getType()).getSimpleVT();
912 i != e; ++i, ++GTI) {
915 const StructLayout *SL =
DL.getStructLayout(STy);
926 Disp += CI->getSExtValue() * S;
929 if (canFoldAddIntoGEP(U,
Op)) {
938 if (!IndexReg && (!AM.
GV || !Subtarget->isPICStyleRIPRel()) &&
939 (S == 1 || S == 2 || S == 4 || S == 8)) {
942 IndexReg = getRegForGEPIndex(PtrVT,
Op);
948 goto unsupported_gep;
958 AM.
Disp = (uint32_t)Disp;
961 if (
const GetElementPtrInst *
GEP =
976 if (handleConstantAddresses(
I, AM))
986 return handleConstantAddresses(V, AM);
991bool X86FastISel::X86SelectCallAddress(
const Value *V, X86AddressMode &AM) {
992 const User *
U =
nullptr;
993 unsigned Opcode = Instruction::UserOp1;
1020 Opcode =
I->getOpcode();
1022 InMBB =
I->getParent() == FuncInfo.MBB->getBasicBlock();
1024 Opcode =
C->getOpcode();
1030 case Instruction::BitCast:
1033 return X86SelectCallAddress(
U->getOperand(0), AM);
1036 case Instruction::IntToPtr:
1039 TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
1040 TLI.getPointerTy(
DL))
1041 return X86SelectCallAddress(
U->getOperand(0), AM);
1044 case Instruction::PtrToInt:
1046 if (InMBB && TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
1047 return X86SelectCallAddress(
U->getOperand(0), AM);
1059 if (Subtarget->isPICStyleRIPRel() &&
1065 if (GVar->isThreadLocal())
1074 if (Subtarget->isPICStyleRIPRel()) {
1080 AM.
GVOpFlags = Subtarget->classifyLocalReference(
nullptr);
1087 if (!AM.
GV || !Subtarget->isPICStyleRIPRel()) {
1088 auto GetCallRegForValue = [
this](
const Value *
V) {
1092 if (
Reg && Subtarget->isTarget64BitILP32()) {
1093 Register CopyReg = createResultReg(&X86::GR32RegClass);
1094 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV32rr),
1098 Register ExtReg = createResultReg(&X86::GR64RegClass);
1099 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1100 TII.get(TargetOpcode::SUBREG_TO_REG), ExtReg)
1110 AM.
Base.
Reg = GetCallRegForValue(V);
1115 AM.
IndexReg = GetCallRegForValue(V);
1125bool X86FastISel::X86SelectStore(
const Instruction *
I) {
1132 const Value *PtrV =
I->getOperand(1);
1133 if (TLI.supportSwiftError()) {
1137 if (Arg->hasSwiftErrorAttr())
1142 if (Alloca->isSwiftError())
1151 if (!isTypeLegal(Val->
getType(), VT,
true))
1156 bool Aligned = Alignment >= ABIAlignment;
1162 return X86FastEmitStore(VT, Val, AM, createMachineMemOperandFor(
I),
Aligned);
1166bool X86FastISel::X86SelectRet(
const Instruction *
I) {
1168 const Function &
F = *
I->getParent()->getParent();
1169 const X86MachineFunctionInfo *X86MFInfo =
1170 FuncInfo.MF->getInfo<X86MachineFunctionInfo>();
1172 if (!FuncInfo.CanLowerReturn)
1175 if (TLI.supportSwiftError() &&
1176 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
1179 if (TLI.supportSplitCSR(FuncInfo.MF))
1182 CallingConv::ID CC =
F.getCallingConv();
1183 if (CC != CallingConv::C &&
1184 CC != CallingConv::Fast &&
1185 CC != CallingConv::Tail &&
1186 CC != CallingConv::SwiftTail &&
1187 CC != CallingConv::X86_FastCall &&
1188 CC != CallingConv::X86_StdCall &&
1189 CC != CallingConv::X86_ThisCall &&
1190 CC != CallingConv::X86_64_SysV &&
1191 CC != CallingConv::Win64)
1200 if ((CC == CallingConv::Fast && TM.Options.GuaranteedTailCallOpt) ||
1201 CC == CallingConv::Tail || CC == CallingConv::SwiftTail)
1217 CCState CCInfo(CC,
F.isVarArg(), *FuncInfo.MF, ValLocs,
I->getContext());
1226 if (ValLocs.
size() != 1)
1229 CCValAssign &VA = ValLocs[0];
1244 EVT SrcVT = TLI.getValueType(
DL, RV->
getType());
1247 if (SrcVT != DstVT) {
1248 if (SrcVT != MVT::i1 && SrcVT != MVT::i8 && SrcVT != MVT::i16)
1251 if (!Outs[0].
Flags.isZExt() && !Outs[0].Flags.isSExt())
1254 if (SrcVT == MVT::i1) {
1255 if (Outs[0].
Flags.isSExt())
1257 SrcReg = fastEmitZExtFromI1(MVT::i8, SrcReg);
1260 if (SrcVT != DstVT) {
1270 const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
1274 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1275 TII.get(TargetOpcode::COPY), DstReg).
addReg(SrcReg);
1288 if (
F.hasStructRetAttr() && CC != CallingConv::Swift &&
1289 CC != CallingConv::SwiftTail) {
1292 "SRetReturnReg should have been set in LowerFormalArguments()!");
1293 Register RetReg = Subtarget->isTarget64BitLP64() ? X86::RAX : X86::EAX;
1294 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1300 MachineInstrBuilder MIB;
1302 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1303 TII.get(Subtarget->is64Bit() ? X86::RETI64 : X86::RETI32))
1306 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1307 TII.get(Subtarget->is64Bit() ? X86::RET64 : X86::RET32));
1316bool X86FastISel::X86SelectLoad(
const Instruction *
I) {
1323 const Value *SV =
I->getOperand(0);
1324 if (TLI.supportSwiftError()) {
1328 if (Arg->hasSwiftErrorAttr())
1333 if (Alloca->isSwiftError())
1339 if (!isTypeLegal(LI->
getType(), VT,
true))
1349 if (!X86FastEmitLoad(VT, AM, createMachineMemOperandFor(LI), ResultReg,
1353 updateValueMap(
I, ResultReg);
1358 bool HasAVX512 = Subtarget->
hasAVX512();
1359 bool HasAVX = Subtarget->
hasAVX();
1360 bool HasSSE1 = Subtarget->
hasSSE1();
1361 bool HasSSE2 = Subtarget->
hasSSE2();
1365 case MVT::i8:
return X86::CMP8rr;
1366 case MVT::i16:
return X86::CMP16rr;
1367 case MVT::i32:
return X86::CMP32rr;
1368 case MVT::i64:
return X86::CMP64rr;
1370 return HasAVX512 ? X86::VUCOMISSZrr
1371 : HasAVX ? X86::VUCOMISSrr
1372 : HasSSE1 ? X86::UCOMISSrr
1375 return HasAVX512 ? X86::VUCOMISDZrr
1376 : HasAVX ? X86::VUCOMISDrr
1377 : HasSSE2 ? X86::UCOMISDrr
1392 return X86::CMP16ri;
1394 return X86::CMP32ri;
1402bool X86FastISel::X86FastEmitCompare(
const Value *Op0,
const Value *Op1, EVT VT,
1404 Register Op0Reg = getRegForValue(Op0);
1417 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, CurMIMD,
TII.get(CompareImmOpc))
1419 .
addImm(Op1C->getSExtValue());
1425 if (CompareOpc == 0)
return false;
1427 Register Op1Reg = getRegForValue(Op1);
1430 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, CurMIMD,
TII.get(CompareOpc))
1438 ((!Subtarget->hasZU() || Subtarget->preferLegacySetCC()) ? X86::SETCCr \
1445 if (!isTypeLegal(
I->getOperand(0)->getType(), VT))
1458 ResultReg = createResultReg(&X86::GR32RegClass);
1459 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV32r0),
1461 ResultReg = fastEmitInst_extractsubreg(MVT::i8, ResultReg, X86::sub_8bit);
1467 ResultReg = createResultReg(&X86::GR8RegClass);
1468 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV8ri),
1475 updateValueMap(
I, ResultReg);
1487 if (RHSC && RHSC->isNullValue())
1492 static const uint16_t SETFOpcTable[2][3] = {
1503 ResultReg = createResultReg(&X86::GR8RegClass);
1505 if (!X86FastEmitCompare(
LHS,
RHS, VT,
I->getDebugLoc()))
1508 Register FlagReg1 = createResultReg(&X86::GR8RegClass);
1509 Register FlagReg2 = createResultReg(&X86::GR8RegClass);
1516 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(SETFOpc[2]),
1518 updateValueMap(
I, ResultReg);
1531 if (!X86FastEmitCompare(
LHS,
RHS, VT,
I->getDebugLoc()))
1536 updateValueMap(
I, ResultReg);
1540bool X86FastISel::X86SelectZExt(
const Instruction *
I) {
1541 EVT DstVT = TLI.getValueType(
DL,
I->getType());
1542 if (!TLI.isTypeLegal(DstVT))
1545 Register ResultReg = getRegForValue(
I->getOperand(0));
1550 MVT SrcVT = TLI.getSimpleValueType(
DL,
I->getOperand(0)->getType());
1551 if (SrcVT == MVT::i1) {
1553 ResultReg = fastEmitZExtFromI1(MVT::i8, ResultReg);
1560 if (DstVT == MVT::i64) {
1565 case MVT::i8: MovInst = X86::MOVZX32rr8;
break;
1566 case MVT::i16: MovInst = X86::MOVZX32rr16;
break;
1567 case MVT::i32: MovInst = X86::MOV32rr;
break;
1571 Register Result32 = createResultReg(&X86::GR32RegClass);
1572 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(MovInst), Result32)
1575 ResultReg = createResultReg(&X86::GR64RegClass);
1576 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1577 TII.get(TargetOpcode::SUBREG_TO_REG), ResultReg)
1580 }
else if (DstVT == MVT::i16) {
1583 Register Result32 = createResultReg(&X86::GR32RegClass);
1584 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOVZX32rr8),
1585 Result32).
addReg(ResultReg);
1587 ResultReg = fastEmitInst_extractsubreg(MVT::i16, Result32, X86::sub_16bit);
1588 }
else if (DstVT != MVT::i8) {
1595 updateValueMap(
I, ResultReg);
1599bool X86FastISel::X86SelectSExt(
const Instruction *
I) {
1600 EVT DstVT = TLI.getValueType(
DL,
I->getType());
1601 if (!TLI.isTypeLegal(DstVT))
1604 Register ResultReg = getRegForValue(
I->getOperand(0));
1609 MVT SrcVT = TLI.getSimpleValueType(
DL,
I->getOperand(0)->getType());
1610 if (SrcVT == MVT::i1) {
1612 Register ZExtReg = fastEmitZExtFromI1(MVT::i8, ResultReg);
1617 ResultReg = createResultReg(&X86::GR8RegClass);
1618 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::NEG8r),
1619 ResultReg).
addReg(ZExtReg);
1624 if (DstVT == MVT::i16) {
1627 Register Result32 = createResultReg(&X86::GR32RegClass);
1628 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOVSX32rr8),
1629 Result32).
addReg(ResultReg);
1631 ResultReg = fastEmitInst_extractsubreg(MVT::i16, Result32, X86::sub_16bit);
1632 }
else if (DstVT != MVT::i8) {
1639 updateValueMap(
I, ResultReg);
1643bool X86FastISel::X86SelectBranch(
const Instruction *
I) {
1647 MachineBasicBlock *TrueMBB = FuncInfo.getMBB(BI->
getSuccessor(0));
1648 MachineBasicBlock *FalseMBB = FuncInfo.getMBB(BI->
getSuccessor(1));
1655 if (CI->
hasOneUse() && CI->getParent() ==
I->getParent()) {
1660 switch (Predicate) {
1675 if (CmpRHSC && CmpRHSC->isNullValue())
1680 if (FuncInfo.MBB->isLayoutSuccessor(TrueMBB)) {
1690 bool NeedExtraBranch =
false;
1691 switch (Predicate) {
1697 NeedExtraBranch =
true;
1710 if (!X86FastEmitCompare(CmpLHS, CmpRHS, VT, CI->getDebugLoc()))
1713 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1718 if (NeedExtraBranch) {
1719 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1723 finishCondBranch(BI->getParent(), TrueMBB, FalseMBB);
1730 if (TI->hasOneUse() && TI->getParent() ==
I->getParent() &&
1731 isTypeLegal(TI->getOperand(0)->getType(), SourceVT)) {
1732 unsigned TestOpc = 0;
1735 case MVT::i8: TestOpc = X86::TEST8ri;
break;
1736 case MVT::i16: TestOpc = X86::TEST16ri;
break;
1737 case MVT::i32: TestOpc = X86::TEST32ri;
break;
1738 case MVT::i64: TestOpc = X86::TEST64ri32;
break;
1741 Register OpReg = getRegForValue(TI->getOperand(0));
1745 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TestOpc))
1749 if (FuncInfo.MBB->isLayoutSuccessor(TrueMBB)) {
1754 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1757 finishCondBranch(BI->getParent(), TrueMBB, FalseMBB);
1761 }
else if (foldX86XALUIntrinsic(CC, BI, BI->
getCondition())) {
1768 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1770 finishCondBranch(BI->getParent(), TrueMBB, FalseMBB);
1782 if (MRI.getRegClass(OpReg) == &X86::VK1RegClass) {
1784 OpReg = createResultReg(&X86::GR32RegClass);
1785 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1786 TII.get(TargetOpcode::COPY), OpReg)
1788 OpReg = fastEmitInst_extractsubreg(MVT::i8, OpReg, X86::sub_8bit);
1790 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TEST8ri))
1793 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1795 finishCondBranch(BI->getParent(), TrueMBB, FalseMBB);
1799bool X86FastISel::X86SelectShift(
const Instruction *
I) {
1802 const TargetRegisterClass *RC =
nullptr;
1803 if (
I->getType()->isIntegerTy(8)) {
1805 RC = &X86::GR8RegClass;
1806 switch (
I->getOpcode()) {
1807 case Instruction::LShr: OpReg = X86::SHR8rCL;
break;
1808 case Instruction::AShr: OpReg = X86::SAR8rCL;
break;
1809 case Instruction::Shl: OpReg = X86::SHL8rCL;
break;
1810 default:
return false;
1812 }
else if (
I->getType()->isIntegerTy(16)) {
1814 RC = &X86::GR16RegClass;
1815 switch (
I->getOpcode()) {
1817 case Instruction::LShr: OpReg = X86::SHR16rCL;
break;
1818 case Instruction::AShr: OpReg = X86::SAR16rCL;
break;
1819 case Instruction::Shl: OpReg = X86::SHL16rCL;
break;
1821 }
else if (
I->getType()->isIntegerTy(32)) {
1823 RC = &X86::GR32RegClass;
1824 switch (
I->getOpcode()) {
1826 case Instruction::LShr: OpReg = X86::SHR32rCL;
break;
1827 case Instruction::AShr: OpReg = X86::SAR32rCL;
break;
1828 case Instruction::Shl: OpReg = X86::SHL32rCL;
break;
1830 }
else if (
I->getType()->isIntegerTy(64)) {
1832 RC = &X86::GR64RegClass;
1833 switch (
I->getOpcode()) {
1835 case Instruction::LShr: OpReg = X86::SHR64rCL;
break;
1836 case Instruction::AShr: OpReg = X86::SAR64rCL;
break;
1837 case Instruction::Shl: OpReg = X86::SHL64rCL;
break;
1844 if (!isTypeLegal(
I->getType(), VT))
1847 Register Op0Reg = getRegForValue(
I->getOperand(0));
1851 Register Op1Reg = getRegForValue(
I->getOperand(1));
1854 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
1859 if (CReg != X86::CL)
1860 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1861 TII.get(TargetOpcode::KILL), X86::CL)
1862 .
addReg(CReg, RegState::Kill);
1864 Register ResultReg = createResultReg(RC);
1865 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(OpReg), ResultReg)
1867 updateValueMap(
I, ResultReg);
1871bool X86FastISel::X86SelectDivRem(
const Instruction *
I) {
1872 const static unsigned NumTypes = 4;
1873 const static unsigned NumOps = 4;
1874 const static bool S =
true;
1875 const static bool U =
false;
1876 const static unsigned Copy = TargetOpcode::COPY;
1886 const static struct DivRemEntry {
1888 const TargetRegisterClass *RC;
1892 struct DivRemResult {
1894 unsigned OpSignExtend;
1898 unsigned DivRemResultReg;
1901 } OpTable[NumTypes] = {
1902 { &X86::GR8RegClass, X86::AX, 0, {
1903 { X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AL, S },
1904 { X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AH, S },
1905 { X86::DIV8r, 0, X86::MOVZX16rr8, X86::AL,
U },
1906 { X86::DIV8r, 0, X86::MOVZX16rr8, X86::AH,
U },
1909 { &X86::GR16RegClass, X86::AX, X86::DX, {
1910 { X86::IDIV16r, X86::CWD,
Copy, X86::AX, S },
1911 { X86::IDIV16r, X86::CWD,
Copy, X86::DX, S },
1912 { X86::DIV16r, X86::MOV32r0,
Copy, X86::AX,
U },
1913 { X86::DIV16r, X86::MOV32r0,
Copy, X86::DX,
U },
1916 { &X86::GR32RegClass, X86::EAX, X86::EDX, {
1917 { X86::IDIV32r, X86::CDQ,
Copy, X86::EAX, S },
1918 { X86::IDIV32r, X86::CDQ,
Copy, X86::EDX, S },
1919 { X86::DIV32r, X86::MOV32r0,
Copy, X86::EAX,
U },
1920 { X86::DIV32r, X86::MOV32r0,
Copy, X86::EDX,
U },
1923 { &X86::GR64RegClass, X86::RAX, X86::RDX, {
1924 { X86::IDIV64r, X86::CQO,
Copy, X86::RAX, S },
1925 { X86::IDIV64r, X86::CQO,
Copy, X86::RDX, S },
1926 { X86::DIV64r, X86::MOV32r0,
Copy, X86::RAX,
U },
1927 { X86::DIV64r, X86::MOV32r0,
Copy, X86::RDX,
U },
1933 if (!isTypeLegal(
I->getType(), VT))
1938 default:
return false;
1939 case MVT::i8: TypeIndex = 0;
break;
1940 case MVT::i16: TypeIndex = 1;
break;
1941 case MVT::i32: TypeIndex = 2;
break;
1942 case MVT::i64: TypeIndex = 3;
1943 if (!Subtarget->is64Bit())
1948 switch (
I->getOpcode()) {
1950 case Instruction::SDiv:
OpIndex = 0;
break;
1951 case Instruction::SRem:
OpIndex = 1;
break;
1952 case Instruction::UDiv:
OpIndex = 2;
break;
1953 case Instruction::URem:
OpIndex = 3;
break;
1956 const DivRemEntry &
TypeEntry = OpTable[TypeIndex];
1958 Register Op0Reg = getRegForValue(
I->getOperand(0));
1961 Register Op1Reg = getRegForValue(
I->getOperand(1));
1966 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1969 if (OpEntry.OpSignExtend) {
1970 if (OpEntry.IsOpSigned)
1971 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1972 TII.get(OpEntry.OpSignExtend));
1974 Register Zero32 = createResultReg(&X86::GR32RegClass);
1975 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1976 TII.get(X86::MOV32r0), Zero32);
1981 if (VT == MVT::i16) {
1982 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Copy),
1984 .
addReg(Zero32, {}, X86::sub_16bit);
1985 }
else if (VT == MVT::i32) {
1986 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1989 }
else if (VT == MVT::i64) {
1990 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1991 TII.get(TargetOpcode::SUBREG_TO_REG),
TypeEntry.HighInReg)
1998 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1999 TII.get(OpEntry.OpDivRem)).
addReg(Op1Reg);
2009 if ((
I->getOpcode() == Instruction::SRem ||
2010 I->getOpcode() == Instruction::URem) &&
2011 OpEntry.DivRemResultReg == X86::AH && Subtarget->is64Bit()) {
2012 Register SourceSuperReg = createResultReg(&X86::GR16RegClass);
2013 Register ResultSuperReg = createResultReg(&X86::GR16RegClass);
2014 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2015 TII.get(Copy), SourceSuperReg).
addReg(X86::AX);
2018 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SHR16ri),
2022 ResultReg = fastEmitInst_extractsubreg(MVT::i8, ResultSuperReg,
2027 ResultReg = createResultReg(
TypeEntry.RC);
2028 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Copy), ResultReg)
2029 .
addReg(OpEntry.DivRemResultReg);
2031 updateValueMap(
I, ResultReg);
2038bool X86FastISel::X86FastEmitCMoveSelect(MVT RetVT,
const Instruction *
I) {
2040 if (!Subtarget->canUseCMOV())
2044 if (RetVT < MVT::i16 || RetVT > MVT::i64)
2048 const TargetRegisterClass *RC = TLI.getRegClassFor(RetVT);
2049 bool NeedTest =
true;
2056 if (CI && (CI->getParent() ==
I->getParent())) {
2060 static const uint16_t SETFOpcTable[2][3] = {
2064 const uint16_t *SETFOpc =
nullptr;
2065 switch (Predicate) {
2068 SETFOpc = &SETFOpcTable[0][0];
2072 SETFOpc = &SETFOpcTable[1][0];
2086 EVT CmpVT = TLI.getValueType(
DL, CmpLHS->
getType());
2088 if (!X86FastEmitCompare(CmpLHS, CmpRHS, CmpVT, CI->getDebugLoc()))
2092 Register FlagReg1 = createResultReg(&X86::GR8RegClass);
2093 Register FlagReg2 = createResultReg(&X86::GR8RegClass);
2100 auto const &
II =
TII.get(SETFOpc[2]);
2101 if (
II.getNumDefs()) {
2102 Register TmpReg = createResultReg(&X86::GR8RegClass);
2103 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, TmpReg)
2106 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2111 }
else if (foldX86XALUIntrinsic(CC,
I,
Cond)) {
2132 if (MRI.getRegClass(CondReg) == &X86::VK1RegClass) {
2134 CondReg = createResultReg(&X86::GR32RegClass);
2135 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2136 TII.get(TargetOpcode::COPY), CondReg)
2138 CondReg = fastEmitInst_extractsubreg(MVT::i8, CondReg, X86::sub_8bit);
2140 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TEST8ri))
2150 if (!LHSReg || !RHSReg)
2153 const TargetRegisterInfo &
TRI = *Subtarget->getRegisterInfo();
2155 Subtarget->hasNDD());
2156 Register ResultReg = fastEmitInst_rri(
Opc, RC, RHSReg, LHSReg, CC);
2157 updateValueMap(
I, ResultReg);
2166bool X86FastISel::X86FastEmitSSESelect(MVT RetVT,
const Instruction *
I) {
2171 if (!CI || (CI->getParent() !=
I->getParent()))
2175 !((Subtarget->hasSSE1() && RetVT == MVT::f32) ||
2176 (Subtarget->hasSSE2() && RetVT == MVT::f64)))
2188 if (CmpRHSC && CmpRHSC->isNullValue())
2195 if (CC > 7 && !Subtarget->hasAVX())
2206 Register CmpLHSReg = getRegForValue(CmpLHS);
2207 Register CmpRHSReg = getRegForValue(CmpRHS);
2208 if (!LHSReg || !RHSReg || !CmpLHSReg || !CmpRHSReg)
2211 const TargetRegisterClass *RC = TLI.getRegClassFor(RetVT);
2214 if (Subtarget->hasAVX512()) {
2216 const TargetRegisterClass *VR128X = &X86::VR128XRegClass;
2217 const TargetRegisterClass *VK1 = &X86::VK1RegClass;
2219 unsigned CmpOpcode =
2220 (RetVT == MVT::f32) ? X86::VCMPSSZrri :
X86::VCMPSDZrri;
2221 Register CmpReg = fastEmitInst_rri(CmpOpcode, VK1, CmpLHSReg, CmpRHSReg,
2226 Register ImplicitDefReg = createResultReg(VR128X);
2227 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2228 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2232 unsigned MovOpcode =
2233 (RetVT == MVT::f32) ? X86::VMOVSSZrrk :
X86::VMOVSDZrrk;
2234 Register MovReg = fastEmitInst_rrrr(MovOpcode, VR128X, RHSReg, CmpReg,
2235 ImplicitDefReg, LHSReg);
2237 ResultReg = createResultReg(RC);
2238 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2239 TII.get(TargetOpcode::COPY), ResultReg).
addReg(MovReg);
2241 }
else if (Subtarget->hasAVX()) {
2242 const TargetRegisterClass *VR128 = &X86::VR128RegClass;
2249 unsigned CmpOpcode =
2250 (RetVT == MVT::f32) ? X86::VCMPSSrri :
X86::VCMPSDrri;
2251 unsigned BlendOpcode =
2252 (RetVT == MVT::f32) ? X86::VBLENDVPSrrr :
X86::VBLENDVPDrrr;
2254 Register CmpReg = fastEmitInst_rri(CmpOpcode, RC, CmpLHSReg, CmpRHSReg,
2256 Register VBlendReg = fastEmitInst_rrr(BlendOpcode, VR128, RHSReg, LHSReg,
2258 ResultReg = createResultReg(RC);
2259 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2260 TII.get(TargetOpcode::COPY), ResultReg).
addReg(VBlendReg);
2263 static const uint16_t OpcTable[2][4] = {
2264 { X86::CMPSSrri, X86::ANDPSrr, X86::ANDNPSrr, X86::ORPSrr },
2265 { X86::CMPSDrri, X86::ANDPDrr, X86::ANDNPDrr, X86::ORPDrr }
2268 const uint16_t *
Opc =
nullptr;
2270 default:
return false;
2271 case MVT::f32:
Opc = &OpcTable[0][0];
break;
2272 case MVT::f64:
Opc = &OpcTable[1][0];
break;
2275 const TargetRegisterClass *VR128 = &X86::VR128RegClass;
2276 Register CmpReg = fastEmitInst_rri(
Opc[0], RC, CmpLHSReg, CmpRHSReg, CC);
2277 Register AndReg = fastEmitInst_rr(
Opc[1], VR128, CmpReg, LHSReg);
2278 Register AndNReg = fastEmitInst_rr(
Opc[2], VR128, CmpReg, RHSReg);
2279 Register OrReg = fastEmitInst_rr(
Opc[3], VR128, AndNReg, AndReg);
2280 ResultReg = createResultReg(RC);
2281 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2282 TII.get(TargetOpcode::COPY), ResultReg).
addReg(OrReg);
2284 updateValueMap(
I, ResultReg);
2288bool X86FastISel::X86FastEmitPseudoSelect(MVT RetVT,
const Instruction *
I) {
2293 default:
return false;
2294 case MVT::i8:
Opc = X86::CMOV_GR8;
break;
2295 case MVT::i16:
Opc = X86::CMOV_GR16;
break;
2296 case MVT::i32:
Opc = X86::CMOV_GR32;
break;
2298 Opc = Subtarget->hasAVX512() ? X86::CMOV_FR16X : X86::CMOV_FR16;
break;
2300 Opc = Subtarget->hasAVX512() ? X86::CMOV_FR32X : X86::CMOV_FR32;
break;
2302 Opc = Subtarget->hasAVX512() ? X86::CMOV_FR64X : X86::CMOV_FR64;
break;
2312 if (CI && (CI->getParent() ==
I->getParent())) {
2324 EVT CmpVT = TLI.getValueType(
DL, CmpLHS->
getType());
2325 if (!X86FastEmitCompare(CmpLHS, CmpRHS, CmpVT, CI->getDebugLoc()))
2333 if (MRI.getRegClass(CondReg) == &X86::VK1RegClass) {
2335 CondReg = createResultReg(&X86::GR32RegClass);
2336 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2337 TII.get(TargetOpcode::COPY), CondReg)
2339 CondReg = fastEmitInst_extractsubreg(MVT::i8, CondReg, X86::sub_8bit);
2341 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TEST8ri))
2351 if (!LHSReg || !RHSReg)
2354 const TargetRegisterClass *RC = TLI.getRegClassFor(RetVT);
2357 fastEmitInst_rri(
Opc, RC, RHSReg, LHSReg, CC);
2358 updateValueMap(
I, ResultReg);
2362bool X86FastISel::X86SelectSelect(
const Instruction *
I) {
2364 if (!isTypeLegal(
I->getType(), RetVT))
2370 const Value *Opnd =
nullptr;
2371 switch (Predicate) {
2378 Register OpReg = getRegForValue(Opnd);
2381 const TargetRegisterClass *RC = TLI.getRegClassFor(RetVT);
2382 Register ResultReg = createResultReg(RC);
2383 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2384 TII.get(TargetOpcode::COPY), ResultReg)
2386 updateValueMap(
I, ResultReg);
2392 if (X86FastEmitCMoveSelect(RetVT,
I))
2396 if (X86FastEmitSSESelect(RetVT,
I))
2401 if (X86FastEmitPseudoSelect(RetVT,
I))
2408bool X86FastISel::X86SelectIntToFP(
const Instruction *
I,
bool IsSigned) {
2413 bool HasAVX512 = Subtarget->hasAVX512();
2414 if (!Subtarget->hasAVX() || (!IsSigned && !HasAVX512))
2418 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
2419 if (SrcVT != MVT::i32 && SrcVT != MVT::i64)
2423 Register OpReg = getRegForValue(
I->getOperand(0));
2429 static const uint16_t SCvtOpc[2][2][2] = {
2430 { { X86::VCVTSI2SSrr, X86::VCVTSI642SSrr },
2431 { X86::VCVTSI2SDrr, X86::VCVTSI642SDrr } },
2432 { { X86::VCVTSI2SSZrr, X86::VCVTSI642SSZrr },
2433 { X86::VCVTSI2SDZrr, X86::VCVTSI642SDZrr } },
2435 static const uint16_t UCvtOpc[2][2] = {
2436 { X86::VCVTUSI2SSZrr, X86::VCVTUSI642SSZrr },
2437 { X86::VCVTUSI2SDZrr, X86::VCVTUSI642SDZrr },
2439 bool Is64Bit = SrcVT == MVT::i64;
2441 if (
I->getType()->isDoubleTy()) {
2443 Opcode = IsSigned ? SCvtOpc[HasAVX512][1][Is64Bit] : UCvtOpc[1][Is64Bit];
2444 }
else if (
I->getType()->isFloatTy()) {
2446 Opcode = IsSigned ? SCvtOpc[HasAVX512][0][Is64Bit] : UCvtOpc[0][Is64Bit];
2451 const TargetRegisterClass *RC = TLI.getRegClassFor(DstVT);
2452 Register ImplicitDefReg = createResultReg(RC);
2453 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2454 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2455 Register ResultReg = fastEmitInst_rr(Opcode, RC, ImplicitDefReg, OpReg);
2456 updateValueMap(
I, ResultReg);
2460bool X86FastISel::X86SelectSIToFP(
const Instruction *
I) {
2461 return X86SelectIntToFP(
I,
true);
2464bool X86FastISel::X86SelectUIToFP(
const Instruction *
I) {
2465 return X86SelectIntToFP(
I,
false);
2469bool X86FastISel::X86SelectFPExtOrFPTrunc(
const Instruction *
I,
2471 const TargetRegisterClass *RC) {
2472 assert((
I->getOpcode() == Instruction::FPExt ||
2473 I->getOpcode() == Instruction::FPTrunc) &&
2474 "Instruction must be an FPExt or FPTrunc!");
2475 bool HasAVX = Subtarget->hasAVX();
2477 Register OpReg = getRegForValue(
I->getOperand(0));
2483 ImplicitDefReg = createResultReg(RC);
2484 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2485 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2489 Register ResultReg = createResultReg(RC);
2490 MachineInstrBuilder MIB;
2491 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpc),
2495 MIB.
addReg(ImplicitDefReg);
2498 updateValueMap(
I, ResultReg);
2502bool X86FastISel::X86SelectFPExt(
const Instruction *
I) {
2503 if (Subtarget->hasSSE2() &&
I->getType()->isDoubleTy() &&
2504 I->getOperand(0)->getType()->isFloatTy()) {
2505 bool HasAVX512 = Subtarget->hasAVX512();
2508 HasAVX512 ? X86::VCVTSS2SDZrr
2509 : Subtarget->hasAVX() ? X86::VCVTSS2SDrr : X86::CVTSS2SDrr;
2510 return X86SelectFPExtOrFPTrunc(
I,
Opc, TLI.getRegClassFor(MVT::f64));
2516bool X86FastISel::X86SelectFPTrunc(
const Instruction *
I) {
2517 if (Subtarget->hasSSE2() &&
I->getType()->isFloatTy() &&
2518 I->getOperand(0)->getType()->isDoubleTy()) {
2519 bool HasAVX512 = Subtarget->hasAVX512();
2522 HasAVX512 ? X86::VCVTSD2SSZrr
2523 : Subtarget->hasAVX() ? X86::VCVTSD2SSrr : X86::CVTSD2SSrr;
2524 return X86SelectFPExtOrFPTrunc(
I,
Opc, TLI.getRegClassFor(MVT::f32));
2530bool X86FastISel::X86SelectTrunc(
const Instruction *
I) {
2531 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
2532 EVT DstVT = TLI.getValueType(
DL,
I->getType());
2535 if (DstVT != MVT::i8 && DstVT != MVT::i1)
2537 if (!TLI.isTypeLegal(SrcVT))
2540 Register InputReg = getRegForValue(
I->getOperand(0));
2545 if (SrcVT == MVT::i8) {
2547 updateValueMap(
I, InputReg);
2552 Register ResultReg = fastEmitInst_extractsubreg(MVT::i8, InputReg,
2557 updateValueMap(
I, ResultReg);
2561bool X86FastISel::X86SelectBitCast(
const Instruction *
I) {
2564 if (!Subtarget->hasSSE2() ||
2565 !isTypeLegal(
I->getOperand(0)->getType(), SrcVT) ||
2566 !isTypeLegal(
I->getType(), DstVT))
2581 const TargetRegisterClass *DstClass = TLI.getRegClassFor(DstVT);
2582 Register ResultReg = createResultReg(DstClass);
2583 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
2587 updateValueMap(
I, ResultReg);
2591bool X86FastISel::IsMemcpySmall(uint64_t Len) {
2592 return Len <= (Subtarget->is64Bit() ? 32 : 16);
2595bool X86FastISel::TryEmitSmallMemcpy(X86AddressMode DestAM,
2596 X86AddressMode SrcAM, uint64_t Len) {
2599 if (!IsMemcpySmall(Len))
2602 bool i64Legal = Subtarget->is64Bit();
2607 if (Len >= 8 && i64Legal)
2617 bool RV = X86FastEmitLoad(VT, SrcAM,
nullptr,
Reg);
2618 RV &= X86FastEmitStore(VT,
Reg, DestAM);
2619 assert(RV &&
"Failed to emit load or store??");
2631bool X86FastISel::fastLowerIntrinsicCall(
const IntrinsicInst *
II) {
2633 switch (
II->getIntrinsicID()) {
2636 case Intrinsic::frameaddress: {
2637 MachineFunction *MF = FuncInfo.MF;
2641 Type *RetTy =
II->getCalledFunction()->getReturnType();
2644 if (!isTypeLegal(RetTy, VT))
2648 const TargetRegisterClass *RC =
nullptr;
2652 case MVT::i32:
Opc = X86::MOV32rm; RC = &X86::GR32RegClass;
break;
2653 case MVT::i64:
Opc = X86::MOV64rm; RC = &X86::GR64RegClass;
break;
2661 const X86RegisterInfo *RegInfo = Subtarget->getRegisterInfo();
2663 assert(((FrameReg == X86::RBP && VT == MVT::i64) ||
2664 (FrameReg == X86::EBP && VT == MVT::i32)) &&
2665 "Invalid Frame Register!");
2670 Register SrcReg = createResultReg(RC);
2671 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2672 TII.get(TargetOpcode::COPY), SrcReg).
addReg(FrameReg);
2681 Register DestReg = createResultReg(RC);
2683 TII.get(
Opc), DestReg), SrcReg);
2687 updateValueMap(
II, SrcReg);
2690 case Intrinsic::memcpy: {
2700 if (IsMemcpySmall(Len)) {
2701 X86AddressMode DestAM, SrcAM;
2705 TryEmitSmallMemcpy(DestAM, SrcAM, Len);
2710 unsigned SizeWidth = Subtarget->is64Bit() ? 64 : 32;
2717 return lowerCallTo(
II,
"memcpy",
II->arg_size() - 1);
2719 case Intrinsic::memset: {
2725 unsigned SizeWidth = Subtarget->is64Bit() ? 64 : 32;
2732 return lowerCallTo(
II,
"memset",
II->arg_size() - 1);
2734 case Intrinsic::stackprotector: {
2736 EVT PtrTy = TLI.getPointerTy(
DL);
2738 const Value *Op1 =
II->getArgOperand(0);
2746 if (!X86FastEmitStore(PtrTy, Op1, AM))
return false;
2749 case Intrinsic::dbg_declare: {
2755 const MCInstrDesc &
II =
TII.get(TargetOpcode::DBG_VALUE);
2757 "Expected inlined-at fields to agree");
2764 case Intrinsic::trap: {
2765 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TRAP));
2768 case Intrinsic::sqrt: {
2769 if (!Subtarget->hasSSE1())
2772 Type *RetTy =
II->getCalledFunction()->getReturnType();
2775 if (!isTypeLegal(RetTy, VT))
2781 static const uint16_t SqrtOpc[3][2] = {
2782 { X86::SQRTSSr, X86::SQRTSDr },
2783 { X86::VSQRTSSr, X86::VSQRTSDr },
2784 { X86::VSQRTSSZr, X86::VSQRTSDZr },
2786 unsigned AVXLevel = Subtarget->hasAVX512() ? 2 :
2787 Subtarget->hasAVX() ? 1 :
2791 default:
return false;
2792 case MVT::f32:
Opc = SqrtOpc[AVXLevel][0];
break;
2793 case MVT::f64:
Opc = SqrtOpc[AVXLevel][1];
break;
2796 const Value *SrcVal =
II->getArgOperand(0);
2797 Register SrcReg = getRegForValue(SrcVal);
2802 const TargetRegisterClass *RC = TLI.getRegClassFor(VT);
2805 ImplicitDefReg = createResultReg(RC);
2806 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2807 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2810 Register ResultReg = createResultReg(RC);
2811 MachineInstrBuilder MIB;
2812 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc),
2816 MIB.
addReg(ImplicitDefReg);
2820 updateValueMap(
II, ResultReg);
2823 case Intrinsic::sadd_with_overflow:
2824 case Intrinsic::uadd_with_overflow:
2825 case Intrinsic::ssub_with_overflow:
2826 case Intrinsic::usub_with_overflow:
2827 case Intrinsic::smul_with_overflow:
2828 case Intrinsic::umul_with_overflow: {
2833 Type *RetTy = Ty->getTypeAtIndex(0U);
2836 "Overflow value expected to be an i1");
2839 if (!isTypeLegal(RetTy, VT))
2842 if (VT < MVT::i8 || VT > MVT::i64)
2853 switch (
II->getIntrinsicID()) {
2855 case Intrinsic::sadd_with_overflow:
2857 case Intrinsic::uadd_with_overflow:
2859 case Intrinsic::ssub_with_overflow:
2861 case Intrinsic::usub_with_overflow:
2863 case Intrinsic::smul_with_overflow:
2865 case Intrinsic::umul_with_overflow:
2876 static const uint16_t
Opc[2][4] = {
2877 { X86::INC8r, X86::INC16r, X86::INC32r, X86::INC64r },
2878 { X86::DEC8r, X86::DEC16r, X86::DEC32r, X86::DEC64r }
2884 ResultReg = createResultReg(TLI.getRegClassFor(VT));
2886 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2890 ResultReg = fastEmit_ri(VT, VT, BaseOpc, LHSReg, CI->
getZExtValue());
2895 RHSReg = getRegForValue(
RHS);
2898 ResultReg = fastEmit_rr(VT, VT, BaseOpc, LHSReg, RHSReg);
2903 if (BaseOpc == X86ISD::UMUL && !ResultReg) {
2904 static const uint16_t MULOpc[] =
2905 { X86::MUL8r, X86::MUL16r, X86::MUL32r, X86::MUL64r };
2906 static const MCPhysReg Reg[] = { X86::AL, X86::AX, X86::EAX, X86::RAX };
2909 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2912 ResultReg = fastEmitInst_r(MULOpc[VT.
SimpleTy-MVT::i8],
2913 TLI.getRegClassFor(VT), RHSReg);
2914 }
else if (BaseOpc == X86ISD::SMUL && !ResultReg) {
2915 static const uint16_t MULOpc[] =
2916 { X86::IMUL8r, X86::IMUL16rr, X86::IMUL32rr, X86::IMUL64rr };
2917 if (VT == MVT::i8) {
2920 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2921 TII.get(TargetOpcode::COPY), X86::AL)
2923 ResultReg = fastEmitInst_r(MULOpc[0], TLI.getRegClassFor(VT), RHSReg);
2925 ResultReg = fastEmitInst_rr(MULOpc[VT.
SimpleTy-MVT::i8],
2926 TLI.getRegClassFor(VT), LHSReg, RHSReg);
2933 Register ResultReg2 = createResultReg(&X86::GR8RegClass);
2934 assert((ResultReg+1) == ResultReg2 &&
"Nonconsecutive result registers.");
2939 updateValueMap(
II, ResultReg, 2);
2942 case Intrinsic::x86_sse_cvttss2si:
2943 case Intrinsic::x86_sse_cvttss2si64:
2944 case Intrinsic::x86_sse2_cvttsd2si:
2945 case Intrinsic::x86_sse2_cvttsd2si64: {
2947 switch (
II->getIntrinsicID()) {
2949 case Intrinsic::x86_sse_cvttss2si:
2950 case Intrinsic::x86_sse_cvttss2si64:
2951 if (!Subtarget->hasSSE1())
2953 IsInputDouble =
false;
2955 case Intrinsic::x86_sse2_cvttsd2si:
2956 case Intrinsic::x86_sse2_cvttsd2si64:
2957 if (!Subtarget->hasSSE2())
2959 IsInputDouble =
true;
2963 Type *RetTy =
II->getCalledFunction()->getReturnType();
2965 if (!isTypeLegal(RetTy, VT))
2968 static const uint16_t CvtOpc[3][2][2] = {
2969 { { X86::CVTTSS2SIrr, X86::CVTTSS2SI64rr },
2970 { X86::CVTTSD2SIrr, X86::CVTTSD2SI64rr } },
2971 { { X86::VCVTTSS2SIrr, X86::VCVTTSS2SI64rr },
2972 { X86::VCVTTSD2SIrr, X86::VCVTTSD2SI64rr } },
2973 { { X86::VCVTTSS2SIZrr, X86::VCVTTSS2SI64Zrr },
2974 { X86::VCVTTSD2SIZrr, X86::VCVTTSD2SI64Zrr } },
2976 unsigned AVXLevel = Subtarget->hasAVX512() ? 2 :
2977 Subtarget->hasAVX() ? 1 :
2982 case MVT::i32:
Opc = CvtOpc[AVXLevel][IsInputDouble][0];
break;
2983 case MVT::i64:
Opc = CvtOpc[AVXLevel][IsInputDouble][1];
break;
2995 Op =
IE->getOperand(1);
2998 Op =
IE->getOperand(0);
3005 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3006 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
3009 updateValueMap(
II, ResultReg);
3012 case Intrinsic::x86_sse42_crc32_32_8:
3013 case Intrinsic::x86_sse42_crc32_32_16:
3014 case Intrinsic::x86_sse42_crc32_32_32:
3015 case Intrinsic::x86_sse42_crc32_64_64: {
3016 if (!Subtarget->hasCRC32())
3019 Type *RetTy =
II->getCalledFunction()->getReturnType();
3022 if (!isTypeLegal(RetTy, VT))
3026 const TargetRegisterClass *RC =
nullptr;
3028 switch (
II->getIntrinsicID()) {
3031#define GET_EGPR_IF_ENABLED(OPC) Subtarget->hasEGPR() ? OPC##_EVEX : OPC
3032 case Intrinsic::x86_sse42_crc32_32_8:
3034 RC = &X86::GR32RegClass;
3036 case Intrinsic::x86_sse42_crc32_32_16:
3038 RC = &X86::GR32RegClass;
3040 case Intrinsic::x86_sse42_crc32_32_32:
3042 RC = &X86::GR32RegClass;
3044 case Intrinsic::x86_sse42_crc32_64_64:
3046 RC = &X86::GR64RegClass;
3048#undef GET_EGPR_IF_ENABLED
3056 if (!LHSReg || !RHSReg)
3059 Register ResultReg = fastEmitInst_rr(
Opc, RC, LHSReg, RHSReg);
3063 updateValueMap(
II, ResultReg);
3069bool X86FastISel::fastLowerArguments() {
3070 if (!FuncInfo.CanLowerReturn)
3077 CallingConv::ID CC =
F->getCallingConv();
3078 if (CC != CallingConv::C)
3081 if (Subtarget->isCallingConvWin64(CC))
3084 if (!Subtarget->is64Bit())
3087 if (Subtarget->useSoftFloat())
3091 unsigned GPRCnt = 0;
3092 unsigned FPRCnt = 0;
3093 for (
auto const &Arg :
F->args()) {
3094 if (Arg.hasAttribute(Attribute::ByVal) ||
3095 Arg.hasAttribute(Attribute::InReg) ||
3096 Arg.hasAttribute(Attribute::StructRet) ||
3097 Arg.hasAttribute(Attribute::SwiftSelf) ||
3098 Arg.hasAttribute(Attribute::SwiftAsync) ||
3099 Arg.hasAttribute(Attribute::SwiftError) ||
3100 Arg.hasAttribute(Attribute::Nest))
3103 Type *ArgTy = Arg.getType();
3107 EVT ArgVT = TLI.getValueType(
DL, ArgTy);
3108 if (!ArgVT.
isSimple())
return false;
3110 default:
return false;
3117 if (!Subtarget->hasSSE1())
3130 static const MCPhysReg GPR32ArgRegs[] = {
3131 X86::EDI, X86::ESI, X86::EDX, X86::ECX, X86::R8D, X86::R9D
3133 static const MCPhysReg GPR64ArgRegs[] = {
3134 X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8 , X86::R9
3137 X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,
3138 X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
3141 unsigned GPRIdx = 0;
3142 unsigned FPRIdx = 0;
3143 for (
auto const &Arg :
F->args()) {
3144 MVT VT = TLI.getSimpleValueType(
DL, Arg.getType());
3145 const TargetRegisterClass *RC = TLI.getRegClassFor(VT);
3149 case MVT::i32: SrcReg = GPR32ArgRegs[GPRIdx++];
break;
3150 case MVT::i64: SrcReg = GPR64ArgRegs[GPRIdx++];
break;
3151 case MVT::f32: [[fallthrough]];
3152 case MVT::f64: SrcReg = XMMArgRegs[FPRIdx++];
break;
3154 Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
3158 Register ResultReg = createResultReg(RC);
3159 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3160 TII.get(TargetOpcode::COPY), ResultReg)
3162 updateValueMap(&Arg, ResultReg);
3170 if (Subtarget->is64Bit())
3187bool X86FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3188 auto &OutVals = CLI.OutVals;
3189 auto &OutFlags = CLI.OutFlags;
3190 auto &OutRegs = CLI.OutRegs;
3191 auto &Ins = CLI.Ins;
3192 auto &InRegs = CLI.InRegs;
3193 CallingConv::ID CC = CLI.CallConv;
3194 bool &IsTailCall = CLI.IsTailCall;
3195 bool IsVarArg = CLI.IsVarArg;
3198 const auto *CB = CLI.CB;
3200 bool Is64Bit = Subtarget->is64Bit();
3201 bool IsWin64 = Subtarget->isCallingConvWin64(CC);
3213 for (
Type *RetTy : RetTys) {
3214 MVT RetVT = MVT::Other;
3215 if (!isTypeLegal(RetTy, RetVT)) {
3216 if (RetVT == MVT::Other)
3221 MVT ABIVT = TLI.getRegisterTypeForCallingConv(CLI.RetTy->getContext(),
3222 CLI.CallConv, RetVT);
3223 MVT RegVT = TLI.getRegisterType(CLI.RetTy->getContext(), RetVT);
3231 if (CB && CB->doesNoCfCheck())
3235 if ((CB &&
isa<CallInst>(CB) && CB->hasFnAttr(
"no_caller_saved_registers")))
3239 if ((CB && CB->hasFnAttr(
"no_callee_saved_registers")))
3247 if (Subtarget->useIndirectThunkCalls())
3252 default:
return false;
3253 case CallingConv::C:
3254 case CallingConv::Fast:
3255 case CallingConv::Tail:
3256 case CallingConv::Swift:
3257 case CallingConv::SwiftTail:
3258 case CallingConv::X86_FastCall:
3259 case CallingConv::X86_StdCall:
3260 case CallingConv::X86_ThisCall:
3261 case CallingConv::Win64:
3262 case CallingConv::X86_64_SysV:
3263 case CallingConv::CFGuard_Check:
3273 if ((CC == CallingConv::Fast && TM.Options.GuaranteedTailCallOpt) ||
3274 CC == CallingConv::Tail || CC == CallingConv::SwiftTail)
3279 if (IsVarArg && IsWin64)
3283 if (CLI.CB && CLI.CB->hasInAllocaArgument())
3286 for (
auto Flag : CLI.OutFlags)
3287 if (
Flag.isSwiftError() ||
Flag.isPreallocated())
3297 SmallVector<Register, 16> ArgRegs;
3302 for (
int i = 0, e = OutVals.size(); i != e; ++i) {
3303 Value *&Val = OutVals[i];
3304 ISD::ArgFlagsTy
Flags = OutFlags[i];
3319 if (TI && TI->getType()->isIntegerTy(1) && CLI.CB &&
3320 (TI->getParent() == CLI.CB->getParent()) && TI->hasOneUse()) {
3321 Value *PrevVal = TI->getOperand(0);
3322 ResultReg = getRegForValue(PrevVal);
3327 if (!isTypeLegal(PrevVal->
getType(), VT))
3330 ResultReg = fastEmit_ri(VT, VT,
ISD::AND, ResultReg, 1);
3334 ResultReg = getRegForValue(Val);
3347 CCState CCInfo(CC, IsVarArg, *FuncInfo.MF, ArgLocs, CLI.RetTy->getContext());
3351 CCInfo.AllocateStack(32,
Align(8));
3353 CCInfo.AnalyzeCallOperands(OutVTs, OutFlags, ArgTys,
CC_X86);
3356 unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
3359 unsigned AdjStackDown =
TII.getCallFrameSetupOpcode();
3360 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackDown))
3364 const X86RegisterInfo *RegInfo = Subtarget->getRegisterInfo();
3365 for (
const CCValAssign &VA : ArgLocs) {
3369 if (ArgVT == MVT::x86mmx)
3379 "Unexpected extend");
3381 if (ArgVT == MVT::i1)
3386 assert(Emitted &&
"Failed to emit a sext!"); (void)Emitted;
3392 "Unexpected extend");
3395 if (ArgVT == MVT::i1) {
3397 ArgReg = fastEmitZExtFromI1(MVT::i8, ArgReg);
3406 assert(Emitted &&
"Failed to emit a zext!"); (void)Emitted;
3412 "Unexpected extend");
3422 assert(Emitted &&
"Failed to emit a aext!"); (void)Emitted;
3428 assert(ArgReg &&
"Failed to emit a bitcast!");
3449 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3462 AM.
Disp = LocMemOffset;
3465 MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
3468 if (
Flags.isByVal()) {
3469 X86AddressMode SrcAM;
3471 if (!TryEmitSmallMemcpy(AM, SrcAM,
Flags.getByValSize()))
3477 if (!X86FastEmitStore(ArgVT, ArgVal, AM, MMO))
3480 if (!X86FastEmitStore(ArgVT, ArgReg, AM, MMO))
3488 if (Subtarget->isPICStyleGOT()) {
3489 Register Base = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
3490 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3494 if (Is64Bit && IsVarArg && !IsWin64) {
3505 X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,
3506 X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
3508 unsigned NumXMMRegs = CCInfo.getFirstUnallocated(XMMArgRegs);
3509 assert((Subtarget->hasSSE1() || !NumXMMRegs)
3510 &&
"SSE registers cannot be used when SSE is disabled");
3511 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV8ri),
3512 X86::AL).
addImm(NumXMMRegs);
3517 X86AddressMode CalleeAM;
3518 if (!X86SelectCallAddress(Callee, CalleeAM))
3522 const GlobalValue *GV =
nullptr;
3523 if (CalleeAM.
GV !=
nullptr) {
3525 }
else if (CalleeAM.
Base.
Reg) {
3531 MachineInstrBuilder MIB;
3534 unsigned CallOpc = Is64Bit ? X86::CALL64r : X86::CALL32r;
3535 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CallOpc))
3539 assert(GV &&
"Not a direct call");
3541 unsigned char OpFlags = Subtarget->classifyGlobalFunctionReference(GV);
3553 unsigned CallOpc = NeedLoad
3554 ? (Is64Bit ? X86::CALL64m : X86::CALL32m)
3555 : (Is64Bit ?
X86::CALL64pcrel32 :
X86::CALLpcrel32);
3557 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CallOpc));
3561 MIB.
addSym(Symbol, OpFlags);
3573 if (Subtarget->isPICStyleGOT())
3574 MIB.
addReg(X86::EBX, RegState::Implicit);
3576 if (Is64Bit && IsVarArg && !IsWin64)
3577 MIB.
addReg(X86::AL, RegState::Implicit);
3580 for (
auto Reg : OutRegs)
3584 unsigned NumBytesForCalleeToPop =
3586 TM.Options.GuaranteedTailCallOpt)
3589 unsigned AdjStackUp =
TII.getCallFrameDestroyOpcode();
3590 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackUp))
3595 CCState CCRetInfo(CC, IsVarArg, *FuncInfo.MF, RVLocs,
3596 CLI.RetTy->getContext());
3597 CCRetInfo.AnalyzeCallResult(Ins,
RetCC_X86);
3600 Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);
3601 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
3602 CCValAssign &VA = RVLocs[i];
3608 if ((CopyVT == MVT::f32 || CopyVT == MVT::f64) &&
3609 ((Is64Bit || Ins[i].
Flags.isInReg()) && !Subtarget->hasSSE1())) {
3615 if ((SrcReg == X86::FP0 || SrcReg == X86::FP1) &&
3616 isScalarFPTypeInSSEReg(VA.
getValVT())) {
3618 CopyReg = createResultReg(&X86::RFP80RegClass);
3622 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3623 TII.get(TargetOpcode::COPY), CopyReg).
addReg(SrcReg);
3631 unsigned Opc = ResVT == MVT::f32 ? X86::ST_Fp80m32 : X86::ST_Fp80m64;
3637 Opc = ResVT == MVT::f32 ? X86::MOVSSrm_alt : X86::MOVSDrm_alt;
3639 TII.get(
Opc), ResultReg + i), FI);
3643 CLI.ResultReg = ResultReg;
3644 CLI.NumResultRegs = RVLocs.
size();
3648 if (TM.Options.EmitCallGraphSection && CB && CB->isIndirectCall()) {
3649 MachineFunction::CallSiteInfo CSInfo(*CB);
3657X86FastISel::fastSelectInstruction(
const Instruction *
I) {
3658 switch (
I->getOpcode()) {
3660 case Instruction::Load:
3661 return X86SelectLoad(
I);
3662 case Instruction::Store:
3663 return X86SelectStore(
I);
3664 case Instruction::Ret:
3665 return X86SelectRet(
I);
3666 case Instruction::ICmp:
3667 case Instruction::FCmp:
3668 return X86SelectCmp(
I);
3669 case Instruction::ZExt:
3670 return X86SelectZExt(
I);
3671 case Instruction::SExt:
3672 return X86SelectSExt(
I);
3673 case Instruction::CondBr:
3674 return X86SelectBranch(
I);
3675 case Instruction::LShr:
3676 case Instruction::AShr:
3677 case Instruction::Shl:
3678 return X86SelectShift(
I);
3679 case Instruction::SDiv:
3680 case Instruction::UDiv:
3681 case Instruction::SRem:
3682 case Instruction::URem:
3683 return X86SelectDivRem(
I);
3684 case Instruction::Select:
3685 return X86SelectSelect(
I);
3686 case Instruction::Trunc:
3687 return X86SelectTrunc(
I);
3688 case Instruction::FPExt:
3689 return X86SelectFPExt(
I);
3690 case Instruction::FPTrunc:
3691 return X86SelectFPTrunc(
I);
3692 case Instruction::SIToFP:
3693 return X86SelectSIToFP(
I);
3694 case Instruction::UIToFP:
3695 return X86SelectUIToFP(
I);
3696 case Instruction::IntToPtr:
3697 case Instruction::PtrToInt: {
3698 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
3699 EVT DstVT = TLI.getValueType(
DL,
I->getType());
3701 return X86SelectZExt(
I);
3703 return X86SelectTrunc(
I);
3707 updateValueMap(
I,
Reg);
3710 case Instruction::BitCast:
3711 return X86SelectBitCast(
I);
3717Register X86FastISel::X86MaterializeInt(
const ConstantInt *CI, MVT VT) {
3723 Register SrcReg = fastEmitInst_(X86::MOV32r0, &X86::GR32RegClass);
3728 return fastEmitInst_extractsubreg(MVT::i8, SrcReg, X86::sub_8bit);
3730 return fastEmitInst_extractsubreg(MVT::i16, SrcReg, X86::sub_16bit);
3734 Register ResultReg = createResultReg(&X86::GR64RegClass);
3735 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3736 TII.get(TargetOpcode::SUBREG_TO_REG), ResultReg)
3750 case MVT::i8:
Opc = X86::MOV8ri;
break;
3751 case MVT::i16:
Opc = X86::MOV16ri;
break;
3752 case MVT::i32:
Opc = X86::MOV32ri;
break;
3755 Opc = X86::MOV32ri64;
3757 Opc = X86::MOV64ri32;
3763 return fastEmitInst_i(
Opc, TLI.getRegClassFor(VT), Imm);
3766Register X86FastISel::X86MaterializeFP(
const ConstantFP *CFP, MVT VT) {
3768 return fastMaterializeFloatZero(CFP);
3778 bool HasSSE1 = Subtarget->hasSSE1();
3779 bool HasSSE2 = Subtarget->hasSSE2();
3780 bool HasAVX = Subtarget->hasAVX();
3781 bool HasAVX512 = Subtarget->hasAVX512();
3786 Opc = HasAVX512 ? X86::VMOVSSZrm_alt
3787 : HasAVX ? X86::VMOVSSrm_alt
3788 : HasSSE1 ? X86::MOVSSrm_alt
3792 Opc = HasAVX512 ? X86::VMOVSDZrm_alt
3793 : HasAVX ? X86::VMOVSDrm_alt
3794 : HasSSE2 ? X86::MOVSDrm_alt
3807 unsigned char OpFlag = Subtarget->classifyLocalReference(
nullptr);
3809 PICBase = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
3811 PICBase = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
3816 unsigned CPI = MCP.getConstantPoolIndex(CFP, Alignment);
3821 Register AddrReg = createResultReg(&X86::GR64RegClass);
3822 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV64ri),
3825 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3826 TII.get(
Opc), ResultReg);
3827 addRegReg(MIB, AddrReg,
false, X86::NoSubRegister, PICBase,
false,
3828 X86::NoSubRegister);
3829 MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
3837 TII.get(
Opc), ResultReg),
3838 CPI, PICBase, OpFlag);
3842Register X86FastISel::X86MaterializeGV(
const GlobalValue *GV, MVT VT) {
3847 if (TM.isLargeGlobalValue(GV))
3859 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3861 TLI.getPointerTy(
DL) == MVT::i64) {
3864 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV64ri),
3869 TLI.getPointerTy(
DL) == MVT::i32
3870 ? (Subtarget->isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r)
3873 TII.get(
Opc), ResultReg), AM);
3880Register X86FastISel::fastMaterializeConstant(
const Constant *
C) {
3881 EVT CEVT = TLI.getValueType(
DL,
C->getType(),
true);
3889 return X86MaterializeInt(CI, VT);
3891 return X86MaterializeFP(CFP, VT);
3893 return X86MaterializeGV(GV, VT);
3900 if (!Subtarget->hasSSE1())
3901 Opc = X86::LD_Fp032;
3904 if (!Subtarget->hasSSE2())
3905 Opc = X86::LD_Fp064;
3908 Opc = X86::LD_Fp080;
3913 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3914 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc),
3923Register X86FastISel::fastMaterializeAlloca(
const AllocaInst *
C) {
3931 if (!FuncInfo.StaticAllocaMap.count(
C))
3933 assert(
C->isStaticAlloca() &&
"dynamic alloca in the static alloca map?");
3939 TLI.getPointerTy(
DL) == MVT::i32
3940 ? (Subtarget->isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r)
3942 const TargetRegisterClass *RC = TLI.getRegClassFor(TLI.getPointerTy(
DL));
3943 Register ResultReg = createResultReg(RC);
3945 TII.get(
Opc), ResultReg), AM);
3949Register X86FastISel::fastMaterializeFloatZero(
const ConstantFP *CF) {
3951 if (!isTypeLegal(CF->
getType(), VT))
3955 bool HasSSE1 = Subtarget->hasSSE1();
3956 bool HasSSE2 = Subtarget->hasSSE2();
3957 bool HasAVX512 = Subtarget->hasAVX512();
3962 Opc = HasAVX512 ? X86::AVX512_FsFLD0SH : X86::FsFLD0SH;
3965 Opc = HasAVX512 ? X86::AVX512_FsFLD0SS
3966 : HasSSE1 ? X86::FsFLD0SS
3970 Opc = HasAVX512 ? X86::AVX512_FsFLD0SD
3971 : HasSSE2 ? X86::FsFLD0SD
3979 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3980 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg);
3984bool X86FastISel::tryToFoldLoadIntoMI(MachineInstr *
MI,
unsigned OpNo,
3985 const LoadInst *LI) {
3991 const X86InstrInfo &XII = (
const X86InstrInfo &)
TII;
3998 MachineInstr *CopyMI =
nullptr;
4000 *FuncInfo.MF, *
MI, OpNo, AddrOps, FuncInfo.InsertPt,
Size, LI->
getAlign(),
4010 unsigned OperandNo = 0;
4012 E =
Result->operands_end();
I !=
E; ++
I, ++OperandNo) {
4013 MachineOperand &MO = *
I;
4019 if (IndexReg == MO.
getReg())
4025 FuncInfo.MF->moveAdditionalCallInfo(
MI, Result);
4026 Result->addMemOperand(*FuncInfo.MF, createMachineMemOperandFor(LI));
4027 Result->cloneInstrSymbols(*FuncInfo.MF, *
MI);
4029 removeDeadCode(
I, std::next(
I));
4033Register X86FastISel::fastEmitInst_rrrr(
unsigned MachineInstOpcode,
4034 const TargetRegisterClass *RC,
4037 const MCInstrDesc &
II =
TII.get(MachineInstOpcode);
4039 Register ResultReg = createResultReg(RC);
4045 if (
II.getNumDefs() >= 1)
4046 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
4052 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
4057 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
4068 return new X86FastISel(funcInfo, libInfo, libcallLowering);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file defines the FastISel class.
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
Register const TargetRegisterInfo * TRI
Promote Memory to Register
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > & Cond
#define GET_EGPR_IF_ENABLED(OPC)
static unsigned X86ChooseCmpImmediateOpcode(EVT VT, const ConstantInt *RHSC)
If we have a comparison with RHS as the RHS of the comparison, return an opcode that works for the co...
static std::pair< unsigned, bool > getX86SSEConditionCode(CmpInst::Predicate Predicate)
static unsigned computeBytesPoppedByCalleeForSRet(const X86Subtarget *Subtarget, CallingConv::ID CC, const CallBase *CB)
static unsigned X86ChooseCmpOpcode(EVT VT, const X86Subtarget *Subtarget)
static bool X86SelectAddress(MachineInstr &I, const X86TargetMachine &TM, const MachineRegisterInfo &MRI, const X86Subtarget &STI, X86AddressMode &AM)
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
LLVM_ABI APInt sext(unsigned width) const
Sign extend to a new width.
InstListType::const_iterator const_iterator
Register getLocReg() const
LocInfo getLocInfo() const
int64_t getLocMemOffset() const
unsigned getValNo() const
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
LLVM_ABI bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
This class is the base class for the comparison instructions.
Predicate
This enumeration lists the possible predicates for CmpInst subclasses.
@ FCMP_OEQ
0 0 0 1 True if ordered and equal
@ FCMP_TRUE
1 1 1 1 Always true (always folded)
@ FCMP_OLT
0 1 0 0 True if ordered and less than
@ FCMP_ULE
1 1 0 1 True if unordered, less than, or equal
@ FCMP_OGT
0 0 1 0 True if ordered and greater than
@ FCMP_OGE
0 0 1 1 True if ordered and greater than or equal
@ FCMP_ULT
1 1 0 0 True if unordered or less than
@ FCMP_ONE
0 1 1 0 True if ordered and operands are unequal
@ FCMP_UEQ
1 0 0 1 True if unordered or equal
@ FCMP_UGT
1 0 1 0 True if unordered or greater than
@ FCMP_OLE
0 1 0 1 True if ordered and less than or equal
@ FCMP_ORD
0 1 1 1 True if ordered (no nans)
@ FCMP_UNE
1 1 1 0 True if unordered or not equal
@ FCMP_UGE
1 0 1 1 True if unordered, greater than, or equal
@ FCMP_FALSE
0 0 0 0 Always false (always folded)
@ FCMP_UNO
1 0 0 0 True if unordered: isnan(X) | isnan(Y)
Predicate getInversePredicate() const
For example, EQ -> NE, UGT -> ULE, SLT -> SGE, OEQ -> UNE, UGT -> OLE, OLT -> UGE,...
Value * getCondition() const
BasicBlock * getSuccessor(unsigned i) const
This is the shared class of boolean and integer constants.
bool isOne() const
This is just a convenience method to make client code smaller for a common case.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
unsigned getBitWidth() const
getBitWidth - Return the scalar bitwidth of this constant.
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
const APInt & getValue() const
Return the constant as an APInt value reference.
bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
bool isValidLocationForIntrinsic(const DILocation *DL) const
Check that a location is valid for this variable.
Value * getAddress() const
DILocalVariable * getVariable() const
DIExpression * getExpression() const
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...
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
Tracks which library functions to use for a particular subtarget.
Value * getPointerOperand()
Align getAlign() const
Return the alignment of the access that is being performed.
bool usesWindowsCFI() const
bool isVectorOf(MVT EltVT) const
Return true if this is a vector with matching element type.
bool isVector() const
Return true if this is a vector value type.
bool isInteger() const
Return true if this is an integer or a vector integer type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
TypeSize getStoreSize() const
Return the number of bytes overwritten by a store of the specified value type.
MVT getVectorElementType() const
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setFrameAddressIsTaken(bool T)
void setStackProtectorIndex(int I)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
Function & getFunction()
Return the LLVM function that this machine code represents.
void addCallSiteInfo(const MachineInstr *CallI, CallSiteInfo &&CallInfo)
Start tracking the arguments passed to the call CallI.
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
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 & addMetadata(const MDNode *MD) const
const MachineInstrBuilder & addSym(MCSymbol *Sym, unsigned char TargetFlags=0) const
const MachineInstrBuilder & addConstantPoolIndex(unsigned Idx, int Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addRegMask(const uint32_t *Mask) const
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
unsigned getNumOperands() const
Retuns the total number of operands.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
MachineOperand * mop_iterator
iterator/begin/end - Iterate over all operands of a machine instruction.
LLVM_ABI void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
bool isNonTemporal() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
LLVM_ABI void setReg(Register Reg)
Change the register this operand corresponds to.
Register getReg() const
getReg - Returns the register number.
Value * getLength() const
Value * getRawDest() const
unsigned getDestAddressSpace() const
Value * getRawSource() const
Return the arguments to the instruction.
unsigned getSourceAddressSpace() const
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
Wrapper class representing virtual and physical registers.
void push_back(const T &Elt)
Value * getValueOperand()
Value * getPointerOperand()
TypeSize getElementOffset(unsigned Idx) const
Provides information about what library functions are available for the current target.
const MCAsmInfo & getMCAsmInfo() const
Return target specific asm information.
bool contains(Register Reg) const
Return true if the specified register is included in this register class.
bool isOSMSVCRT() const
Is this a "Windows" OS targeting a "MSVCRT.dll" environment.
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 unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isIntegerTy() const
True if this is an instance of IntegerType.
const Use * const_op_iterator
Value * getOperand(unsigned i) const
unsigned getNumOperands() const
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
bool hasOneUse() const
Return true if there is exactly one use of this value.
LLVMContext & getContext() const
All values hold a context through their type.
MachineInstr * foldMemoryOperandImpl(MachineFunction &MF, MachineInstr &MI, ArrayRef< unsigned > Ops, int FrameIndex, MachineInstr *&CopyMI, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
Fold a load or store of the specified stack slot into the specified machine instruction for the speci...
Register getSRetReturnReg() const
unsigned getBytesToPopOnReturn() const
Register getPtrSizedFrameRegister(const MachineFunction &MF) const
Register getStackRegister() const
const Triple & getTargetTriple() const
StructType * getStructTypeOrNull() const
TypeSize getSequentialElementStride(const DataLayout &DL) const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ HiPE
Used by the High-Performance Erlang Compiler (HiPE).
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ Fast
Attempts to make calls as fast as possible (e.g.
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
@ SwiftTail
This follows the Swift calling convention in how arguments are passed but guarantees tail calls will ...
@ C
The default llvm calling convention, compatible with C.
NodeType
ISD::NodeType enum - This enum defines the target-independent operators for a SelectionDAG.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
@ BasicBlock
Various leaf nodes.
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ AND
Bitwise operators - logical and, logical or, logical xor.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Predicate
Predicate - These are "(BI << 5) | BO" for various predicates.
@ X86
Windows x64, Windows Itanium (IA-64)
@ MO_GOTPCREL_NORELAX
MO_GOTPCREL_NORELAX - Same as MO_GOTPCREL except that R_X86_64_GOTPCREL relocations are guaranteed to...
@ MO_GOTOFF
MO_GOTOFF - On a symbol operand this indicates that the immediate is the offset to the location of th...
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
@ MO_PLT
MO_PLT - On a symbol operand this indicates that the immediate is offset to the PLT entry of symbol n...
@ MO_NO_FLAG
MO_NO_FLAG - No flag for the operand.
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand "FOO", this indicates that the reference is actually to the "__imp...
@ MO_PIC_BASE_OFFSET
MO_PIC_BASE_OFFSET - On a symbol operand this indicates that the immediate should get the value of th...
@ MO_GOTPCREL
MO_GOTPCREL - On a symbol operand this indicates that the immediate is offset to the GOT entry for th...
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo, const LibcallLoweringInfo *libcallLowering)
std::pair< CondCode, bool > getX86ConditionCode(CmpInst::Predicate Predicate)
Return a pair of condition code for the given predicate and whether the instruction operands should b...
bool isCalleePop(CallingConv::ID CallingConv, bool is64Bit, bool IsVarArg, bool GuaranteeTCO)
Determines whether the callee is required to pop its own arguments.
unsigned getCMovOpcode(unsigned RegBytes, bool HasMemoryOperand=false, bool HasNDD=false)
Return a cmov opcode for the given register size in bytes, and operand type.
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
@ User
could "use" a pointer
@ Emitted
Assigned address, still materializing.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
static bool isGlobalStubReference(unsigned char TargetFlag)
isGlobalStubReference - Return true if the specified TargetFlag operand is a reference to a stub for ...
FunctionAddr VTableAddr Value
static bool isGlobalRelativeToPICBase(unsigned char TargetFlag)
isGlobalRelativeToPICBase - Return true if the specified global value reference is relative to a 32-b...
LLVM_ABI Register constrainOperandRegClass(const MachineFunction &MF, const TargetRegisterInfo &TRI, MachineRegisterInfo &MRI, const TargetInstrInfo &TII, const RegisterBankInfo &RBI, MachineInstr &InsertPt, const TargetRegisterClass &RegClass, MachineOperand &RegMO)
Constrain the Register operand OpIdx, so that it is now constrained to the TargetRegisterClass passed...
LLVM_ABI void GetReturnInfo(CallingConv::ID CC, Type *ReturnType, AttributeList attr, SmallVectorImpl< ISD::OutputArg > &Outs, const TargetLowering &TLI, const DataLayout &DL)
Given an LLVM IR type and return type attributes, compute the return value EVTs and flags,...
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
constexpr RegState getKillRegState(bool B)
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
auto successors(const MachineBasicBlock *BB)
static const MachineInstrBuilder & addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI, Register GlobalBaseReg, unsigned char OpFlags)
addConstantPoolReference - This function is used to add a reference to the base of a constant value s...
static const MachineInstrBuilder & addRegReg(const MachineInstrBuilder &MIB, Register Reg1, bool isKill1, unsigned SubReg1, Register Reg2, bool isKill2, unsigned SubReg2)
addRegReg - This function is used to add a memory reference of the form: [Reg + Reg].
static const MachineInstrBuilder & addFrameReference(const MachineInstrBuilder &MIB, int FI, int Offset=0, bool mem=true)
addFrameReference - This function is used to add a reference to the base of an abstract object on the...
static const MachineInstrBuilder & addFullAddress(const MachineInstrBuilder &MIB, const X86AddressMode &AM)
LLVM_ABI void ComputeValueTypes(const DataLayout &DL, Type *Ty, SmallVectorImpl< Type * > &Types, SmallVectorImpl< TypeSize > *Offsets=nullptr, TypeSize StartingOffset=TypeSize::getZero())
Given an LLVM IR type, compute non-aggregate subtypes.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
generic_gep_type_iterator<> gep_type_iterator
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
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...
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
DWARFExpression::Operation Op
bool CC_X86(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
bool RetCC_X86(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, Type *OrigTy, CCState &State)
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)
static const MachineInstrBuilder & addDirectMem(const MachineInstrBuilder &MIB, Register Reg)
addDirectMem - This function is used to add a direct memory reference to the current instruction – th...
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
constexpr uint64_t value() const
This is a hole in the type system and should not be abused.
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
bool bitsGT(EVT VT) const
Return true if this has more bits than VT.
bool bitsLT(EVT VT) const
Return true if this has less bits than VT.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
static LLVM_ABI MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
X86AddressMode - This struct holds a generalized full x86 address mode.
void getFullAddress(SmallVectorImpl< MachineOperand > &MO)
union llvm::X86AddressMode::BaseUnion Base
enum llvm::X86AddressMode::@202116273335065351270200035056227005202106004277 BaseType