36#include "llvm/IR/IntrinsicsX86.h"
46class X86FastISel final :
public FastISel {
71#include "X86GenFastISel.inc"
74 bool X86FastEmitCompare(
const Value *LHS,
const Value *RHS,
EVT VT,
78 unsigned &ResultReg,
unsigned Alignment = 1);
119 bool X86SelectFPExtOrFPTrunc(
const Instruction *
I,
unsigned Opc,
126 bool X86SelectIntToFP(
const Instruction *
I,
bool IsSigned);
129 return Subtarget->getInstrInfo();
148 bool isScalarFPTypeInSSEReg(
EVT VT)
const {
149 return (VT == MVT::f64 && Subtarget->hasSSE2()) ||
150 (VT == MVT::f32 && Subtarget->hasSSE1()) || VT == MVT::f16;
153 bool isTypeLegal(
Type *Ty,
MVT &VT,
bool AllowI1 =
false);
166 unsigned fastEmitInst_rrrr(
unsigned MachineInstOpcode,
168 unsigned Op1,
unsigned Op2,
unsigned Op3);
173static std::pair<unsigned, bool>
176 bool NeedSwap =
false;
205 return std::make_pair(
CC, NeedSwap);
219 return ::addFullAddress(MIB, AM);
226 if (!isa<ExtractValueInst>(
Cond))
229 const auto *EV = cast<ExtractValueInst>(
Cond);
230 if (!isa<IntrinsicInst>(EV->getAggregateOperand()))
233 const auto *
II = cast<IntrinsicInst>(EV->getAggregateOperand());
237 cast<StructType>(
Callee->getReturnType())->getTypeAtIndex(0U);
238 if (!isTypeLegal(
RetTy, RetVT))
241 if (RetVT != MVT::i32 && RetVT != MVT::i64)
245 switch (
II->getIntrinsicID()) {
246 default:
return false;
247 case Intrinsic::sadd_with_overflow:
248 case Intrinsic::ssub_with_overflow:
249 case Intrinsic::smul_with_overflow:
250 case Intrinsic::umul_with_overflow: TmpCC =
X86::COND_O;
break;
251 case Intrinsic::uadd_with_overflow:
252 case Intrinsic::usub_with_overflow: TmpCC =
X86::COND_B;
break;
256 if (
II->getParent() !=
I->getParent())
262 for (
auto Itr = std::prev(Start); Itr !=
End; --Itr) {
265 if (!isa<ExtractValueInst>(Itr))
269 const auto *EVI = cast<ExtractValueInst>(Itr);
270 if (EVI->getAggregateOperand() !=
II)
276 auto HasPhis = [](
const BasicBlock *Succ) {
return !Succ->phis().empty(); };
289bool X86FastISel::isTypeLegal(
Type *Ty,
MVT &VT,
bool AllowI1) {
290 EVT evt = TLI.getValueType(
DL, Ty,
true);
291 if (evt == MVT::Other || !evt.
isSimple())
298 if (VT == MVT::f64 && !Subtarget->hasSSE2())
300 if (VT == MVT::f32 && !Subtarget->hasSSE1())
309 return (AllowI1 && VT == MVT::i1) || TLI.isTypeLegal(VT);
317 unsigned Alignment) {
318 bool HasSSE1 = Subtarget->hasSSE1();
319 bool HasSSE2 = Subtarget->hasSSE2();
320 bool HasSSE41 = Subtarget->hasSSE41();
321 bool HasAVX = Subtarget->hasAVX();
322 bool HasAVX2 = Subtarget->hasAVX2();
323 bool HasAVX512 = Subtarget->hasAVX512();
324 bool HasVLX = Subtarget->hasVLX();
334 default:
return false;
349 Opc = HasAVX512 ? X86::VMOVSSZrm_alt
350 : HasAVX ? X86::VMOVSSrm_alt
351 : HasSSE1 ? X86::MOVSSrm_alt
355 Opc = HasAVX512 ? X86::VMOVSDZrm_alt
356 : HasAVX ? X86::VMOVSDrm_alt
357 : HasSSE2 ? X86::MOVSDrm_alt
364 if (IsNonTemporal && Alignment >= 16 && HasSSE41)
365 Opc = HasVLX ? X86::VMOVNTDQAZ128rm :
366 HasAVX ? X86::VMOVNTDQArm : X86::MOVNTDQArm;
367 else if (Alignment >= 16)
368 Opc = HasVLX ? X86::VMOVAPSZ128rm :
369 HasAVX ? X86::VMOVAPSrm : X86::MOVAPSrm;
371 Opc = HasVLX ? X86::VMOVUPSZ128rm :
372 HasAVX ? X86::VMOVUPSrm : X86::MOVUPSrm;
375 if (IsNonTemporal && Alignment >= 16 && HasSSE41)
376 Opc = HasVLX ? X86::VMOVNTDQAZ128rm :
377 HasAVX ? X86::VMOVNTDQArm : X86::MOVNTDQArm;
378 else if (Alignment >= 16)
379 Opc = HasVLX ? X86::VMOVAPDZ128rm :
380 HasAVX ? X86::VMOVAPDrm : X86::MOVAPDrm;
382 Opc = HasVLX ? X86::VMOVUPDZ128rm :
383 HasAVX ? X86::VMOVUPDrm : X86::MOVUPDrm;
389 if (IsNonTemporal && Alignment >= 16 && HasSSE41)
390 Opc = HasVLX ? X86::VMOVNTDQAZ128rm :
391 HasAVX ? X86::VMOVNTDQArm : X86::MOVNTDQArm;
392 else if (Alignment >= 16)
393 Opc = HasVLX ? X86::VMOVDQA64Z128rm :
394 HasAVX ? X86::VMOVDQArm : X86::MOVDQArm;
396 Opc = HasVLX ? X86::VMOVDQU64Z128rm :
397 HasAVX ? X86::VMOVDQUrm : X86::MOVDQUrm;
401 if (IsNonTemporal && Alignment >= 32 && HasAVX2)
402 Opc = HasVLX ? X86::VMOVNTDQAZ256rm : X86::VMOVNTDQAYrm;
403 else if (IsNonTemporal && Alignment >= 16)
405 else if (Alignment >= 32)
406 Opc = HasVLX ? X86::VMOVAPSZ256rm : X86::VMOVAPSYrm;
408 Opc = HasVLX ? X86::VMOVUPSZ256rm : X86::VMOVUPSYrm;
412 if (IsNonTemporal && Alignment >= 32 && HasAVX2)
413 Opc = HasVLX ? X86::VMOVNTDQAZ256rm : X86::VMOVNTDQAYrm;
414 else if (IsNonTemporal && Alignment >= 16)
416 else if (Alignment >= 32)
417 Opc = HasVLX ? X86::VMOVAPDZ256rm : X86::VMOVAPDYrm;
419 Opc = HasVLX ? X86::VMOVUPDZ256rm : X86::VMOVUPDYrm;
426 if (IsNonTemporal && Alignment >= 32 && HasAVX2)
427 Opc = HasVLX ? X86::VMOVNTDQAZ256rm : X86::VMOVNTDQAYrm;
428 else if (IsNonTemporal && Alignment >= 16)
430 else if (Alignment >= 32)
431 Opc = HasVLX ? X86::VMOVDQA64Z256rm : X86::VMOVDQAYrm;
433 Opc = HasVLX ? X86::VMOVDQU64Z256rm : X86::VMOVDQUYrm;
437 if (IsNonTemporal && Alignment >= 64)
438 Opc = X86::VMOVNTDQAZrm;
440 Opc = (Alignment >= 64) ? X86::VMOVAPSZrm : X86::VMOVUPSZrm;
444 if (IsNonTemporal && Alignment >= 64)
445 Opc = X86::VMOVNTDQAZrm;
447 Opc = (Alignment >= 64) ? X86::VMOVAPDZrm : X86::VMOVUPDZrm;
456 if (IsNonTemporal && Alignment >= 64)
457 Opc = X86::VMOVNTDQAZrm;
459 Opc = (Alignment >= 64) ? X86::VMOVDQA64Zrm : X86::VMOVDQU64Zrm;
465 ResultReg = createResultReg(RC);
467 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg);
480 bool HasSSE1 = Subtarget->hasSSE1();
481 bool HasSSE2 = Subtarget->hasSSE2();
482 bool HasSSE4A = Subtarget->hasSSE4A();
483 bool HasAVX = Subtarget->hasAVX();
484 bool HasAVX512 = Subtarget->hasAVX512();
485 bool HasVLX = Subtarget->hasVLX();
492 default:
return false;
495 Register AndResult = createResultReg(&X86::GR8RegClass);
496 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
497 TII.get(X86::AND8ri), AndResult)
502 case MVT::i8: Opc = X86::MOV8mr;
break;
503 case MVT::i16: Opc = X86::MOV16mr;
break;
505 Opc = (IsNonTemporal && HasSSE2) ? X86::MOVNTImr : X86::MOV32mr;
509 Opc = (IsNonTemporal && HasSSE2) ? X86::MOVNTI_64mr : X86::MOV64mr;
513 if (IsNonTemporal && HasSSE4A)
516 Opc = HasAVX512 ? X86::VMOVSSZmr :
517 HasAVX ? X86::VMOVSSmr : X86::MOVSSmr;
523 if (IsNonTemporal && HasSSE4A)
526 Opc = HasAVX512 ? X86::VMOVSDZmr :
527 HasAVX ? X86::VMOVSDmr : X86::MOVSDmr;
532 Opc = (IsNonTemporal && HasSSE1) ? X86::MMX_MOVNTQmr : X86::MMX_MOVQ64mr;
537 Opc = HasVLX ? X86::VMOVNTPSZ128mr :
538 HasAVX ? X86::VMOVNTPSmr : X86::MOVNTPSmr;
540 Opc = HasVLX ? X86::VMOVAPSZ128mr :
541 HasAVX ? X86::VMOVAPSmr : X86::MOVAPSmr;
543 Opc = HasVLX ? X86::VMOVUPSZ128mr :
544 HasAVX ? X86::VMOVUPSmr : X86::MOVUPSmr;
549 Opc = HasVLX ? X86::VMOVNTPDZ128mr :
550 HasAVX ? X86::VMOVNTPDmr : X86::MOVNTPDmr;
552 Opc = HasVLX ? X86::VMOVAPDZ128mr :
553 HasAVX ? X86::VMOVAPDmr : X86::MOVAPDmr;
555 Opc = HasVLX ? X86::VMOVUPDZ128mr :
556 HasAVX ? X86::VMOVUPDmr : X86::MOVUPDmr;
564 Opc = HasVLX ? X86::VMOVNTDQZ128mr :
565 HasAVX ? X86::VMOVNTDQmr : X86::MOVNTDQmr;
567 Opc = HasVLX ? X86::VMOVDQA64Z128mr :
568 HasAVX ? X86::VMOVDQAmr : X86::MOVDQAmr;
570 Opc = HasVLX ? X86::VMOVDQU64Z128mr :
571 HasAVX ? X86::VMOVDQUmr : X86::MOVDQUmr;
577 Opc = HasVLX ? X86::VMOVNTPSZ256mr : X86::VMOVNTPSYmr;
579 Opc = HasVLX ? X86::VMOVAPSZ256mr : X86::VMOVAPSYmr;
581 Opc = HasVLX ? X86::VMOVUPSZ256mr : X86::VMOVUPSYmr;
587 Opc = HasVLX ? X86::VMOVNTPDZ256mr : X86::VMOVNTPDYmr;
589 Opc = HasVLX ? X86::VMOVAPDZ256mr : X86::VMOVAPDYmr;
591 Opc = HasVLX ? X86::VMOVUPDZ256mr : X86::VMOVUPDYmr;
600 Opc = HasVLX ? X86::VMOVNTDQZ256mr : X86::VMOVNTDQYmr;
602 Opc = HasVLX ? X86::VMOVDQA64Z256mr : X86::VMOVDQAYmr;
604 Opc = HasVLX ? X86::VMOVDQU64Z256mr : X86::VMOVDQUYmr;
609 Opc = IsNonTemporal ? X86::VMOVNTPSZmr : X86::VMOVAPSZmr;
611 Opc = X86::VMOVUPSZmr;
616 Opc = IsNonTemporal ? X86::VMOVNTPDZmr : X86::VMOVAPDZmr;
618 Opc = X86::VMOVUPDZmr;
628 Opc = IsNonTemporal ? X86::VMOVNTDQZmr : X86::VMOVDQA64Zmr;
630 Opc = X86::VMOVDQU64Zmr;
643 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
Desc);
651bool X86FastISel::X86FastEmitStore(
EVT VT,
const Value *Val,
655 if (isa<ConstantPointerNull>(Val))
659 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(Val)) {
667 case MVT::i8: Opc = X86::MOV8mi;
break;
668 case MVT::i16: Opc = X86::MOV16mi;
break;
669 case MVT::i32: Opc = X86::MOV32mi;
break;
672 if (isInt<32>(CI->getSExtValue()))
673 Opc = X86::MOV64mi32;
679 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc));
681 : CI->getZExtValue());
688 Register ValReg = getRegForValue(Val);
692 return X86FastEmitStore(VT, ValReg, AM, MMO,
Aligned);
699 unsigned Src,
EVT SrcVT,
700 unsigned &ResultReg) {
711 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
718 if (
TM.isLargeGlobalValue(GV))
722 if (GV->isThreadLocal())
726 if (GV->isAbsoluteSymbolRef())
732 if (!Subtarget->isPICStyleRIPRel() ||
738 unsigned char GVFlags = Subtarget->classifyGlobalReference(GV);
743 AM.
Base.
Reg = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
749 if (Subtarget->isPICStyleRIPRel()) {
763 if (
I != LocalValueMap.end() &&
I->second) {
775 SavePoint SaveInsertPt = enterLocalValueArea();
777 if (TLI.getPointerTy(
DL) == MVT::i64) {
779 RC = &X86::GR64RegClass;
782 RC = &X86::GR32RegClass;
789 LoadReg = createResultReg(RC);
791 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), LoadReg);
795 leaveLocalValueArea(SaveInsertPt);
798 LocalValueMap[
V] = LoadReg;
810 if (!AM.
GV || !Subtarget->isPICStyleRIPRel()) {
812 AM.
Base.
Reg = getRegForValue(V);
830 const User *
U =
nullptr;
831 unsigned Opcode = Instruction::UserOp1;
836 if (FuncInfo.StaticAllocaMap.count(
static_cast<const AllocaInst *
>(V)) ||
837 FuncInfo.getMBB(
I->getParent()) == FuncInfo.MBB) {
838 Opcode =
I->getOpcode();
841 }
else if (
const ConstantExpr *
C = dyn_cast<ConstantExpr>(V)) {
842 Opcode =
C->getOpcode();
846 if (
PointerType *Ty = dyn_cast<PointerType>(
V->getType()))
847 if (Ty->getAddressSpace() > 255)
854 case Instruction::BitCast:
858 case Instruction::IntToPtr:
860 if (TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
861 TLI.getPointerTy(
DL))
865 case Instruction::PtrToInt:
867 if (TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
871 case Instruction::Alloca: {
875 FuncInfo.StaticAllocaMap.find(
A);
876 if (SI != FuncInfo.StaticAllocaMap.end()) {
884 case Instruction::Add: {
886 if (
const ConstantInt *CI = dyn_cast<ConstantInt>(
U->getOperand(1))) {
889 if (isInt<32>(Disp)) {
897 case Instruction::GetElementPtr: {
903 unsigned Scale = AM.
Scale;
910 i != e; ++i, ++GTI) {
924 Disp += CI->getSExtValue() * S;
927 if (canFoldAddIntoGEP(U,
Op)) {
930 cast<ConstantInt>(cast<AddOperator>(
Op)->getOperand(1));
933 Op = cast<AddOperator>(
Op)->getOperand(0);
937 (!AM.
GV || !Subtarget->isPICStyleRIPRel()) &&
938 (S == 1 || S == 2 || S == 4 || S == 8)) {
941 IndexReg = getRegForGEPIndex(PtrVT,
Op);
947 goto unsupported_gep;
952 if (!isInt<32>(Disp))
961 dyn_cast<GetElementPtrInst>(
U->getOperand(0))) {
975 if (handleConstantAddresses(
I, AM))
985 return handleConstantAddresses(V, AM);
991 const User *
U =
nullptr;
992 unsigned Opcode = Instruction::UserOp1;
1019 Opcode =
I->getOpcode();
1021 InMBB =
I->getParent() == FuncInfo.MBB->getBasicBlock();
1022 }
else if (
const ConstantExpr *
C = dyn_cast<ConstantExpr>(V)) {
1023 Opcode =
C->getOpcode();
1029 case Instruction::BitCast:
1032 return X86SelectCallAddress(
U->getOperand(0), AM);
1035 case Instruction::IntToPtr:
1038 TLI.getValueType(
DL,
U->getOperand(0)->getType()) ==
1039 TLI.getPointerTy(
DL))
1040 return X86SelectCallAddress(
U->getOperand(0), AM);
1043 case Instruction::PtrToInt:
1045 if (InMBB && TLI.getValueType(
DL,
U->getType()) == TLI.getPointerTy(
DL))
1046 return X86SelectCallAddress(
U->getOperand(0), AM);
1051 if (
const GlobalValue *GV = dyn_cast<GlobalValue>(V)) {
1058 if (Subtarget->isPICStyleRIPRel() &&
1064 if (GVar->isThreadLocal())
1073 if (Subtarget->isPICStyleRIPRel()) {
1079 AM.
GVOpFlags = Subtarget->classifyLocalReference(
nullptr);
1086 if (!AM.
GV || !Subtarget->isPICStyleRIPRel()) {
1087 auto GetCallRegForValue = [
this](
const Value *
V) {
1091 if (Reg && Subtarget->isTarget64BitILP32()) {
1092 Register CopyReg = createResultReg(&X86::GR32RegClass);
1093 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV32rr),
1097 Register ExtReg = createResultReg(&X86::GR64RegClass);
1098 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1099 TII.get(TargetOpcode::SUBREG_TO_REG), ExtReg)
1110 AM.
Base.
Reg = GetCallRegForValue(V);
1115 AM.
IndexReg = GetCallRegForValue(V);
1125bool X86FastISel::X86SelectStore(
const Instruction *
I) {
1132 const Value *PtrV =
I->getOperand(1);
1133 if (TLI.supportSwiftError()) {
1136 if (
const Argument *Arg = dyn_cast<Argument>(PtrV)) {
1137 if (Arg->hasSwiftErrorAttr())
1141 if (
const AllocaInst *Alloca = dyn_cast<AllocaInst>(PtrV)) {
1142 if (Alloca->isSwiftError())
1151 if (!isTypeLegal(Val->
getType(), VT,
true))
1156 bool Aligned = Alignment >= ABIAlignment;
1162 return X86FastEmitStore(VT, Val, AM, createMachineMemOperandFor(
I),
Aligned);
1168 const Function &
F = *
I->getParent()->getParent();
1172 if (!FuncInfo.CanLowerReturn)
1175 if (TLI.supportSwiftError() &&
1176 F.getAttributes().hasAttrSomewhere(Attribute::SwiftError))
1179 if (TLI.supportSplitCSR(FuncInfo.MF))
1211 if (
Ret->getNumOperands() > 0) {
1217 CCState CCInfo(
CC,
F.isVarArg(), *FuncInfo.MF, ValLocs,
I->getContext());
1220 const Value *RV =
Ret->getOperand(0);
1226 if (ValLocs.
size() != 1)
1247 if (SrcVT != DstVT) {
1248 if (SrcVT != MVT::i1 && SrcVT != MVT::i8 && SrcVT != MVT::i16)
1251 if (!Outs[0].
Flags.isZExt() && !Outs[0].Flags.isSExt())
1254 if (SrcVT == MVT::i1) {
1255 if (Outs[0].
Flags.isSExt())
1257 SrcReg = fastEmitZExtFromI1(MVT::i8, SrcReg);
1260 if (SrcVT != DstVT) {
1274 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1275 TII.get(TargetOpcode::COPY), DstReg).
addReg(SrcReg);
1292 "SRetReturnReg should have been set in LowerFormalArguments()!");
1293 unsigned RetReg = Subtarget->isTarget64BitLP64() ? X86::RAX : X86::EAX;
1294 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1295 TII.get(TargetOpcode::COPY), RetReg).
addReg(Reg);
1302 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1303 TII.get(Subtarget->is64Bit() ? X86::RETI64 : X86::RETI32))
1306 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1307 TII.get(Subtarget->is64Bit() ? X86::RET64 : X86::RET32));
1309 for (
unsigned Reg : RetRegs)
1323 const Value *SV =
I->getOperand(0);
1324 if (TLI.supportSwiftError()) {
1327 if (
const Argument *Arg = dyn_cast<Argument>(SV)) {
1328 if (Arg->hasSwiftErrorAttr())
1332 if (
const AllocaInst *Alloca = dyn_cast<AllocaInst>(SV)) {
1333 if (Alloca->isSwiftError())
1339 if (!isTypeLegal(LI->
getType(), VT,
true))
1348 unsigned ResultReg = 0;
1349 if (!X86FastEmitLoad(VT, AM, createMachineMemOperandFor(LI), ResultReg,
1353 updateValueMap(
I, ResultReg);
1358 bool HasAVX512 = Subtarget->
hasAVX512();
1359 bool HasAVX = Subtarget->
hasAVX();
1360 bool HasSSE1 = Subtarget->
hasSSE1();
1361 bool HasSSE2 = Subtarget->
hasSSE2();
1365 case MVT::i8:
return X86::CMP8rr;
1366 case MVT::i16:
return X86::CMP16rr;
1367 case MVT::i32:
return X86::CMP32rr;
1368 case MVT::i64:
return X86::CMP64rr;
1370 return HasAVX512 ? X86::VUCOMISSZrr
1371 : HasAVX ? X86::VUCOMISSrr
1372 : HasSSE1 ? X86::UCOMISSrr
1375 return HasAVX512 ? X86::VUCOMISDZrr
1376 : HasAVX ? X86::VUCOMISDrr
1377 : HasSSE2 ? X86::UCOMISDrr
1392 return X86::CMP16ri;
1394 return X86::CMP32ri;
1398 return isInt<32>(RHSC->
getSExtValue()) ? X86::CMP64ri32 : 0;
1402bool X86FastISel::X86FastEmitCompare(
const Value *Op0,
const Value *Op1,
EVT VT,
1404 Register Op0Reg = getRegForValue(Op0);
1405 if (Op0Reg == 0)
return false;
1408 if (isa<ConstantPointerNull>(Op1))
1414 if (
const ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
1416 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, CurMIMD,
TII.get(CompareImmOpc))
1418 .
addImm(Op1C->getSExtValue());
1424 if (CompareOpc == 0)
return false;
1426 Register Op1Reg = getRegForValue(Op1);
1427 if (Op1Reg == 0)
return false;
1428 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, CurMIMD,
TII.get(CompareOpc))
1436 const CmpInst *CI = cast<CmpInst>(
I);
1439 if (!isTypeLegal(
I->getOperand(0)->getType(), VT))
1448 unsigned ResultReg = 0;
1449 switch (Predicate) {
1452 ResultReg = createResultReg(&X86::GR32RegClass);
1453 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV32r0),
1455 ResultReg = fastEmitInst_extractsubreg(MVT::i8, ResultReg, X86::sub_8bit);
1461 ResultReg = createResultReg(&X86::GR8RegClass);
1462 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV8ri),
1469 updateValueMap(
I, ResultReg);
1480 const auto *RHSC = dyn_cast<ConstantFP>(RHS);
1481 if (RHSC && RHSC->isNullValue())
1486 static const uint16_t SETFOpcTable[2][3] = {
1491 switch (Predicate) {
1497 ResultReg = createResultReg(&X86::GR8RegClass);
1499 if (!X86FastEmitCompare(LHS, RHS, VT,
I->getDebugLoc()))
1502 Register FlagReg1 = createResultReg(&X86::GR8RegClass);
1503 Register FlagReg2 = createResultReg(&X86::GR8RegClass);
1504 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SETCCr),
1505 FlagReg1).
addImm(SETFOpc[0]);
1506 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SETCCr),
1507 FlagReg2).
addImm(SETFOpc[1]);
1508 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(SETFOpc[2]),
1510 updateValueMap(
I, ResultReg);
1523 if (!X86FastEmitCompare(LHS, RHS, VT,
I->getDebugLoc()))
1526 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SETCCr),
1528 updateValueMap(
I, ResultReg);
1533 EVT DstVT = TLI.getValueType(
DL,
I->getType());
1534 if (!TLI.isTypeLegal(DstVT))
1537 Register ResultReg = getRegForValue(
I->getOperand(0));
1542 MVT SrcVT = TLI.getSimpleValueType(
DL,
I->getOperand(0)->getType());
1543 if (SrcVT == MVT::i1) {
1545 ResultReg = fastEmitZExtFromI1(MVT::i8, ResultReg);
1552 if (DstVT == MVT::i64) {
1557 case MVT::i8: MovInst = X86::MOVZX32rr8;
break;
1558 case MVT::i16: MovInst = X86::MOVZX32rr16;
break;
1559 case MVT::i32: MovInst = X86::MOV32rr;
break;
1563 Register Result32 = createResultReg(&X86::GR32RegClass);
1564 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(MovInst), Result32)
1567 ResultReg = createResultReg(&X86::GR64RegClass);
1568 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::SUBREG_TO_REG),
1571 }
else if (DstVT == MVT::i16) {
1574 Register Result32 = createResultReg(&X86::GR32RegClass);
1575 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOVZX32rr8),
1576 Result32).
addReg(ResultReg);
1578 ResultReg = fastEmitInst_extractsubreg(MVT::i16, Result32, X86::sub_16bit);
1579 }
else if (DstVT != MVT::i8) {
1586 updateValueMap(
I, ResultReg);
1591 EVT DstVT = TLI.getValueType(
DL,
I->getType());
1592 if (!TLI.isTypeLegal(DstVT))
1595 Register ResultReg = getRegForValue(
I->getOperand(0));
1600 MVT SrcVT = TLI.getSimpleValueType(
DL,
I->getOperand(0)->getType());
1601 if (SrcVT == MVT::i1) {
1603 Register ZExtReg = fastEmitZExtFromI1(MVT::i8, ResultReg);
1608 ResultReg = createResultReg(&X86::GR8RegClass);
1609 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::NEG8r),
1610 ResultReg).
addReg(ZExtReg);
1615 if (DstVT == MVT::i16) {
1618 Register Result32 = createResultReg(&X86::GR32RegClass);
1619 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOVSX32rr8),
1620 Result32).
addReg(ResultReg);
1622 ResultReg = fastEmitInst_extractsubreg(MVT::i16, Result32, X86::sub_16bit);
1623 }
else if (DstVT != MVT::i8) {
1630 updateValueMap(
I, ResultReg);
1634bool X86FastISel::X86SelectBranch(
const Instruction *
I) {
1651 switch (Predicate) {
1665 const auto *CmpRHSC = dyn_cast<ConstantFP>(CmpRHS);
1666 if (CmpRHSC && CmpRHSC->isNullValue())
1671 if (FuncInfo.MBB->isLayoutSuccessor(TrueMBB)) {
1681 bool NeedExtraBranch =
false;
1682 switch (Predicate) {
1688 NeedExtraBranch =
true;
1701 if (!X86FastEmitCompare(CmpLHS, CmpRHS, VT, CI->
getDebugLoc()))
1704 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1709 if (NeedExtraBranch) {
1710 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1714 finishCondBranch(BI->
getParent(), TrueMBB, FalseMBB);
1721 if (TI->hasOneUse() && TI->getParent() ==
I->getParent() &&
1722 isTypeLegal(TI->getOperand(0)->getType(), SourceVT)) {
1723 unsigned TestOpc = 0;
1726 case MVT::i8: TestOpc = X86::TEST8ri;
break;
1727 case MVT::i16: TestOpc = X86::TEST16ri;
break;
1728 case MVT::i32: TestOpc = X86::TEST32ri;
break;
1729 case MVT::i64: TestOpc = X86::TEST64ri32;
break;
1732 Register OpReg = getRegForValue(TI->getOperand(0));
1733 if (OpReg == 0)
return false;
1735 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TestOpc))
1739 if (FuncInfo.MBB->isLayoutSuccessor(TrueMBB)) {
1744 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1747 finishCondBranch(BI->
getParent(), TrueMBB, FalseMBB);
1758 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1760 finishCondBranch(BI->
getParent(), TrueMBB, FalseMBB);
1768 if (OpReg == 0)
return false;
1771 if (
MRI.getRegClass(OpReg) == &X86::VK1RegClass) {
1772 unsigned KOpReg = OpReg;
1773 OpReg = createResultReg(&X86::GR32RegClass);
1774 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1775 TII.get(TargetOpcode::COPY), OpReg)
1777 OpReg = fastEmitInst_extractsubreg(MVT::i8, OpReg, X86::sub_8bit);
1779 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TEST8ri))
1782 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::JCC_1))
1784 finishCondBranch(BI->
getParent(), TrueMBB, FalseMBB);
1788bool X86FastISel::X86SelectShift(
const Instruction *
I) {
1789 unsigned CReg = 0, OpReg = 0;
1791 if (
I->getType()->isIntegerTy(8)) {
1793 RC = &X86::GR8RegClass;
1794 switch (
I->getOpcode()) {
1795 case Instruction::LShr: OpReg = X86::SHR8rCL;
break;
1796 case Instruction::AShr: OpReg = X86::SAR8rCL;
break;
1797 case Instruction::Shl: OpReg = X86::SHL8rCL;
break;
1798 default:
return false;
1800 }
else if (
I->getType()->isIntegerTy(16)) {
1802 RC = &X86::GR16RegClass;
1803 switch (
I->getOpcode()) {
1805 case Instruction::LShr: OpReg = X86::SHR16rCL;
break;
1806 case Instruction::AShr: OpReg = X86::SAR16rCL;
break;
1807 case Instruction::Shl: OpReg = X86::SHL16rCL;
break;
1809 }
else if (
I->getType()->isIntegerTy(32)) {
1811 RC = &X86::GR32RegClass;
1812 switch (
I->getOpcode()) {
1814 case Instruction::LShr: OpReg = X86::SHR32rCL;
break;
1815 case Instruction::AShr: OpReg = X86::SAR32rCL;
break;
1816 case Instruction::Shl: OpReg = X86::SHL32rCL;
break;
1818 }
else if (
I->getType()->isIntegerTy(64)) {
1820 RC = &X86::GR64RegClass;
1821 switch (
I->getOpcode()) {
1823 case Instruction::LShr: OpReg = X86::SHR64rCL;
break;
1824 case Instruction::AShr: OpReg = X86::SAR64rCL;
break;
1825 case Instruction::Shl: OpReg = X86::SHL64rCL;
break;
1832 if (!isTypeLegal(
I->getType(), VT))
1835 Register Op0Reg = getRegForValue(
I->getOperand(0));
1836 if (Op0Reg == 0)
return false;
1838 Register Op1Reg = getRegForValue(
I->getOperand(1));
1839 if (Op1Reg == 0)
return false;
1840 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
1845 if (CReg != X86::CL)
1846 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1847 TII.get(TargetOpcode::KILL), X86::CL)
1850 Register ResultReg = createResultReg(RC);
1851 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(OpReg), ResultReg)
1853 updateValueMap(
I, ResultReg);
1857bool X86FastISel::X86SelectDivRem(
const Instruction *
I) {
1858 const static unsigned NumTypes = 4;
1859 const static unsigned NumOps = 4;
1860 const static bool S =
true;
1861 const static bool U =
false;
1862 const static unsigned Copy = TargetOpcode::COPY;
1872 const static struct DivRemEntry {
1878 struct DivRemResult {
1880 unsigned OpSignExtend;
1884 unsigned DivRemResultReg;
1886 } ResultTable[NumOps];
1887 } OpTable[NumTypes] = {
1888 { &X86::GR8RegClass, X86::AX, 0, {
1889 { X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AL, S },
1890 { X86::IDIV8r, 0, X86::MOVSX16rr8, X86::AH, S },
1891 { X86::DIV8r, 0, X86::MOVZX16rr8, X86::AL,
U },
1892 { X86::DIV8r, 0, X86::MOVZX16rr8, X86::AH,
U },
1895 { &X86::GR16RegClass, X86::AX, X86::DX, {
1896 { X86::IDIV16r, X86::CWD,
Copy, X86::AX, S },
1897 { X86::IDIV16r, X86::CWD,
Copy, X86::DX, S },
1898 { X86::DIV16r, X86::MOV32r0,
Copy, X86::AX,
U },
1899 { X86::DIV16r, X86::MOV32r0,
Copy, X86::DX,
U },
1902 { &X86::GR32RegClass, X86::EAX, X86::EDX, {
1903 { X86::IDIV32r, X86::CDQ,
Copy, X86::EAX, S },
1904 { X86::IDIV32r, X86::CDQ,
Copy, X86::EDX, S },
1905 { X86::DIV32r, X86::MOV32r0,
Copy, X86::EAX,
U },
1906 { X86::DIV32r, X86::MOV32r0,
Copy, X86::EDX,
U },
1909 { &X86::GR64RegClass, X86::RAX, X86::RDX, {
1910 { X86::IDIV64r, X86::CQO,
Copy, X86::RAX, S },
1911 { X86::IDIV64r, X86::CQO,
Copy, X86::RDX, S },
1912 { X86::DIV64r, X86::MOV32r0,
Copy, X86::RAX,
U },
1913 { X86::DIV64r, X86::MOV32r0,
Copy, X86::RDX,
U },
1919 if (!isTypeLegal(
I->getType(), VT))
1924 default:
return false;
1925 case MVT::i8: TypeIndex = 0;
break;
1926 case MVT::i16: TypeIndex = 1;
break;
1927 case MVT::i32: TypeIndex = 2;
break;
1928 case MVT::i64: TypeIndex = 3;
1929 if (!Subtarget->is64Bit())
1934 switch (
I->getOpcode()) {
1936 case Instruction::SDiv:
OpIndex = 0;
break;
1937 case Instruction::SRem:
OpIndex = 1;
break;
1938 case Instruction::UDiv:
OpIndex = 2;
break;
1939 case Instruction::URem:
OpIndex = 3;
break;
1942 const DivRemEntry &
TypeEntry = OpTable[TypeIndex];
1944 Register Op0Reg = getRegForValue(
I->getOperand(0));
1947 Register Op1Reg = getRegForValue(
I->getOperand(1));
1952 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1955 if (OpEntry.OpSignExtend) {
1956 if (OpEntry.IsOpSigned)
1957 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1958 TII.get(OpEntry.OpSignExtend));
1960 Register Zero32 = createResultReg(&X86::GR32RegClass);
1961 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1962 TII.get(X86::MOV32r0), Zero32);
1967 if (VT == MVT::i16) {
1968 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1970 .
addReg(Zero32, 0, X86::sub_16bit);
1971 }
else if (VT == MVT::i32) {
1972 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1975 }
else if (VT == MVT::i64) {
1976 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1977 TII.get(TargetOpcode::SUBREG_TO_REG),
TypeEntry.HighInReg)
1983 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
1984 TII.get(OpEntry.OpDivRem)).
addReg(Op1Reg);
1993 unsigned ResultReg = 0;
1994 if ((
I->getOpcode() == Instruction::SRem ||
1995 I->getOpcode() == Instruction::URem) &&
1996 OpEntry.DivRemResultReg == X86::AH && Subtarget->is64Bit()) {
1997 Register SourceSuperReg = createResultReg(&X86::GR16RegClass);
1998 Register ResultSuperReg = createResultReg(&X86::GR16RegClass);
1999 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2000 TII.get(Copy), SourceSuperReg).
addReg(X86::AX);
2003 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SHR16ri),
2007 ResultReg = fastEmitInst_extractsubreg(MVT::i8, ResultSuperReg,
2012 ResultReg = createResultReg(
TypeEntry.RC);
2013 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Copy), ResultReg)
2014 .
addReg(OpEntry.DivRemResultReg);
2016 updateValueMap(
I, ResultReg);
2023bool X86FastISel::X86FastEmitCMoveSelect(
MVT RetVT,
const Instruction *
I) {
2025 if (!Subtarget->canUseCMOV())
2029 if (RetVT < MVT::i16 || RetVT > MVT::i64)
2034 bool NeedTest =
true;
2040 const auto *CI = dyn_cast<CmpInst>(
Cond);
2041 if (CI && (CI->
getParent() ==
I->getParent())) {
2045 static const uint16_t SETFOpcTable[2][3] = {
2050 switch (Predicate) {
2053 SETFOpc = &SETFOpcTable[0][0];
2057 SETFOpc = &SETFOpcTable[1][0];
2073 if (!X86FastEmitCompare(CmpLHS, CmpRHS, CmpVT, CI->
getDebugLoc()))
2077 Register FlagReg1 = createResultReg(&X86::GR8RegClass);
2078 Register FlagReg2 = createResultReg(&X86::GR8RegClass);
2079 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SETCCr),
2080 FlagReg1).
addImm(SETFOpc[0]);
2081 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SETCCr),
2082 FlagReg2).
addImm(SETFOpc[1]);
2083 auto const &
II =
TII.get(SETFOpc[2]);
2084 if (
II.getNumDefs()) {
2085 Register TmpReg = createResultReg(&X86::GR8RegClass);
2086 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, TmpReg)
2089 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
2094 }
else if (foldX86XALUIntrinsic(
CC,
I,
Cond)) {
2115 if (
MRI.getRegClass(CondReg) == &X86::VK1RegClass) {
2116 unsigned KCondReg = CondReg;
2117 CondReg = createResultReg(&X86::GR32RegClass);
2118 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2119 TII.get(TargetOpcode::COPY), CondReg)
2121 CondReg = fastEmitInst_extractsubreg(MVT::i8, CondReg, X86::sub_8bit);
2123 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TEST8ri))
2131 Register RHSReg = getRegForValue(RHS);
2132 Register LHSReg = getRegForValue(LHS);
2133 if (!LHSReg || !RHSReg)
2138 Subtarget->hasNDD());
2139 Register ResultReg = fastEmitInst_rri(Opc, RC, RHSReg, LHSReg,
CC);
2140 updateValueMap(
I, ResultReg);
2149bool X86FastISel::X86FastEmitSSESelect(
MVT RetVT,
const Instruction *
I) {
2153 const auto *CI = dyn_cast<FCmpInst>(
I->getOperand(0));
2154 if (!CI || (CI->
getParent() !=
I->getParent()))
2158 !((Subtarget->hasSSE1() && RetVT == MVT::f32) ||
2159 (Subtarget->hasSSE2() && RetVT == MVT::f64)))
2170 const auto *CmpRHSC = dyn_cast<ConstantFP>(CmpRHS);
2171 if (CmpRHSC && CmpRHSC->isNullValue())
2178 if (
CC > 7 && !Subtarget->hasAVX())
2187 Register LHSReg = getRegForValue(LHS);
2188 Register RHSReg = getRegForValue(RHS);
2189 Register CmpLHSReg = getRegForValue(CmpLHS);
2190 Register CmpRHSReg = getRegForValue(CmpRHS);
2191 if (!LHSReg || !RHSReg || !CmpLHSReg || !CmpRHSReg)
2197 if (Subtarget->hasAVX512()) {
2202 unsigned CmpOpcode =
2203 (RetVT == MVT::f32) ? X86::VCMPSSZrri : X86::VCMPSDZrri;
2204 Register CmpReg = fastEmitInst_rri(CmpOpcode, VK1, CmpLHSReg, CmpRHSReg,
2209 Register ImplicitDefReg = createResultReg(VR128X);
2210 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2211 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2215 unsigned MovOpcode =
2216 (RetVT == MVT::f32) ? X86::VMOVSSZrrk : X86::VMOVSDZrrk;
2217 unsigned MovReg = fastEmitInst_rrrr(MovOpcode, VR128X, RHSReg, CmpReg,
2218 ImplicitDefReg, LHSReg);
2220 ResultReg = createResultReg(RC);
2221 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2222 TII.get(TargetOpcode::COPY), ResultReg).
addReg(MovReg);
2224 }
else if (Subtarget->hasAVX()) {
2232 unsigned CmpOpcode =
2233 (RetVT == MVT::f32) ? X86::VCMPSSrri : X86::VCMPSDrri;
2234 unsigned BlendOpcode =
2235 (RetVT == MVT::f32) ? X86::VBLENDVPSrrr : X86::VBLENDVPDrrr;
2237 Register CmpReg = fastEmitInst_rri(CmpOpcode, RC, CmpLHSReg, CmpRHSReg,
2239 Register VBlendReg = fastEmitInst_rrr(BlendOpcode, VR128, RHSReg, LHSReg,
2241 ResultReg = createResultReg(RC);
2242 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2243 TII.get(TargetOpcode::COPY), ResultReg).
addReg(VBlendReg);
2246 static const uint16_t OpcTable[2][4] = {
2247 { X86::CMPSSrri, X86::ANDPSrr, X86::ANDNPSrr, X86::ORPSrr },
2248 { X86::CMPSDrri, X86::ANDPDrr, X86::ANDNPDrr, X86::ORPDrr }
2253 default:
return false;
2254 case MVT::f32: Opc = &OpcTable[0][0];
break;
2255 case MVT::f64: Opc = &OpcTable[1][0];
break;
2259 Register CmpReg = fastEmitInst_rri(Opc[0], RC, CmpLHSReg, CmpRHSReg,
CC);
2260 Register AndReg = fastEmitInst_rr(Opc[1], VR128, CmpReg, LHSReg);
2261 Register AndNReg = fastEmitInst_rr(Opc[2], VR128, CmpReg, RHSReg);
2262 Register OrReg = fastEmitInst_rr(Opc[3], VR128, AndNReg, AndReg);
2263 ResultReg = createResultReg(RC);
2264 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2265 TII.get(TargetOpcode::COPY), ResultReg).
addReg(OrReg);
2267 updateValueMap(
I, ResultReg);
2271bool X86FastISel::X86FastEmitPseudoSelect(
MVT RetVT,
const Instruction *
I) {
2276 default:
return false;
2277 case MVT::i8: Opc = X86::CMOV_GR8;
break;
2278 case MVT::i16: Opc = X86::CMOV_GR16;
break;
2279 case MVT::i32: Opc = X86::CMOV_GR32;
break;
2281 Opc = Subtarget->hasAVX512() ? X86::CMOV_FR16X : X86::CMOV_FR16;
break;
2283 Opc = Subtarget->hasAVX512() ? X86::CMOV_FR32X : X86::CMOV_FR32;
break;
2285 Opc = Subtarget->hasAVX512() ? X86::CMOV_FR64X : X86::CMOV_FR64;
break;
2294 const auto *CI = dyn_cast<CmpInst>(
Cond);
2295 if (CI && (CI->
getParent() ==
I->getParent())) {
2308 if (!X86FastEmitCompare(CmpLHS, CmpRHS, CmpVT, CI->
getDebugLoc()))
2316 if (
MRI.getRegClass(CondReg) == &X86::VK1RegClass) {
2317 unsigned KCondReg = CondReg;
2318 CondReg = createResultReg(&X86::GR32RegClass);
2319 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2320 TII.get(TargetOpcode::COPY), CondReg)
2322 CondReg = fastEmitInst_extractsubreg(MVT::i8, CondReg, X86::sub_8bit);
2324 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TEST8ri))
2332 Register LHSReg = getRegForValue(LHS);
2333 Register RHSReg = getRegForValue(RHS);
2334 if (!LHSReg || !RHSReg)
2340 fastEmitInst_rri(Opc, RC, RHSReg, LHSReg,
CC);
2341 updateValueMap(
I, ResultReg);
2345bool X86FastISel::X86SelectSelect(
const Instruction *
I) {
2347 if (!isTypeLegal(
I->getType(), RetVT))
2351 if (
const auto *CI = dyn_cast<CmpInst>(
I->getOperand(0))) {
2353 const Value *Opnd =
nullptr;
2354 switch (Predicate) {
2361 Register OpReg = getRegForValue(Opnd);
2365 Register ResultReg = createResultReg(RC);
2366 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2367 TII.get(TargetOpcode::COPY), ResultReg)
2369 updateValueMap(
I, ResultReg);
2375 if (X86FastEmitCMoveSelect(RetVT,
I))
2379 if (X86FastEmitSSESelect(RetVT,
I))
2384 if (X86FastEmitPseudoSelect(RetVT,
I))
2391bool X86FastISel::X86SelectIntToFP(
const Instruction *
I,
bool IsSigned) {
2396 bool HasAVX512 = Subtarget->hasAVX512();
2397 if (!Subtarget->hasAVX() || (!IsSigned && !HasAVX512))
2401 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
2402 if (SrcVT != MVT::i32 && SrcVT != MVT::i64)
2406 Register OpReg = getRegForValue(
I->getOperand(0));
2412 static const uint16_t SCvtOpc[2][2][2] = {
2413 { { X86::VCVTSI2SSrr, X86::VCVTSI642SSrr },
2414 { X86::VCVTSI2SDrr, X86::VCVTSI642SDrr } },
2415 { { X86::VCVTSI2SSZrr, X86::VCVTSI642SSZrr },
2416 { X86::VCVTSI2SDZrr, X86::VCVTSI642SDZrr } },
2418 static const uint16_t UCvtOpc[2][2] = {
2419 { X86::VCVTUSI2SSZrr, X86::VCVTUSI642SSZrr },
2420 { X86::VCVTUSI2SDZrr, X86::VCVTUSI642SDZrr },
2422 bool Is64Bit = SrcVT == MVT::i64;
2424 if (
I->getType()->isDoubleTy()) {
2426 Opcode = IsSigned ? SCvtOpc[HasAVX512][1][Is64Bit] : UCvtOpc[1][Is64Bit];
2427 }
else if (
I->getType()->isFloatTy()) {
2429 Opcode = IsSigned ? SCvtOpc[HasAVX512][0][Is64Bit] : UCvtOpc[0][Is64Bit];
2435 Register ImplicitDefReg = createResultReg(RC);
2436 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2437 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2438 Register ResultReg = fastEmitInst_rr(Opcode, RC, ImplicitDefReg, OpReg);
2439 updateValueMap(
I, ResultReg);
2443bool X86FastISel::X86SelectSIToFP(
const Instruction *
I) {
2444 return X86SelectIntToFP(
I,
true);
2447bool X86FastISel::X86SelectUIToFP(
const Instruction *
I) {
2448 return X86SelectIntToFP(
I,
false);
2452bool X86FastISel::X86SelectFPExtOrFPTrunc(
const Instruction *
I,
2455 assert((
I->getOpcode() == Instruction::FPExt ||
2456 I->getOpcode() == Instruction::FPTrunc) &&
2457 "Instruction must be an FPExt or FPTrunc!");
2458 bool HasAVX = Subtarget->hasAVX();
2460 Register OpReg = getRegForValue(
I->getOperand(0));
2464 unsigned ImplicitDefReg;
2466 ImplicitDefReg = createResultReg(RC);
2467 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2468 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2472 Register ResultReg = createResultReg(RC);
2474 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpc),
2478 MIB.
addReg(ImplicitDefReg);
2481 updateValueMap(
I, ResultReg);
2485bool X86FastISel::X86SelectFPExt(
const Instruction *
I) {
2486 if (Subtarget->hasSSE2() &&
I->getType()->isDoubleTy() &&
2487 I->getOperand(0)->getType()->isFloatTy()) {
2488 bool HasAVX512 = Subtarget->hasAVX512();
2491 HasAVX512 ? X86::VCVTSS2SDZrr
2492 : Subtarget->hasAVX() ? X86::VCVTSS2SDrr : X86::CVTSS2SDrr;
2493 return X86SelectFPExtOrFPTrunc(
I, Opc, TLI.getRegClassFor(MVT::f64));
2499bool X86FastISel::X86SelectFPTrunc(
const Instruction *
I) {
2500 if (Subtarget->hasSSE2() &&
I->getType()->isFloatTy() &&
2501 I->getOperand(0)->getType()->isDoubleTy()) {
2502 bool HasAVX512 = Subtarget->hasAVX512();
2505 HasAVX512 ? X86::VCVTSD2SSZrr
2506 : Subtarget->hasAVX() ? X86::VCVTSD2SSrr : X86::CVTSD2SSrr;
2507 return X86SelectFPExtOrFPTrunc(
I, Opc, TLI.getRegClassFor(MVT::f32));
2513bool X86FastISel::X86SelectTrunc(
const Instruction *
I) {
2514 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
2515 EVT DstVT = TLI.getValueType(
DL,
I->getType());
2518 if (DstVT != MVT::i8 && DstVT != MVT::i1)
2520 if (!TLI.isTypeLegal(SrcVT))
2523 Register InputReg = getRegForValue(
I->getOperand(0));
2528 if (SrcVT == MVT::i8) {
2530 updateValueMap(
I, InputReg);
2535 Register ResultReg = fastEmitInst_extractsubreg(MVT::i8, InputReg,
2540 updateValueMap(
I, ResultReg);
2544bool X86FastISel::IsMemcpySmall(
uint64_t Len) {
2545 return Len <= (Subtarget->is64Bit() ? 32 : 16);
2552 if (!IsMemcpySmall(Len))
2555 bool i64Legal = Subtarget->is64Bit();
2560 if (Len >= 8 && i64Legal)
2570 bool RV = X86FastEmitLoad(VT, SrcAM,
nullptr, Reg);
2571 RV &= X86FastEmitStore(VT, Reg, DestAM);
2572 assert(RV &&
"Failed to emit load or store??");
2586 switch (
II->getIntrinsicID()) {
2587 default:
return false;
2588 case Intrinsic::convert_from_fp16:
2589 case Intrinsic::convert_to_fp16: {
2590 if (Subtarget->useSoftFloat() || !Subtarget->hasF16C())
2599 bool IsFloatToHalf =
II->getIntrinsicID() == Intrinsic::convert_to_fp16;
2600 if (IsFloatToHalf) {
2601 if (!
Op->getType()->isFloatTy())
2604 if (!
II->getType()->isFloatTy())
2608 unsigned ResultReg = 0;
2610 if (IsFloatToHalf) {
2618 unsigned Opc = Subtarget->hasVLX() ? X86::VCVTPS2PHZ128rr
2620 InputReg = fastEmitInst_ri(Opc, RC, InputReg, 4);
2623 Opc = Subtarget->hasAVX512() ? X86::VMOVPDI2DIZrr
2624 : X86::VMOVPDI2DIrr;
2625 ResultReg = createResultReg(&X86::GR32RegClass);
2626 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg)
2630 unsigned RegIdx = X86::sub_16bit;
2631 ResultReg = fastEmitInst_extractsubreg(MVT::i16, ResultReg, RegIdx);
2633 assert(
Op->getType()->isIntegerTy(16) &&
"Expected a 16-bit integer!");
2641 unsigned Opc = Subtarget->hasVLX() ? X86::VCVTPH2PSZ128rr
2643 InputReg = fastEmitInst_r(Opc, RC, InputReg);
2647 ResultReg = createResultReg(TLI.getRegClassFor(MVT::f32));
2648 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2649 TII.get(TargetOpcode::COPY), ResultReg)
2653 updateValueMap(
II, ResultReg);
2656 case Intrinsic::frameaddress: {
2661 Type *
RetTy =
II->getCalledFunction()->getReturnType();
2664 if (!isTypeLegal(
RetTy, VT))
2672 case MVT::i32: Opc = X86::MOV32rm; RC = &X86::GR32RegClass;
break;
2673 case MVT::i64: Opc = X86::MOV64rm; RC = &X86::GR64RegClass;
break;
2682 unsigned FrameReg =
RegInfo->getPtrSizedFrameRegister(*MF);
2683 assert(((FrameReg == X86::RBP && VT == MVT::i64) ||
2684 (FrameReg == X86::EBP && VT == MVT::i32)) &&
2685 "Invalid Frame Register!");
2690 Register SrcReg = createResultReg(RC);
2691 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2692 TII.get(TargetOpcode::COPY), SrcReg).
addReg(FrameReg);
2699 unsigned Depth = cast<ConstantInt>(
II->getOperand(0))->getZExtValue();
2701 Register DestReg = createResultReg(RC);
2703 TII.get(Opc), DestReg), SrcReg);
2707 updateValueMap(
II, SrcReg);
2710 case Intrinsic::memcpy: {
2716 if (isa<ConstantInt>(MCI->
getLength())) {
2720 if (IsMemcpySmall(Len)) {
2725 TryEmitSmallMemcpy(DestAM, SrcAM, Len);
2730 unsigned SizeWidth = Subtarget->is64Bit() ? 64 : 32;
2737 return lowerCallTo(
II,
"memcpy",
II->arg_size() - 1);
2739 case Intrinsic::memset: {
2745 unsigned SizeWidth = Subtarget->is64Bit() ? 64 : 32;
2752 return lowerCallTo(
II,
"memset",
II->arg_size() - 1);
2754 case Intrinsic::stackprotector: {
2756 EVT PtrTy = TLI.getPointerTy(
DL);
2758 const Value *Op1 =
II->getArgOperand(0);
2766 if (!X86FastEmitStore(PtrTy, Op1, AM))
return false;
2769 case Intrinsic::dbg_declare: {
2777 "Expected inlined-at fields to agree");
2784 case Intrinsic::trap: {
2785 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::TRAP));
2788 case Intrinsic::sqrt: {
2789 if (!Subtarget->hasSSE1())
2792 Type *
RetTy =
II->getCalledFunction()->getReturnType();
2795 if (!isTypeLegal(
RetTy, VT))
2801 static const uint16_t SqrtOpc[3][2] = {
2802 { X86::SQRTSSr, X86::SQRTSDr },
2803 { X86::VSQRTSSr, X86::VSQRTSDr },
2804 { X86::VSQRTSSZr, X86::VSQRTSDZr },
2806 unsigned AVXLevel = Subtarget->hasAVX512() ? 2 :
2807 Subtarget->hasAVX() ? 1 :
2811 default:
return false;
2812 case MVT::f32: Opc = SqrtOpc[AVXLevel][0];
break;
2813 case MVT::f64: Opc = SqrtOpc[AVXLevel][1];
break;
2816 const Value *SrcVal =
II->getArgOperand(0);
2817 Register SrcReg = getRegForValue(SrcVal);
2823 unsigned ImplicitDefReg = 0;
2825 ImplicitDefReg = createResultReg(RC);
2826 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2827 TII.get(TargetOpcode::IMPLICIT_DEF), ImplicitDefReg);
2830 Register ResultReg = createResultReg(RC);
2832 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc),
2836 MIB.
addReg(ImplicitDefReg);
2840 updateValueMap(
II, ResultReg);
2843 case Intrinsic::sadd_with_overflow:
2844 case Intrinsic::uadd_with_overflow:
2845 case Intrinsic::ssub_with_overflow:
2846 case Intrinsic::usub_with_overflow:
2847 case Intrinsic::smul_with_overflow:
2848 case Intrinsic::umul_with_overflow: {
2852 auto *Ty = cast<StructType>(
Callee->getReturnType());
2856 "Overflow value expected to be an i1");
2859 if (!isTypeLegal(
RetTy, VT))
2862 if (VT < MVT::i8 || VT > MVT::i64)
2869 if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS) &&
II->isCommutative())
2873 switch (
II->getIntrinsicID()) {
2875 case Intrinsic::sadd_with_overflow:
2877 case Intrinsic::uadd_with_overflow:
2879 case Intrinsic::ssub_with_overflow:
2881 case Intrinsic::usub_with_overflow:
2883 case Intrinsic::smul_with_overflow:
2885 case Intrinsic::umul_with_overflow:
2889 Register LHSReg = getRegForValue(LHS);
2893 unsigned ResultReg = 0;
2895 if (
const auto *CI = dyn_cast<ConstantInt>(RHS)) {
2896 static const uint16_t Opc[2][4] = {
2897 { X86::INC8r, X86::INC16r, X86::INC32r, X86::INC64r },
2898 { X86::DEC8r, X86::DEC16r, X86::DEC32r, X86::DEC64r }
2904 ResultReg = createResultReg(TLI.getRegClassFor(VT));
2906 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2907 TII.get(Opc[IsDec][VT.
SimpleTy-MVT::i8]), ResultReg)
2910 ResultReg = fastEmit_ri(VT, VT, BaseOpc, LHSReg, CI->getZExtValue());
2915 RHSReg = getRegForValue(RHS);
2918 ResultReg = fastEmit_rr(VT, VT, BaseOpc, LHSReg, RHSReg);
2925 { X86::MUL8r, X86::MUL16r, X86::MUL32r, X86::MUL64r };
2926 static const MCPhysReg Reg[] = { X86::AL, X86::AX, X86::EAX, X86::RAX };
2929 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2930 TII.get(TargetOpcode::COPY), Reg[VT.
SimpleTy-MVT::i8])
2932 ResultReg = fastEmitInst_r(MULOpc[VT.
SimpleTy-MVT::i8],
2933 TLI.getRegClassFor(VT), RHSReg);
2936 { X86::IMUL8r, X86::IMUL16rr, X86::IMUL32rr, X86::IMUL64rr };
2937 if (VT == MVT::i8) {
2940 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
2941 TII.get(TargetOpcode::COPY), X86::AL)
2943 ResultReg = fastEmitInst_r(MULOpc[0], TLI.getRegClassFor(VT), RHSReg);
2945 ResultReg = fastEmitInst_rr(MULOpc[VT.
SimpleTy-MVT::i8],
2946 TLI.getRegClassFor(VT), LHSReg, RHSReg);
2953 Register ResultReg2 = createResultReg(&X86::GR8RegClass);
2954 assert((ResultReg+1) == ResultReg2 &&
"Nonconsecutive result registers.");
2955 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::SETCCr),
2956 ResultReg2).
addImm(CondCode);
2958 updateValueMap(
II, ResultReg, 2);
2961 case Intrinsic::x86_sse_cvttss2si:
2962 case Intrinsic::x86_sse_cvttss2si64:
2963 case Intrinsic::x86_sse2_cvttsd2si:
2964 case Intrinsic::x86_sse2_cvttsd2si64: {
2966 switch (
II->getIntrinsicID()) {
2968 case Intrinsic::x86_sse_cvttss2si:
2969 case Intrinsic::x86_sse_cvttss2si64:
2970 if (!Subtarget->hasSSE1())
2972 IsInputDouble =
false;
2974 case Intrinsic::x86_sse2_cvttsd2si:
2975 case Intrinsic::x86_sse2_cvttsd2si64:
2976 if (!Subtarget->hasSSE2())
2978 IsInputDouble =
true;
2982 Type *
RetTy =
II->getCalledFunction()->getReturnType();
2984 if (!isTypeLegal(
RetTy, VT))
2987 static const uint16_t CvtOpc[3][2][2] = {
2988 { { X86::CVTTSS2SIrr, X86::CVTTSS2SI64rr },
2989 { X86::CVTTSD2SIrr, X86::CVTTSD2SI64rr } },
2990 { { X86::VCVTTSS2SIrr, X86::VCVTTSS2SI64rr },
2991 { X86::VCVTTSD2SIrr, X86::VCVTTSD2SI64rr } },
2992 { { X86::VCVTTSS2SIZrr, X86::VCVTTSS2SI64Zrr },
2993 { X86::VCVTTSD2SIZrr, X86::VCVTTSD2SI64Zrr } },
2995 unsigned AVXLevel = Subtarget->hasAVX512() ? 2 :
2996 Subtarget->hasAVX() ? 1 :
3001 case MVT::i32: Opc = CvtOpc[AVXLevel][IsInputDouble][0];
break;
3002 case MVT::i64: Opc = CvtOpc[AVXLevel][IsInputDouble][1];
break;
3007 while (
auto *IE = dyn_cast<InsertElementInst>(
Op)) {
3009 if (!isa<ConstantInt>(Index))
3011 unsigned Idx = cast<ConstantInt>(Index)->getZExtValue();
3014 Op =
IE->getOperand(1);
3017 Op =
IE->getOperand(0);
3024 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3025 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg)
3028 updateValueMap(
II, ResultReg);
3031 case Intrinsic::x86_sse42_crc32_32_8:
3032 case Intrinsic::x86_sse42_crc32_32_16:
3033 case Intrinsic::x86_sse42_crc32_32_32:
3034 case Intrinsic::x86_sse42_crc32_64_64: {
3035 if (!Subtarget->hasCRC32())
3038 Type *
RetTy =
II->getCalledFunction()->getReturnType();
3041 if (!isTypeLegal(
RetTy, VT))
3047 switch (
II->getIntrinsicID()) {
3050#define GET_EGPR_IF_ENABLED(OPC) Subtarget->hasEGPR() ? OPC##_EVEX : OPC
3051 case Intrinsic::x86_sse42_crc32_32_8:
3053 RC = &X86::GR32RegClass;
3055 case Intrinsic::x86_sse42_crc32_32_16:
3057 RC = &X86::GR32RegClass;
3059 case Intrinsic::x86_sse42_crc32_32_32:
3061 RC = &X86::GR32RegClass;
3063 case Intrinsic::x86_sse42_crc32_64_64:
3065 RC = &X86::GR64RegClass;
3067#undef GET_EGPR_IF_ENABLED
3073 Register LHSReg = getRegForValue(LHS);
3074 Register RHSReg = getRegForValue(RHS);
3075 if (!LHSReg || !RHSReg)
3078 Register ResultReg = fastEmitInst_rr(Opc, RC, LHSReg, RHSReg);
3082 updateValueMap(
II, ResultReg);
3088bool X86FastISel::fastLowerArguments() {
3089 if (!FuncInfo.CanLowerReturn)
3100 if (Subtarget->isCallingConvWin64(
CC))
3103 if (!Subtarget->is64Bit())
3106 if (Subtarget->useSoftFloat())
3110 unsigned GPRCnt = 0;
3111 unsigned FPRCnt = 0;
3112 for (
auto const &Arg :
F->args()) {
3113 if (Arg.hasAttribute(Attribute::ByVal) ||
3114 Arg.hasAttribute(Attribute::InReg) ||
3115 Arg.hasAttribute(Attribute::StructRet) ||
3116 Arg.hasAttribute(Attribute::SwiftSelf) ||
3117 Arg.hasAttribute(Attribute::SwiftAsync) ||
3118 Arg.hasAttribute(Attribute::SwiftError) ||
3119 Arg.hasAttribute(Attribute::Nest))
3122 Type *ArgTy = Arg.getType();
3126 EVT ArgVT = TLI.getValueType(
DL, ArgTy);
3127 if (!ArgVT.
isSimple())
return false;
3129 default:
return false;
3136 if (!Subtarget->hasSSE1())
3149 static const MCPhysReg GPR32ArgRegs[] = {
3150 X86::EDI, X86::ESI, X86::EDX, X86::ECX, X86::R8D, X86::R9D
3152 static const MCPhysReg GPR64ArgRegs[] = {
3153 X86::RDI, X86::RSI, X86::RDX, X86::RCX, X86::R8 , X86::R9
3156 X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,
3157 X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
3161 unsigned FPRIdx = 0;
3162 for (
auto const &Arg :
F->args()) {
3163 MVT VT = TLI.getSimpleValueType(
DL, Arg.getType());
3168 case MVT::i32: SrcReg = GPR32ArgRegs[
GPRIdx++];
break;
3169 case MVT::i64: SrcReg = GPR64ArgRegs[
GPRIdx++];
break;
3170 case MVT::f32: [[fallthrough]];
3171 case MVT::f64: SrcReg = XMMArgRegs[FPRIdx++];
break;
3173 Register DstReg = FuncInfo.MF->addLiveIn(SrcReg, RC);
3177 Register ResultReg = createResultReg(RC);
3178 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3179 TII.get(TargetOpcode::COPY), ResultReg)
3181 updateValueMap(&Arg, ResultReg);
3189 if (Subtarget->is64Bit())
3206bool X86FastISel::fastLowerCall(CallLoweringInfo &CLI) {
3207 auto &OutVals = CLI.OutVals;
3208 auto &OutFlags = CLI.OutFlags;
3209 auto &OutRegs = CLI.OutRegs;
3210 auto &
Ins = CLI.Ins;
3211 auto &InRegs = CLI.InRegs;
3213 bool &IsTailCall = CLI.IsTailCall;
3214 bool IsVarArg = CLI.IsVarArg;
3217 const auto *CB = CLI.CB;
3219 bool Is64Bit = Subtarget->is64Bit();
3220 bool IsWin64 = Subtarget->isCallingConvWin64(
CC);
3224 if (CB && CB->doesNoCfCheck())
3228 if ((CB && isa<CallInst>(CB) && CB->hasFnAttr(
"no_caller_saved_registers")))
3232 if ((CB && CB->hasFnAttr(
"no_callee_saved_registers")))
3240 if (Subtarget->useIndirectThunkCalls())
3245 default:
return false;
3272 if (IsVarArg && IsWin64)
3276 if (CLI.CB && CLI.CB->hasInAllocaArgument())
3279 for (
auto Flag : CLI.OutFlags)
3280 if (
Flag.isSwiftError() ||
Flag.isPreallocated())
3289 for (
int i = 0, e = OutVals.size(); i != e; ++i) {
3290 Value *&Val = OutVals[i];
3292 if (
auto *CI = dyn_cast<ConstantInt>(Val)) {
3293 if (CI->getBitWidth() < 32) {
3295 Val = ConstantInt::get(CI->
getContext(), CI->getValue().sext(32));
3297 Val = ConstantInt::get(CI->
getContext(), CI->getValue().zext(32));
3304 auto *TI = dyn_cast<TruncInst>(Val);
3306 if (TI && TI->getType()->isIntegerTy(1) && CLI.CB &&
3307 (TI->getParent() == CLI.CB->getParent()) && TI->hasOneUse()) {
3308 Value *PrevVal = TI->getOperand(0);
3309 ResultReg = getRegForValue(PrevVal);
3314 if (!isTypeLegal(PrevVal->
getType(), VT))
3317 ResultReg = fastEmit_ri(VT, VT,
ISD::AND, ResultReg, 1);
3319 if (!isTypeLegal(Val->
getType(), VT) ||
3322 ResultReg = getRegForValue(Val);
3334 CCState CCInfo(
CC, IsVarArg, *FuncInfo.MF, ArgLocs, CLI.RetTy->getContext());
3338 CCInfo.AllocateStack(32,
Align(8));
3340 CCInfo.AnalyzeCallOperands(OutVTs, OutFlags,
CC_X86);
3343 unsigned NumBytes = CCInfo.getAlignedCallFrameSize();
3346 unsigned AdjStackDown =
TII.getCallFrameSetupOpcode();
3347 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackDown))
3356 if (ArgVT == MVT::x86mmx)
3359 unsigned ArgReg = ArgRegs[VA.
getValNo()];
3366 "Unexpected extend");
3368 if (ArgVT == MVT::i1)
3373 assert(Emitted &&
"Failed to emit a sext!"); (void)Emitted;
3379 "Unexpected extend");
3382 if (ArgVT == MVT::i1) {
3384 ArgReg = fastEmitZExtFromI1(MVT::i8, ArgReg);
3393 assert(Emitted &&
"Failed to emit a zext!"); (void)Emitted;
3399 "Unexpected extend");
3409 assert(Emitted &&
"Failed to emit a aext!"); (void)Emitted;
3415 assert(ArgReg &&
"Failed to emit a bitcast!");
3436 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3443 if (isa<UndefValue>(ArgVal))
3449 AM.
Disp = LocMemOffset;
3455 if (
Flags.isByVal()) {
3458 if (!TryEmitSmallMemcpy(AM, SrcAM,
Flags.getByValSize()))
3460 }
else if (isa<ConstantInt>(ArgVal) || isa<ConstantPointerNull>(ArgVal)) {
3464 if (!X86FastEmitStore(ArgVT, ArgVal, AM, MMO))
3467 if (!X86FastEmitStore(ArgVT, ArgReg, AM, MMO))
3475 if (Subtarget->isPICStyleGOT()) {
3476 unsigned Base = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
3477 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3481 if (Is64Bit && IsVarArg && !IsWin64) {
3492 X86::XMM0, X86::XMM1, X86::XMM2, X86::XMM3,
3493 X86::XMM4, X86::XMM5, X86::XMM6, X86::XMM7
3495 unsigned NumXMMRegs = CCInfo.getFirstUnallocated(XMMArgRegs);
3496 assert((Subtarget->hasSSE1() || !NumXMMRegs)
3497 &&
"SSE registers cannot be used when SSE is disabled");
3498 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV8ri),
3499 X86::AL).
addImm(NumXMMRegs);
3505 if (!X86SelectCallAddress(Callee, CalleeAM))
3508 unsigned CalleeOp = 0;
3510 if (CalleeAM.
GV !=
nullptr) {
3512 }
else if (CalleeAM.
Base.
Reg != 0) {
3521 unsigned CallOpc = Is64Bit ? X86::CALL64r : X86::CALL32r;
3522 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CallOpc))
3526 assert(GV &&
"Not a direct call");
3528 unsigned char OpFlags = Subtarget->classifyGlobalFunctionReference(GV);
3531 cast<Function>(GV)->isIntrinsic())
3540 unsigned CallOpc = NeedLoad
3541 ? (Is64Bit ? X86::CALL64m : X86::CALL32m)
3542 : (Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32);
3544 MIB =
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(CallOpc));
3548 MIB.
addSym(Symbol, OpFlags);
3560 if (Subtarget->isPICStyleGOT())
3563 if (Is64Bit && IsVarArg && !IsWin64)
3567 for (
auto Reg : OutRegs)
3571 unsigned NumBytesForCalleeToPop =
3573 TM.Options.GuaranteedTailCallOpt)
3576 unsigned AdjStackUp =
TII.getCallFrameDestroyOpcode();
3577 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(AdjStackUp))
3582 CCState CCRetInfo(
CC, IsVarArg, *FuncInfo.MF, RVLocs,
3583 CLI.RetTy->getContext());
3584 CCRetInfo.AnalyzeCallResult(Ins,
RetCC_X86);
3587 Register ResultReg = FuncInfo.CreateRegs(CLI.RetTy);
3588 for (
unsigned i = 0; i != RVLocs.
size(); ++i) {
3591 unsigned CopyReg = ResultReg + i;
3595 if ((CopyVT == MVT::f32 || CopyVT == MVT::f64) &&
3596 ((Is64Bit || Ins[i].
Flags.isInReg()) && !Subtarget->hasSSE1())) {
3602 if ((SrcReg == X86::FP0 || SrcReg == X86::FP1) &&
3603 isScalarFPTypeInSSEReg(VA.
getValVT())) {
3605 CopyReg = createResultReg(&X86::RFP80RegClass);
3609 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3610 TII.get(TargetOpcode::COPY), CopyReg).
addReg(SrcReg);
3618 unsigned Opc = ResVT == MVT::f32 ? X86::ST_Fp80m32 : X86::ST_Fp80m64;
3624 Opc = ResVT == MVT::f32 ? X86::MOVSSrm_alt : X86::MOVSDrm_alt;
3626 TII.get(Opc), ResultReg + i), FI);
3630 CLI.ResultReg = ResultReg;
3631 CLI.NumResultRegs = RVLocs.
size();
3638X86FastISel::fastSelectInstruction(
const Instruction *
I) {
3639 switch (
I->getOpcode()) {
3641 case Instruction::Load:
3642 return X86SelectLoad(
I);
3643 case Instruction::Store:
3644 return X86SelectStore(
I);
3645 case Instruction::Ret:
3646 return X86SelectRet(
I);
3647 case Instruction::ICmp:
3648 case Instruction::FCmp:
3649 return X86SelectCmp(
I);
3650 case Instruction::ZExt:
3651 return X86SelectZExt(
I);
3652 case Instruction::SExt:
3653 return X86SelectSExt(
I);
3654 case Instruction::Br:
3655 return X86SelectBranch(
I);
3656 case Instruction::LShr:
3657 case Instruction::AShr:
3658 case Instruction::Shl:
3659 return X86SelectShift(
I);
3660 case Instruction::SDiv:
3661 case Instruction::UDiv:
3662 case Instruction::SRem:
3663 case Instruction::URem:
3664 return X86SelectDivRem(
I);
3665 case Instruction::Select:
3666 return X86SelectSelect(
I);
3667 case Instruction::Trunc:
3668 return X86SelectTrunc(
I);
3669 case Instruction::FPExt:
3670 return X86SelectFPExt(
I);
3671 case Instruction::FPTrunc:
3672 return X86SelectFPTrunc(
I);
3673 case Instruction::SIToFP:
3674 return X86SelectSIToFP(
I);
3675 case Instruction::UIToFP:
3676 return X86SelectUIToFP(
I);
3677 case Instruction::IntToPtr:
3678 case Instruction::PtrToInt: {
3679 EVT SrcVT = TLI.getValueType(
DL,
I->getOperand(0)->getType());
3680 EVT DstVT = TLI.getValueType(
DL,
I->getType());
3682 return X86SelectZExt(
I);
3684 return X86SelectTrunc(
I);
3686 if (Reg == 0)
return false;
3687 updateValueMap(
I, Reg);
3690 case Instruction::BitCast: {
3692 if (!Subtarget->hasSSE2())
3696 if (!isTypeLegal(
I->getOperand(0)->getType(), SrcVT) ||
3697 !isTypeLegal(
I->getType(), DstVT))
3713 Register ResultReg = createResultReg(DstClass);
3714 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3715 TII.get(TargetOpcode::COPY), ResultReg).
addReg(Reg);
3717 updateValueMap(
I, ResultReg);
3725unsigned X86FastISel::X86MaterializeInt(
const ConstantInt *CI,
MVT VT) {
3731 Register SrcReg = fastEmitInst_(X86::MOV32r0, &X86::GR32RegClass);
3736 return fastEmitInst_extractsubreg(MVT::i8, SrcReg, X86::sub_8bit);
3738 return fastEmitInst_extractsubreg(MVT::i16, SrcReg, X86::sub_16bit);
3742 Register ResultReg = createResultReg(&X86::GR64RegClass);
3743 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
3744 TII.get(TargetOpcode::SUBREG_TO_REG), ResultReg)
3757 case MVT::i8: Opc = X86::MOV8ri;
break;
3758 case MVT::i16: Opc = X86::MOV16ri;
break;
3759 case MVT::i32: Opc = X86::MOV32ri;
break;
3761 if (isUInt<32>(Imm))
3762 Opc = X86::MOV32ri64;
3763 else if (isInt<32>(Imm))
3764 Opc = X86::MOV64ri32;
3770 return fastEmitInst_i(Opc, TLI.getRegClassFor(VT), Imm);
3773unsigned X86FastISel::X86MaterializeFP(
const ConstantFP *CFP,
MVT VT) {
3775 return fastMaterializeFloatZero(CFP);
3785 bool HasSSE1 = Subtarget->hasSSE1();
3786 bool HasSSE2 = Subtarget->hasSSE2();
3787 bool HasAVX = Subtarget->hasAVX();
3788 bool HasAVX512 = Subtarget->hasAVX512();
3792 Opc = HasAVX512 ? X86::VMOVSSZrm_alt
3793 : HasAVX ? X86::VMOVSSrm_alt
3794 : HasSSE1 ? X86::MOVSSrm_alt
3798 Opc = HasAVX512 ? X86::VMOVSDZrm_alt
3799 : HasAVX ? X86::VMOVSDrm_alt
3800 : HasSSE2 ? X86::MOVSDrm_alt
3812 unsigned PICBase = 0;
3813 unsigned char OpFlag = Subtarget->classifyLocalReference(
nullptr);
3815 PICBase = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
3817 PICBase = getInstrInfo()->getGlobalBaseReg(FuncInfo.MF);
3822 unsigned CPI = MCP.getConstantPoolIndex(CFP, Alignment);
3827 Register AddrReg = createResultReg(&X86::GR64RegClass);
3828 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV64ri),
3832 TII.get(Opc), ResultReg);
3833 addRegReg(MIB, AddrReg,
false, PICBase,
false);
3842 TII.get(Opc), ResultReg),
3843 CPI, PICBase, OpFlag);
3847unsigned X86FastISel::X86MaterializeGV(
const GlobalValue *GV,
MVT VT) {
3852 if (
TM.isLargeGlobalValue(GV))
3864 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3866 TLI.getPointerTy(
DL) == MVT::i64) {
3869 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(X86::MOV64ri),
3874 TLI.getPointerTy(
DL) == MVT::i32
3875 ? (Subtarget->isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r)
3878 TII.get(Opc), ResultReg), AM);
3885unsigned X86FastISel::fastMaterializeConstant(
const Constant *
C) {
3886 EVT CEVT = TLI.getValueType(
DL,
C->getType(),
true);
3893 if (
const auto *CI = dyn_cast<ConstantInt>(
C))
3894 return X86MaterializeInt(CI, VT);
3895 if (
const auto *CFP = dyn_cast<ConstantFP>(
C))
3896 return X86MaterializeFP(CFP, VT);
3897 if (
const auto *GV = dyn_cast<GlobalValue>(
C))
3898 return X86MaterializeGV(GV, VT);
3899 if (isa<UndefValue>(
C)) {
3905 if (!Subtarget->hasSSE1())
3906 Opc = X86::LD_Fp032;
3909 if (!Subtarget->hasSSE2())
3910 Opc = X86::LD_Fp064;
3913 Opc = X86::LD_Fp080;
3918 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3919 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc),
3928unsigned X86FastISel::fastMaterializeAlloca(
const AllocaInst *
C) {
3936 if (!FuncInfo.StaticAllocaMap.count(
C))
3938 assert(
C->isStaticAlloca() &&
"dynamic alloca in the static alloca map?");
3944 TLI.getPointerTy(
DL) == MVT::i32
3945 ? (Subtarget->isTarget64BitILP32() ? X86::LEA64_32r : X86::LEA32r)
3948 Register ResultReg = createResultReg(RC);
3950 TII.get(Opc), ResultReg), AM);
3954unsigned X86FastISel::fastMaterializeFloatZero(
const ConstantFP *CF) {
3956 if (!isTypeLegal(CF->
getType(), VT))
3960 bool HasSSE1 = Subtarget->hasSSE1();
3961 bool HasSSE2 = Subtarget->hasSSE2();
3962 bool HasAVX512 = Subtarget->hasAVX512();
3967 Opc = HasAVX512 ? X86::AVX512_FsFLD0SH : X86::FsFLD0SH;
3970 Opc = HasAVX512 ? X86::AVX512_FsFLD0SS
3971 : HasSSE1 ? X86::FsFLD0SS
3975 Opc = HasAVX512 ? X86::AVX512_FsFLD0SD
3976 : HasSSE2 ? X86::FsFLD0SD
3984 Register ResultReg = createResultReg(TLI.getRegClassFor(VT));
3985 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(Opc), ResultReg);
3990bool X86FastISel::tryToFoldLoadIntoMI(
MachineInstr *
MI,
unsigned OpNo,
4005 *FuncInfo.MF, *
MI, OpNo, AddrOps, FuncInfo.InsertPt,
Size, LI->
getAlign(),
4015 unsigned OperandNo = 0;
4017 E =
Result->operands_end();
I != E; ++
I, ++OperandNo) {
4024 if (IndexReg == MO.
getReg())
4029 Result->addMemOperand(*FuncInfo.MF, createMachineMemOperandFor(LI));
4030 Result->cloneInstrSymbols(*FuncInfo.MF, *
MI);
4032 removeDeadCode(
I, std::next(
I));
4036unsigned X86FastISel::fastEmitInst_rrrr(
unsigned MachineInstOpcode,
4038 unsigned Op0,
unsigned Op1,
4039 unsigned Op2,
unsigned Op3) {
4042 Register ResultReg = createResultReg(RC);
4048 if (
II.getNumDefs() >= 1)
4049 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II, ResultReg)
4055 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
II)
4060 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,
TII.get(TargetOpcode::COPY),
4071 return new X86FastISel(funcInfo, libInfo);
unsigned const MachineRegisterInfo * MRI
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
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
uint64_t IntrinsicInst * II
const SmallVectorImpl< MachineOperand > & Cond
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static LLVM_ATTRIBUTE_ALWAYS_INLINE MVT::SimpleValueType getSimpleVT(const unsigned char *MatcherTable, unsigned &MatcherIndex)
getSimpleVT - Decode a value in MatcherTable, if it's a VBR encoded value, use GetVBR to decode it.
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...
#define GET_EGPR_IF_ENABLED(OPC)
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)
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...
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,...
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.
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...
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.
A wrapper class for inspecting calls to intrinsic functions.
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.
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 TargetMachine & 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.
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
Fold a load or store of the specified stack slot into the specified machine instruction for the speci...
X86MachineFunctionInfo - This class is derived from MachineFunction and contains private X86 target-s...
Register getSRetReturnReg() const
unsigned getBytesToPopOnReturn() const
const Triple & getTargetTriple() const
StructType * getStructTypeOrNull() const
TypeSize getSequentialElementStride(const DataLayout &DL) const
const ParentTy * getParent() 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, bool HasNDD=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::@662 BaseType
union llvm::X86AddressMode::@663 Base