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 DenseMap<const Value *, Register>::iterator
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 DenseMap<const AllocaInst *, int>::iterator
SI =
878 FuncInfo.StaticAllocaMap.find(
A);
879 if (SI != FuncInfo.StaticAllocaMap.end()) {
887 case Instruction::Add: {
890 uint64_t Disp = (int32_t)AM.
Disp + (uint64_t)CI->getSExtValue();
893 AM.
Disp = (uint32_t)Disp;
900 case Instruction::GetElementPtr: {
901 X86AddressMode SavedAM = AM;
904 uint64_t Disp = (int32_t)AM.
Disp;
906 unsigned Scale = AM.
Scale;
907 MVT PtrVT = TLI.getValueType(
DL,
U->getType()).getSimpleVT();
913 i != e; ++i, ++GTI) {
916 const StructLayout *SL =
DL.getStructLayout(STy);
927 Disp += CI->getSExtValue() * S;
930 if (canFoldAddIntoGEP(U,
Op)) {
939 if (!IndexReg && (!AM.
GV || !Subtarget->isPICStyleRIPRel()) &&
940 (S == 1 || S == 2 || S == 4 || S == 8)) {
943 IndexReg = getRegForGEPIndex(PtrVT,
Op);
949 goto unsupported_gep;
959 AM.
Disp = (uint32_t)Disp;
962 if (
const GetElementPtrInst *
GEP =
977 if (handleConstantAddresses(
I, AM))
987 return handleConstantAddresses(V, AM);
992bool X86FastISel::X86SelectCallAddress(
const Value *V, X86AddressMode &AM) {
993 const User *
U =
nullptr;
994 unsigned Opcode = Instruction::UserOp1;
1021 Opcode =
I->getOpcode();
1023 InMBB =
I->getParent() == FuncInfo.MBB->getBasicBlock();
1025 Opcode =
C->getOpcode();
1031 case Instruction::BitCast:
1034 return X86SelectCallAddress(
U->getOperand(0), AM);
1037 case Instruction::IntToPtr:
1040 TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
1041 TLI.getPointerTy(
DL))
1042 return X86SelectCallAddress(
U->getOperand(0), AM);
1045 case Instruction::PtrToInt:
1047 if (InMBB && TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
1048 return X86SelectCallAddress(
U->getOperand(0), AM);
1060 if (Subtarget->isPICStyleRIPRel() &&
1066 if (GVar->isThreadLocal())
1075 if (Subtarget->isPICStyleRIPRel()) {
1081 AM.
GVOpFlags = Subtarget->classifyLocalReference(
nullptr);
1088 if (!AM.
GV || !Subtarget->isPICStyleRIPRel()) {
1089 auto GetCallRegForValue = [
this](
const Value *
V) {
1093 if (
Reg && Subtarget->isTarget64BitILP32()) {
1094 Register CopyReg = createResultReg(&X86::GR32RegClass);
1095 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV32rr),
1099 Register ExtReg = createResultReg(&X86::GR64RegClass);
1100 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1101 TII.get(TargetOpcode::SUBREG_TO_REG), ExtReg)
1111 AM.
Base.
Reg = GetCallRegForValue(V);
1116 AM.
IndexReg = GetCallRegForValue(V);
1126bool X86FastISel::X86SelectStore(
const Instruction *
I) {
1133 const Value *PtrV =
I->getOperand(1);
1134 if (TLI.supportSwiftError()) {
1138 if (Arg->hasSwiftErrorAttr())
1143 if (Alloca->isSwiftError())
1152 if (!isTypeLegal(Val->
getType(), VT,
true))
1157 bool Aligned = Alignment >= ABIAlignment;
1163 return X86FastEmitStore(VT, Val, AM, createMachineMemOperandFor(
I),
Aligned);
1167bool X86FastISel::X86SelectRet(
const Instruction *
I) {
1169 const Function &
F = *
I->getParent()->getParent();
1170 const X86MachineFunctionInfo *X86MFInfo =
1171 FuncInfo.MF->getInfo<X86MachineFunctionInfo>();
1173 if (!FuncInfo.CanLowerReturn)
1176 if (TLI.supportSwiftError() &&
1177 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
1180 if (TLI.supportSplitCSR(FuncInfo.MF))
1183 CallingConv::ID CC =
F.getCallingConv();
1184 if (CC != CallingConv::C &&
1185 CC != CallingConv::Fast &&
1186 CC != CallingConv::Tail &&
1187 CC != CallingConv::SwiftTail &&
1188 CC != CallingConv::X86_FastCall &&
1189 CC != CallingConv::X86_StdCall &&
1190 CC != CallingConv::X86_ThisCall &&
1191 CC != CallingConv::X86_64_SysV &&
1192 CC != CallingConv::Win64)
1201 if ((CC == CallingConv::Fast && TM.Options.GuaranteedTailCallOpt) ||
1202 CC == CallingConv::Tail || CC == CallingConv::SwiftTail)
1218 CCState CCInfo(CC,
F.isVarArg(), *FuncInfo.MF, ValLocs,
I->getContext());
1227 if (ValLocs.
size() != 1)
1230 CCValAssign &VA = ValLocs[0];
1245 EVT SrcVT = TLI.getValueType(
DL, RV->
getType());
1248 if (SrcVT != DstVT) {
1249 if (SrcVT != MVT::i1 && SrcVT != MVT::i8 && SrcVT != MVT::i16)
1252 if (!Outs[0].
Flags.isZExt() && !Outs[0].Flags.isSExt())
1255 if (SrcVT == MVT::i1) {
1256 if (Outs[0].
Flags.isSExt())
1258 SrcReg = fastEmitZExtFromI1(MVT::i8, SrcReg);
1261 if (SrcVT != DstVT) {
1271 const TargetRegisterClass *SrcRC = MRI.getRegClass(SrcReg);
1275 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1276 TII.get(TargetOpcode::COPY), DstReg).
addReg(SrcReg);
1289 if (
F.hasStructRetAttr() && CC != CallingConv::Swift &&
1290 CC != CallingConv::SwiftTail) {
1293 "SRetReturnReg should have been set in LowerFormalArguments()!");
1294 Register RetReg = Subtarget->isTarget64BitLP64() ? X86::RAX : X86::EAX;
1295 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1301 MachineInstrBuilder MIB;
1303 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1304 TII.get(Subtarget->is64Bit() ? X86::RETI64 : X86::RETI32))
1307 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1308 TII.get(Subtarget->is64Bit() ? X86::RET64 : X86::RET32));
1317bool X86FastISel::X86SelectLoad(
const Instruction *
I) {
1324 const Value *SV =
I->getOperand(0);
1325 if (TLI.supportSwiftError()) {
1329 if (Arg->hasSwiftErrorAttr())
1334 if (Alloca->isSwiftError())
1340 if (!isTypeLegal(LI->
getType(), VT,
true))
1350 if (!X86FastEmitLoad(VT, AM, createMachineMemOperandFor(LI), ResultReg,
1354 updateValueMap(
I, ResultReg);
1359 bool HasAVX512 = Subtarget->
hasAVX512();
1360 bool HasAVX = Subtarget->
hasAVX();
1361 bool HasSSE1 = Subtarget->
hasSSE1();
1362 bool HasSSE2 = Subtarget->
hasSSE2();
1366 case MVT::i8:
return X86::CMP8rr;
1367 case MVT::i16:
return X86::CMP16rr;
1368 case MVT::i32:
return X86::CMP32rr;
1369 case MVT::i64:
return X86::CMP64rr;
1371 return HasAVX512 ? X86::VUCOMISSZrr
1372 : HasAVX ? X86::VUCOMISSrr
1373 : HasSSE1 ? X86::UCOMISSrr
1376 return HasAVX512 ? X86::VUCOMISDZrr
1377 : HasAVX ? X86::VUCOMISDrr
1378 : HasSSE2 ? X86::UCOMISDrr
1393 return X86::CMP16ri;
1395 return X86::CMP32ri;
1403bool X86FastISel::X86FastEmitCompare(
const Value *Op0,
const Value *Op1, EVT VT,
1405 Register Op0Reg = getRegForValue(Op0);
1418 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, CurMIMD,
TII.get(CompareImmOpc))
1420 .
addImm(Op1C->getSExtValue());
1426 if (CompareOpc == 0)
return false;
1428 Register Op1Reg = getRegForValue(Op1);
1431 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, CurMIMD,
TII.get(CompareOpc))
1439 ((!Subtarget->hasZU() || Subtarget->preferLegacySetCC()) ? X86::SETCCr \
1446 if (!isTypeLegal(
I->getOperand(0)->getType(), VT))
1459 ResultReg = createResultReg(&X86::GR32RegClass);
1460 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV32r0),
1462 ResultReg = fastEmitInst_extractsubreg(MVT::i8, ResultReg, X86::sub_8bit);
1468 ResultReg = createResultReg(&X86::GR8RegClass);
1469 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV8ri),
1476 updateValueMap(
I, ResultReg);
1488 if (RHSC && RHSC->isNullValue())
1493 static const uint16_t SETFOpcTable[2][3] = {
1504 ResultReg = createResultReg(&X86::GR8RegClass);
1506 if (!X86FastEmitCompare(
LHS,
RHS, VT,
I->getDebugLoc()))
1509 Register FlagReg1 = createResultReg(&X86::GR8RegClass);
1510 Register FlagReg2 = createResultReg(&X86::GR8RegClass);
1517 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(SETFOpc[2]),
1519 updateValueMap(
I, ResultReg);
1532 if (!X86FastEmitCompare(
LHS,
RHS, VT,
I->getDebugLoc()))
1537 updateValueMap(
I, ResultReg);
1541bool X86FastISel::X86SelectZExt(
const Instruction *
I) {
1542 EVT DstVT = TLI.getValueType(
DL,
I->getType());
1543 if (!TLI.isTypeLegal(DstVT))
1546 Register ResultReg = getRegForValue(
I->getOperand(0));
1551 MVT SrcVT = TLI.getSimpleValueType(
DL,
I->getOperand(0)->getType());
1552 if (SrcVT == MVT::i1) {
1554 ResultReg = fastEmitZExtFromI1(MVT::i8, ResultReg);
1561 if (DstVT == MVT::i64) {
1566 case MVT::i8: MovInst = X86::MOVZX32rr8;
break;
1567 case MVT::i16: MovInst = X86::MOVZX32rr16;
break;
1568 case MVT::i32: MovInst = X86::MOV32rr;
break;
1572 Register Result32 = createResultReg(&X86::GR32RegClass);
1573 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(MovInst), Result32)
1576 ResultReg = createResultReg(&X86::GR64RegClass);
1577 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1578 TII.get(TargetOpcode::SUBREG_TO_REG), ResultReg)
1581 }
else if (DstVT == MVT::i16) {
1584 Register Result32 = createResultReg(&X86::GR32RegClass);
1585 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOVZX32rr8),
1586 Result32).
addReg(ResultReg);
1588 ResultReg = fastEmitInst_extractsubreg(MVT::i16, Result32, X86::sub_16bit);
1589 }
else if (DstVT != MVT::i8) {
1596 updateValueMap(
I, ResultReg);
1600bool X86FastISel::X86SelectSExt(
const Instruction *
I) {
1601 EVT DstVT = TLI.getValueType(
DL,
I->getType());
1602 if (!TLI.isTypeLegal(DstVT))
1605 Register ResultReg = getRegForValue(
I->getOperand(0));
1610 MVT SrcVT = TLI.getSimpleValueType(
DL,
I->getOperand(0)->getType());
1611 if (SrcVT == MVT::i1) {
1613 Register ZExtReg = fastEmitZExtFromI1(MVT::i8, ResultReg);
1618 ResultReg = createResultReg(&X86::GR8RegClass);
1619 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::NEG8r),
1620 ResultReg).
addReg(ZExtReg);
1625 if (DstVT == MVT::i16) {
1628 Register Result32 = createResultReg(&X86::GR32RegClass);
1629 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOVSX32rr8),
1630 Result32).
addReg(ResultReg);
1632 ResultReg = fastEmitInst_extractsubreg(MVT::i16, Result32, X86::sub_16bit);
1633 }
else if (DstVT != MVT::i8) {
1640 updateValueMap(
I, ResultReg);
1644bool X86FastISel::X86SelectBranch(
const Instruction *
I) {
1648 MachineBasicBlock *TrueMBB = FuncInfo.getMBB(BI->
getSuccessor(0));
1649 MachineBasicBlock *FalseMBB = FuncInfo.getMBB(BI->
getSuccessor(1));
1656 if (CI->
hasOneUse() && CI->getParent() ==
I->getParent()) {
1661 switch (Predicate) {
1676 if (CmpRHSC && CmpRHSC->isNullValue())
1681 if (FuncInfo.MBB->isLayoutSuccessor(TrueMBB)) {
1691 bool NeedExtraBranch =
false;
1692 switch (Predicate) {
1698 NeedExtraBranch =
true;
1711 if (!X86FastEmitCompare(CmpLHS, CmpRHS, VT, CI->getDebugLoc()))
1714 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1719 if (NeedExtraBranch) {
1720 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1724 finishCondBranch(BI->getParent(), TrueMBB, FalseMBB);
1731 if (TI->hasOneUse() && TI->getParent() ==
I->getParent() &&
1732 isTypeLegal(TI->getOperand(0)->getType(), SourceVT)) {
1733 unsigned TestOpc = 0;
1736 case MVT::i8: TestOpc = X86::TEST8ri;
break;
1737 case MVT::i16: TestOpc = X86::TEST16ri;
break;
1738 case MVT::i32: TestOpc = X86::TEST32ri;
break;
1739 case MVT::i64: TestOpc = X86::TEST64ri32;
break;
1742 Register OpReg = getRegForValue(TI->getOperand(0));
1746 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TestOpc))
1750 if (FuncInfo.MBB->isLayoutSuccessor(TrueMBB)) {
1755 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1758 finishCondBranch(BI->getParent(), TrueMBB, FalseMBB);
1762 }
else if (foldX86XALUIntrinsic(CC, BI, BI->
getCondition())) {
1769 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1771 finishCondBranch(BI->getParent(), TrueMBB, FalseMBB);
1783 if (MRI.getRegClass(OpReg) == &X86::VK1RegClass) {
1785 OpReg = createResultReg(&X86::GR32RegClass);
1786 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1787 TII.get(TargetOpcode::COPY), OpReg)
1789 OpReg = fastEmitInst_extractsubreg(MVT::i8, OpReg, X86::sub_8bit);
1791 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TEST8ri))
1794 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1796 finishCondBranch(BI->getParent(), TrueMBB, FalseMBB);
1800bool X86FastISel::X86SelectShift(
const Instruction *
I) {
1803 const TargetRegisterClass *RC =
nullptr;
1804 if (
I->getType()->isIntegerTy(8)) {
1806 RC = &X86::GR8RegClass;
1807 switch (
I->getOpcode()) {
1808 case Instruction::LShr: OpReg = X86::SHR8rCL;
break;
1809 case Instruction::AShr: OpReg = X86::SAR8rCL;
break;
1810 case Instruction::Shl: OpReg = X86::SHL8rCL;
break;
1811 default:
return false;
1813 }
else if (
I->getType()->isIntegerTy(16)) {
1815 RC = &X86::GR16RegClass;
1816 switch (
I->getOpcode()) {
1818 case Instruction::LShr: OpReg = X86::SHR16rCL;
break;
1819 case Instruction::AShr: OpReg = X86::SAR16rCL;
break;
1820 case Instruction::Shl: OpReg = X86::SHL16rCL;
break;
1822 }
else if (
I->getType()->isIntegerTy(32)) {
1824 RC = &X86::GR32RegClass;
1825 switch (
I->getOpcode()) {
1827 case Instruction::LShr: OpReg = X86::SHR32rCL;
break;
1828 case Instruction::AShr: OpReg = X86::SAR32rCL;
break;
1829 case Instruction::Shl: OpReg = X86::SHL32rCL;
break;
1831 }
else if (
I->getType()->isIntegerTy(64)) {
1833 RC = &X86::GR64RegClass;
1834 switch (
I->getOpcode()) {
1836 case Instruction::LShr: OpReg = X86::SHR64rCL;
break;
1837 case Instruction::AShr: OpReg = X86::SAR64rCL;
break;
1838 case Instruction::Shl: OpReg = X86::SHL64rCL;
break;
1845 if (!isTypeLegal(
I->getType(), VT))
1848 Register Op0Reg = getRegForValue(
I->getOperand(0));
1852 Register Op1Reg = getRegForValue(
I->getOperand(1));
1855 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
1860 if (CReg != X86::CL)
1861 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1862 TII.get(TargetOpcode::KILL), X86::CL)
1863 .
addReg(CReg, RegState::Kill);
1865 Register ResultReg = createResultReg(RC);
1866 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(OpReg), ResultReg)
1868 updateValueMap(
I, ResultReg);
1872bool X86FastISel::X86SelectDivRem(
const Instruction *
I) {
1873 const static unsigned NumTypes = 4;
1874 const static unsigned NumOps = 4;
1875 const static bool S =
true;
1876 const static bool U =
false;
1877 const static unsigned Copy = TargetOpcode::COPY;
1887 const static struct DivRemEntry {
1889 const TargetRegisterClass *RC;
1893 struct DivRemResult {
1895 unsigned OpSignExtend;
1899 unsigned DivRemResultReg;
1902 } OpTable[NumTypes] = {
1903 { &X86::GR8RegClass, X86::AX, 0, {
1904 { X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AL, S },
1905 { X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AH, S },
1906 { X86::DIV8r, 0, X86::MOVZX16rr8, X86::AL,
U },
1907 { X86::DIV8r, 0, X86::MOVZX16rr8, X86::AH,
U },
1910 { &X86::GR16RegClass, X86::AX, X86::DX, {
1911 { X86::IDIV16r, X86::CWD,
Copy, X86::AX, S },
1912 { X86::IDIV16r, X86::CWD,
Copy, X86::DX, S },
1913 { X86::DIV16r, X86::MOV32r0,
Copy, X86::AX,
U },
1914 { X86::DIV16r, X86::MOV32r0,
Copy, X86::DX,
U },
1917 { &X86::GR32RegClass, X86::EAX, X86::EDX, {
1918 { X86::IDIV32r, X86::CDQ,
Copy, X86::EAX, S },
1919 { X86::IDIV32r, X86::CDQ,
Copy, X86::EDX, S },
1920 { X86::DIV32r, X86::MOV32r0,
Copy, X86::EAX,
U },
1921 { X86::DIV32r, X86::MOV32r0,
Copy, X86::EDX,
U },
1924 { &X86::GR64RegClass, X86::RAX, X86::RDX, {
1925 { X86::IDIV64r, X86::CQO,
Copy, X86::RAX, S },
1926 { X86::IDIV64r, X86::CQO,
Copy, X86::RDX, S },
1927 { X86::DIV64r, X86::MOV32r0,
Copy, X86::RAX,
U },
1928 { X86::DIV64r, X86::MOV32r0,
Copy, X86::RDX,
U },
1934 if (!isTypeLegal(
I->getType(), VT))
1939 default:
return false;
1940 case MVT::i8: TypeIndex = 0;
break;
1941 case MVT::i16: TypeIndex = 1;
break;
1942 case MVT::i32: TypeIndex = 2;
break;
1943 case MVT::i64: TypeIndex = 3;
1944 if (!Subtarget->is64Bit())
1949 switch (
I->getOpcode()) {
1951 case Instruction::SDiv:
OpIndex = 0;
break;
1952 case Instruction::SRem:
OpIndex = 1;
break;
1953 case Instruction::UDiv:
OpIndex = 2;
break;
1954 case Instruction::URem:
OpIndex = 3;
break;
1957 const DivRemEntry &
TypeEntry = OpTable[TypeIndex];
1959 Register Op0Reg = getRegForValue(
I->getOperand(0));
1962 Register Op1Reg = getRegForValue(
I->getOperand(1));
1967 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1970 if (OpEntry.OpSignExtend) {
1971 if (OpEntry.IsOpSigned)
1972 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1973 TII.get(OpEntry.OpSignExtend));
1975 Register Zero32 = createResultReg(&X86::GR32RegClass);
1976 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1977 TII.get(X86::MOV32r0), Zero32);
1982 if (VT == MVT::i16) {
1983 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Copy),
1985 .
addReg(Zero32, {}, X86::sub_16bit);
1986 }
else if (VT == MVT::i32) {
1987 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1990 }
else if (VT == MVT::i64) {
1991 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1992 TII.get(TargetOpcode::SUBREG_TO_REG),
TypeEntry.HighInReg)
1999 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2000 TII.get(OpEntry.OpDivRem)).
addReg(Op1Reg);
2010 if ((
I->getOpcode() == Instruction::SRem ||
2011 I->getOpcode() == Instruction::URem) &&
2012 OpEntry.DivRemResultReg == X86::AH && Subtarget->is64Bit()) {
2013 Register SourceSuperReg = createResultReg(&X86::GR16RegClass);
2014 Register ResultSuperReg = createResultReg(&X86::GR16RegClass);
2015 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2016 TII.get(Copy), SourceSuperReg).
addReg(X86::AX);
2019 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SHR16ri),
2023 ResultReg = fastEmitInst_extractsubreg(MVT::i8, ResultSuperReg,
2028 ResultReg = createResultReg(
TypeEntry.RC);
2029 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Copy), ResultReg)
2030 .
addReg(OpEntry.DivRemResultReg);
2032 updateValueMap(
I, ResultReg);
2039bool X86FastISel::X86FastEmitCMoveSelect(MVT RetVT,
const Instruction *
I) {
2041 if (!Subtarget->canUseCMOV())
2045 if (RetVT < MVT::i16 || RetVT > MVT::i64)
2049 const TargetRegisterClass *RC = TLI.getRegClassFor(RetVT);
2050 bool NeedTest =
true;
2057 if (CI && (CI->getParent() ==
I->getParent())) {
2061 static const uint16_t SETFOpcTable[2][3] = {
2065 const uint16_t *SETFOpc =
nullptr;
2066 switch (Predicate) {
2069 SETFOpc = &SETFOpcTable[0][0];
2073 SETFOpc = &SETFOpcTable[1][0];
2087 EVT CmpVT = TLI.getValueType(
DL, CmpLHS->
getType());
2089 if (!X86FastEmitCompare(CmpLHS, CmpRHS, CmpVT, CI->getDebugLoc()))
2093 Register FlagReg1 = createResultReg(&X86::GR8RegClass);
2094 Register FlagReg2 = createResultReg(&X86::GR8RegClass);
2101 auto const &
II =
TII.get(SETFOpc[2]);
2102 if (
II.getNumDefs()) {
2103 Register TmpReg = createResultReg(&X86::GR8RegClass);
2104 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, TmpReg)
2107 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2112 }
else if (foldX86XALUIntrinsic(CC,
I,
Cond)) {
2133 if (MRI.getRegClass(CondReg) == &X86::VK1RegClass) {
2135 CondReg = createResultReg(&X86::GR32RegClass);
2136 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2137 TII.get(TargetOpcode::COPY), CondReg)
2139 CondReg = fastEmitInst_extractsubreg(MVT::i8, CondReg, X86::sub_8bit);
2141 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TEST8ri))
2151 if (!LHSReg || !RHSReg)
2154 const TargetRegisterInfo &
TRI = *Subtarget->getRegisterInfo();
2156 Subtarget->hasNDD());
2157 Register ResultReg = fastEmitInst_rri(
Opc, RC, RHSReg, LHSReg, CC);
2158 updateValueMap(
I, ResultReg);
2167bool X86FastISel::X86FastEmitSSESelect(MVT RetVT,
const Instruction *
I) {
2172 if (!CI || (CI->getParent() !=
I->getParent()))
2176 !((Subtarget->hasSSE1() && RetVT == MVT::f32) ||
2177 (Subtarget->hasSSE2() && RetVT == MVT::f64)))
2189 if (CmpRHSC && CmpRHSC->isNullValue())
2196 if (CC > 7 && !Subtarget->hasAVX())
2207 Register CmpLHSReg = getRegForValue(CmpLHS);
2208 Register CmpRHSReg = getRegForValue(CmpRHS);
2209 if (!LHSReg || !RHSReg || !CmpLHSReg || !CmpRHSReg)
2212 const TargetRegisterClass *RC = TLI.getRegClassFor(RetVT);
2215 if (Subtarget->hasAVX512()) {
2217 const TargetRegisterClass *VR128X = &X86::VR128XRegClass;
2218 const TargetRegisterClass *VK1 = &X86::VK1RegClass;
2220 unsigned CmpOpcode =
2221 (RetVT == MVT::f32) ? X86::VCMPSSZrri :
X86::VCMPSDZrri;
2222 Register CmpReg = fastEmitInst_rri(CmpOpcode, VK1, CmpLHSReg, CmpRHSReg,
2227 Register ImplicitDefReg = createResultReg(VR128X);
2228 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2229 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2233 unsigned MovOpcode =
2234 (RetVT == MVT::f32) ? X86::VMOVSSZrrk :
X86::VMOVSDZrrk;
2235 Register MovReg = fastEmitInst_rrrr(MovOpcode, VR128X, RHSReg, CmpReg,
2236 ImplicitDefReg, LHSReg);
2238 ResultReg = createResultReg(RC);
2239 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2240 TII.get(TargetOpcode::COPY), ResultReg).
addReg(MovReg);
2242 }
else if (Subtarget->hasAVX()) {
2243 const TargetRegisterClass *VR128 = &X86::VR128RegClass;
2250 unsigned CmpOpcode =
2251 (RetVT == MVT::f32) ? X86::VCMPSSrri :
X86::VCMPSDrri;
2252 unsigned BlendOpcode =
2253 (RetVT == MVT::f32) ? X86::VBLENDVPSrrr :
X86::VBLENDVPDrrr;
2255 Register CmpReg = fastEmitInst_rri(CmpOpcode, RC, CmpLHSReg, CmpRHSReg,
2257 Register VBlendReg = fastEmitInst_rrr(BlendOpcode, VR128, RHSReg, LHSReg,
2259 ResultReg = createResultReg(RC);
2260 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2261 TII.get(TargetOpcode::COPY), ResultReg).
addReg(VBlendReg);
2264 static const uint16_t OpcTable[2][4] = {
2265 { X86::CMPSSrri, X86::ANDPSrr, X86::ANDNPSrr, X86::ORPSrr },
2266 { X86::CMPSDrri, X86::ANDPDrr, X86::ANDNPDrr, X86::ORPDrr }
2269 const uint16_t *
Opc =
nullptr;
2271 default:
return false;
2272 case MVT::f32:
Opc = &OpcTable[0][0];
break;
2273 case MVT::f64:
Opc = &OpcTable[1][0];
break;
2276 const TargetRegisterClass *VR128 = &X86::VR128RegClass;
2277 Register CmpReg = fastEmitInst_rri(
Opc[0], RC, CmpLHSReg, CmpRHSReg, CC);
2278 Register AndReg = fastEmitInst_rr(
Opc[1], VR128, CmpReg, LHSReg);
2279 Register AndNReg = fastEmitInst_rr(
Opc[2], VR128, CmpReg, RHSReg);
2280 Register OrReg = fastEmitInst_rr(
Opc[3], VR128, AndNReg, AndReg);
2281 ResultReg = createResultReg(RC);
2282 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2283 TII.get(TargetOpcode::COPY), ResultReg).
addReg(OrReg);
2285 updateValueMap(
I, ResultReg);
2289bool X86FastISel::X86FastEmitPseudoSelect(MVT RetVT,
const Instruction *
I) {
2294 default:
return false;
2295 case MVT::i8:
Opc = X86::CMOV_GR8;
break;
2296 case MVT::i16:
Opc = X86::CMOV_GR16;
break;
2297 case MVT::i32:
Opc = X86::CMOV_GR32;
break;
2299 Opc = Subtarget->hasAVX512() ? X86::CMOV_FR16X : X86::CMOV_FR16;
break;
2301 Opc = Subtarget->hasAVX512() ? X86::CMOV_FR32X : X86::CMOV_FR32;
break;
2303 Opc = Subtarget->hasAVX512() ? X86::CMOV_FR64X : X86::CMOV_FR64;
break;
2313 if (CI && (CI->getParent() ==
I->getParent())) {
2325 EVT CmpVT = TLI.getValueType(
DL, CmpLHS->
getType());
2326 if (!X86FastEmitCompare(CmpLHS, CmpRHS, CmpVT, CI->getDebugLoc()))
2334 if (MRI.getRegClass(CondReg) == &X86::VK1RegClass) {
2336 CondReg = createResultReg(&X86::GR32RegClass);
2337 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2338 TII.get(TargetOpcode::COPY), CondReg)
2340 CondReg = fastEmitInst_extractsubreg(MVT::i8, CondReg, X86::sub_8bit);
2342 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TEST8ri))
2352 if (!LHSReg || !RHSReg)
2355 const TargetRegisterClass *RC = TLI.getRegClassFor(RetVT);
2358 fastEmitInst_rri(
Opc, RC, RHSReg, LHSReg, CC);
2359 updateValueMap(
I, ResultReg);
2363bool X86FastISel::X86SelectSelect(
const Instruction *
I) {
2365 if (!isTypeLegal(
I->getType(), RetVT))
2371 const Value *Opnd =
nullptr;
2372 switch (Predicate) {
2379 Register OpReg = getRegForValue(Opnd);
2382 const TargetRegisterClass *RC = TLI.getRegClassFor(RetVT);
2383 Register ResultReg = createResultReg(RC);
2384 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2385 TII.get(TargetOpcode::COPY), ResultReg)
2387 updateValueMap(
I, ResultReg);
2393 if (X86FastEmitCMoveSelect(RetVT,
I))
2397 if (X86FastEmitSSESelect(RetVT,
I))
2402 if (X86FastEmitPseudoSelect(RetVT,
I))
2409bool X86FastISel::X86SelectIntToFP(
const Instruction *
I,
bool IsSigned) {
2414 bool HasAVX512 = Subtarget->hasAVX512();
2415 if (!Subtarget->hasAVX() || (!IsSigned && !HasAVX512))
2419 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
2420 if (SrcVT != MVT::i32 && SrcVT != MVT::i64)
2424 Register OpReg = getRegForValue(
I->getOperand(0));
2430 static const uint16_t SCvtOpc[2][2][2] = {
2431 { { X86::VCVTSI2SSrr, X86::VCVTSI642SSrr },
2432 { X86::VCVTSI2SDrr, X86::VCVTSI642SDrr } },
2433 { { X86::VCVTSI2SSZrr, X86::VCVTSI642SSZrr },
2434 { X86::VCVTSI2SDZrr, X86::VCVTSI642SDZrr } },
2436 static const uint16_t UCvtOpc[2][2] = {
2437 { X86::VCVTUSI2SSZrr, X86::VCVTUSI642SSZrr },
2438 { X86::VCVTUSI2SDZrr, X86::VCVTUSI642SDZrr },
2440 bool Is64Bit = SrcVT == MVT::i64;
2442 if (
I->getType()->isDoubleTy()) {
2444 Opcode = IsSigned ? SCvtOpc[HasAVX512][1][Is64Bit] : UCvtOpc[1][Is64Bit];
2445 }
else if (
I->getType()->isFloatTy()) {
2447 Opcode = IsSigned ? SCvtOpc[HasAVX512][0][Is64Bit] : UCvtOpc[0][Is64Bit];
2452 const TargetRegisterClass *RC = TLI.getRegClassFor(DstVT);
2453 Register ImplicitDefReg = createResultReg(RC);
2454 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2455 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2456 Register ResultReg = fastEmitInst_rr(Opcode, RC, ImplicitDefReg, OpReg);
2457 updateValueMap(
I, ResultReg);
2461bool X86FastISel::X86SelectSIToFP(
const Instruction *
I) {
2462 return X86SelectIntToFP(
I,
true);
2465bool X86FastISel::X86SelectUIToFP(
const Instruction *
I) {
2466 return X86SelectIntToFP(
I,
false);
2470bool X86FastISel::X86SelectFPExtOrFPTrunc(
const Instruction *
I,
2472 const TargetRegisterClass *RC) {
2473 assert((
I->getOpcode() == Instruction::FPExt ||
2474 I->getOpcode() == Instruction::FPTrunc) &&
2475 "Instruction must be an FPExt or FPTrunc!");
2476 bool HasAVX = Subtarget->hasAVX();
2478 Register OpReg = getRegForValue(
I->getOperand(0));
2484 ImplicitDefReg = createResultReg(RC);
2485 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2486 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2490 Register ResultReg = createResultReg(RC);
2491 MachineInstrBuilder MIB;
2492 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpc),
2496 MIB.
addReg(ImplicitDefReg);
2499 updateValueMap(
I, ResultReg);
2503bool X86FastISel::X86SelectFPExt(
const Instruction *
I) {
2504 if (Subtarget->hasSSE2() &&
I->getType()->isDoubleTy() &&
2505 I->getOperand(0)->getType()->isFloatTy()) {
2506 bool HasAVX512 = Subtarget->hasAVX512();
2509 HasAVX512 ? X86::VCVTSS2SDZrr
2510 : Subtarget->hasAVX() ? X86::VCVTSS2SDrr : X86::CVTSS2SDrr;
2511 return X86SelectFPExtOrFPTrunc(
I,
Opc, TLI.getRegClassFor(MVT::f64));
2517bool X86FastISel::X86SelectFPTrunc(
const Instruction *
I) {
2518 if (Subtarget->hasSSE2() &&
I->getType()->isFloatTy() &&
2519 I->getOperand(0)->getType()->isDoubleTy()) {
2520 bool HasAVX512 = Subtarget->hasAVX512();
2523 HasAVX512 ? X86::VCVTSD2SSZrr
2524 : Subtarget->hasAVX() ? X86::VCVTSD2SSrr : X86::CVTSD2SSrr;
2525 return X86SelectFPExtOrFPTrunc(
I,
Opc, TLI.getRegClassFor(MVT::f32));
2531bool X86FastISel::X86SelectTrunc(
const Instruction *
I) {
2532 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
2533 EVT DstVT = TLI.getValueType(
DL,
I->getType());
2536 if (DstVT != MVT::i8 && DstVT != MVT::i1)
2538 if (!TLI.isTypeLegal(SrcVT))
2541 Register InputReg = getRegForValue(
I->getOperand(0));
2546 if (SrcVT == MVT::i8) {
2548 updateValueMap(
I, InputReg);
2553 Register ResultReg = fastEmitInst_extractsubreg(MVT::i8, InputReg,
2558 updateValueMap(
I, ResultReg);
2562bool X86FastISel::X86SelectBitCast(
const Instruction *
I) {
2565 if (!Subtarget->hasSSE2() ||
2566 !isTypeLegal(
I->getOperand(0)->getType(), SrcVT) ||
2567 !isTypeLegal(
I->getType(), DstVT))
2582 const TargetRegisterClass *DstClass = TLI.getRegClassFor(DstVT);
2583 Register ResultReg = createResultReg(DstClass);
2584 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
2588 updateValueMap(
I, ResultReg);
2592bool X86FastISel::IsMemcpySmall(uint64_t Len) {
2593 return Len <= (Subtarget->is64Bit() ? 32 : 16);
2596bool X86FastISel::TryEmitSmallMemcpy(X86AddressMode DestAM,
2597 X86AddressMode SrcAM, uint64_t Len) {
2600 if (!IsMemcpySmall(Len))
2603 bool i64Legal = Subtarget->is64Bit();
2608 if (Len >= 8 && i64Legal)
2618 bool RV = X86FastEmitLoad(VT, SrcAM,
nullptr,
Reg);
2619 RV &= X86FastEmitStore(VT,
Reg, DestAM);
2620 assert(RV &&
"Failed to emit load or store??");
2632bool X86FastISel::fastLowerIntrinsicCall(
const IntrinsicInst *
II) {
2634 switch (
II->getIntrinsicID()) {
2637 case Intrinsic::frameaddress: {
2638 MachineFunction *MF = FuncInfo.MF;
2642 Type *RetTy =
II->getCalledFunction()->getReturnType();
2645 if (!isTypeLegal(RetTy, VT))
2649 const TargetRegisterClass *RC =
nullptr;
2653 case MVT::i32:
Opc = X86::MOV32rm; RC = &X86::GR32RegClass;
break;
2654 case MVT::i64:
Opc = X86::MOV64rm; RC = &X86::GR64RegClass;
break;
2662 const X86RegisterInfo *RegInfo = Subtarget->getRegisterInfo();
2664 assert(((FrameReg == X86::RBP && VT == MVT::i64) ||
2665 (FrameReg == X86::EBP && VT == MVT::i32)) &&
2666 "Invalid Frame Register!");
2671 Register SrcReg = createResultReg(RC);
2672 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2673 TII.get(TargetOpcode::COPY), SrcReg).
addReg(FrameReg);
2682 Register DestReg = createResultReg(RC);
2684 TII.get(
Opc), DestReg), SrcReg);
2688 updateValueMap(
II, SrcReg);
2691 case Intrinsic::memcpy: {
2701 if (IsMemcpySmall(Len)) {
2702 X86AddressMode DestAM, SrcAM;
2706 TryEmitSmallMemcpy(DestAM, SrcAM, Len);
2711 unsigned SizeWidth = Subtarget->is64Bit() ? 64 : 32;
2718 return lowerCallTo(
II,
"memcpy",
II->arg_size() - 1);
2720 case Intrinsic::memset: {
2726 unsigned SizeWidth = Subtarget->is64Bit() ? 64 : 32;
2733 return lowerCallTo(
II,
"memset",
II->arg_size() - 1);
2735 case Intrinsic::stackprotector: {
2737 EVT PtrTy = TLI.getPointerTy(
DL);
2739 const Value *Op1 =
II->getArgOperand(0);
2747 if (!X86FastEmitStore(PtrTy, Op1, AM))
return false;
2750 case Intrinsic::dbg_declare: {
2756 const MCInstrDesc &
II =
TII.get(TargetOpcode::DBG_VALUE);
2758 "Expected inlined-at fields to agree");
2765 case Intrinsic::trap: {
2766 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TRAP));
2769 case Intrinsic::sqrt: {
2770 if (!Subtarget->hasSSE1())
2773 Type *RetTy =
II->getCalledFunction()->getReturnType();
2776 if (!isTypeLegal(RetTy, VT))
2782 static const uint16_t SqrtOpc[3][2] = {
2783 { X86::SQRTSSr, X86::SQRTSDr },
2784 { X86::VSQRTSSr, X86::VSQRTSDr },
2785 { X86::VSQRTSSZr, X86::VSQRTSDZr },
2787 unsigned AVXLevel = Subtarget->hasAVX512() ? 2 :
2788 Subtarget->hasAVX() ? 1 :
2792 default:
return false;
2793 case MVT::f32:
Opc = SqrtOpc[AVXLevel][0];
break;
2794 case MVT::f64:
Opc = SqrtOpc[AVXLevel][1];
break;
2797 const Value *SrcVal =
II->getArgOperand(0);
2798 Register SrcReg = getRegForValue(SrcVal);
2803 const TargetRegisterClass *RC = TLI.getRegClassFor(VT);
2806 ImplicitDefReg = createResultReg(RC);
2807 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2808 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2811 Register ResultReg = createResultReg(RC);
2812 MachineInstrBuilder MIB;
2813 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc),
2817 MIB.
addReg(ImplicitDefReg);
2821 updateValueMap(
II, ResultReg);
2824 case Intrinsic::sadd_with_overflow:
2825 case Intrinsic::uadd_with_overflow:
2826 case Intrinsic::ssub_with_overflow:
2827 case Intrinsic::usub_with_overflow:
2828 case Intrinsic::smul_with_overflow:
2829 case Intrinsic::umul_with_overflow: {
2834 Type *RetTy = Ty->getTypeAtIndex(0U);
2837 "Overflow value expected to be an i1");
2840 if (!isTypeLegal(RetTy, VT))
2843 if (VT < MVT::i8 || VT > MVT::i64)
2854 switch (
II->getIntrinsicID()) {
2856 case Intrinsic::sadd_with_overflow:
2858 case Intrinsic::uadd_with_overflow:
2860 case Intrinsic::ssub_with_overflow:
2862 case Intrinsic::usub_with_overflow:
2864 case Intrinsic::smul_with_overflow:
2866 case Intrinsic::umul_with_overflow:
2877 static const uint16_t
Opc[2][4] = {
2878 { X86::INC8r, X86::INC16r, X86::INC32r, X86::INC64r },
2879 { X86::DEC8r, X86::DEC16r, X86::DEC32r, X86::DEC64r }
2885 ResultReg = createResultReg(TLI.getRegClassFor(VT));
2887 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2891 ResultReg = fastEmit_ri(VT, VT, BaseOpc, LHSReg, CI->
getZExtValue());
2896 RHSReg = getRegForValue(
RHS);
2899 ResultReg = fastEmit_rr(VT, VT, BaseOpc, LHSReg, RHSReg);
2904 if (BaseOpc == X86ISD::UMUL && !ResultReg) {
2905 static const uint16_t MULOpc[] =
2906 { X86::MUL8r, X86::MUL16r, X86::MUL32r, X86::MUL64r };
2907 static const MCPhysReg Reg[] = { X86::AL, X86::AX, X86::EAX, X86::RAX };
2910 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2913 ResultReg = fastEmitInst_r(MULOpc[VT.
SimpleTy-MVT::i8],
2914 TLI.getRegClassFor(VT), RHSReg);
2915 }
else if (BaseOpc == X86ISD::SMUL && !ResultReg) {
2916 static const uint16_t MULOpc[] =
2917 { X86::IMUL8r, X86::IMUL16rr, X86::IMUL32rr, X86::IMUL64rr };
2918 if (VT == MVT::i8) {
2921 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2922 TII.get(TargetOpcode::COPY), X86::AL)
2924 ResultReg = fastEmitInst_r(MULOpc[0], TLI.getRegClassFor(VT), RHSReg);
2926 ResultReg = fastEmitInst_rr(MULOpc[VT.
SimpleTy-MVT::i8],
2927 TLI.getRegClassFor(VT), LHSReg, RHSReg);
2934 Register ResultReg2 = createResultReg(&X86::GR8RegClass);
2935 assert((ResultReg+1) == ResultReg2 &&
"Nonconsecutive result registers.");
2940 updateValueMap(
II, ResultReg, 2);
2943 case Intrinsic::x86_sse_cvttss2si:
2944 case Intrinsic::x86_sse_cvttss2si64:
2945 case Intrinsic::x86_sse2_cvttsd2si:
2946 case Intrinsic::x86_sse2_cvttsd2si64: {
2948 switch (
II->getIntrinsicID()) {
2950 case Intrinsic::x86_sse_cvttss2si:
2951 case Intrinsic::x86_sse_cvttss2si64:
2952 if (!Subtarget->hasSSE1())
2954 IsInputDouble =
false;
2956 case Intrinsic::x86_sse2_cvttsd2si:
2957 case Intrinsic::x86_sse2_cvttsd2si64:
2958 if (!Subtarget->hasSSE2())
2960 IsInputDouble =
true;
2964 Type *RetTy =
II->getCalledFunction()->getReturnType();
2966 if (!isTypeLegal(RetTy, VT))
2969 static const uint16_t CvtOpc[3][2][2] = {
2970 { { X86::CVTTSS2SIrr, X86::CVTTSS2SI64rr },
2971 { X86::CVTTSD2SIrr, X86::CVTTSD2SI64rr } },
2972 { { X86::VCVTTSS2SIrr, X86::VCVTTSS2SI64rr },
2973 { X86::VCVTTSD2SIrr, X86::VCVTTSD2SI64rr } },
2974 { { X86::VCVTTSS2SIZrr, X86::VCVTTSS2SI64Zrr },
2975 { X86::VCVTTSD2SIZrr, X86::VCVTTSD2SI64Zrr } },
2977 unsigned AVXLevel = Subtarget->hasAVX512() ? 2 :
2978 Subtarget->hasAVX() ? 1 :
2983 case MVT::i32:
Opc = CvtOpc[AVXLevel][IsInputDouble][0];
break;
2984 case MVT::i64:
Opc = CvtOpc[AVXLevel][IsInputDouble][1];
break;
2996 Op =
IE->getOperand(1);
2999 Op =
IE->getOperand(0);
3006 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3007 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg)
3010 updateValueMap(
II, ResultReg);
3013 case Intrinsic::x86_sse42_crc32_32_8:
3014 case Intrinsic::x86_sse42_crc32_32_16:
3015 case Intrinsic::x86_sse42_crc32_32_32:
3016 case Intrinsic::x86_sse42_crc32_64_64: {
3017 if (!Subtarget->hasCRC32())
3020 Type *RetTy =
II->getCalledFunction()->getReturnType();
3023 if (!isTypeLegal(RetTy, VT))
3027 const TargetRegisterClass *RC =
nullptr;
3029 switch (
II->getIntrinsicID()) {
3032#define GET_EGPR_IF_ENABLED(OPC) Subtarget->hasEGPR() ? OPC##_EVEX : OPC
3033 case Intrinsic::x86_sse42_crc32_32_8:
3035 RC = &X86::GR32RegClass;
3037 case Intrinsic::x86_sse42_crc32_32_16:
3039 RC = &X86::GR32RegClass;
3041 case Intrinsic::x86_sse42_crc32_32_32:
3043 RC = &X86::GR32RegClass;
3045 case Intrinsic::x86_sse42_crc32_64_64:
3047 RC = &X86::GR64RegClass;
3049#undef GET_EGPR_IF_ENABLED
3057 if (!LHSReg || !RHSReg)
3060 Register ResultReg = fastEmitInst_rr(
Opc, RC, LHSReg, RHSReg);
3064 updateValueMap(
II, ResultReg);
3070bool X86FastISel::fastLowerArguments() {
3071 if (!FuncInfo.CanLowerReturn)
3078 CallingConv::ID CC =
F->getCallingConv();
3079 if (CC != CallingConv::C)
3082 if (Subtarget->isCallingConvWin64(CC))
3085 if (!Subtarget->is64Bit())
3088 if (Subtarget->useSoftFloat())
3092 unsigned GPRCnt = 0;
3093 unsigned FPRCnt = 0;
3094 for (
auto const &Arg :
F->args()) {
3095 if (Arg.hasAttribute(Attribute::ByVal) ||
3096 Arg.hasAttribute(Attribute::InReg) ||
3097 Arg.hasAttribute(Attribute::StructRet) ||
3098 Arg.hasAttribute(Attribute::SwiftSelf) ||
3099 Arg.hasAttribute(Attribute::SwiftAsync) ||
3100 Arg.hasAttribute(Attribute::SwiftError) ||
3101 Arg.hasAttribute(Attribute::Nest))
3104 Type *ArgTy = Arg.getType();
3108 EVT ArgVT = TLI.getValueType(
DL, ArgTy);
3109 if (!ArgVT.
isSimple())
return false;
3111 default:
return false;
3118 if (!Subtarget->hasSSE1())
3131 static const MCPhysReg GPR32ArgRegs[] = {
3132 X86::EDI, X86::ESI, X86::EDX, X86::ECX, X86::R8D, X86::R9D
3134 static const MCPhysReg GPR64ArgRegs[] = {
3135 X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8 , X86::R9
3138 X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,
3139 X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
3142 unsigned GPRIdx = 0;
3143 unsigned FPRIdx = 0;
3144 for (
auto const &Arg :
F->args()) {
3145 MVT VT = TLI.getSimpleValueType(
DL, Arg.getType());
3146 const TargetRegisterClass *RC = TLI.getRegClassFor(VT);
3150 case MVT::i32: SrcReg = GPR32ArgRegs[GPRIdx++];
break;
3151 case MVT::i64: SrcReg = GPR64ArgRegs[GPRIdx++];
break;
3152 case MVT::f32: [[fallthrough]];
3153 case MVT::f64: SrcReg = XMMArgRegs[FPRIdx++];
break;
3155 Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
3159 Register ResultReg = createResultReg(RC);
3160 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3161 TII.get(TargetOpcode::COPY), ResultReg)
3163 updateValueMap(&Arg, ResultReg);
3171 if (Subtarget->is64Bit())
3188bool X86FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3189 auto &OutVals = CLI.OutVals;
3190 auto &OutFlags = CLI.OutFlags;
3191 auto &OutRegs = CLI.OutRegs;
3192 auto &Ins = CLI.Ins;
3193 auto &InRegs = CLI.InRegs;
3194 CallingConv::ID CC = CLI.CallConv;
3195 bool &IsTailCall = CLI.IsTailCall;
3196 bool IsVarArg = CLI.IsVarArg;
3199 const auto *CB = CLI.CB;
3201 bool Is64Bit = Subtarget->is64Bit();
3202 bool IsWin64 = Subtarget->isCallingConvWin64(CC);
3214 for (
Type *RetTy : RetTys) {
3215 MVT RetVT = MVT::Other;
3216 if (!isTypeLegal(RetTy, RetVT)) {
3217 if (RetVT == MVT::Other)
3222 MVT ABIVT = TLI.getRegisterTypeForCallingConv(CLI.RetTy->getContext(),
3223 CLI.CallConv, RetVT);
3224 MVT RegVT = TLI.getRegisterType(CLI.RetTy->getContext(), RetVT);
3232 if (CB && CB->doesNoCfCheck())
3236 if ((CB &&
isa<CallInst>(CB) && CB->hasFnAttr(
"no_caller_saved_registers")))
3240 if ((CB && CB->hasFnAttr(
"no_callee_saved_registers")))
3248 if (Subtarget->useIndirectThunkCalls())
3253 default:
return false;
3254 case CallingConv::C:
3255 case CallingConv::Fast:
3256 case CallingConv::Tail:
3257 case CallingConv::Swift:
3258 case CallingConv::SwiftTail:
3259 case CallingConv::X86_FastCall:
3260 case CallingConv::X86_StdCall:
3261 case CallingConv::X86_ThisCall:
3262 case CallingConv::Win64:
3263 case CallingConv::X86_64_SysV:
3264 case CallingConv::CFGuard_Check:
3274 if ((CC == CallingConv::Fast && TM.Options.GuaranteedTailCallOpt) ||
3275 CC == CallingConv::Tail || CC == CallingConv::SwiftTail)
3280 if (IsVarArg && IsWin64)
3284 if (CLI.CB && CLI.CB->hasInAllocaArgument())
3287 for (
auto Flag : CLI.OutFlags)
3288 if (
Flag.isSwiftError() ||
Flag.isPreallocated())
3298 SmallVector<Register, 16> ArgRegs;
3303 for (
int i = 0, e = OutVals.size(); i != e; ++i) {
3304 Value *&Val = OutVals[i];
3305 ISD::ArgFlagsTy
Flags = OutFlags[i];
3320 if (TI && TI->getType()->isIntegerTy(1) && CLI.CB &&
3321 (TI->getParent() == CLI.CB->getParent()) && TI->hasOneUse()) {
3322 Value *PrevVal = TI->getOperand(0);
3323 ResultReg = getRegForValue(PrevVal);
3328 if (!isTypeLegal(PrevVal->
getType(), VT))
3331 ResultReg = fastEmit_ri(VT, VT,
ISD::AND, ResultReg, 1);
3333 if (!isTypeLegal(Val->
getType(), VT) ||
3336 ResultReg = getRegForValue(Val);
3349 CCState CCInfo(CC, IsVarArg, *FuncInfo.MF, ArgLocs, CLI.RetTy->getContext());
3353 CCInfo.AllocateStack(32,
Align(8));
3355 CCInfo.AnalyzeCallOperands(OutVTs, OutFlags, ArgTys,
CC_X86);
3358 unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
3361 unsigned AdjStackDown =
TII.getCallFrameSetupOpcode();
3362 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackDown))
3366 const X86RegisterInfo *RegInfo = Subtarget->getRegisterInfo();
3367 for (
const CCValAssign &VA : ArgLocs) {
3371 if (ArgVT == MVT::x86mmx)
3381 "Unexpected extend");
3383 if (ArgVT == MVT::i1)
3388 assert(Emitted &&
"Failed to emit a sext!"); (void)Emitted;
3394 "Unexpected extend");
3397 if (ArgVT == MVT::i1) {
3399 ArgReg = fastEmitZExtFromI1(MVT::i8, ArgReg);
3408 assert(Emitted &&
"Failed to emit a zext!"); (void)Emitted;
3414 "Unexpected extend");
3424 assert(Emitted &&
"Failed to emit a aext!"); (void)Emitted;
3430 assert(ArgReg &&
"Failed to emit a bitcast!");
3451 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3464 AM.
Disp = LocMemOffset;
3467 MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
3470 if (
Flags.isByVal()) {
3471 X86AddressMode SrcAM;
3473 if (!TryEmitSmallMemcpy(AM, SrcAM,
Flags.getByValSize()))
3479 if (!X86FastEmitStore(ArgVT, ArgVal, AM, MMO))
3482 if (!X86FastEmitStore(ArgVT, ArgReg, AM, MMO))
3490 if (Subtarget->isPICStyleGOT()) {
3491 Register Base = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
3492 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3496 if (Is64Bit && IsVarArg && !IsWin64) {
3507 X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,
3508 X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
3510 unsigned NumXMMRegs = CCInfo.getFirstUnallocated(XMMArgRegs);
3511 assert((Subtarget->hasSSE1() || !NumXMMRegs)
3512 &&
"SSE registers cannot be used when SSE is disabled");
3513 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV8ri),
3514 X86::AL).
addImm(NumXMMRegs);
3519 X86AddressMode CalleeAM;
3520 if (!X86SelectCallAddress(Callee, CalleeAM))
3524 const GlobalValue *GV =
nullptr;
3525 if (CalleeAM.
GV !=
nullptr) {
3527 }
else if (CalleeAM.
Base.
Reg) {
3533 MachineInstrBuilder MIB;
3536 unsigned CallOpc = Is64Bit ? X86::CALL64r : X86::CALL32r;
3537 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CallOpc))
3541 assert(GV &&
"Not a direct call");
3543 unsigned char OpFlags = Subtarget->classifyGlobalFunctionReference(GV);
3555 unsigned CallOpc = NeedLoad
3556 ? (Is64Bit ? X86::CALL64m : X86::CALL32m)
3557 : (Is64Bit ?
X86::CALL64pcrel32 :
X86::CALLpcrel32);
3559 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CallOpc));
3563 MIB.
addSym(Symbol, OpFlags);
3575 if (Subtarget->isPICStyleGOT())
3576 MIB.
addReg(X86::EBX, RegState::Implicit);
3578 if (Is64Bit && IsVarArg && !IsWin64)
3579 MIB.
addReg(X86::AL, RegState::Implicit);
3582 for (
auto Reg : OutRegs)
3586 unsigned NumBytesForCalleeToPop =
3588 TM.Options.GuaranteedTailCallOpt)
3591 unsigned AdjStackUp =
TII.getCallFrameDestroyOpcode();
3592 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackUp))
3597 CCState CCRetInfo(CC, IsVarArg, *FuncInfo.MF, RVLocs,
3598 CLI.RetTy->getContext());
3599 CCRetInfo.AnalyzeCallResult(Ins,
RetCC_X86);
3602 Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);
3603 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
3604 CCValAssign &VA = RVLocs[i];
3610 if ((CopyVT == MVT::f32 || CopyVT == MVT::f64) &&
3611 ((Is64Bit || Ins[i].
Flags.isInReg()) && !Subtarget->hasSSE1())) {
3617 if ((SrcReg == X86::FP0 || SrcReg == X86::FP1) &&
3618 isScalarFPTypeInSSEReg(VA.
getValVT())) {
3620 CopyReg = createResultReg(&X86::RFP80RegClass);
3624 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3625 TII.get(TargetOpcode::COPY), CopyReg).
addReg(SrcReg);
3633 unsigned Opc = ResVT == MVT::f32 ? X86::ST_Fp80m32 : X86::ST_Fp80m64;
3639 Opc = ResVT == MVT::f32 ? X86::MOVSSrm_alt : X86::MOVSDrm_alt;
3641 TII.get(
Opc), ResultReg + i), FI);
3645 CLI.ResultReg = ResultReg;
3646 CLI.NumResultRegs = RVLocs.
size();
3650 if (TM.Options.EmitCallGraphSection && CB && CB->isIndirectCall()) {
3651 MachineFunction::CallSiteInfo CSInfo(*CB);
3659X86FastISel::fastSelectInstruction(
const Instruction *
I) {
3660 switch (
I->getOpcode()) {
3662 case Instruction::Load:
3663 return X86SelectLoad(
I);
3664 case Instruction::Store:
3665 return X86SelectStore(
I);
3666 case Instruction::Ret:
3667 return X86SelectRet(
I);
3668 case Instruction::ICmp:
3669 case Instruction::FCmp:
3670 return X86SelectCmp(
I);
3671 case Instruction::ZExt:
3672 return X86SelectZExt(
I);
3673 case Instruction::SExt:
3674 return X86SelectSExt(
I);
3675 case Instruction::CondBr:
3676 return X86SelectBranch(
I);
3677 case Instruction::LShr:
3678 case Instruction::AShr:
3679 case Instruction::Shl:
3680 return X86SelectShift(
I);
3681 case Instruction::SDiv:
3682 case Instruction::UDiv:
3683 case Instruction::SRem:
3684 case Instruction::URem:
3685 return X86SelectDivRem(
I);
3686 case Instruction::Select:
3687 return X86SelectSelect(
I);
3688 case Instruction::Trunc:
3689 return X86SelectTrunc(
I);
3690 case Instruction::FPExt:
3691 return X86SelectFPExt(
I);
3692 case Instruction::FPTrunc:
3693 return X86SelectFPTrunc(
I);
3694 case Instruction::SIToFP:
3695 return X86SelectSIToFP(
I);
3696 case Instruction::UIToFP:
3697 return X86SelectUIToFP(
I);
3698 case Instruction::IntToPtr:
3699 case Instruction::PtrToInt: {
3700 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
3701 EVT DstVT = TLI.getValueType(
DL,
I->getType());
3703 return X86SelectZExt(
I);
3705 return X86SelectTrunc(
I);
3709 updateValueMap(
I,
Reg);
3712 case Instruction::BitCast:
3713 return X86SelectBitCast(
I);
3719Register X86FastISel::X86MaterializeInt(
const ConstantInt *CI, MVT VT) {
3725 Register SrcReg = fastEmitInst_(X86::MOV32r0, &X86::GR32RegClass);
3730 return fastEmitInst_extractsubreg(MVT::i8, SrcReg, X86::sub_8bit);
3732 return fastEmitInst_extractsubreg(MVT::i16, SrcReg, X86::sub_16bit);
3736 Register ResultReg = createResultReg(&X86::GR64RegClass);
3737 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3738 TII.get(TargetOpcode::SUBREG_TO_REG), ResultReg)
3752 case MVT::i8:
Opc = X86::MOV8ri;
break;
3753 case MVT::i16:
Opc = X86::MOV16ri;
break;
3754 case MVT::i32:
Opc = X86::MOV32ri;
break;
3757 Opc = X86::MOV32ri64;
3759 Opc = X86::MOV64ri32;
3765 return fastEmitInst_i(
Opc, TLI.getRegClassFor(VT), Imm);
3768Register X86FastISel::X86MaterializeFP(
const ConstantFP *CFP, MVT VT) {
3770 return fastMaterializeFloatZero(CFP);
3780 bool HasSSE1 = Subtarget->hasSSE1();
3781 bool HasSSE2 = Subtarget->hasSSE2();
3782 bool HasAVX = Subtarget->hasAVX();
3783 bool HasAVX512 = Subtarget->hasAVX512();
3788 Opc = HasAVX512 ? X86::VMOVSSZrm_alt
3789 : HasAVX ? X86::VMOVSSrm_alt
3790 : HasSSE1 ? X86::MOVSSrm_alt
3794 Opc = HasAVX512 ? X86::VMOVSDZrm_alt
3795 : HasAVX ? X86::VMOVSDrm_alt
3796 : HasSSE2 ? X86::MOVSDrm_alt
3809 unsigned char OpFlag = Subtarget->classifyLocalReference(
nullptr);
3811 PICBase = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
3813 PICBase = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
3818 unsigned CPI = MCP.getConstantPoolIndex(CFP, Alignment);
3823 Register AddrReg = createResultReg(&X86::GR64RegClass);
3824 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV64ri),
3827 MachineInstrBuilder MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3828 TII.get(
Opc), ResultReg);
3829 addRegReg(MIB, AddrReg,
false, X86::NoSubRegister, PICBase,
false,
3830 X86::NoSubRegister);
3831 MachineMemOperand *MMO = FuncInfo.MF->getMachineMemOperand(
3839 TII.get(
Opc), ResultReg),
3840 CPI, PICBase, OpFlag);
3844Register X86FastISel::X86MaterializeGV(
const GlobalValue *GV, MVT VT) {
3849 if (TM.isLargeGlobalValue(GV))
3861 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3863 TLI.getPointerTy(
DL) == MVT::i64) {
3866 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV64ri),
3871 TLI.getPointerTy(
DL) == MVT::i32
3872 ? (Subtarget->isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r)
3875 TII.get(
Opc), ResultReg), AM);
3882Register X86FastISel::fastMaterializeConstant(
const Constant *
C) {
3883 EVT CEVT = TLI.getValueType(
DL,
C->getType(),
true);
3891 return X86MaterializeInt(CI, VT);
3893 return X86MaterializeFP(CFP, VT);
3895 return X86MaterializeGV(GV, VT);
3902 if (!Subtarget->hasSSE1())
3903 Opc = X86::LD_Fp032;
3906 if (!Subtarget->hasSSE2())
3907 Opc = X86::LD_Fp064;
3910 Opc = X86::LD_Fp080;
3915 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3916 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc),
3925Register X86FastISel::fastMaterializeAlloca(
const AllocaInst *
C) {
3933 if (!FuncInfo.StaticAllocaMap.count(
C))
3935 assert(
C->isStaticAlloca() &&
"dynamic alloca in the static alloca map?");
3941 TLI.getPointerTy(
DL) == MVT::i32
3942 ? (Subtarget->isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r)
3944 const TargetRegisterClass *RC = TLI.getRegClassFor(TLI.getPointerTy(
DL));
3945 Register ResultReg = createResultReg(RC);
3947 TII.get(
Opc), ResultReg), AM);
3951Register X86FastISel::fastMaterializeFloatZero(
const ConstantFP *CF) {
3953 if (!isTypeLegal(CF->
getType(), VT))
3957 bool HasSSE1 = Subtarget->hasSSE1();
3958 bool HasSSE2 = Subtarget->hasSSE2();
3959 bool HasAVX512 = Subtarget->hasAVX512();
3964 Opc = HasAVX512 ? X86::AVX512_FsFLD0SH : X86::FsFLD0SH;
3967 Opc = HasAVX512 ? X86::AVX512_FsFLD0SS
3968 : HasSSE1 ? X86::FsFLD0SS
3972 Opc = HasAVX512 ? X86::AVX512_FsFLD0SD
3973 : HasSSE2 ? X86::FsFLD0SD
3981 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3982 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(
Opc), ResultReg);
3986bool X86FastISel::tryToFoldLoadIntoMI(MachineInstr *
MI,
unsigned OpNo,
3987 const LoadInst *LI) {
3993 const X86InstrInfo &XII = (
const X86InstrInfo &)
TII;
4000 MachineInstr *CopyMI =
nullptr;
4002 *FuncInfo.MF, *
MI, OpNo, AddrOps, FuncInfo.InsertPt,
Size, LI->
getAlign(),
4012 unsigned OperandNo = 0;
4014 E =
Result->operands_end();
I !=
E; ++
I, ++OperandNo) {
4015 MachineOperand &MO = *
I;
4021 if (IndexReg == MO.
getReg())
4027 FuncInfo.MF->moveAdditionalCallInfo(
MI, Result);
4028 Result->addMemOperand(*FuncInfo.MF, createMachineMemOperandFor(LI));
4029 Result->cloneInstrSymbols(*FuncInfo.MF, *
MI);
4031 removeDeadCode(
I, std::next(
I));
4035Register X86FastISel::fastEmitInst_rrrr(
unsigned MachineInstOpcode,
4036 const TargetRegisterClass *RC,
4039 const MCInstrDesc &
II =
TII.get(MachineInstOpcode);
4041 Register ResultReg = createResultReg(RC);
4047 if (
II.getNumDefs() >= 1)
4048 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
4054 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
4059 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
4070 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.
static LLVM_ABI Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
LLVM_ABI bool isNullValue() const
Return true if this is the value that would be returned by getNullValue.
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 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)
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