37#include "llvm/IR/IntrinsicsX86.h"
47class X86FastISel final :
public FastISel {
72#include "X86GenFastISel.inc"
75 bool X86FastEmitCompare(
const Value *LHS,
const Value *RHS,
EVT VT,
79 unsigned &ResultReg,
unsigned Alignment = 1);
120 bool X86SelectFPExtOrFPTrunc(
const Instruction *
I,
unsigned Opc,
127 bool X86SelectIntToFP(
const Instruction *
I,
bool IsSigned);
130 return Subtarget->getInstrInfo();
149 bool isScalarFPTypeInSSEReg(
EVT VT)
const {
150 return (VT == MVT::f64 && Subtarget->hasSSE2()) ||
151 (VT == MVT::f32 && Subtarget->hasSSE1()) || VT == MVT::f16;
154 bool isTypeLegal(
Type *Ty,
MVT &VT,
bool AllowI1 =
false);
167 unsigned fastEmitInst_rrrr(
unsigned MachineInstOpcode,
169 unsigned Op1,
unsigned Op2,
unsigned Op3);
174static std::pair<unsigned, bool>
177 bool NeedSwap =
false;
206 return std::make_pair(
CC, NeedSwap);
220 return ::addFullAddress(MIB, AM);
227 if (!isa<ExtractValueInst>(
Cond))
230 const auto *EV = cast<ExtractValueInst>(
Cond);
231 if (!isa<IntrinsicInst>(EV->getAggregateOperand()))
234 const auto *II = cast<IntrinsicInst>(EV->getAggregateOperand());
238 cast<StructType>(
Callee->getReturnType())->getTypeAtIndex(0U);
239 if (!isTypeLegal(
RetTy, RetVT))
242 if (RetVT != MVT::i32 && RetVT != MVT::i64)
246 switch (II->getIntrinsicID()) {
247 default:
return false;
248 case Intrinsic::sadd_with_overflow:
249 case Intrinsic::ssub_with_overflow:
250 case Intrinsic::smul_with_overflow:
251 case Intrinsic::umul_with_overflow: TmpCC =
X86::COND_O;
break;
252 case Intrinsic::uadd_with_overflow:
253 case Intrinsic::usub_with_overflow: TmpCC =
X86::COND_B;
break;
257 if (II->getParent() !=
I->getParent())
263 for (
auto Itr = std::prev(Start); Itr !=
End; --Itr) {
266 if (!isa<ExtractValueInst>(Itr))
270 const auto *EVI = cast<ExtractValueInst>(Itr);
271 if (EVI->getAggregateOperand() != II)
277 auto HasPhis = [](
const BasicBlock *Succ) {
return !Succ->phis().empty(); };
290bool X86FastISel::isTypeLegal(
Type *Ty,
MVT &VT,
bool AllowI1) {
291 EVT evt = TLI.getValueType(
DL, Ty,
true);
292 if (evt == MVT::Other || !evt.
isSimple())
299 if (VT == MVT::f64 && !Subtarget->hasSSE2())
301 if (VT == MVT::f32 && !Subtarget->hasSSE1())
310 return (AllowI1 && VT == MVT::i1) || TLI.isTypeLegal(VT);
318 unsigned Alignment) {
319 bool HasSSE1 = Subtarget->hasSSE1();
320 bool HasSSE2 = Subtarget->hasSSE2();
321 bool HasSSE41 = Subtarget->hasSSE41();
322 bool HasAVX = Subtarget->hasAVX();
323 bool HasAVX2 = Subtarget->hasAVX2();
324 bool HasAVX512 = Subtarget->hasAVX512();
325 bool HasVLX = Subtarget->hasVLX();
335 default:
return false;
350 Opc = HasAVX512 ? X86::VMOVSSZrm_alt
351 : HasAVX ? X86::VMOVSSrm_alt
352 : HasSSE1 ? X86::MOVSSrm_alt
356 Opc = HasAVX512 ? X86::VMOVSDZrm_alt
357 : HasAVX ? X86::VMOVSDrm_alt
358 : HasSSE2 ? X86::MOVSDrm_alt
365 if (IsNonTemporal && Alignment >= 16 && HasSSE41)
366 Opc = HasVLX ? X86::VMOVNTDQAZ128rm :
367 HasAVX ? X86::VMOVNTDQArm : X86::MOVNTDQArm;
368 else if (Alignment >= 16)
369 Opc = HasVLX ? X86::VMOVAPSZ128rm :
370 HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm;
372 Opc = HasVLX ? X86::VMOVUPSZ128rm :
373 HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm;
376 if (IsNonTemporal && Alignment >= 16 && HasSSE41)
377 Opc = HasVLX ? X86::VMOVNTDQAZ128rm :
378 HasAVX ? X86::VMOVNTDQArm : X86::MOVNTDQArm;
379 else if (Alignment >= 16)
380 Opc = HasVLX ? X86::VMOVAPDZ128rm :
381 HasAVX ? X86::VMOVAPDrm : X86::MOVAPDrm;
383 Opc = HasVLX ? X86::VMOVUPDZ128rm :
384 HasAVX ? X86::VMOVUPDrm : X86::MOVUPDrm;
390 if (IsNonTemporal && Alignment >= 16 && HasSSE41)
391 Opc = HasVLX ? X86::VMOVNTDQAZ128rm :
392 HasAVX ? X86::VMOVNTDQArm : X86::MOVNTDQArm;
393 else if (Alignment >= 16)
394 Opc = HasVLX ? X86::VMOVDQA64Z128rm :
395 HasAVX ? X86::VMOVDQArm : X86::MOVDQArm;
397 Opc = HasVLX ? X86::VMOVDQU64Z128rm :
398 HasAVX ? X86::VMOVDQUrm : X86::MOVDQUrm;
402 if (IsNonTemporal && Alignment >= 32 && HasAVX2)
403 Opc = HasVLX ? X86::VMOVNTDQAZ256rm : X86::VMOVNTDQAYrm;
404 else if (IsNonTemporal && Alignment >= 16)
406 else if (Alignment >= 32)
407 Opc = HasVLX ? X86::VMOVAPSZ256rm : X86::VMOVAPSYrm;
409 Opc = HasVLX ? X86::VMOVUPSZ256rm : X86::VMOVUPSYrm;
413 if (IsNonTemporal && Alignment >= 32 && HasAVX2)
414 Opc = HasVLX ? X86::VMOVNTDQAZ256rm : X86::VMOVNTDQAYrm;
415 else if (IsNonTemporal && Alignment >= 16)
417 else if (Alignment >= 32)
418 Opc = HasVLX ? X86::VMOVAPDZ256rm : X86::VMOVAPDYrm;
420 Opc = HasVLX ? X86::VMOVUPDZ256rm : X86::VMOVUPDYrm;
427 if (IsNonTemporal && Alignment >= 32 && HasAVX2)
428 Opc = HasVLX ? X86::VMOVNTDQAZ256rm : X86::VMOVNTDQAYrm;
429 else if (IsNonTemporal && Alignment >= 16)
431 else if (Alignment >= 32)
432 Opc = HasVLX ? X86::VMOVDQA64Z256rm : X86::VMOVDQAYrm;
434 Opc = HasVLX ? X86::VMOVDQU64Z256rm : X86::VMOVDQUYrm;
438 if (IsNonTemporal && Alignment >= 64)
439 Opc = X86::VMOVNTDQAZrm;
441 Opc = (Alignment >= 64) ? X86::VMOVAPSZrm : X86::VMOVUPSZrm;
445 if (IsNonTemporal && Alignment >= 64)
446 Opc = X86::VMOVNTDQAZrm;
448 Opc = (Alignment >= 64) ? X86::VMOVAPDZrm : X86::VMOVUPDZrm;
457 if (IsNonTemporal && Alignment >= 64)
458 Opc = X86::VMOVNTDQAZrm;
460 Opc = (Alignment >= 64) ? X86::VMOVDQA64Zrm : X86::VMOVDQU64Zrm;
466 ResultReg = createResultReg(RC);
468 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg);
481 bool HasSSE1 = Subtarget->hasSSE1();
482 bool HasSSE2 = Subtarget->hasSSE2();
483 bool HasSSE4A = Subtarget->hasSSE4A();
484 bool HasAVX = Subtarget->hasAVX();
485 bool HasAVX512 = Subtarget->hasAVX512();
486 bool HasVLX = Subtarget->hasVLX();
493 default:
return false;
496 Register AndResult = createResultReg(&X86::GR8RegClass);
497 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
498 TII.get(X86::AND8ri), AndResult)
503 case MVT::i8: Opc = X86::MOV8mr;
break;
504 case MVT::i16: Opc = X86::MOV16mr;
break;
506 Opc = (IsNonTemporal && HasSSE2) ? X86::MOVNTImr : X86::MOV32mr;
510 Opc = (IsNonTemporal && HasSSE2) ? X86::MOVNTI_64mr : X86::MOV64mr;
514 if (IsNonTemporal && HasSSE4A)
517 Opc = HasAVX512 ? X86::VMOVSSZmr :
518 HasAVX ? X86::VMOVSSmr : X86::MOVSSmr;
524 if (IsNonTemporal && HasSSE4A)
527 Opc = HasAVX512 ? X86::VMOVSDZmr :
528 HasAVX ? X86::VMOVSDmr : X86::MOVSDmr;
533 Opc = (IsNonTemporal && HasSSE1) ? X86::MMX_MOVNTQmr : X86::MMX_MOVQ64mr;
538 Opc = HasVLX ? X86::VMOVNTPSZ128mr :
539 HasAVX ? X86::VMOVNTPSmr : X86::MOVNTPSmr;
541 Opc = HasVLX ? X86::VMOVAPSZ128mr :
542 HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr;
544 Opc = HasVLX ? X86::VMOVUPSZ128mr :
545 HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr;
550 Opc = HasVLX ? X86::VMOVNTPDZ128mr :
551 HasAVX ? X86::VMOVNTPDmr : X86::MOVNTPDmr;
553 Opc = HasVLX ? X86::VMOVAPDZ128mr :
554 HasAVX ? X86::VMOVAPDmr : X86::MOVAPDmr;
556 Opc = HasVLX ? X86::VMOVUPDZ128mr :
557 HasAVX ? X86::VMOVUPDmr : X86::MOVUPDmr;
565 Opc = HasVLX ? X86::VMOVNTDQZ128mr :
566 HasAVX ? X86::VMOVNTDQmr : X86::MOVNTDQmr;
568 Opc = HasVLX ? X86::VMOVDQA64Z128mr :
569 HasAVX ? X86::VMOVDQAmr : X86::MOVDQAmr;
571 Opc = HasVLX ? X86::VMOVDQU64Z128mr :
572 HasAVX ? X86::VMOVDQUmr : X86::MOVDQUmr;
578 Opc = HasVLX ? X86::VMOVNTPSZ256mr : X86::VMOVNTPSYmr;
580 Opc = HasVLX ? X86::VMOVAPSZ256mr : X86::VMOVAPSYmr;
582 Opc = HasVLX ? X86::VMOVUPSZ256mr : X86::VMOVUPSYmr;
588 Opc = HasVLX ? X86::VMOVNTPDZ256mr : X86::VMOVNTPDYmr;
590 Opc = HasVLX ? X86::VMOVAPDZ256mr : X86::VMOVAPDYmr;
592 Opc = HasVLX ? X86::VMOVUPDZ256mr : X86::VMOVUPDYmr;
601 Opc = HasVLX ? X86::VMOVNTDQZ256mr : X86::VMOVNTDQYmr;
603 Opc = HasVLX ? X86::VMOVDQA64Z256mr : X86::VMOVDQAYmr;
605 Opc = HasVLX ? X86::VMOVDQU64Z256mr : X86::VMOVDQUYmr;
610 Opc = IsNonTemporal ? X86::VMOVNTPSZmr : X86::VMOVAPSZmr;
612 Opc = X86::VMOVUPSZmr;
617 Opc = IsNonTemporal ? X86::VMOVNTPDZmr : X86::VMOVAPDZmr;
619 Opc = X86::VMOVUPDZmr;
629 Opc = IsNonTemporal ? X86::VMOVNTDQZmr : X86::VMOVDQA64Zmr;
631 Opc = X86::VMOVDQU64Zmr;
644 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
Desc);
652bool X86FastISel::X86FastEmitStore(
EVT VT,
const Value *Val,
656 if (isa<ConstantPointerNull>(Val))
660 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(Val)) {
668 case MVT::i8: Opc = X86::MOV8mi;
break;
669 case MVT::i16: Opc = X86::MOV16mi;
break;
670 case MVT::i32: Opc = X86::MOV32mi;
break;
673 if (isInt<32>(CI->getSExtValue()))
674 Opc = X86::MOV64mi32;
680 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc));
682 : CI->getZExtValue());
689 Register ValReg = getRegForValue(Val);
693 return X86FastEmitStore(VT, ValReg, AM, MMO,
Aligned);
700 unsigned Src,
EVT SrcVT,
701 unsigned &ResultReg) {
712 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
718 if (GV->isThreadLocal())
722 if (GV->isAbsoluteSymbolRef())
728 if (!Subtarget->isPICStyleRIPRel() ||
734 unsigned char GVFlags = Subtarget->classifyGlobalReference(GV);
739 AM.
Base.
Reg = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
745 if (Subtarget->isPICStyleRIPRel()) {
759 if (
I != LocalValueMap.end() &&
I->second) {
771 SavePoint SaveInsertPt = enterLocalValueArea();
773 if (TLI.getPointerTy(
DL) == MVT::i64) {
775 RC = &X86::GR64RegClass;
778 RC = &X86::GR32RegClass;
785 LoadReg = createResultReg(RC);
787 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), LoadReg);
791 leaveLocalValueArea(SaveInsertPt);
794 LocalValueMap[
V] = LoadReg;
806 if (!AM.
GV || !Subtarget->isPICStyleRIPRel()) {
808 AM.
Base.
Reg = getRegForValue(V);
826 const User *
U =
nullptr;
827 unsigned Opcode = Instruction::UserOp1;
832 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(V)) ||
833 FuncInfo.MBBMap[
I->getParent()] == FuncInfo.MBB) {
837 }
else if (
const ConstantExpr *
C = dyn_cast<ConstantExpr>(V)) {
842 if (
PointerType *Ty = dyn_cast<PointerType>(
V->getType()))
843 if (Ty->getAddressSpace() > 255)
850 case Instruction::BitCast:
854 case Instruction::IntToPtr:
856 if (TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
857 TLI.getPointerTy(
DL))
861 case Instruction::PtrToInt:
863 if (TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
867 case Instruction::Alloca: {
871 FuncInfo.StaticAllocaMap.find(
A);
872 if (SI != FuncInfo.StaticAllocaMap.end()) {
880 case Instruction::Add: {
882 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(
U->getOperand(1))) {
885 if (isInt<32>(Disp)) {
893 case Instruction::GetElementPtr: {
899 unsigned Scale = AM.
Scale;
904 i !=
e; ++i, ++GTI) {
906 if (
StructType *STy = GTI.getStructTypeOrNull()) {
914 uint64_t S =
DL.getTypeAllocSize(GTI.getIndexedType());
918 Disp += CI->getSExtValue() * S;
921 if (canFoldAddIntoGEP(U,
Op)) {
924 cast<ConstantInt>(cast<AddOperator>(
Op)->getOperand(1));
927 Op = cast<AddOperator>(
Op)->getOperand(0);
931 (!AM.
GV || !Subtarget->isPICStyleRIPRel()) &&
932 (S == 1 || S == 2 || S == 4 || S == 8)) {
935 IndexReg = getRegForGEPIndex(
Op);
941 goto unsupported_gep;
946 if (!isInt<32>(Disp))
955 dyn_cast<GetElementPtrInst>(
U->getOperand(0))) {
969 if (handleConstantAddresses(
I, AM))
979 return handleConstantAddresses(V, AM);
985 const User *
U =
nullptr;
986 unsigned Opcode = Instruction::UserOp1;
1015 InMBB =
I->getParent() == FuncInfo.MBB->getBasicBlock();
1016 }
else if (
const ConstantExpr *
C = dyn_cast<ConstantExpr>(V)) {
1023 case Instruction::BitCast:
1026 return X86SelectCallAddress(
U->getOperand(0), AM);
1029 case Instruction::IntToPtr:
1032 TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
1033 TLI.getPointerTy(
DL))
1034 return X86SelectCallAddress(
U->getOperand(0), AM);
1037 case Instruction::PtrToInt:
1039 if (InMBB && TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
1040 return X86SelectCallAddress(
U->getOperand(0), AM);
1045 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
1051 if (Subtarget->isPICStyleRIPRel() &&
1057 if (GVar->isThreadLocal())
1066 if (Subtarget->isPICStyleRIPRel()) {
1072 AM.
GVOpFlags = Subtarget->classifyLocalReference(
nullptr);
1079 if (!AM.
GV || !Subtarget->isPICStyleRIPRel()) {
1080 auto GetCallRegForValue = [
this](
const Value *
V) {
1084 if (Reg && Subtarget->isTarget64BitILP32()) {
1085 Register CopyReg = createResultReg(&X86::GR32RegClass);
1086 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV32rr),
1090 Register ExtReg = createResultReg(&X86::GR64RegClass);
1091 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1092 TII.get(TargetOpcode::SUBREG_TO_REG), ExtReg)
1103 AM.
Base.
Reg = GetCallRegForValue(V);
1108 AM.
IndexReg = GetCallRegForValue(V);
1118bool X86FastISel::X86SelectStore(
const Instruction *
I) {
1125 const Value *PtrV =
I->getOperand(1);
1126 if (TLI.supportSwiftError()) {
1129 if (
const Argument *Arg = dyn_cast<Argument>(PtrV)) {
1130 if (Arg->hasSwiftErrorAttr())
1134 if (
const AllocaInst *Alloca = dyn_cast<AllocaInst>(PtrV)) {
1135 if (Alloca->isSwiftError())
1144 if (!isTypeLegal(Val->
getType(), VT,
true))
1149 bool Aligned = Alignment >= ABIAlignment;
1155 return X86FastEmitStore(VT, Val, AM, createMachineMemOperandFor(
I),
Aligned);
1161 const Function &
F = *
I->getParent()->getParent();
1165 if (!FuncInfo.CanLowerReturn)
1168 if (TLI.supportSwiftError() &&
1169 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
1172 if (TLI.supportSplitCSR(FuncInfo.MF))
1204 if (
Ret->getNumOperands() > 0) {
1210 CCState CCInfo(
CC,
F.isVarArg(), *FuncInfo.MF, ValLocs,
I->getContext());
1213 const Value *RV =
Ret->getOperand(0);
1219 if (ValLocs.
size() != 1)
1240 if (SrcVT != DstVT) {
1241 if (SrcVT != MVT::i1 && SrcVT != MVT::i8 && SrcVT != MVT::i16)
1244 if (!Outs[0].
Flags.isZExt() && !Outs[0].Flags.isSExt())
1247 assert(DstVT == MVT::i32 &&
"X86 should always ext to i32");
1249 if (SrcVT == MVT::i1) {
1250 if (Outs[0].
Flags.isSExt())
1253 SrcReg = fastEmitZExtFromI1(MVT::i8, SrcReg);
1268 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1269 TII.get(TargetOpcode::COPY), DstReg).
addReg(SrcReg);
1286 "SRetReturnReg should have been set in LowerFormalArguments()!");
1287 unsigned RetReg = Subtarget->isTarget64BitLP64() ? X86::RAX : X86::EAX;
1288 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1289 TII.get(TargetOpcode::COPY), RetReg).
addReg(Reg);
1296 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1297 TII.get(Subtarget->is64Bit() ? X86::RETI64 : X86::RETI32))
1300 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1301 TII.get(Subtarget->is64Bit() ? X86::RET64 : X86::RET32));
1303 for (
unsigned i = 0, e = RetRegs.
size(); i != e; ++i)
1317 const Value *SV =
I->getOperand(0);
1318 if (TLI.supportSwiftError()) {
1321 if (
const Argument *Arg = dyn_cast<Argument>(SV)) {
1322 if (Arg->hasSwiftErrorAttr())
1326 if (
const AllocaInst *Alloca = dyn_cast<AllocaInst>(SV)) {
1327 if (Alloca->isSwiftError())
1333 if (!isTypeLegal(LI->
getType(), VT,
true))
1342 unsigned ResultReg = 0;
1343 if (!X86FastEmitLoad(VT, AM, createMachineMemOperandFor(LI), ResultReg,
1347 updateValueMap(
I, ResultReg);
1352 bool HasAVX512 = Subtarget->
hasAVX512();
1353 bool HasAVX = Subtarget->
hasAVX();
1354 bool HasSSE1 = Subtarget->
hasSSE1();
1355 bool HasSSE2 = Subtarget->
hasSSE2();
1359 case MVT::i8:
return X86::CMP8rr;
1360 case MVT::i16:
return X86::CMP16rr;
1361 case MVT::i32:
return X86::CMP32rr;
1362 case MVT::i64:
return X86::CMP64rr;
1364 return HasAVX512 ? X86::VUCOMISSZrr
1365 : HasAVX ? X86::VUCOMISSrr
1366 : HasSSE1 ? X86::UCOMISSrr
1369 return HasAVX512 ? X86::VUCOMISDZrr
1370 : HasAVX ? X86::VUCOMISDrr
1371 : HasSSE2 ? X86::UCOMISDrr
1386 return X86::CMP16ri;
1388 return X86::CMP32ri;
1392 return isInt<32>(RHSC->
getSExtValue()) ? X86::CMP64ri32 : 0;
1396bool X86FastISel::X86FastEmitCompare(
const Value *Op0,
const Value *Op1,
EVT VT,
1398 Register Op0Reg = getRegForValue(Op0);
1399 if (Op0Reg == 0)
return false;
1402 if (isa<ConstantPointerNull>(Op1))
1408 if (
const ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
1410 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, CurMIMD,
TII.get(CompareImmOpc))
1412 .
addImm(Op1C->getSExtValue());
1418 if (CompareOpc == 0)
return false;
1420 Register Op1Reg = getRegForValue(Op1);
1421 if (Op1Reg == 0)
return false;
1422 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, CurMIMD,
TII.get(CompareOpc))
1430 const CmpInst *CI = cast<CmpInst>(
I);
1433 if (!isTypeLegal(
I->getOperand(0)->getType(), VT))
1442 unsigned ResultReg = 0;
1443 switch (Predicate) {
1446 ResultReg = createResultReg(&X86::GR32RegClass);
1447 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV32r0),
1449 ResultReg = fastEmitInst_extractsubreg(MVT::i8, ResultReg, X86::sub_8bit);
1455 ResultReg = createResultReg(&X86::GR8RegClass);
1456 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV8ri),
1463 updateValueMap(
I, ResultReg);
1474 const auto *RHSC = dyn_cast<ConstantFP>(RHS);
1475 if (RHSC && RHSC->isNullValue())
1480 static const uint16_t SETFOpcTable[2][3] = {
1485 switch (Predicate) {
1491 ResultReg = createResultReg(&X86::GR8RegClass);
1493 if (!X86FastEmitCompare(LHS, RHS, VT,
I->getDebugLoc()))
1496 Register FlagReg1 = createResultReg(&X86::GR8RegClass);
1497 Register FlagReg2 = createResultReg(&X86::GR8RegClass);
1498 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SETCCr),
1499 FlagReg1).
addImm(SETFOpc[0]);
1500 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SETCCr),
1501 FlagReg2).
addImm(SETFOpc[1]);
1502 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(SETFOpc[2]),
1504 updateValueMap(
I, ResultReg);
1517 if (!X86FastEmitCompare(LHS, RHS, VT,
I->getDebugLoc()))
1520 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SETCCr),
1522 updateValueMap(
I, ResultReg);
1527 EVT DstVT = TLI.getValueType(
DL,
I->getType());
1528 if (!TLI.isTypeLegal(DstVT))
1531 Register ResultReg = getRegForValue(
I->getOperand(0));
1536 MVT SrcVT = TLI.getSimpleValueType(
DL,
I->getOperand(0)->getType());
1537 if (SrcVT == MVT::i1) {
1539 ResultReg = fastEmitZExtFromI1(MVT::i8, ResultReg);
1546 if (DstVT == MVT::i64) {
1551 case MVT::i8: MovInst = X86::MOVZX32rr8;
break;
1552 case MVT::i16: MovInst = X86::MOVZX32rr16;
break;
1553 case MVT::i32: MovInst = X86::MOV32rr;
break;
1557 Register Result32 = createResultReg(&X86::GR32RegClass);
1558 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(MovInst), Result32)
1561 ResultReg = createResultReg(&X86::GR64RegClass);
1562 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::SUBREG_TO_REG),
1565 }
else if (DstVT == MVT::i16) {
1568 Register Result32 = createResultReg(&X86::GR32RegClass);
1569 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOVZX32rr8),
1570 Result32).
addReg(ResultReg);
1572 ResultReg = fastEmitInst_extractsubreg(MVT::i16, Result32, X86::sub_16bit);
1573 }
else if (DstVT != MVT::i8) {
1580 updateValueMap(
I, ResultReg);
1585 EVT DstVT = TLI.getValueType(
DL,
I->getType());
1586 if (!TLI.isTypeLegal(DstVT))
1589 Register ResultReg = getRegForValue(
I->getOperand(0));
1594 MVT SrcVT = TLI.getSimpleValueType(
DL,
I->getOperand(0)->getType());
1595 if (SrcVT == MVT::i1) {
1597 Register ZExtReg = fastEmitZExtFromI1(MVT::i8, ResultReg);
1602 ResultReg = createResultReg(&X86::GR8RegClass);
1603 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::NEG8r),
1604 ResultReg).
addReg(ZExtReg);
1609 if (DstVT == MVT::i16) {
1612 Register Result32 = createResultReg(&X86::GR32RegClass);
1613 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOVSX32rr8),
1614 Result32).
addReg(ResultReg);
1616 ResultReg = fastEmitInst_extractsubreg(MVT::i16, Result32, X86::sub_16bit);
1617 }
else if (DstVT != MVT::i8) {
1624 updateValueMap(
I, ResultReg);
1628bool X86FastISel::X86SelectBranch(
const Instruction *
I) {
1645 switch (Predicate) {
1659 const auto *CmpRHSC = dyn_cast<ConstantFP>(CmpRHS);
1660 if (CmpRHSC && CmpRHSC->isNullValue())
1665 if (FuncInfo.MBB->isLayoutSuccessor(TrueMBB)) {
1675 bool NeedExtraBranch =
false;
1676 switch (Predicate) {
1682 NeedExtraBranch =
true;
1695 if (!X86FastEmitCompare(CmpLHS, CmpRHS, VT, CI->
getDebugLoc()))
1698 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1703 if (NeedExtraBranch) {
1704 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1708 finishCondBranch(BI->
getParent(), TrueMBB, FalseMBB);
1715 if (TI->hasOneUse() && TI->getParent() ==
I->getParent() &&
1716 isTypeLegal(TI->getOperand(0)->getType(), SourceVT)) {
1717 unsigned TestOpc = 0;
1720 case MVT::i8: TestOpc = X86::TEST8ri;
break;
1721 case MVT::i16: TestOpc = X86::TEST16ri;
break;
1722 case MVT::i32: TestOpc = X86::TEST32ri;
break;
1723 case MVT::i64: TestOpc = X86::TEST64ri32;
break;
1726 Register OpReg = getRegForValue(TI->getOperand(0));
1727 if (OpReg == 0)
return false;
1729 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TestOpc))
1733 if (FuncInfo.MBB->isLayoutSuccessor(TrueMBB)) {
1738 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1741 finishCondBranch(BI->
getParent(), TrueMBB, FalseMBB);
1752 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1754 finishCondBranch(BI->
getParent(), TrueMBB, FalseMBB);
1762 if (OpReg == 0)
return false;
1765 if (
MRI.getRegClass(OpReg) == &X86::VK1RegClass) {
1766 unsigned KOpReg = OpReg;
1767 OpReg = createResultReg(&X86::GR32RegClass);
1768 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1769 TII.get(TargetOpcode::COPY), OpReg)
1771 OpReg = fastEmitInst_extractsubreg(MVT::i8, OpReg, X86::sub_8bit);
1773 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TEST8ri))
1776 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1778 finishCondBranch(BI->
getParent(), TrueMBB, FalseMBB);
1782bool X86FastISel::X86SelectShift(
const Instruction *
I) {
1783 unsigned CReg = 0, OpReg = 0;
1785 if (
I->getType()->isIntegerTy(8)) {
1787 RC = &X86::GR8RegClass;
1788 switch (
I->getOpcode()) {
1789 case Instruction::LShr: OpReg = X86::SHR8rCL;
break;
1790 case Instruction::AShr: OpReg = X86::SAR8rCL;
break;
1791 case Instruction::Shl: OpReg = X86::SHL8rCL;
break;
1792 default:
return false;
1794 }
else if (
I->getType()->isIntegerTy(16)) {
1796 RC = &X86::GR16RegClass;
1797 switch (
I->getOpcode()) {
1799 case Instruction::LShr: OpReg = X86::SHR16rCL;
break;
1800 case Instruction::AShr: OpReg = X86::SAR16rCL;
break;
1801 case Instruction::Shl: OpReg = X86::SHL16rCL;
break;
1803 }
else if (
I->getType()->isIntegerTy(32)) {
1805 RC = &X86::GR32RegClass;
1806 switch (
I->getOpcode()) {
1808 case Instruction::LShr: OpReg = X86::SHR32rCL;
break;
1809 case Instruction::AShr: OpReg = X86::SAR32rCL;
break;
1810 case Instruction::Shl: OpReg = X86::SHL32rCL;
break;
1812 }
else if (
I->getType()->isIntegerTy(64)) {
1814 RC = &X86::GR64RegClass;
1815 switch (
I->getOpcode()) {
1817 case Instruction::LShr: OpReg = X86::SHR64rCL;
break;
1818 case Instruction::AShr: OpReg = X86::SAR64rCL;
break;
1819 case Instruction::Shl: OpReg = X86::SHL64rCL;
break;
1826 if (!isTypeLegal(
I->getType(), VT))
1829 Register Op0Reg = getRegForValue(
I->getOperand(0));
1830 if (Op0Reg == 0)
return false;
1832 Register Op1Reg = getRegForValue(
I->getOperand(1));
1833 if (Op1Reg == 0)
return false;
1834 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
1839 if (CReg != X86::CL)
1840 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1841 TII.get(TargetOpcode::KILL), X86::CL)
1844 Register ResultReg = createResultReg(RC);
1845 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(OpReg), ResultReg)
1847 updateValueMap(
I, ResultReg);
1851bool X86FastISel::X86SelectDivRem(
const Instruction *
I) {
1852 const static unsigned NumTypes = 4;
1853 const static unsigned NumOps = 4;
1854 const static bool S =
true;
1855 const static bool U =
false;
1856 const static unsigned Copy = TargetOpcode::COPY;
1866 const static struct DivRemEntry {
1872 struct DivRemResult {
1874 unsigned OpSignExtend;
1878 unsigned DivRemResultReg;
1880 } ResultTable[NumOps];
1881 } OpTable[NumTypes] = {
1882 { &X86::GR8RegClass, X86::AX, 0, {
1883 { X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AL, S },
1884 { X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AH, S },
1885 { X86::DIV8r, 0, X86::MOVZX16rr8, X86::AL,
U },
1886 { X86::DIV8r, 0, X86::MOVZX16rr8, X86::AH,
U },
1889 { &X86::GR16RegClass, X86::AX, X86::DX, {
1890 { X86::IDIV16r, X86::CWD,
Copy, X86::AX, S },
1891 { X86::IDIV16r, X86::CWD,
Copy, X86::DX, S },
1892 { X86::DIV16r, X86::MOV32r0,
Copy, X86::AX,
U },
1893 { X86::DIV16r, X86::MOV32r0,
Copy, X86::DX,
U },
1896 { &X86::GR32RegClass, X86::EAX, X86::EDX, {
1897 { X86::IDIV32r, X86::CDQ,
Copy, X86::EAX, S },
1898 { X86::IDIV32r, X86::CDQ,
Copy, X86::EDX, S },
1899 { X86::DIV32r, X86::MOV32r0,
Copy, X86::EAX,
U },
1900 { X86::DIV32r, X86::MOV32r0,
Copy, X86::EDX,
U },
1903 { &X86::GR64RegClass, X86::RAX, X86::RDX, {
1904 { X86::IDIV64r, X86::CQO,
Copy, X86::RAX, S },
1905 { X86::IDIV64r, X86::CQO,
Copy, X86::RDX, S },
1906 { X86::DIV64r, X86::MOV32r0,
Copy, X86::RAX,
U },
1907 { X86::DIV64r, X86::MOV32r0,
Copy, X86::RDX,
U },
1913 if (!isTypeLegal(
I->getType(), VT))
1918 default:
return false;
1919 case MVT::i8: TypeIndex = 0;
break;
1920 case MVT::i16: TypeIndex = 1;
break;
1921 case MVT::i32: TypeIndex = 2;
break;
1922 case MVT::i64: TypeIndex = 3;
1923 if (!Subtarget->is64Bit())
1928 switch (
I->getOpcode()) {
1930 case Instruction::SDiv:
OpIndex = 0;
break;
1931 case Instruction::SRem:
OpIndex = 1;
break;
1932 case Instruction::UDiv:
OpIndex = 2;
break;
1933 case Instruction::URem:
OpIndex = 3;
break;
1936 const DivRemEntry &
TypeEntry = OpTable[TypeIndex];
1938 Register Op0Reg = getRegForValue(
I->getOperand(0));
1941 Register Op1Reg = getRegForValue(
I->getOperand(1));
1946 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1949 if (OpEntry.OpSignExtend) {
1950 if (OpEntry.IsOpSigned)
1951 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1952 TII.get(OpEntry.OpSignExtend));
1954 Register Zero32 = createResultReg(&X86::GR32RegClass);
1955 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1956 TII.get(X86::MOV32r0), Zero32);
1961 if (VT == MVT::i16) {
1962 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1964 .
addReg(Zero32, 0, X86::sub_16bit);
1965 }
else if (VT == MVT::i32) {
1966 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1969 }
else if (VT == MVT::i64) {
1970 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1971 TII.get(TargetOpcode::SUBREG_TO_REG),
TypeEntry.HighInReg)
1977 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1978 TII.get(OpEntry.OpDivRem)).
addReg(Op1Reg);
1987 unsigned ResultReg = 0;
1988 if ((
I->getOpcode() == Instruction::SRem ||
1989 I->getOpcode() == Instruction::URem) &&
1990 OpEntry.DivRemResultReg == X86::AH && Subtarget->is64Bit()) {
1991 Register SourceSuperReg = createResultReg(&X86::GR16RegClass);
1992 Register ResultSuperReg = createResultReg(&X86::GR16RegClass);
1993 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1994 TII.get(Copy), SourceSuperReg).
addReg(X86::AX);
1997 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SHR16ri),
2001 ResultReg = fastEmitInst_extractsubreg(MVT::i8, ResultSuperReg,
2006 ResultReg = createResultReg(
TypeEntry.RC);
2007 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Copy), ResultReg)
2008 .
addReg(OpEntry.DivRemResultReg);
2010 updateValueMap(
I, ResultReg);
2017bool X86FastISel::X86FastEmitCMoveSelect(
MVT RetVT,
const Instruction *
I) {
2019 if (!Subtarget->canUseCMOV())
2023 if (RetVT < MVT::i16 || RetVT > MVT::i64)
2028 bool NeedTest =
true;
2034 const auto *CI = dyn_cast<CmpInst>(
Cond);
2035 if (CI && (CI->
getParent() ==
I->getParent())) {
2039 static const uint16_t SETFOpcTable[2][3] = {
2044 switch (Predicate) {
2047 SETFOpc = &SETFOpcTable[0][0];
2051 SETFOpc = &SETFOpcTable[1][0];
2067 if (!X86FastEmitCompare(CmpLHS, CmpRHS, CmpVT, CI->
getDebugLoc()))
2071 Register FlagReg1 = createResultReg(&X86::GR8RegClass);
2072 Register FlagReg2 = createResultReg(&X86::GR8RegClass);
2073 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SETCCr),
2074 FlagReg1).
addImm(SETFOpc[0]);
2075 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SETCCr),
2076 FlagReg2).
addImm(SETFOpc[1]);
2077 auto const &II =
TII.get(SETFOpc[2]);
2078 if (II.getNumDefs()) {
2079 Register TmpReg = createResultReg(&X86::GR8RegClass);
2080 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, TmpReg)
2083 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
2088 }
else if (foldX86XALUIntrinsic(
CC,
I,
Cond)) {
2109 if (
MRI.getRegClass(CondReg) == &X86::VK1RegClass) {
2110 unsigned KCondReg = CondReg;
2111 CondReg = createResultReg(&X86::GR32RegClass);
2112 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2113 TII.get(TargetOpcode::COPY), CondReg)
2115 CondReg = fastEmitInst_extractsubreg(MVT::i8, CondReg, X86::sub_8bit);
2117 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TEST8ri))
2125 Register RHSReg = getRegForValue(RHS);
2126 Register LHSReg = getRegForValue(LHS);
2127 if (!LHSReg || !RHSReg)
2132 Register ResultReg = fastEmitInst_rri(Opc, RC, RHSReg, LHSReg,
CC);
2133 updateValueMap(
I, ResultReg);
2142bool X86FastISel::X86FastEmitSSESelect(
MVT RetVT,
const Instruction *
I) {
2146 const auto *CI = dyn_cast<FCmpInst>(
I->getOperand(0));
2147 if (!CI || (CI->
getParent() !=
I->getParent()))
2151 !((Subtarget->hasSSE1() && RetVT == MVT::f32) ||
2152 (Subtarget->hasSSE2() && RetVT == MVT::f64)))
2163 const auto *CmpRHSC = dyn_cast<ConstantFP>(CmpRHS);
2164 if (CmpRHSC && CmpRHSC->isNullValue())
2171 if (
CC > 7 && !Subtarget->hasAVX())
2180 Register LHSReg = getRegForValue(LHS);
2181 Register RHSReg = getRegForValue(RHS);
2182 Register CmpLHSReg = getRegForValue(CmpLHS);
2183 Register CmpRHSReg = getRegForValue(CmpRHS);
2184 if (!LHSReg || !RHSReg || !CmpLHSReg || !CmpRHSReg)
2190 if (Subtarget->hasAVX512()) {
2195 unsigned CmpOpcode =
2196 (RetVT == MVT::f32) ? X86::VCMPSSZrr : X86::VCMPSDZrr;
2197 Register CmpReg = fastEmitInst_rri(CmpOpcode, VK1, CmpLHSReg, CmpRHSReg,
2202 Register ImplicitDefReg = createResultReg(VR128X);
2203 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2204 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2208 unsigned MovOpcode =
2209 (RetVT == MVT::f32) ? X86::VMOVSSZrrk : X86::VMOVSDZrrk;
2210 unsigned MovReg = fastEmitInst_rrrr(MovOpcode, VR128X, RHSReg, CmpReg,
2211 ImplicitDefReg, LHSReg);
2213 ResultReg = createResultReg(RC);
2214 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2215 TII.get(TargetOpcode::COPY), ResultReg).
addReg(MovReg);
2217 }
else if (Subtarget->hasAVX()) {
2225 unsigned CmpOpcode =
2226 (RetVT == MVT::f32) ? X86::VCMPSSrr : X86::VCMPSDrr;
2227 unsigned BlendOpcode =
2228 (RetVT == MVT::f32) ? X86::VBLENDVPSrr : X86::VBLENDVPDrr;
2230 Register CmpReg = fastEmitInst_rri(CmpOpcode, RC, CmpLHSReg, CmpRHSReg,
2232 Register VBlendReg = fastEmitInst_rrr(BlendOpcode, VR128, RHSReg, LHSReg,
2234 ResultReg = createResultReg(RC);
2235 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2236 TII.get(TargetOpcode::COPY), ResultReg).
addReg(VBlendReg);
2239 static const uint16_t OpcTable[2][4] = {
2240 { X86::CMPSSrr, X86::ANDPSrr, X86::ANDNPSrr, X86::ORPSrr },
2241 { X86::CMPSDrr, X86::ANDPDrr, X86::ANDNPDrr, X86::ORPDrr }
2246 default:
return false;
2247 case MVT::f32: Opc = &OpcTable[0][0];
break;
2248 case MVT::f64: Opc = &OpcTable[1][0];
break;
2252 Register CmpReg = fastEmitInst_rri(Opc[0], RC, CmpLHSReg, CmpRHSReg,
CC);
2253 Register AndReg = fastEmitInst_rr(Opc[1], VR128, CmpReg, LHSReg);
2254 Register AndNReg = fastEmitInst_rr(Opc[2], VR128, CmpReg, RHSReg);
2255 Register OrReg = fastEmitInst_rr(Opc[3], VR128, AndNReg, AndReg);
2256 ResultReg = createResultReg(RC);
2257 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2258 TII.get(TargetOpcode::COPY), ResultReg).
addReg(OrReg);
2260 updateValueMap(
I, ResultReg);
2264bool X86FastISel::X86FastEmitPseudoSelect(
MVT RetVT,
const Instruction *
I) {
2269 default:
return false;
2270 case MVT::i8: Opc = X86::CMOV_GR8;
break;
2271 case MVT::i16: Opc = X86::CMOV_GR16;
break;
2272 case MVT::i32: Opc = X86::CMOV_GR32;
break;
2274 Opc = Subtarget->hasAVX512() ? X86::CMOV_FR16X : X86::CMOV_FR16;
break;
2276 Opc = Subtarget->hasAVX512() ? X86::CMOV_FR32X : X86::CMOV_FR32;
break;
2278 Opc = Subtarget->hasAVX512() ? X86::CMOV_FR64X : X86::CMOV_FR64;
break;
2287 const auto *CI = dyn_cast<CmpInst>(
Cond);
2288 if (CI && (CI->
getParent() ==
I->getParent())) {
2301 if (!X86FastEmitCompare(CmpLHS, CmpRHS, CmpVT, CI->
getDebugLoc()))
2309 if (
MRI.getRegClass(CondReg) == &X86::VK1RegClass) {
2310 unsigned KCondReg = CondReg;
2311 CondReg = createResultReg(&X86::GR32RegClass);
2312 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2313 TII.get(TargetOpcode::COPY), CondReg)
2315 CondReg = fastEmitInst_extractsubreg(MVT::i8, CondReg, X86::sub_8bit);
2317 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TEST8ri))
2325 Register LHSReg = getRegForValue(LHS);
2326 Register RHSReg = getRegForValue(RHS);
2327 if (!LHSReg || !RHSReg)
2333 fastEmitInst_rri(Opc, RC, RHSReg, LHSReg,
CC);
2334 updateValueMap(
I, ResultReg);
2338bool X86FastISel::X86SelectSelect(
const Instruction *
I) {
2340 if (!isTypeLegal(
I->getType(), RetVT))
2344 if (
const auto *CI = dyn_cast<CmpInst>(
I->getOperand(0))) {
2346 const Value *Opnd =
nullptr;
2347 switch (Predicate) {
2354 Register OpReg = getRegForValue(Opnd);
2358 Register ResultReg = createResultReg(RC);
2359 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2360 TII.get(TargetOpcode::COPY), ResultReg)
2362 updateValueMap(
I, ResultReg);
2368 if (X86FastEmitCMoveSelect(RetVT,
I))
2372 if (X86FastEmitSSESelect(RetVT,
I))
2377 if (X86FastEmitPseudoSelect(RetVT,
I))
2384bool X86FastISel::X86SelectIntToFP(
const Instruction *
I,
bool IsSigned) {
2389 bool HasAVX512 = Subtarget->hasAVX512();
2390 if (!Subtarget->hasAVX() || (!IsSigned && !HasAVX512))
2394 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
2395 if (SrcVT != MVT::i32 && SrcVT != MVT::i64)
2399 Register OpReg = getRegForValue(
I->getOperand(0));
2405 static const uint16_t SCvtOpc[2][2][2] = {
2406 { { X86::VCVTSI2SSrr, X86::VCVTSI642SSrr },
2407 { X86::VCVTSI2SDrr, X86::VCVTSI642SDrr } },
2408 { { X86::VCVTSI2SSZrr, X86::VCVTSI642SSZrr },
2409 { X86::VCVTSI2SDZrr, X86::VCVTSI642SDZrr } },
2411 static const uint16_t UCvtOpc[2][2] = {
2412 { X86::VCVTUSI2SSZrr, X86::VCVTUSI642SSZrr },
2413 { X86::VCVTUSI2SDZrr, X86::VCVTUSI642SDZrr },
2415 bool Is64Bit = SrcVT == MVT::i64;
2417 if (
I->getType()->isDoubleTy()) {
2419 Opcode = IsSigned ? SCvtOpc[HasAVX512][1][Is64Bit] : UCvtOpc[1][Is64Bit];
2420 }
else if (
I->getType()->isFloatTy()) {
2422 Opcode = IsSigned ? SCvtOpc[HasAVX512][0][Is64Bit] : UCvtOpc[0][Is64Bit];
2428 Register ImplicitDefReg = createResultReg(RC);
2429 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2430 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2431 Register ResultReg = fastEmitInst_rr(
Opcode, RC, ImplicitDefReg, OpReg);
2432 updateValueMap(
I, ResultReg);
2436bool X86FastISel::X86SelectSIToFP(
const Instruction *
I) {
2437 return X86SelectIntToFP(
I,
true);
2440bool X86FastISel::X86SelectUIToFP(
const Instruction *
I) {
2441 return X86SelectIntToFP(
I,
false);
2445bool X86FastISel::X86SelectFPExtOrFPTrunc(
const Instruction *
I,
2448 assert((
I->getOpcode() == Instruction::FPExt ||
2449 I->getOpcode() == Instruction::FPTrunc) &&
2450 "Instruction must be an FPExt or FPTrunc!");
2451 bool HasAVX = Subtarget->hasAVX();
2453 Register OpReg = getRegForValue(
I->getOperand(0));
2457 unsigned ImplicitDefReg;
2459 ImplicitDefReg = createResultReg(RC);
2460 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2461 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2465 Register ResultReg = createResultReg(RC);
2467 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpc),
2471 MIB.
addReg(ImplicitDefReg);
2474 updateValueMap(
I, ResultReg);
2478bool X86FastISel::X86SelectFPExt(
const Instruction *
I) {
2479 if (Subtarget->hasSSE2() &&
I->getType()->isDoubleTy() &&
2480 I->getOperand(0)->getType()->isFloatTy()) {
2481 bool HasAVX512 = Subtarget->hasAVX512();
2484 HasAVX512 ? X86::VCVTSS2SDZrr
2485 : Subtarget->hasAVX() ? X86::VCVTSS2SDrr : X86::CVTSS2SDrr;
2486 return X86SelectFPExtOrFPTrunc(
I, Opc, TLI.getRegClassFor(MVT::f64));
2492bool X86FastISel::X86SelectFPTrunc(
const Instruction *
I) {
2493 if (Subtarget->hasSSE2() &&
I->getType()->isFloatTy() &&
2494 I->getOperand(0)->getType()->isDoubleTy()) {
2495 bool HasAVX512 = Subtarget->hasAVX512();
2498 HasAVX512 ? X86::VCVTSD2SSZrr
2499 : Subtarget->hasAVX() ? X86::VCVTSD2SSrr : X86::CVTSD2SSrr;
2500 return X86SelectFPExtOrFPTrunc(
I, Opc, TLI.getRegClassFor(MVT::f32));
2506bool X86FastISel::X86SelectTrunc(
const Instruction *
I) {
2507 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
2508 EVT DstVT = TLI.getValueType(
DL,
I->getType());
2511 if (DstVT != MVT::i8 && DstVT != MVT::i1)
2513 if (!TLI.isTypeLegal(SrcVT))
2516 Register InputReg = getRegForValue(
I->getOperand(0));
2521 if (SrcVT == MVT::i8) {
2523 updateValueMap(
I, InputReg);
2528 Register ResultReg = fastEmitInst_extractsubreg(MVT::i8, InputReg,
2533 updateValueMap(
I, ResultReg);
2537bool X86FastISel::IsMemcpySmall(
uint64_t Len) {
2538 return Len <= (Subtarget->is64Bit() ? 32 : 16);
2545 if (!IsMemcpySmall(Len))
2548 bool i64Legal = Subtarget->is64Bit();
2553 if (Len >= 8 && i64Legal)
2563 bool RV = X86FastEmitLoad(VT, SrcAM,
nullptr, Reg);
2564 RV &= X86FastEmitStore(VT, Reg, DestAM);
2565 assert(RV &&
"Failed to emit load or store??");
2577bool X86FastISel::fastLowerIntrinsicCall(
const IntrinsicInst *II) {
2580 default:
return false;
2581 case Intrinsic::convert_from_fp16:
2582 case Intrinsic::convert_to_fp16: {
2583 if (Subtarget->useSoftFloat() || !Subtarget->hasF16C())
2592 bool IsFloatToHalf = II->
getIntrinsicID() == Intrinsic::convert_to_fp16;
2593 if (IsFloatToHalf) {
2594 if (!
Op->getType()->isFloatTy())
2601 unsigned ResultReg = 0;
2603 if (IsFloatToHalf) {
2611 unsigned Opc = Subtarget->hasVLX() ? X86::VCVTPS2PHZ128rr
2613 InputReg = fastEmitInst_ri(Opc, RC, InputReg, 4);
2616 Opc = Subtarget->hasAVX512() ? X86::VMOVPDI2DIZrr
2617 : X86::VMOVPDI2DIrr;
2618 ResultReg = createResultReg(&X86::GR32RegClass);
2619 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg)
2623 unsigned RegIdx = X86::sub_16bit;
2624 ResultReg = fastEmitInst_extractsubreg(MVT::i16, ResultReg, RegIdx);
2626 assert(
Op->getType()->isIntegerTy(16) &&
"Expected a 16-bit integer!");
2634 unsigned Opc = Subtarget->hasVLX() ? X86::VCVTPH2PSZ128rr
2636 InputReg = fastEmitInst_r(Opc, RC, InputReg);
2640 ResultReg = createResultReg(TLI.getRegClassFor(MVT::f32));
2641 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2642 TII.get(TargetOpcode::COPY), ResultReg)
2646 updateValueMap(II, ResultReg);
2649 case Intrinsic::frameaddress: {
2657 if (!isTypeLegal(
RetTy, VT))
2665 case MVT::i32: Opc = X86::MOV32rm; RC = &X86::GR32RegClass;
break;
2666 case MVT::i64: Opc = X86::MOV64rm; RC = &X86::GR64RegClass;
break;
2675 unsigned FrameReg =
RegInfo->getPtrSizedFrameRegister(*MF);
2676 assert(((FrameReg == X86::RBP && VT == MVT::i64) ||
2677 (FrameReg == X86::EBP && VT == MVT::i32)) &&
2678 "Invalid Frame Register!");
2683 Register SrcReg = createResultReg(RC);
2684 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2685 TII.get(TargetOpcode::COPY), SrcReg).
addReg(FrameReg);
2692 unsigned Depth = cast<ConstantInt>(II->
getOperand(0))->getZExtValue();
2694 Register DestReg = createResultReg(RC);
2696 TII.get(Opc), DestReg), SrcReg);
2700 updateValueMap(II, SrcReg);
2703 case Intrinsic::memcpy: {
2704 const MemCpyInst *MCI = cast<MemCpyInst>(II);
2709 if (isa<ConstantInt>(MCI->
getLength())) {
2713 if (IsMemcpySmall(Len)) {
2718 TryEmitSmallMemcpy(DestAM, SrcAM, Len);
2723 unsigned SizeWidth = Subtarget->is64Bit() ? 64 : 32;
2730 return lowerCallTo(II,
"memcpy", II->
arg_size() - 1);
2732 case Intrinsic::memset: {
2733 const MemSetInst *MSI = cast<MemSetInst>(II);
2738 unsigned SizeWidth = Subtarget->is64Bit() ? 64 : 32;
2745 return lowerCallTo(II,
"memset", II->
arg_size() - 1);
2747 case Intrinsic::stackprotector: {
2749 EVT PtrTy = TLI.getPointerTy(
DL);
2759 if (!X86FastEmitStore(PtrTy, Op1, AM))
return false;
2762 case Intrinsic::dbg_declare: {
2770 "Expected inlined-at fields to agree");
2777 case Intrinsic::trap: {
2778 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TRAP));
2781 case Intrinsic::sqrt: {
2782 if (!Subtarget->hasSSE1())
2785 Type *
RetTy = II->getCalledFunction()->getReturnType();
2788 if (!isTypeLegal(
RetTy, VT))
2794 static const uint16_t SqrtOpc[3][2] = {
2795 { X86::SQRTSSr, X86::SQRTSDr },
2796 { X86::VSQRTSSr, X86::VSQRTSDr },
2797 { X86::VSQRTSSZr, X86::VSQRTSDZr },
2799 unsigned AVXLevel = Subtarget->hasAVX512() ? 2 :
2800 Subtarget->hasAVX() ? 1 :
2804 default:
return false;
2805 case MVT::f32: Opc = SqrtOpc[AVXLevel][0];
break;
2806 case MVT::f64: Opc = SqrtOpc[AVXLevel][1];
break;
2809 const Value *SrcVal = II->getArgOperand(0);
2810 Register SrcReg = getRegForValue(SrcVal);
2816 unsigned ImplicitDefReg = 0;
2818 ImplicitDefReg = createResultReg(RC);
2819 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2820 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2823 Register ResultReg = createResultReg(RC);
2825 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc),
2829 MIB.
addReg(ImplicitDefReg);
2833 updateValueMap(II, ResultReg);
2836 case Intrinsic::sadd_with_overflow:
2837 case Intrinsic::uadd_with_overflow:
2838 case Intrinsic::ssub_with_overflow:
2839 case Intrinsic::usub_with_overflow:
2840 case Intrinsic::smul_with_overflow:
2841 case Intrinsic::umul_with_overflow: {
2845 auto *Ty = cast<StructType>(
Callee->getReturnType());
2849 "Overflow value expected to be an i1");
2852 if (!isTypeLegal(
RetTy, VT))
2855 if (VT < MVT::i8 || VT > MVT::i64)
2858 const Value *
LHS = II->getArgOperand(0);
2859 const Value *
RHS = II->getArgOperand(1);
2862 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) && II->isCommutative())
2866 switch (II->getIntrinsicID()) {
2868 case Intrinsic::sadd_with_overflow:
2870 case Intrinsic::uadd_with_overflow:
2872 case Intrinsic::ssub_with_overflow:
2874 case Intrinsic::usub_with_overflow:
2876 case Intrinsic::smul_with_overflow:
2878 case Intrinsic::umul_with_overflow:
2882 Register LHSReg = getRegForValue(LHS);
2886 unsigned ResultReg = 0;
2888 if (
const auto *CI = dyn_cast<ConstantInt>(RHS)) {
2889 static const uint16_t Opc[2][4] = {
2890 { X86::INC8r, X86::INC16r, X86::INC32r, X86::INC64r },
2891 { X86::DEC8r, X86::DEC16r, X86::DEC32r, X86::DEC64r }
2897 ResultReg = createResultReg(TLI.getRegClassFor(VT));
2899 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2900 TII.get(Opc[IsDec][VT.
SimpleTy-MVT::i8]), ResultReg)
2903 ResultReg = fastEmit_ri(VT, VT, BaseOpc, LHSReg, CI->getZExtValue());
2908 RHSReg = getRegForValue(RHS);
2911 ResultReg = fastEmit_rr(VT, VT, BaseOpc, LHSReg, RHSReg);
2918 { X86::MUL8r, X86::MUL16r, X86::MUL32r, X86::MUL64r };
2919 static const MCPhysReg Reg[] = { X86::AL, X86::AX, X86::EAX, X86::RAX };
2922 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2923 TII.get(TargetOpcode::COPY), Reg[VT.
SimpleTy-MVT::i8])
2925 ResultReg = fastEmitInst_r(MULOpc[VT.
SimpleTy-MVT::i8],
2926 TLI.getRegClassFor(VT), RHSReg);
2929 { X86::IMUL8r, X86::IMUL16rr, X86::IMUL32rr, X86::IMUL64rr };
2930 if (VT == MVT::i8) {
2933 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2934 TII.get(TargetOpcode::COPY), X86::AL)
2936 ResultReg = fastEmitInst_r(MULOpc[0], TLI.getRegClassFor(VT), RHSReg);
2938 ResultReg = fastEmitInst_rr(MULOpc[VT.
SimpleTy-MVT::i8],
2939 TLI.getRegClassFor(VT), LHSReg, RHSReg);
2946 Register ResultReg2 = createResultReg(&X86::GR8RegClass);
2947 assert((ResultReg+1) == ResultReg2 &&
"Nonconsecutive result registers.");
2948 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SETCCr),
2949 ResultReg2).
addImm(CondCode);
2951 updateValueMap(II, ResultReg, 2);
2954 case Intrinsic::x86_sse_cvttss2si:
2955 case Intrinsic::x86_sse_cvttss2si64:
2956 case Intrinsic::x86_sse2_cvttsd2si:
2957 case Intrinsic::x86_sse2_cvttsd2si64: {
2959 switch (II->getIntrinsicID()) {
2961 case Intrinsic::x86_sse_cvttss2si:
2962 case Intrinsic::x86_sse_cvttss2si64:
2963 if (!Subtarget->hasSSE1())
2965 IsInputDouble =
false;
2967 case Intrinsic::x86_sse2_cvttsd2si:
2968 case Intrinsic::x86_sse2_cvttsd2si64:
2969 if (!Subtarget->hasSSE2())
2971 IsInputDouble =
true;
2975 Type *
RetTy = II->getCalledFunction()->getReturnType();
2977 if (!isTypeLegal(
RetTy, VT))
2980 static const uint16_t CvtOpc[3][2][2] = {
2981 { { X86::CVTTSS2SIrr, X86::CVTTSS2SI64rr },
2982 { X86::CVTTSD2SIrr, X86::CVTTSD2SI64rr } },
2983 { { X86::VCVTTSS2SIrr, X86::VCVTTSS2SI64rr },
2984 { X86::VCVTTSD2SIrr, X86::VCVTTSD2SI64rr } },
2985 { { X86::VCVTTSS2SIZrr, X86::VCVTTSS2SI64Zrr },
2986 { X86::VCVTTSD2SIZrr, X86::VCVTTSD2SI64Zrr } },
2988 unsigned AVXLevel = Subtarget->hasAVX512() ? 2 :
2989 Subtarget->hasAVX() ? 1 :
2994 case MVT::i32: Opc = CvtOpc[AVXLevel][IsInputDouble][0];
break;
2995 case MVT::i64: Opc = CvtOpc[AVXLevel][IsInputDouble][1];
break;
2999 const Value *
Op = II->getArgOperand(0);
3000 while (
auto *IE = dyn_cast<InsertElementInst>(
Op)) {
3002 if (!isa<ConstantInt>(
Index))
3004 unsigned Idx = cast<ConstantInt>(
Index)->getZExtValue();
3007 Op =
IE->getOperand(1);
3010 Op =
IE->getOperand(0);
3017 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3018 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg)
3021 updateValueMap(II, ResultReg);
3024 case Intrinsic::x86_sse42_crc32_32_8:
3025 case Intrinsic::x86_sse42_crc32_32_16:
3026 case Intrinsic::x86_sse42_crc32_32_32:
3027 case Intrinsic::x86_sse42_crc32_64_64: {
3028 if (!Subtarget->hasCRC32())
3031 Type *
RetTy = II->getCalledFunction()->getReturnType();
3034 if (!isTypeLegal(
RetTy, VT))
3040 switch (II->getIntrinsicID()) {
3043 case Intrinsic::x86_sse42_crc32_32_8:
3044 Opc = X86::CRC32r32r8;
3045 RC = &X86::GR32RegClass;
3047 case Intrinsic::x86_sse42_crc32_32_16:
3048 Opc = X86::CRC32r32r16;
3049 RC = &X86::GR32RegClass;
3051 case Intrinsic::x86_sse42_crc32_32_32:
3052 Opc = X86::CRC32r32r32;
3053 RC = &X86::GR32RegClass;
3055 case Intrinsic::x86_sse42_crc32_64_64:
3056 Opc = X86::CRC32r64r64;
3057 RC = &X86::GR64RegClass;
3061 const Value *
LHS = II->getArgOperand(0);
3062 const Value *
RHS = II->getArgOperand(1);
3064 Register LHSReg = getRegForValue(LHS);
3065 Register RHSReg = getRegForValue(RHS);
3066 if (!LHSReg || !RHSReg)
3069 Register ResultReg = fastEmitInst_rr(Opc, RC, LHSReg, RHSReg);
3073 updateValueMap(II, ResultReg);
3079bool X86FastISel::fastLowerArguments() {
3080 if (!FuncInfo.CanLowerReturn)
3091 if (Subtarget->isCallingConvWin64(
CC))
3094 if (!Subtarget->is64Bit())
3097 if (Subtarget->useSoftFloat())
3101 unsigned GPRCnt = 0;
3102 unsigned FPRCnt = 0;
3103 for (
auto const &Arg :
F->args()) {
3104 if (Arg.hasAttribute(Attribute::ByVal) ||
3105 Arg.hasAttribute(Attribute::InReg) ||
3106 Arg.hasAttribute(Attribute::StructRet) ||
3107 Arg.hasAttribute(Attribute::SwiftSelf) ||
3108 Arg.hasAttribute(Attribute::SwiftAsync) ||
3109 Arg.hasAttribute(Attribute::SwiftError) ||
3110 Arg.hasAttribute(Attribute::Nest))
3113 Type *ArgTy = Arg.getType();
3117 EVT ArgVT = TLI.getValueType(
DL, ArgTy);
3118 if (!ArgVT.
isSimple())
return false;
3120 default:
return false;
3127 if (!Subtarget->hasSSE1())
3140 static const MCPhysReg GPR32ArgRegs[] = {
3141 X86::EDI, X86::ESI, X86::EDX, X86::ECX, X86::R8D, X86::R9D
3143 static const MCPhysReg GPR64ArgRegs[] = {
3144 X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8 , X86::R9
3147 X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,
3148 X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
3152 unsigned FPRIdx = 0;
3153 for (
auto const &Arg :
F->args()) {
3154 MVT VT = TLI.getSimpleValueType(
DL, Arg.getType());
3159 case MVT::i32: SrcReg = GPR32ArgRegs[
GPRIdx++];
break;
3160 case MVT::i64: SrcReg = GPR64ArgRegs[
GPRIdx++];
break;
3161 case MVT::f32: [[fallthrough]];
3162 case MVT::f64: SrcReg = XMMArgRegs[FPRIdx++];
break;
3164 Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
3168 Register ResultReg = createResultReg(RC);
3169 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3170 TII.get(TargetOpcode::COPY), ResultReg)
3172 updateValueMap(&Arg, ResultReg);
3180 if (Subtarget->is64Bit())
3197bool X86FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3198 auto &OutVals = CLI.OutVals;
3199 auto &OutFlags = CLI.OutFlags;
3200 auto &OutRegs = CLI.OutRegs;
3201 auto &
Ins = CLI.Ins;
3202 auto &InRegs = CLI.InRegs;
3204 bool &IsTailCall = CLI.IsTailCall;
3205 bool IsVarArg = CLI.IsVarArg;
3208 const auto *CB = CLI.CB;
3210 bool Is64Bit = Subtarget->is64Bit();
3211 bool IsWin64 = Subtarget->isCallingConvWin64(
CC);
3215 if (CB && CB->doesNoCfCheck())
3219 if ((CB && isa<CallInst>(CB) && CB->hasFnAttr(
"no_caller_saved_registers")))
3223 if ((CB && CB->hasFnAttr(
"no_callee_saved_registers")))
3231 if (Subtarget->useIndirectThunkCalls())
3236 default:
return false;
3263 if (IsVarArg && IsWin64)
3267 if (CLI.CB && CLI.CB->hasInAllocaArgument())
3270 for (
auto Flag : CLI.OutFlags)
3271 if (
Flag.isSwiftError() ||
Flag.isPreallocated())
3280 for (
int i = 0, e = OutVals.size(); i != e; ++i) {
3281 Value *&Val = OutVals[i];
3283 if (
auto *CI = dyn_cast<ConstantInt>(Val)) {
3284 if (CI->getBitWidth() < 32) {
3295 auto *TI = dyn_cast<TruncInst>(Val);
3297 if (TI && TI->getType()->isIntegerTy(1) && CLI.CB &&
3298 (TI->getParent() == CLI.CB->getParent()) && TI->hasOneUse()) {
3299 Value *PrevVal = TI->getOperand(0);
3300 ResultReg = getRegForValue(PrevVal);
3305 if (!isTypeLegal(PrevVal->
getType(), VT))
3308 ResultReg = fastEmit_ri(VT, VT,
ISD::AND, ResultReg, 1);
3310 if (!isTypeLegal(Val->
getType(), VT) ||
3313 ResultReg = getRegForValue(Val);
3325 CCState CCInfo(
CC, IsVarArg, *FuncInfo.MF, ArgLocs, CLI.RetTy->getContext());
3329 CCInfo.AllocateStack(32,
Align(8));
3331 CCInfo.AnalyzeCallOperands(OutVTs, OutFlags,
CC_X86);
3334 unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
3337 unsigned AdjStackDown =
TII.getCallFrameSetupOpcode();
3338 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackDown))
3343 for (
unsigned i = 0, e = ArgLocs.
size(); i != e; ++i) {
3348 if (ArgVT == MVT::x86mmx)
3351 unsigned ArgReg = ArgRegs[VA.
getValNo()];
3358 "Unexpected extend");
3360 if (ArgVT == MVT::i1)
3365 assert(Emitted &&
"Failed to emit a sext!"); (void)Emitted;
3371 "Unexpected extend");
3374 if (ArgVT == MVT::i1) {
3376 ArgReg = fastEmitZExtFromI1(MVT::i8, ArgReg);
3385 assert(Emitted &&
"Failed to emit a zext!"); (void)Emitted;
3391 "Unexpected extend");
3401 assert(Emitted &&
"Failed to emit a aext!"); (void)Emitted;
3407 assert(ArgReg &&
"Failed to emit a bitcast!");
3428 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3435 if (isa<UndefValue>(ArgVal))
3441 AM.
Disp = LocMemOffset;
3447 if (
Flags.isByVal()) {
3450 if (!TryEmitSmallMemcpy(AM, SrcAM,
Flags.getByValSize()))
3452 }
else if (isa<ConstantInt>(ArgVal) || isa<ConstantPointerNull>(ArgVal)) {
3456 if (!X86FastEmitStore(ArgVT, ArgVal, AM, MMO))
3459 if (!X86FastEmitStore(ArgVT, ArgReg, AM, MMO))
3467 if (Subtarget->isPICStyleGOT()) {
3468 unsigned Base = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
3469 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3473 if (Is64Bit && IsVarArg && !IsWin64) {
3484 X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,
3485 X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
3487 unsigned NumXMMRegs = CCInfo.getFirstUnallocated(XMMArgRegs);
3488 assert((Subtarget->hasSSE1() || !NumXMMRegs)
3489 &&
"SSE registers cannot be used when SSE is disabled");
3490 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV8ri),
3491 X86::AL).
addImm(NumXMMRegs);
3497 if (!X86SelectCallAddress(Callee, CalleeAM))
3500 unsigned CalleeOp = 0;
3502 if (CalleeAM.
GV !=
nullptr) {
3504 }
else if (CalleeAM.
Base.
Reg != 0) {
3513 unsigned CallOpc = Is64Bit ? X86::CALL64r : X86::CALL32r;
3514 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CallOpc))
3518 assert(GV &&
"Not a direct call");
3520 unsigned char OpFlags = Subtarget->classifyGlobalFunctionReference(GV);
3523 cast<Function>(GV)->isIntrinsic())
3532 unsigned CallOpc = NeedLoad
3533 ? (Is64Bit ? X86::CALL64m : X86::CALL32m)
3534 : (Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32);
3536 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CallOpc));
3540 MIB.
addSym(Symbol, OpFlags);
3552 if (Subtarget->isPICStyleGOT())
3555 if (Is64Bit && IsVarArg && !IsWin64)
3559 for (
auto Reg : OutRegs)
3563 unsigned NumBytesForCalleeToPop =
3565 TM.Options.GuaranteedTailCallOpt)
3568 unsigned AdjStackUp =
TII.getCallFrameDestroyOpcode();
3569 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackUp))
3574 CCState CCRetInfo(
CC, IsVarArg, *FuncInfo.MF, RVLocs,
3575 CLI.RetTy->getContext());
3576 CCRetInfo.AnalyzeCallResult(Ins,
RetCC_X86);
3579 Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);
3580 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
3583 unsigned CopyReg = ResultReg + i;
3587 if ((CopyVT == MVT::f32 || CopyVT == MVT::f64) &&
3588 ((Is64Bit || Ins[i].
Flags.isInReg()) && !Subtarget->hasSSE1())) {
3594 if ((SrcReg == X86::FP0 || SrcReg == X86::FP1) &&
3595 isScalarFPTypeInSSEReg(VA.
getValVT())) {
3597 CopyReg = createResultReg(&X86::RFP80RegClass);
3601 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3602 TII.get(TargetOpcode::COPY), CopyReg).
addReg(SrcReg);
3610 unsigned Opc = ResVT == MVT::f32 ? X86::ST_Fp80m32 : X86::ST_Fp80m64;
3616 Opc = ResVT == MVT::f32 ? X86::MOVSSrm_alt : X86::MOVSDrm_alt;
3618 TII.get(Opc), ResultReg + i), FI);
3622 CLI.ResultReg = ResultReg;
3623 CLI.NumResultRegs = RVLocs.
size();
3630X86FastISel::fastSelectInstruction(
const Instruction *
I) {
3631 switch (
I->getOpcode()) {
3633 case Instruction::Load:
3634 return X86SelectLoad(
I);
3635 case Instruction::Store:
3636 return X86SelectStore(
I);
3637 case Instruction::Ret:
3638 return X86SelectRet(
I);
3639 case Instruction::ICmp:
3640 case Instruction::FCmp:
3641 return X86SelectCmp(
I);
3642 case Instruction::ZExt:
3643 return X86SelectZExt(
I);
3644 case Instruction::SExt:
3645 return X86SelectSExt(
I);
3646 case Instruction::Br:
3647 return X86SelectBranch(
I);
3648 case Instruction::LShr:
3649 case Instruction::AShr:
3650 case Instruction::Shl:
3651 return X86SelectShift(
I);
3652 case Instruction::SDiv:
3653 case Instruction::UDiv:
3654 case Instruction::SRem:
3655 case Instruction::URem:
3656 return X86SelectDivRem(
I);
3657 case Instruction::Select:
3658 return X86SelectSelect(
I);
3659 case Instruction::Trunc:
3660 return X86SelectTrunc(
I);
3661 case Instruction::FPExt:
3662 return X86SelectFPExt(
I);
3663 case Instruction::FPTrunc:
3664 return X86SelectFPTrunc(
I);
3665 case Instruction::SIToFP:
3666 return X86SelectSIToFP(
I);
3667 case Instruction::UIToFP:
3668 return X86SelectUIToFP(
I);
3669 case Instruction::IntToPtr:
3670 case Instruction::PtrToInt: {
3671 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
3672 EVT DstVT = TLI.getValueType(
DL,
I->getType());
3674 return X86SelectZExt(
I);
3676 return X86SelectTrunc(
I);
3678 if (Reg == 0)
return false;
3679 updateValueMap(
I, Reg);
3682 case Instruction::BitCast: {
3684 if (!Subtarget->hasSSE2())
3688 if (!isTypeLegal(
I->getOperand(0)->getType(), SrcVT) ||
3689 !isTypeLegal(
I->getType(), DstVT))
3705 Register ResultReg = createResultReg(DstClass);
3706 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3707 TII.get(TargetOpcode::COPY), ResultReg).
addReg(Reg);
3709 updateValueMap(
I, ResultReg);
3717unsigned 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)
3749 case MVT::i8: Opc = X86::MOV8ri;
break;
3750 case MVT::i16: Opc = X86::MOV16ri;
break;
3751 case MVT::i32: Opc = X86::MOV32ri;
break;
3753 if (isUInt<32>(Imm))
3754 Opc = X86::MOV32ri64;
3755 else if (isInt<32>(Imm))
3756 Opc = X86::MOV64ri32;
3762 return fastEmitInst_i(Opc, TLI.getRegClassFor(VT), Imm);
3765unsigned X86FastISel::X86MaterializeFP(
const ConstantFP *CFP,
MVT VT) {
3767 return fastMaterializeFloatZero(CFP);
3776 bool HasSSE1 = Subtarget->hasSSE1();
3777 bool HasSSE2 = Subtarget->hasSSE2();
3778 bool HasAVX = Subtarget->hasAVX();
3779 bool HasAVX512 = Subtarget->hasAVX512();
3783 Opc = HasAVX512 ? X86::VMOVSSZrm_alt
3784 : HasAVX ? X86::VMOVSSrm_alt
3785 : HasSSE1 ? X86::MOVSSrm_alt
3789 Opc = HasAVX512 ? X86::VMOVSDZrm_alt
3790 : HasAVX ? X86::VMOVSDrm_alt
3791 : HasSSE2 ? X86::MOVSDrm_alt
3803 unsigned PICBase = 0;
3804 unsigned char OpFlag = Subtarget->classifyLocalReference(
nullptr);
3806 PICBase = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
3808 PICBase = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
3813 unsigned CPI = MCP.getConstantPoolIndex(CFP, Alignment);
3818 Register AddrReg = createResultReg(&X86::GR64RegClass);
3819 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV64ri),
3823 TII.get(Opc), ResultReg);
3824 addRegReg(MIB, AddrReg,
false, PICBase,
false);
3833 TII.get(Opc), ResultReg),
3834 CPI, PICBase, OpFlag);
3838unsigned X86FastISel::X86MaterializeGV(
const GlobalValue *GV,
MVT VT) {
3852 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3854 TLI.getPointerTy(
DL) == MVT::i64) {
3857 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV64ri),
3862 TLI.getPointerTy(
DL) == MVT::i32
3863 ? (Subtarget->isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r)
3866 TII.get(Opc), ResultReg), AM);
3873unsigned X86FastISel::fastMaterializeConstant(
const Constant *
C) {
3874 EVT CEVT = TLI.getValueType(
DL,
C->getType(),
true);
3881 if (
const auto *CI = dyn_cast<ConstantInt>(
C))
3882 return X86MaterializeInt(CI, VT);
3883 if (
const auto *CFP = dyn_cast<ConstantFP>(
C))
3884 return X86MaterializeFP(CFP, VT);
3885 if (
const auto *GV = dyn_cast<GlobalValue>(
C))
3886 return X86MaterializeGV(GV, VT);
3887 if (isa<UndefValue>(
C)) {
3893 if (!Subtarget->hasSSE1())
3894 Opc = X86::LD_Fp032;
3897 if (!Subtarget->hasSSE2())
3898 Opc = X86::LD_Fp064;
3901 Opc = X86::LD_Fp080;
3906 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3907 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc),
3916unsigned X86FastISel::fastMaterializeAlloca(
const AllocaInst *
C) {
3924 if (!FuncInfo.StaticAllocaMap.count(
C))
3926 assert(
C->isStaticAlloca() &&
"dynamic alloca in the static alloca map?");
3932 TLI.getPointerTy(
DL) == MVT::i32
3933 ? (Subtarget->isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r)
3936 Register ResultReg = createResultReg(RC);
3938 TII.get(Opc), ResultReg), AM);
3942unsigned X86FastISel::fastMaterializeFloatZero(
const ConstantFP *CF) {
3944 if (!isTypeLegal(CF->
getType(), VT))
3948 bool HasSSE1 = Subtarget->hasSSE1();
3949 bool HasSSE2 = Subtarget->hasSSE2();
3950 bool HasAVX512 = Subtarget->hasAVX512();
3955 Opc = HasAVX512 ? X86::AVX512_FsFLD0SH : X86::FsFLD0SH;
3958 Opc = HasAVX512 ? X86::AVX512_FsFLD0SS
3959 : HasSSE1 ? X86::FsFLD0SS
3963 Opc = HasAVX512 ? X86::AVX512_FsFLD0SD
3964 : HasSSE2 ? X86::FsFLD0SD
3972 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3973 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg);
3978bool X86FastISel::tryToFoldLoadIntoMI(
MachineInstr *
MI,
unsigned OpNo,
3993 *FuncInfo.MF, *
MI, OpNo, AddrOps, FuncInfo.InsertPt,
Size, LI->
getAlign(),
4003 unsigned OperandNo = 0;
4005 E =
Result->operands_end();
I !=
E; ++
I, ++OperandNo) {
4012 if (IndexReg == MO.
getReg())
4017 Result->addMemOperand(*FuncInfo.MF, createMachineMemOperandFor(LI));
4018 Result->cloneInstrSymbols(*FuncInfo.MF, *
MI);
4020 removeDeadCode(
I, std::next(
I));
4024unsigned X86FastISel::fastEmitInst_rrrr(
unsigned MachineInstOpcode,
4026 unsigned Op0,
unsigned Op1,
4027 unsigned Op2,
unsigned Op3) {
4030 Register ResultReg = createResultReg(RC);
4037 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II, ResultReg)
4043 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, II)
4048 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
4059 return new X86FastISel(funcInfo, libInfo);
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
This file defines the FastISel class.
const HexagonInstrInfo * TII
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
unsigned const TargetRegisterInfo * TRI
const char LLVMTargetMachineRef TM
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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 void X86SelectAddress(const MachineInstr &I, const MachineRegisterInfo &MRI, X86AddressMode &AM)
static constexpr uint32_t Opcode
an instruction to allocate memory on the stack
This class represents an incoming formal argument to a Function.
LLVM Basic Block Representation.
InstListType::const_iterator const_iterator
Conditional or Unconditional Branch instruction.
BasicBlock * getSuccessor(unsigned i) const
Value * getCondition() const
CCState - This class holds information needed while lowering arguments and return values.
CCValAssign - Represent assignment of one arg/retval to a location.
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...
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
bool paramHasAttr(unsigned ArgNo, Attribute::AttrKind Kind) const
Determine whether the argument or parameter has the given attribute.
Value * getArgOperand(unsigned i) const
unsigned arg_size() const
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,...
Predicate getPredicate() const
Return the predicate for this instruction.
A constant value that is initialized with an expression using other constant values.
ConstantFP - Floating Point Values [float, double].
This is the shared class of boolean and integer constants.
static Constant * get(Type *Ty, uint64_t V, bool IsSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
This is an important base class in LLVM.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
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.
This class represents an Operation in the Expression.
This represents the llvm.dbg.declare instruction.
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 ...
virtual unsigned fastMaterializeFloatZero(const ConstantFP *CF)
Emit the floating-point constant +0.0 in a register using target- specific logic.
virtual bool fastLowerIntrinsicCall(const IntrinsicInst *II)
This method is called by target-independent code to do target- specific intrinsic lowering.
virtual bool tryToFoldLoadIntoMI(MachineInstr *, unsigned, const LoadInst *)
The specified machine instr operand is a vreg, and that vreg is being provided by the specified load ...
virtual unsigned fastMaterializeConstant(const Constant *C)
Emit a constant in a register using target-specific logic, such as constant pool loads.
virtual bool fastLowerCall(CallLoweringInfo &CLI)
This method is called by target-independent code to do target- specific call lowering.
virtual bool fastLowerArguments()
This method is called by target-independent code to do target- specific argument lowering.
virtual bool fastSelectInstruction(const Instruction *I)=0
This method is called by target-independent code when the normal FastISel process fails to select an ...
virtual unsigned fastMaterializeAlloca(const AllocaInst *C)
Emit an alloca address in a register using target-specific logic.
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
Type * getReturnType() const
Returns the type of the ret val.
an instruction for type-safe pointer arithmetic to access elements of arrays and structs
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
bool isAtomic() const LLVM_READONLY
Return true if this instruction has an AtomicOrdering of unordered or higher.
const BasicBlock * getParent() const
A wrapper class for inspecting calls to intrinsic functions.
Intrinsic::ID getIntrinsicID() const
Return the intrinsic ID of this intrinsic.
An instruction for reading from memory.
Value * getPointerOperand()
Align getAlign() const
Return the alignment of the access that is being performed.
bool usesWindowsCFI() const
Describe properties that are true of each instruction in the target description file.
unsigned getNumDefs() const
Return the number of MachineOperands that are register definitions.
ArrayRef< MCPhysReg > implicit_defs() const
Return a list of registers that are potentially written by any instance of this machine instruction.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
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
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
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.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
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 & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & addMBB(MachineBasicBlock *MBB, unsigned TargetFlags=0) const
Representation of each machine instruction.
unsigned getNumOperands() const
Retuns the total number of operands.
const MCInstrDesc & getDesc() const
Returns the target instruction descriptor of this MachineInstr.
void addMemOperand(MachineFunction &MF, MachineMemOperand *MO)
Add a MachineMemOperand to the machine instruction.
A description of a memory reference used in the backend.
bool isNonTemporal() const
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineOperand class - Representation of each machine instruction operand.
bool isReg() const
isReg - Tests if this is a MO_Register operand.
void setReg(Register Reg)
Change the register this operand corresponds to.
Register getReg() const
getReg - Returns the register number.
This class wraps the llvm.memcpy intrinsic.
Value * getLength() const
Value * getRawDest() const
unsigned getDestAddressSpace() const
This class wraps the llvm.memset and llvm.memset.inline intrinsics.
Value * getRawSource() const
Return the arguments to the instruction.
unsigned getSourceAddressSpace() const
Wrapper class representing virtual and physical registers.
Return a value (possibly void), from a function.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
An instruction for storing to memory.
Value * getValueOperand()
Value * getPointerOperand()
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
TypeSize getElementOffset(unsigned Idx) const
Class to represent struct types.
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.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
bool isOSMSVCRT() const
Is this a "Windows" OS targeting a "MSVCRT.dll" environment.
This class represents a truncation of integer types.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isVectorTy() const
True if this is an instance of VectorType.
bool isArrayTy() const
True if this is an instance of ArrayType.
bool isFloatTy() const
Return true if this is 'float', a 32-bit IEEE fp type.
unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type.
bool isStructTy() const
True if this is an instance of StructType.
bool isIntegerTy() const
True if this is an instance of IntegerType.
A Use represents the edge between a Value definition and its users.
Value * getOperand(unsigned i) 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, MachineBasicBlock::iterator InsertPt, int FrameIndex, LiveIntervals *LIS=nullptr, VirtRegMap *VRM=nullptr) const override
foldMemoryOperand - If this target supports it, fold a load or store of the specified stack slot into...
X86MachineFunctionInfo - This class is derived from MachineFunction and contains private X86 target-s...
Register getSRetReturnReg() const
unsigned getBytesToPopOnReturn() const
const Triple & getTargetTriple() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ X86_64_SysV
The C convention as specified in the x86-64 supplement to the System V ABI, used on most non-Windows ...
@ HiPE
Used by the High-Performance Erlang Compiler (HiPE).
@ Swift
Calling convention for Swift.
@ CFGuard_Check
Special calling convention on Windows for calling the Control Guard Check ICall funtion.
@ GHC
Used by the Glasgow Haskell Compiler (GHC).
@ X86_ThisCall
Similar to X86_StdCall.
@ X86_StdCall
stdcall is mostly used by the Win32 API.
@ 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...
@ Win64
The C convention as implemented on Windows/x86-64 and AArch64.
@ 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.
@ X86_FastCall
'fast' analog of X86_StdCall.
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.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ 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.
@ Implicit
Not emitted register (e.g. carry, or temporary result).
@ Kill
The last use of a register.
Reg
All possible values of the reg field in the ModR/M byte.
@ 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...
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.
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
unsigned getCMovOpcode(unsigned RegBytes, bool HasMemoryOperand=false)
Return a cmov opcode for the given register size in bytes, and operand type.
StringMapEntry< std::atomic< TypeEntryBody * > > TypeEntry
@ Emitted
Assigned address, still materializing.
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 ...
static bool isGlobalRelativeToPICBase(unsigned char TargetFlag)
isGlobalRelativeToPICBase - Return true if the specified global value reference is relative to a 32-b...
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...
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.
auto successors(const MachineBasicBlock *BB)
bool RetCC_X86(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
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)
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)
static const MachineInstrBuilder & addConstantPoolReference(const MachineInstrBuilder &MIB, unsigned CPI, unsigned GlobalBaseReg, unsigned char OpFlags)
addConstantPoolReference - This function is used to add a reference to the base of a constant value s...
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
static const MachineInstrBuilder & addRegReg(const MachineInstrBuilder &MIB, unsigned Reg1, bool isKill1, unsigned Reg2, bool isKill2)
addRegReg - This function is used to add a memory reference of the form: [Reg + Reg].
unsigned getKillRegState(bool B)
gep_type_iterator gep_type_begin(const User *GEP)
bool CC_X86(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, CCState &State)
static const MachineInstrBuilder & addDirectMem(const MachineInstrBuilder &MIB, unsigned 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.
This struct is a compact representation of a valid (non-zero power of two) alignment.
uint64_t value() const
This is a hole in the type system and should not be abused.
Description of the encoding of one expression Op.
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 MachinePointerInfo getStack(MachineFunction &MF, int64_t Offset, uint8_t ID=0)
Stack pointer relative access.
static 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)
enum llvm::X86AddressMode::@612 BaseType
union llvm::X86AddressMode::@613 Base