21#include "llvm/Config/llvm-config.h"
26#include "llvm/IR/IntrinsicsX86.h"
38#define DEBUG_TYPE "x86-isel"
39#define PASS_NAME "X86 DAG->DAG Instruction Selection"
41STATISTIC(NumLoadMoved,
"Number of loads moved below TokenFactor");
44 cl::desc(
"Enable setting constant bits to reduce size of mask immediates"),
48 "x86-promote-anyext-load",
cl::init(
true),
60 struct X86ISelAddressMode {
68 int Base_FrameIndex = 0;
74 const GlobalValue *GV =
nullptr;
77 const char *ES =
nullptr;
82 bool NegateIndex =
false;
87 bool IsForLEA =
false;
89 X86ISelAddressMode() =
default;
91 bool hasSymbolicDisplacement()
const {
92 return GV !=
nullptr || CP !=
nullptr || ES !=
nullptr ||
93 MCSym !=
nullptr || JT != -1 || BlockAddr !=
nullptr;
96 bool hasBaseOrIndexReg()
const {
97 return BaseType == FrameIndexBase ||
98 IndexReg.getNode() !=
nullptr || Base_Reg.getNode() !=
nullptr;
103 if (BaseType != RegBase)
return false;
104 if (RegisterSDNode *RegNode =
106 return RegNode->getReg() == X86::RIP;
115#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
116 void dump(SelectionDAG *DAG =
nullptr) {
117 dbgs() <<
"X86ISelAddressMode " <<
this <<
'\n';
118 dbgs() <<
"Base_Reg ";
119 if (Base_Reg.getNode())
120 Base_Reg.getNode()->dump(DAG);
123 if (BaseType == FrameIndexBase)
124 dbgs() <<
" Base.FrameIndex " << Base_FrameIndex <<
'\n';
125 dbgs() <<
" Scale " << Scale <<
'\n'
129 if (IndexReg.getNode())
130 IndexReg.getNode()->dump(DAG);
133 dbgs() <<
" Disp " << Disp <<
'\n'
155 dbgs() <<
" JT" << JT <<
" Align" << Alignment.value() <<
'\n';
169 const X86Subtarget *Subtarget;
175 bool IndirectTlsSegRefs;
178 X86DAGToDAGISel() =
delete;
180 explicit X86DAGToDAGISel(X86TargetMachine &tm,
CodeGenOptLevel OptLevel)
181 : SelectionDAGISel(tm, OptLevel), Subtarget(nullptr),
182 OptForMinSize(
false), IndirectTlsSegRefs(
false) {}
188 "indirect-tls-seg-refs");
195 void emitFunctionEntryCode()
override;
197 bool IsProfitableToFold(
SDValue N, SDNode *U, SDNode *Root)
const override;
199 void PreprocessISelDAG()
override;
200 void PostprocessISelDAG()
override;
203#include "X86GenDAGISel.inc"
206 void Select(SDNode *
N)
override;
208 bool foldOffsetIntoAddress(
uint64_t Offset, X86ISelAddressMode &AM);
209 bool matchLoadInAddress(LoadSDNode *
N, X86ISelAddressMode &AM,
210 bool AllowSegmentRegForX32 =
false);
211 bool matchWrapper(
SDValue N, X86ISelAddressMode &AM);
212 bool matchAddress(
SDValue N, X86ISelAddressMode &AM);
213 bool matchVectorAddress(
SDValue N, X86ISelAddressMode &AM);
214 bool matchAdd(
SDValue &
N, X86ISelAddressMode &AM,
unsigned Depth);
215 bool hasMaterializingUse(
SDValue V)
const;
218 bool matchAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
220 bool matchVectorAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
222 bool matchAddressBase(
SDValue N, X86ISelAddressMode &AM);
225 bool HasNDDM =
true);
228 bool selectVectorAddr(MemSDNode *Parent,
SDValue BasePtr,
SDValue IndexOp,
242 bool tryFoldLoad(SDNode *Root, SDNode *
P,
SDValue N,
252 return tryFoldLoad(
P,
P,
N,
Base, Scale, Index, Disp, Segment);
255 bool tryFoldBroadcast(SDNode *Root, SDNode *
P,
SDValue N,
260 bool isProfitableToFormMaskedOp(SDNode *
N)
const;
263 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
265 std::vector<SDValue> &OutOps)
override;
267 void emitSpecialCodeForMain();
269 inline void getAddressOperands(X86ISelAddressMode &AM,
const SDLoc &
DL,
273 if (AM.BaseType == X86ISelAddressMode::FrameIndexBase)
274 Base = CurDAG->getTargetFrameIndex(
275 AM.Base_FrameIndex, TLI->getPointerTy(CurDAG->getDataLayout()));
276 else if (AM.Base_Reg.
getNode())
279 Base = CurDAG->getRegister(0, VT);
281 Scale = getI8Imm(AM.Scale,
DL);
283#define GET_ND_IF_ENABLED(OPC) (Subtarget->hasNDD() ? OPC##_ND : OPC)
284#define GET_NDM_IF_ENABLED(OPC) \
285 (Subtarget->hasNDD() && Subtarget->hasNDDM() ? OPC##_ND : OPC)
287 if (AM.NegateIndex) {
313 Index = CurDAG->getRegister(0, VT);
318 Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(),
322 Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, AM.Alignment,
323 AM.Disp, AM.SymbolFlags);
325 assert(!AM.Disp &&
"Non-zero displacement is ignored with ES.");
326 Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags);
327 }
else if (AM.MCSym) {
328 assert(!AM.Disp &&
"Non-zero displacement is ignored with MCSym.");
329 assert(AM.SymbolFlags == 0 &&
"oo");
330 Disp = CurDAG->getMCSymbol(AM.MCSym, MVT::i32);
331 }
else if (AM.JT != -1) {
332 assert(!AM.Disp &&
"Non-zero displacement is ignored with JT.");
333 Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags);
334 }
else if (AM.BlockAddr)
335 Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, AM.Disp,
338 Disp = CurDAG->getSignedTargetConstant(AM.Disp,
DL, MVT::i32);
341 Segment = AM.Segment;
343 Segment = CurDAG->getRegister(0, MVT::i16);
348 bool isAMXSDNode(SDNode *
N)
const {
352 for (
unsigned Idx = 0,
E =
N->getNumValues(); Idx !=
E; ++Idx) {
353 if (
N->getValueType(Idx) == MVT::x86amx)
356 for (
unsigned Idx = 0,
E =
N->getNumOperands(); Idx !=
E; ++Idx) {
358 if (
Op.getValueType() == MVT::x86amx)
370 bool shouldAvoidImmediateInstFormsForSize(SDNode *
N)
const {
371 uint32_t UseCount = 0;
376 if (!CurDAG->shouldOptForSize())
380 for (
const SDNode *User :
N->users()) {
386 if (
User->isMachineOpcode()) {
393 User->getOperand(1).getNode() ==
N) {
404 if (
User->getNumOperands() != 2)
417 if (
User->getOpcode() == X86ISD::ADD ||
419 User->getOpcode() == X86ISD::SUB ||
425 OtherOp =
User->getOperand(1);
428 RegisterSDNode *RegNode;
432 if ((RegNode->
getReg() == X86::ESP) ||
433 (RegNode->
getReg() == X86::RSP))
442 return (UseCount > 1);
446 inline SDValue getI8Imm(
unsigned Imm,
const SDLoc &
DL) {
447 return CurDAG->getTargetConstant(
Imm,
DL, MVT::i8);
451 inline SDValue getI32Imm(
unsigned Imm,
const SDLoc &
DL) {
452 return CurDAG->getTargetConstant(
Imm,
DL, MVT::i32);
457 return CurDAG->getTargetConstant(
Imm,
DL, MVT::i64);
460 SDValue getExtractVEXTRACTImmediate(SDNode *
N,
unsigned VecWidth,
462 assert((VecWidth == 128 || VecWidth == 256) &&
"Unexpected vector width");
464 MVT VecVT =
N->getOperand(0).getSimpleValueType();
468 SDValue getInsertVINSERTImmediate(SDNode *
N,
unsigned VecWidth,
470 assert((VecWidth == 128 || VecWidth == 256) &&
"Unexpected vector width");
472 MVT VecVT =
N->getSimpleValueType(0);
476 SDValue getPermuteVINSERTCommutedImmediate(SDNode *
N,
unsigned VecWidth,
478 assert(VecWidth == 128 &&
"Unexpected vector width");
480 MVT VecVT =
N->getSimpleValueType(0);
482 assert((InsertIdx == 0 || InsertIdx == 1) &&
"Bad insertf128 index");
485 return getI8Imm(InsertIdx ? 0x02 : 0x30,
DL);
490 MVT VT =
N->getSimpleValueType(0);
493 SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::i32);
495 SDValue(CurDAG->getMachineNode(X86::MOV32r0, dl, VTs, {}), 0);
496 if (VT == MVT::i64) {
498 CurDAG->getMachineNode(
499 TargetOpcode::SUBREG_TO_REG, dl, MVT::i64, Zero,
500 CurDAG->getTargetConstant(X86::sub_32bit, dl, MVT::i32)),
505 unsigned Opcode =
N->getOpcode();
506 assert((Opcode == X86ISD::SBB || Opcode == X86ISD::SETCC_CARRY) &&
507 "Unexpected opcode for SBB materialization");
508 unsigned FlagOpIndex = Opcode == X86ISD::SBB ? 2 : 1;
510 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EFLAGS,
511 N->getOperand(FlagOpIndex),
SDValue());
515 unsigned Opc = VT == MVT::i64 ? X86::SBB64rr : X86::SBB32rr;
516 MVT SBBVT = VT == MVT::i64 ? MVT::i64 : MVT::i32;
517 VTs = CurDAG->getVTList(SBBVT, MVT::i32);
519 CurDAG->getMachineNode(
Opc, dl, VTs,
520 {Zero, Zero, EFLAGS, EFLAGS.getValue(1)}),
526 bool isUnneededShiftMask(SDNode *
N,
unsigned Width)
const {
528 const APInt &Val =
N->getConstantOperandAPInt(1);
533 APInt
Mask = Val | CurDAG->computeKnownBits(
N->getOperand(0)).Zero;
534 return Mask.countr_one() >= Width;
540 SDNode *getGlobalBaseReg();
544 const X86TargetMachine &getTargetMachine()
const {
545 return static_cast<const X86TargetMachine &
>(TM);
550 const X86InstrInfo *getInstrInfo()
const {
551 return Subtarget->getInstrInfo();
560 bool ComplexPatternFuncMutatesDAG()
const override {
564 bool isSExtAbsoluteSymbolRef(
unsigned Width, SDNode *
N)
const;
567 bool useNonTemporalLoad(LoadSDNode *
N)
const {
568 if (!
N->isNonTemporal())
571 unsigned StoreSize =
N->getMemoryVT().getStoreSize();
573 if (
N->getAlign().value() < StoreSize)
582 return Subtarget->hasSSE41();
584 return Subtarget->hasAVX2();
586 return Subtarget->hasAVX512();
590 bool foldLoadStoreIntoMemOperand(SDNode *Node);
591 MachineSDNode *matchBEXTRFromAndImm(SDNode *Node);
592 bool matchBitExtract(SDNode *Node);
593 bool shrinkAndImmediate(SDNode *
N);
594 bool isMaskZeroExtended(SDNode *
N)
const;
595 bool tryShiftAmountMod(SDNode *
N);
596 bool tryShrinkShlLogicImm(SDNode *
N);
597 bool tryVPTERNLOG(SDNode *
N);
598 bool matchVPTERNLOG(SDNode *Root, SDNode *ParentA, SDNode *ParentB,
602 bool tryMatchBitSelect(SDNode *
N);
604 MachineSDNode *emitPCMPISTR(
unsigned ROpc,
unsigned MOpc,
bool MayFoldLoad,
605 const SDLoc &dl, MVT VT, SDNode *Node);
606 MachineSDNode *emitPCMPESTR(
unsigned ROpc,
unsigned MOpc,
bool MayFoldLoad,
607 const SDLoc &dl, MVT VT, SDNode *Node,
610 bool tryOptimizeRem8Extend(SDNode *
N);
612 bool onlyUsesZeroFlag(
SDValue Flags)
const;
613 bool hasNoSignFlagUses(
SDValue Flags)
const;
614 bool hasNoCarryFlagUses(
SDValue Flags)
const;
615 bool checkTCRetEnoughRegs(SDNode *
N)
const;
621 explicit X86DAGToDAGISelLegacy(X86TargetMachine &tm,
623 : SelectionDAGISelLegacy(
624 ID, std::make_unique<X86DAGToDAGISel>(tm, OptLevel)) {}
628char X86DAGToDAGISelLegacy::ID = 0;
635 unsigned Opcode =
N->getOpcode();
636 if (Opcode == X86ISD::CMPM || Opcode == X86ISD::CMPMM ||
637 Opcode == X86ISD::STRICT_CMPM || Opcode ==
ISD::SETCC ||
638 Opcode == X86ISD::CMPMM_SAE || Opcode == X86ISD::VFPCLASS) {
642 EVT OpVT =
N->getOperand(0).getValueType();
645 if (Opcode == X86ISD::STRICT_CMPM)
646 OpVT =
N->getOperand(1).getValueType();
648 return Subtarget->hasVLX();
653 if (Opcode == X86ISD::VFPCLASSS || Opcode == X86ISD::FSETCCM ||
654 Opcode == X86ISD::FSETCCM_SAE)
662bool X86DAGToDAGISel::isMaskZeroExtended(
SDNode *
N)
const {
674X86DAGToDAGISel::IsProfitableToFold(
SDValue N, SDNode *U, SDNode *Root)
const {
675 if (OptLevel == CodeGenOptLevel::None)
690 switch (
U->getOpcode()) {
717 if (
Imm->getAPIntValue().isSignedIntN(8))
726 Imm->getAPIntValue().getBitWidth() == 64 &&
727 Imm->getAPIntValue().isIntN(32))
734 (
Imm->getAPIntValue() == UINT8_MAX ||
735 Imm->getAPIntValue() == UINT16_MAX ||
736 Imm->getAPIntValue() == UINT32_MAX))
742 (-
Imm->getAPIntValue()).isSignedIntN(8))
745 if ((
U->getOpcode() == X86ISD::ADD ||
U->getOpcode() == X86ISD::SUB) &&
746 (-
Imm->getAPIntValue()).isSignedIntN(8) &&
747 hasNoCarryFlagUses(
SDValue(U, 1)))
761 if (Op1.
getOpcode() == X86ISD::Wrapper) {
772 if (
U->getOperand(0).getOpcode() ==
ISD::SHL &&
776 if (
U->getOperand(1).getOpcode() ==
ISD::SHL &&
785 if (
C &&
C->getSExtValue() == -2)
791 if (
C &&
C->getSExtValue() == -2)
826bool X86DAGToDAGISel::isProfitableToFormMaskedOp(SDNode *
N)
const {
828 (
N->getOpcode() ==
ISD::VSELECT ||
N->getOpcode() == X86ISD::SELECTS) &&
829 "Unexpected opcode!");
834 return N->getOperand(1).hasOneUse();
844 Ops.push_back(
Load.getOperand(0));
847 "Unexpected chain operand");
850 Ops.push_back(
Load.getOperand(0));
856 Ops.push_back(NewChain);
861 Load.getOperand(1),
Load.getOperand(2));
879 if (Callee.getNode() == Chain.
getNode() || !Callee.hasOneUse())
891 if (!Callee.getValue(1).hasOneUse())
922 Callee.getValue(1).hasOneUse())
939 if ((
Imm & 0x00FFFFFF) != 0x0F1EFA)
942 uint8_t OptionalPrefixBytes [] = {0x26, 0x2e, 0x36, 0x3e, 0x64,
943 0x65, 0x66, 0x67, 0xf0, 0xf2};
958 return (VT == MVT::v32i16 || VT == MVT::v32f16 || VT == MVT::v64i8);
961void X86DAGToDAGISel::PreprocessISelDAG() {
962 bool MadeChange =
false;
964 E = CurDAG->allnodes_end();
I !=
E; ) {
983 MVT VT =
N->getSimpleValueType(0);
985 int32_t EndbrImm = Subtarget->is64Bit() ? 0xF30F1EFA : 0xF30F1EFB;
990 "cf-protection-branch");
993 SDValue Complement = CurDAG->getConstant(~
Imm, dl, VT,
false,
true);
994 Complement = CurDAG->getNOT(dl, Complement, VT);
996 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Complement);
1006 if (
N->getOpcode() == X86ISD::AND && !
N->hasAnyUseOfValue(1)) {
1008 N->getOperand(0),
N->getOperand(1));
1010 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1034 auto mayPreventLoadFold = [&]() {
1036 N->getOpcode() ==
ISD::ADD && Subtarget->hasAVX() &&
1037 !
N->getOperand(1).hasOneUse();
1040 N->getSimpleValueType(0).isVector() && !mayPreventLoadFold()) {
1048 MVT VT =
N->getSimpleValueType(0);
1056 CurDAG->getNode(NewOpcode,
DL, VT,
N->getOperand(0),
AllOnes);
1058 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1065 switch (
N->getOpcode()) {
1066 case X86ISD::VBROADCAST: {
1067 MVT VT =
N->getSimpleValueType(0);
1069 if (!Subtarget->hasBWI() &&
needBWI(VT)) {
1073 CurDAG->getNode(X86ISD::VBROADCAST, dl, NarrowVT,
N->getOperand(0));
1076 NarrowBCast, CurDAG->getIntPtrConstant(0, dl));
1079 CurDAG->getIntPtrConstant(Index, dl));
1082 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1090 case X86ISD::VBROADCAST_LOAD: {
1091 MVT VT =
N->getSimpleValueType(0);
1093 if (!Subtarget->hasBWI() &&
needBWI(VT)) {
1097 SDVTList VTs = CurDAG->getVTList(NarrowVT, MVT::Other);
1098 SDValue Ops[] = {MemNode->getChain(), MemNode->getBasePtr()};
1099 SDValue NarrowBCast = CurDAG->getMemIntrinsicNode(
1100 X86ISD::VBROADCAST_LOAD, dl, VTs,
Ops, MemNode->getMemoryVT(),
1101 MemNode->getMemOperand());
1104 NarrowBCast, CurDAG->getIntPtrConstant(0, dl));
1107 CurDAG->getIntPtrConstant(Index, dl));
1111 CurDAG->ReplaceAllUsesWith(
N, To);
1123 MVT VT =
N->getSimpleValueType(0);
1129 SDNode *MaxLd =
nullptr;
1130 SDValue Ptr = Ld->getBasePtr();
1131 SDValue Chain = Ld->getChain();
1132 for (SDNode *User : Ptr->
users()) {
1134 MVT UserVT =
User->getSimpleValueType(0);
1136 UserLd->getBasePtr() == Ptr && UserLd->getChain() == Chain &&
1137 !
User->hasAnyUseOfValue(1) &&
1151 CurDAG->getIntPtrConstant(0, dl));
1152 SDValue Res = CurDAG->getBitcast(VT, Extract);
1156 CurDAG->ReplaceAllUsesWith(
N, To);
1165 EVT EleVT =
N->getOperand(0).getValueType().getVectorElementType();
1166 if (EleVT == MVT::i1)
1169 assert(Subtarget->hasSSE41() &&
"Expected SSE4.1 support!");
1170 assert(
N->getValueType(0).getVectorElementType() != MVT::i16 &&
1171 "We can't replace VSELECT with BLENDV in vXi16!");
1173 if (Subtarget->hasVLX() && CurDAG->ComputeNumSignBits(
N->getOperand(0)) ==
1175 R = CurDAG->getNode(X86ISD::VPTERNLOG, SDLoc(
N),
N->getValueType(0),
1176 N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
1177 CurDAG->getTargetConstant(0xCA, SDLoc(
N), MVT::i8));
1179 R = CurDAG->getNode(X86ISD::BLENDV, SDLoc(
N),
N->getValueType(0),
1180 N->getOperand(0),
N->getOperand(1),
1184 CurDAG->ReplaceAllUsesWith(
N,
R.getNode());
1197 if (!
N->getSimpleValueType(0).isVector())
1201 switch (
N->getOpcode()) {
1211 if (
N->isStrictFPOpcode())
1213 CurDAG->getNode(NewOpc, SDLoc(
N), {
N->getValueType(0), MVT::Other},
1214 {
N->getOperand(0),
N->getOperand(1)});
1217 CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1220 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1230 if (!
N->getValueType(0).isVector())
1234 switch (
N->getOpcode()) {
1236 case ISD::SHL: NewOpc = X86ISD::VSHLV;
break;
1237 case ISD::SRA: NewOpc = X86ISD::VSRAV;
break;
1238 case ISD::SRL: NewOpc = X86ISD::VSRLV;
break;
1240 SDValue Res = CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1241 N->getOperand(0),
N->getOperand(1));
1243 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1252 if (!
N->getValueType(0).isVector())
1256 if (
N->getOperand(0).getScalarValueSizeInBits() == 1) {
1258 "Unexpected opcode for mask vector!");
1266 SDValue Res = CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1269 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1289 switch (
N->getOpcode()) {
1305 bool IsStrict =
N->isStrictFPOpcode();
1308 Res = CurDAG->getNode(X86ISD::STRICT_VRNDSCALE, dl,
1309 {
N->getValueType(0), MVT::Other},
1310 {
N->getOperand(0),
N->getOperand(1),
1311 CurDAG->getTargetConstant(
Imm, dl, MVT::i32)});
1313 Res = CurDAG->getNode(X86ISD::VRNDSCALE, dl,
N->getValueType(0),
1315 CurDAG->getTargetConstant(
Imm, dl, MVT::i32));
1317 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1325 case X86ISD::FXOR: {
1328 MVT VT =
N->getSimpleValueType(0);
1329 if (VT.
isVector() || VT == MVT::f128)
1332 MVT VecVT = VT == MVT::f64 ? MVT::v2f64
1333 : VT == MVT::f32 ? MVT::v4f32
1343 if (Subtarget->hasSSE2()) {
1344 EVT IntVT = EVT(VecVT).changeVectorElementTypeToInteger();
1348 switch (
N->getOpcode()) {
1350 case X86ISD::FANDN:
Opc = X86ISD::ANDNP;
break;
1355 Res = CurDAG->getNode(
Opc, dl, IntVT, Op0, Op1);
1358 Res = CurDAG->getNode(
N->getOpcode(), dl, VecVT, Op0, Op1);
1361 CurDAG->getIntPtrConstant(0, dl));
1363 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1370 if (OptLevel != CodeGenOptLevel::None &&
1373 !Subtarget->useIndirectThunkCalls() &&
1374 ((
N->getOpcode() == X86ISD::CALL && !Subtarget->slowTwoMemOps() &&
1375 !Subtarget->slowIndirectCall()) ||
1376 (
N->getOpcode() == X86ISD::TC_RETURN &&
1377 (Subtarget->is64Bit() ||
1378 !getTargetMachine().isPositionIndependent())))) {
1398 bool HasCallSeq =
N->getOpcode() == X86ISD::CALL;
1403 if (
N->getOpcode() == X86ISD::TC_RETURN && !checkTCRetEnoughRegs(
N))
1419 switch (
N->getOpcode()) {
1424 MVT SrcVT =
N->getOperand(0).getSimpleValueType();
1425 MVT DstVT =
N->getSimpleValueType(0);
1433 const X86TargetLowering *X86Lowering =
1434 static_cast<const X86TargetLowering *
>(TLI);
1437 if (SrcIsSSE && DstIsSSE)
1440 if (!SrcIsSSE && !DstIsSSE) {
1445 if (
N->getConstantOperandVal(1))
1453 SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
1455 MachinePointerInfo MPI =
1462 CurDAG->getEntryNode(), dl,
N->getOperand(0), MemTmp, MPI, MemVT);
1464 MemTmp, MPI, MemVT);
1471 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Result);
1480 MVT SrcVT =
N->getOperand(1).getSimpleValueType();
1481 MVT DstVT =
N->getSimpleValueType(0);
1489 const X86TargetLowering *X86Lowering =
1490 static_cast<const X86TargetLowering *
>(TLI);
1493 if (SrcIsSSE && DstIsSSE)
1496 if (!SrcIsSSE && !DstIsSSE) {
1501 if (
N->getConstantOperandVal(2))
1509 SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
1511 MachinePointerInfo MPI =
1520 SDVTList VTs = CurDAG->getVTList(MVT::Other);
1521 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), MemTmp};
1522 Store = CurDAG->getMemIntrinsicNode(X86ISD::FST, dl, VTs,
Ops, MemVT,
1525 if (
N->getFlags().hasNoFPExcept()) {
1527 Flags.setNoFPExcept(
true);
1528 Store->setFlags(Flags);
1531 assert(SrcVT == MemVT &&
"Unexpected VT!");
1532 Store = CurDAG->getStore(
N->getOperand(0), dl,
N->getOperand(1), MemTmp,
1537 SDVTList VTs = CurDAG->getVTList(DstVT, MVT::Other);
1539 Result = CurDAG->getMemIntrinsicNode(
1540 X86ISD::FLD, dl, VTs,
Ops, MemVT, MPI,
1542 if (
N->getFlags().hasNoFPExcept()) {
1544 Flags.setNoFPExcept(
true);
1548 assert(DstVT == MemVT &&
"Unexpected VT!");
1549 Result = CurDAG->getLoad(DstVT, dl,
Store, MemTmp, MPI);
1557 CurDAG->ReplaceAllUsesWith(
N,
Result.getNode());
1571 CurDAG->RemoveDeadNodes();
1575bool X86DAGToDAGISel::tryOptimizeRem8Extend(SDNode *
N) {
1576 unsigned Opc =
N->getMachineOpcode();
1577 if (
Opc != X86::MOVZX32rr8 &&
Opc != X86::MOVSX32rr8 &&
1578 Opc != X86::MOVSX64rr8)
1590 unsigned ExpectedOpc =
Opc == X86::MOVZX32rr8 ? X86::MOVZX32rr8_NOREX
1591 : X86::MOVSX32rr8_NOREX;
1596 if (
Opc == X86::MOVSX64rr8) {
1599 MachineSDNode *Extend = CurDAG->getMachineNode(X86::MOVSX64rr32, SDLoc(
N),
1601 ReplaceUses(
N, Extend);
1610void X86DAGToDAGISel::PostprocessISelDAG() {
1612 if (TM.getOptLevel() == CodeGenOptLevel::None)
1617 bool MadeChange =
false;
1618 while (Position != CurDAG->allnodes_begin()) {
1619 SDNode *
N = &*--Position;
1621 if (
N->use_empty() || !
N->isMachineOpcode())
1624 if (tryOptimizeRem8Extend(
N)) {
1629 unsigned Opc =
N->getMachineOpcode();
1640 case X86::CTEST16rr:
1641 case X86::CTEST32rr:
1642 case X86::CTEST64rr: {
1648#define CASE_ND(OP) \
1651 switch (
And.getMachineOpcode()) {
1658 if (
And->hasAnyUseOfValue(1))
1661 Ops[0] =
And.getOperand(0);
1662 Ops[1] =
And.getOperand(1);
1663 MachineSDNode *
Test =
1664 CurDAG->getMachineNode(
Opc, SDLoc(
N), MVT::i32,
Ops);
1665 ReplaceUses(
N,
Test);
1673 if (
And->hasAnyUseOfValue(1))
1676 bool IsCTESTCC = X86::isCTESTCC(
Opc);
1677#define FROM_TO(A, B) \
1678 CASE_ND(A) NewOpc = IsCTESTCC ? X86::C##B : X86::B; \
1680 switch (
And.getMachineOpcode()) {
1690 And.getOperand(3),
And.getOperand(4),
1691 And.getOperand(5),
And.getOperand(0)};
1694 Ops.push_back(
N->getOperand(2));
1695 Ops.push_back(
N->getOperand(3));
1698 Ops.push_back(
And.getOperand(6));
1701 Ops.push_back(
N->getOperand(4));
1703 MachineSDNode *
Test = CurDAG->getMachineNode(
1704 NewOpc, SDLoc(
N), MVT::i32, MVT::Other,
Ops);
1705 CurDAG->setNodeMemRefs(
1718 case X86::KORTESTBkk:
1719 case X86::KORTESTWkk:
1720 case X86::KORTESTDkk:
1721 case X86::KORTESTQkk: {
1723 if (Op0 !=
N->getOperand(1) || !
N->isOnlyUserOf(Op0.
getNode()) ||
1738#define FROM_TO(A, B) \
1750 if (NewOpc == X86::KTESTWkk && !Subtarget->hasDQI())
1753 MachineSDNode *KTest = CurDAG->getMachineNode(
1755 ReplaceUses(
N, KTest);
1760 case TargetOpcode::SUBREG_TO_REG: {
1761 unsigned SubRegIdx =
N->getConstantOperandVal(1);
1762 if (SubRegIdx != X86::sub_xmm && SubRegIdx != X86::sub_ymm)
1779 CASE(VMOVAPDZ128rr)
CASE(VMOVUPDZ128rr)
1780 CASE(VMOVAPSZ128rr)
CASE(VMOVUPSZ128rr)
1781 CASE(VMOVDQA32Z128rr)
CASE(VMOVDQU32Z128rr)
1782 CASE(VMOVDQA64Z128rr)
CASE(VMOVDQU64Z128rr)
1783 CASE(VMOVAPDZ256rr)
CASE(VMOVUPDZ256rr)
1784 CASE(VMOVAPSZ256rr)
CASE(VMOVUPSZ256rr)
1785 CASE(VMOVDQA32Z256rr)
CASE(VMOVDQU32Z256rr)
1786 CASE(VMOVDQA64Z256rr)
CASE(VMOVDQU64Z256rr)
1791 if (!
In.isMachineOpcode() ||
1792 In.getMachineOpcode() <= TargetOpcode::GENERIC_OP_END)
1797 uint64_t TSFlags = getInstrInfo()->get(
In.getMachineOpcode()).TSFlags;
1805 CurDAG->UpdateNodeOperands(
N, In,
N->getOperand(1));
1812 CurDAG->RemoveDeadNodes();
1817void X86DAGToDAGISel::emitSpecialCodeForMain() {
1818 if (Subtarget->isTargetCygMing()) {
1819 TargetLowering::ArgListTy
Args;
1820 auto &
DL = CurDAG->getDataLayout();
1822 TargetLowering::CallLoweringInfo CLI(*CurDAG);
1823 CLI.setChain(CurDAG->getRoot())
1824 .setCallee(CallingConv::C, Type::getVoidTy(*CurDAG->getContext()),
1825 CurDAG->getExternalSymbol(
"__main", TLI->getPointerTy(
DL)),
1827 const TargetLowering &TLI = CurDAG->getTargetLoweringInfo();
1829 CurDAG->setRoot(
Result.second);
1833void X86DAGToDAGISel::emitFunctionEntryCode() {
1836 if (
F.hasExternalLinkage() &&
F.getName() ==
"main")
1837 emitSpecialCodeForMain();
1851 X86ISelAddressMode &AM) {
1856 int64_t Val = AM.Disp +
Offset;
1859 if (Val != 0 && (AM.ES || AM.MCSym))
1863 if (Subtarget->is64Bit()) {
1866 AM.hasSymbolicDisplacement()))
1870 if (AM.BaseType == X86ISelAddressMode::FrameIndexBase &&
1889 if (Subtarget->isTarget64BitILP32() &&
1891 !AM.hasBaseOrIndexReg())
1893 }
else if (Subtarget->is16Bit()) {
1896 if (Val < -(int64_t)UINT16_MAX || Val > (int64_t)UINT16_MAX)
1906bool X86DAGToDAGISel::matchLoadInAddress(LoadSDNode *
N, X86ISelAddressMode &AM,
1907 bool AllowSegmentRegForX32) {
1920 !IndirectTlsSegRefs &&
1921 (Subtarget->isTargetGlibc() || Subtarget->isTargetMusl() ||
1922 Subtarget->isTargetAndroid() || Subtarget->isTargetFuchsia())) {
1923 if (Subtarget->isTarget64BitILP32() && !AllowSegmentRegForX32)
1925 switch (
N->getPointerInfo().getAddrSpace()) {
1927 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
1930 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
1943bool X86DAGToDAGISel::matchWrapper(
SDValue N, X86ISelAddressMode &AM) {
1946 if (AM.hasSymbolicDisplacement())
1949 bool IsRIPRelTLS =
false;
1950 bool IsRIPRel =
N.getOpcode() == X86ISD::WrapperRIP;
1967 if (IsRIPRel && AM.hasBaseOrIndexReg())
1971 X86ISelAddressMode Backup = AM;
1976 AM.GV =
G->getGlobal();
1977 AM.SymbolFlags =
G->getTargetFlags();
1980 AM.CP = CP->getConstVal();
1981 AM.Alignment = CP->getAlign();
1982 AM.SymbolFlags = CP->getTargetFlags();
1983 Offset = CP->getOffset();
1985 AM.ES = S->getSymbol();
1986 AM.SymbolFlags = S->getTargetFlags();
1988 AM.MCSym = S->getMCSymbol();
1990 AM.JT = J->getIndex();
1991 AM.SymbolFlags = J->getTargetFlags();
1993 AM.BlockAddr = BA->getBlockAddress();
1994 AM.SymbolFlags = BA->getTargetFlags();
1995 Offset = BA->getOffset();
2000 if (Subtarget->is64Bit() && !IsRIPRel && AM.GV &&
2001 TM.isLargeGlobalValue(AM.GV)) {
2006 if (foldOffsetIntoAddress(
Offset, AM)) {
2012 AM.setBaseReg(CurDAG->getRegister(X86::RIP, MVT::i64));
2020bool X86DAGToDAGISel::matchAddress(
SDValue N, X86ISelAddressMode &AM) {
2021 if (matchAddressRecursively(
N, AM, 0))
2028 if (Subtarget->isTarget64BitILP32() &&
2029 AM.BaseType == X86ISelAddressMode::RegBase &&
2030 AM.Base_Reg.
getNode() !=
nullptr && AM.IndexReg.
getNode() ==
nullptr) {
2031 SDValue Save_Base_Reg = AM.Base_Reg;
2034 if (matchLoadInAddress(LoadN, AM,
true))
2035 AM.Base_Reg = Save_Base_Reg;
2044 if (AM.Scale == 2 && !AM.NegateIndex &&
2045 AM.BaseType == X86ISelAddressMode::RegBase &&
2046 AM.Base_Reg.
getNode() ==
nullptr) {
2047 AM.Base_Reg = AM.IndexReg;
2054 (!AM.GV || !TM.isLargeGlobalValue(AM.GV)) && Subtarget->is64Bit() &&
2055 AM.Scale == 1 && AM.BaseType == X86ISelAddressMode::RegBase &&
2056 AM.Base_Reg.
getNode() ==
nullptr && AM.IndexReg.
getNode() ==
nullptr &&
2068 AM.Base_Reg = CurDAG->getRegister(X86::RIP, MVT::i64);
2081bool X86DAGToDAGISel::hasMaterializingUse(
SDValue V)
const {
2082 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
2083 for (SDUse &U :
V->uses()) {
2084 if (
U.getResNo() !=
V.getResNo())
2086 SDNode *
User =
U.getUser();
2092 if (St->getValue() == V)
2103 if (!
User->isMachineOpcode())
2105 const MCInstrDesc &
Desc =
TII->get(
User->getMachineOpcode());
2106 if (!
Desc.mayStore())
2109 if (MemRefBegin < 0)
2112 for (
unsigned I = 0,
E =
User->getNumOperands();
I !=
E; ++
I) {
2113 if (
I >=
static_cast<unsigned>(MemRefBegin) &&
I < MemRefEnd)
2125bool X86DAGToDAGISel::matchAdd(
SDValue &
N, X86ISelAddressMode &AM,
2129 HandleSDNode Handle(
N);
2131 auto IsAddOrAddLike = [&](
SDValue V) {
2132 return V.getOpcode() ==
ISD::ADD || CurDAG->isADDLike(V);
2141 auto SplitsMaterializedValue = [&](
SDValue Op) {
2142 if (!AM.IsForLEA || !hasMaterializingUse(
Op))
2146 if (IsAddOrAddLike(
Op))
2147 return IsAddOrAddLike(
Op.getOperand(0)) ||
2148 IsAddOrAddLike(
Op.getOperand(1));
2153 return C->getZExtValue() >= 1 &&
C->getZExtValue() <= 3 &&
2154 IsAddOrAddLike(
Op.getOperand(0));
2174 if (SplitsMaterializedValue(
Op) && !AM.isRIPRelative())
2175 return matchAddressBase(
Op, AM);
2176 return matchAddressRecursively(
Op, AM,
Depth + 1);
2179 X86ISelAddressMode Backup = AM;
2180 if (!MatchOperand(
N.getOperand(0)) &&
2181 !MatchOperand(Handle.getValue().getOperand(1)))
2186 if (!MatchOperand(Handle.getValue().getOperand(1)) &&
2187 !MatchOperand(Handle.getValue().getOperand(0)))
2194 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2197 N = Handle.getValue();
2203 N = Handle.getValue();
2213 if (
N->getNodeId() == -1 ||
2233 X86ISelAddressMode &AM) {
2240 if (ScaleLog <= 0 || ScaleLog >= 4 ||
2241 Mask != (0xffu << ScaleLog))
2244 MVT XVT =
X.getSimpleValueType();
2245 MVT VT =
N.getSimpleValueType();
2270 AM.Scale = (1 << ScaleLog);
2278 X86ISelAddressMode &AM) {
2289 bool FoundAnyExtend =
false;
2293 FoundAnyExtend =
true;
2311 if (ShiftAmt != 1 && ShiftAmt != 2 && ShiftAmt != 3)
2314 MVT VT =
N.getSimpleValueType();
2316 if (FoundAnyExtend) {
2337 AM.Scale = 1 << ShiftAmt;
2338 AM.IndexReg = NewAnd;
2372 X86ISelAddressMode &AM) {
2378 unsigned MaskIdx, MaskLen;
2381 unsigned MaskLZ = 64 - (MaskIdx + MaskLen);
2387 unsigned AMShiftAmt = MaskIdx;
2391 if (AMShiftAmt == 0 || AMShiftAmt > 3)
return true;
2395 unsigned ScaleDown = (64 -
X.getSimpleValueType().getSizeInBits()) + ShiftAmt;
2396 if (MaskLZ < ScaleDown)
2398 MaskLZ -= ScaleDown;
2406 bool ReplacingAnyExtend =
false;
2408 unsigned ExtendBits =
X.getSimpleValueType().getSizeInBits() -
2409 X.getOperand(0).getSimpleValueType().getSizeInBits();
2412 X =
X.getOperand(0);
2413 MaskLZ = ExtendBits > MaskLZ ? 0 : MaskLZ - ExtendBits;
2414 ReplacingAnyExtend =
true;
2416 APInt MaskedHighBits =
2423 MVT VT =
N.getSimpleValueType();
2424 if (ReplacingAnyExtend) {
2425 assert(
X.getValueType() != VT);
2432 MVT XVT =
X.getSimpleValueType();
2453 AM.Scale = 1 << AMShiftAmt;
2454 AM.IndexReg = NewExt;
2464 X86ISelAddressMode &AM,
2472 if (!Subtarget.hasTBM() &&
2473 !(Subtarget.hasBMI() && Subtarget.hasFastBEXTR()))
2477 unsigned MaskIdx, MaskLen;
2485 unsigned AMShiftAmt = MaskIdx;
2489 if (AMShiftAmt == 0 || AMShiftAmt > 3)
return true;
2491 MVT XVT =
X.getSimpleValueType();
2492 MVT VT =
N.getSimpleValueType();
2517 AM.Scale = 1 << AMShiftAmt;
2518 AM.IndexReg = NewExt;
2525 X86ISelAddressMode &AM,
2527 assert(AM.IndexReg.
getNode() ==
nullptr &&
"IndexReg already matched");
2528 assert((AM.Scale == 1 || AM.Scale == 2 || AM.Scale == 4 || AM.Scale == 8) &&
2529 "Illegal index scale");
2535 EVT VT =
N.getValueType();
2536 unsigned Opc =
N.getOpcode();
2539 if (CurDAG->isBaseWithConstantOffset(
N)) {
2542 if (!foldOffsetIntoAddress(
Offset, AM))
2543 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2547 if (
Opc ==
ISD::ADD &&
N.getOperand(0) ==
N.getOperand(1)) {
2548 if (AM.Scale <= 4) {
2550 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2555 if (
Opc == X86ISD::VSHLI) {
2556 uint64_t ShiftAmt =
N.getConstantOperandVal(1);
2557 uint64_t ScaleAmt = 1ULL << ShiftAmt;
2558 if ((AM.Scale * ScaleAmt) <= 8) {
2559 AM.Scale *= ScaleAmt;
2560 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2568 if (Src.getOpcode() ==
ISD::ADD && Src->getFlags().hasNoSignedWrap() &&
2570 if (CurDAG->isBaseWithConstantOffset(Src)) {
2571 SDValue AddSrc = Src.getOperand(0);
2573 int64_t
Offset = AddVal->getSExtValue();
2582 CurDAG->ReplaceAllUsesWith(
N, ExtAdd);
2583 CurDAG->RemoveDeadNode(
N.getNode());
2595 unsigned SrcOpc = Src.getOpcode();
2596 if (((SrcOpc ==
ISD::ADD && Src->getFlags().hasNoUnsignedWrap()) ||
2597 CurDAG->isADDLike(Src,
true)) &&
2599 if (CurDAG->isBaseWithConstantOffset(Src)) {
2600 SDValue AddSrc = Src.getOperand(0);
2602 if (!foldOffsetIntoAddress(
Offset * AM.Scale, AM)) {
2613 if ((AM.Scale * ScaleAmt) <= 8 &&
2615 CurDAG->MaskedValueIsZero(ShVal, HiBits))) {
2616 AM.Scale *= ScaleAmt;
2617 SDValue ExtShVal = CurDAG->getNode(
Opc,
DL, VT, ShVal);
2628 SDValue ExtAdd = CurDAG->getNode(SrcOpc,
DL, VT, ExtSrc, ExtVal);
2632 CurDAG->ReplaceAllUsesWith(
N, ExtAdd);
2633 CurDAG->RemoveDeadNode(
N.getNode());
2634 return Res ? Res : ExtSrc;
2644bool X86DAGToDAGISel::matchAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
2647 dbgs() <<
"MatchAddress: ";
2652 return matchAddressBase(
N, AM);
2657 if (AM.isRIPRelative()) {
2661 if (!(AM.ES || AM.MCSym) && AM.JT != -1)
2665 if (!foldOffsetIntoAddress(Cst->getSExtValue(), AM))
2670 switch (
N.getOpcode()) {
2673 if (!AM.hasSymbolicDisplacement() && AM.Disp == 0)
2676 AM.MCSym = ESNode->getMCSymbol();
2683 if (!foldOffsetIntoAddress(Val, AM))
2688 case X86ISD::Wrapper:
2689 case X86ISD::WrapperRIP:
2690 if (!matchWrapper(
N, AM))
2700 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2701 AM.Base_Reg.
getNode() ==
nullptr &&
2703 AM.BaseType = X86ISelAddressMode::FrameIndexBase;
2710 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
2714 unsigned Val = CN->getZExtValue();
2719 if (Val == 1 || Val == 2 || Val == 3) {
2721 AM.Scale = 1 << Val;
2722 AM.IndexReg = matchIndexRecursively(ShVal, AM,
Depth + 1);
2730 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
break;
2734 assert(
N.getSimpleValueType().getSizeInBits() <= 64 &&
2735 "Unexpected value size!");
2747 uint64_t Mask =
And.getConstantOperandVal(1) >>
N.getConstantOperandVal(1);
2759 if (
N.getResNo() != 0)
break;
2762 case X86ISD::MUL_IMM:
2764 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2765 AM.Base_Reg.
getNode() ==
nullptr &&
2766 AM.IndexReg.
getNode() ==
nullptr) {
2768 if (CN->getZExtValue() == 3 || CN->getZExtValue() == 5 ||
2769 CN->getZExtValue() == 9) {
2770 AM.Scale = unsigned(CN->getZExtValue())-1;
2782 uint64_t Disp = AddVal->getSExtValue() * CN->getZExtValue();
2783 if (foldOffsetIntoAddress(Disp, AM))
2784 Reg =
N.getOperand(0);
2786 Reg =
N.getOperand(0);
2789 AM.IndexReg = AM.Base_Reg =
Reg;
2807 HandleSDNode Handle(
N);
2810 X86ISelAddressMode Backup = AM;
2811 if (matchAddressRecursively(
N.getOperand(0), AM,
Depth+1)) {
2812 N = Handle.getValue();
2816 N = Handle.getValue();
2818 if (AM.IndexReg.
getNode() || AM.isRIPRelative()) {
2837 std::optional<unsigned> NegScale;
2840 uint64_t ShVal = ShAmt->getZExtValue();
2841 if (ShVal >= 1 && ShVal <= 3) {
2842 NegScale = 1u << ShVal;
2860 RHS.getOperand(0).getValueType() == MVT::i32))
2863 bool BaseIsNegatedValue = NegScale &&
2864 AM.BaseType == X86ISelAddressMode::RegBase &&
2871 if (((AM.BaseType == X86ISelAddressMode::RegBase && AM.Base_Reg.
getNode() &&
2873 AM.BaseType == X86ISelAddressMode::FrameIndexBase) &&
2874 !BaseIsNegatedValue)
2878 if ((AM.hasSymbolicDisplacement() && !Backup.hasSymbolicDisplacement()) +
2879 ((AM.Disp != 0) && (Backup.Disp == 0)) +
2892 AM.NegateIndex =
true;
2893 AM.Scale = NegScale.value_or(1);
2900 if (!CurDAG->isADDLike(
N))
2904 if (!matchAdd(
N, AM,
Depth))
2913 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
break;
2917 assert(
N.getSimpleValueType().getSizeInBits() <= 64 &&
2918 "Unexpected value size!");
2923 if (
N.getOperand(0).getOpcode() ==
ISD::SRL) {
2952 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
2960 if (
SDValue Index = matchIndexRecursively(
N, AM,
Depth + 1))
2962 AM.IndexReg =
Index;
2968 if (Src.getOpcode() ==
ISD::AND && Src.hasOneUse())
2970 Mask = MaskC->getAPIntValue();
2971 Src = Src.getOperand(0);
2974 if (Src.getOpcode() ==
ISD::SHL && Src.hasOneUse() &&
N->hasOneUse()) {
2976 SDValue ShlSrc = Src.getOperand(0);
2977 SDValue ShlAmt = Src.getOperand(1);
2981 unsigned ShAmtV = ShAmtC->getZExtValue();
2989 if (!Src->getFlags().hasNoUnsignedWrap() &&
2990 !CurDAG->MaskedValueIsZero(ShlSrc, HighZeros & Mask))
2998 MVT VT =
N.getSimpleValueType();
3002 if (!
Mask.isAllOnes()) {
3003 Res = CurDAG->getConstant(
Mask.lshr(ShAmtV),
DL, SrcVT);
3005 Res = CurDAG->getNode(
ISD::AND,
DL, SrcVT, ShlSrc, Res);
3012 CurDAG->ReplaceAllUsesWith(
N, NewShl);
3013 CurDAG->RemoveDeadNode(
N.getNode());
3016 AM.Scale = 1 << ShAmtV;
3020 AM.IndexReg = matchIndexRecursively(Zext, AM,
Depth + 1);
3024 if (Src.getOpcode() ==
ISD::SRL && !
Mask.isAllOnes()) {
3027 Src.getOperand(0), AM))
3032 Src.getOperand(0), AM))
3037 Src.getOperand(0), AM, *Subtarget))
3045 return matchAddressBase(
N, AM);
3050bool X86DAGToDAGISel::matchAddressBase(
SDValue N, X86ISelAddressMode &AM) {
3052 if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base_Reg.
getNode()) {
3065 AM.BaseType = X86ISelAddressMode::RegBase;
3070bool X86DAGToDAGISel::matchVectorAddressRecursively(
SDValue N,
3071 X86ISelAddressMode &AM,
3074 dbgs() <<
"MatchVectorAddress: ";
3079 return matchAddressBase(
N, AM);
3082 switch (
N.getOpcode()) {
3085 if (!foldOffsetIntoAddress(Val, AM))
3089 case X86ISD::Wrapper:
3090 if (!matchWrapper(
N, AM))
3096 HandleSDNode Handle(
N);
3098 X86ISelAddressMode Backup = AM;
3099 if (!matchVectorAddressRecursively(
N.getOperand(0), AM,
Depth + 1) &&
3100 !matchVectorAddressRecursively(Handle.getValue().getOperand(1), AM,
3106 if (!matchVectorAddressRecursively(Handle.getValue().getOperand(1), AM,
3108 !matchVectorAddressRecursively(Handle.getValue().getOperand(0), AM,
3113 N = Handle.getValue();
3118 return matchAddressBase(
N, AM);
3124bool X86DAGToDAGISel::matchVectorAddress(
SDValue N, X86ISelAddressMode &AM) {
3125 return matchVectorAddressRecursively(
N, AM, 0);
3128bool X86DAGToDAGISel::selectVectorAddr(MemSDNode *Parent,
SDValue BasePtr,
3133 X86ISelAddressMode AM;
3139 AM.IndexReg = matchIndexRecursively(IndexOp, AM, 0);
3141 AM.IndexReg = IndexOp;
3145 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
3147 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
3149 AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16);
3152 MVT VT =
BasePtr.getSimpleValueType();
3155 if (matchVectorAddress(BasePtr, AM))
3158 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3171 SDValue &Segment,
bool HasNDDM) {
3172 X86ISelAddressMode AM;
3179 Parent->
getOpcode() != X86ISD::TLSCALL &&
3180 Parent->
getOpcode() != X86ISD::ENQCMD &&
3181 Parent->
getOpcode() != X86ISD::ENQCMDS &&
3182 Parent->
getOpcode() != X86ISD::EH_SJLJ_SETJMP &&
3183 Parent->
getOpcode() != X86ISD::EH_SJLJ_LONGJMP) {
3184 unsigned AddrSpace =
3187 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
3189 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
3191 AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16);
3196 MVT VT =
N.getSimpleValueType();
3198 if (matchAddress(
N, AM))
3201 if (!HasNDDM && !AM.isRIPRelative())
3204 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3211 return selectAddr(Parent,
N,
Base, Scale, Index, Disp, Segment,
3212 Subtarget->hasNDDM());
3224 if (
N->getOpcode() != X86ISD::Wrapper)
3227 N =
N.getOperand(0);
3244 return CR->getUnsignedMax().ult(1ull << 32);
3246 return !TM.isLargeGlobalValue(GV);
3255 if (!selectLEAAddr(
N,
Base, Scale, Index, Disp, Segment))
3261 SubReg = X86::sub_8bit;
3263 SubReg = X86::sub_16bit;
3265 SubReg = X86::sub_32bit;
3268 if (RN &&
RN->getReg() == 0)
3269 Base = CurDAG->getRegister(0, MVT::i64);
3276 Base = CurDAG->getTargetInsertSubreg(SubReg,
DL, MVT::i64, ImplDef,
Base);
3279 [[maybe_unused]] EVT IndexType =
Index.getValueType();
3281 if (RN &&
RN->getReg() == 0)
3282 Index = CurDAG->getRegister(0, MVT::i64);
3285 "Expect to be extending 8/16/32-bit registers for use in LEA");
3288 Index = CurDAG->getTargetInsertSubreg(SubReg,
DL, MVT::i64, ImplDef, Index);
3296bool X86DAGToDAGISel::selectLEAAddr(
SDValue N,
3300 X86ISelAddressMode AM;
3305 MVT VT =
N.getSimpleValueType();
3310 SDValue T = CurDAG->getRegister(0, MVT::i32);
3312 if (matchAddress(
N, AM))
3317 unsigned Complexity = 0;
3318 if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base_Reg.
getNode())
3320 else if (AM.BaseType == X86ISelAddressMode::FrameIndexBase)
3336 if (AM.hasSymbolicDisplacement()) {
3338 if (Subtarget->is64Bit())
3348 auto isMathWithFlags = [](
SDValue V) {
3349 switch (
V.getOpcode()) {
3363 return !
SDValue(
V.getNode(), 1).use_empty();
3370 if (isMathWithFlags(
N.getOperand(0)) || isMathWithFlags(
N.getOperand(1)))
3378 if (Complexity <= 2)
3381 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3392 X86ISelAddressMode AM;
3394 AM.GV = GA->getGlobal();
3395 AM.Disp += GA->getOffset();
3396 AM.SymbolFlags = GA->getTargetFlags();
3399 AM.ES = SA->getSymbol();
3400 AM.SymbolFlags = SA->getTargetFlags();
3403 if (Subtarget->is32Bit()) {
3405 AM.IndexReg = CurDAG->getRegister(X86::EBX, MVT::i32);
3408 MVT VT =
N.getSimpleValueType();
3409 getAddressOperands(AM, SDLoc(
N), VT,
Base, Scale, Index, Disp, Segment);
3417 EVT VT =
N.getValueType();
3418 bool WasTruncated =
false;
3420 WasTruncated =
true;
3421 N =
N.getOperand(0);
3424 if (
N.getOpcode() != X86ISD::Wrapper)
3430 unsigned Opc =
N.getOperand(0)->getOpcode();
3432 Op =
N.getOperand(0);
3435 return !WasTruncated;
3440 std::optional<ConstantRange> CR = GA->getGlobal()->getAbsoluteSymbolRange();
3441 if (!CR || CR->getUnsignedMax().uge(1ull << VT.
getSizeInBits()))
3445 Op = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(
N), VT,
3446 GA->getOffset(), GA->getTargetFlags());
3450bool X86DAGToDAGISel::tryFoldLoad(SDNode *Root, SDNode *
P,
SDValue N,
3454 assert(Root &&
P &&
"Unknown root/parent nodes");
3456 !IsProfitableToFold(
N,
P, Root) ||
3457 !IsLegalToFold(
N,
P, Root, OptLevel))
3460 return selectAddr(
N.getNode(),
3461 N.getOperand(1),
Base, Scale, Index, Disp, Segment);
3464bool X86DAGToDAGISel::tryFoldBroadcast(SDNode *Root, SDNode *
P,
SDValue N,
3468 assert(Root &&
P &&
"Unknown root/parent nodes");
3469 if (
N->getOpcode() != X86ISD::VBROADCAST_LOAD ||
3470 !IsProfitableToFold(
N,
P, Root) ||
3471 !IsLegalToFold(
N,
P, Root, OptLevel))
3474 return selectAddr(
N.getNode(),
3475 N.getOperand(1),
Base, Scale, Index, Disp, Segment);
3481SDNode *X86DAGToDAGISel::getGlobalBaseReg() {
3484 return CurDAG->getRegister(GlobalBaseReg, TLI->
getPointerTy(
DL)).getNode();
3487bool X86DAGToDAGISel::isSExtAbsoluteSymbolRef(
unsigned Width, SDNode *
N)
const {
3489 N =
N->getOperand(0).getNode();
3490 if (
N->getOpcode() != X86ISD::Wrapper)
3497 auto *GV = GA->getGlobal();
3500 return CR->getSignedMin().sge(-1ull << Width) &&
3501 CR->getSignedMax().slt(1ull << Width);
3507 !TM.isLargeGlobalValue(GV);
3511 assert(
N->isMachineOpcode() &&
"Unexpected node");
3512 unsigned Opc =
N->getMachineOpcode();
3513 const MCInstrDesc &MCID = getInstrInfo()->get(
Opc);
3518 return static_cast<X86::CondCode>(
N->getConstantOperandVal(CondNo));
3523bool X86DAGToDAGISel::onlyUsesZeroFlag(
SDValue Flags)
const {
3525 for (SDUse &Use :
Flags->uses()) {
3527 if (
Use.getResNo() !=
Flags.getResNo())
3535 for (SDUse &FlagUse :
User->uses()) {
3537 if (FlagUse.getResNo() != 1)
3540 if (!FlagUse.getUser()->isMachineOpcode())
3560bool X86DAGToDAGISel::hasNoSignFlagUses(
SDValue Flags)
const {
3562 for (SDUse &Use :
Flags->uses()) {
3564 if (
Use.getResNo() !=
Flags.getResNo())
3572 for (SDUse &FlagUse :
User->uses()) {
3574 if (FlagUse.getResNo() != 1)
3577 if (!FlagUse.getUser()->isMachineOpcode())
3617 bool X86DAGToDAGISel::hasNoCarryFlagUses(
SDValue Flags)
const {
3619 for (SDUse &Use :
Flags->uses()) {
3621 if (
Use.getResNo() !=
Flags.getResNo())
3625 unsigned UserOpc =
User->getOpcode();
3632 for (SDUse &FlagUse :
User->uses()) {
3634 if (FlagUse.getResNo() != 1)
3637 if (!FlagUse.getUser()->isMachineOpcode())
3657 case X86ISD::SETCC: CCOpNo = 0;
break;
3658 case X86ISD::SETCC_CARRY: CCOpNo = 0;
break;
3659 case X86ISD::CMOV: CCOpNo = 2;
break;
3660 case X86ISD::BRCOND: CCOpNo = 2;
break;
3670bool X86DAGToDAGISel::checkTCRetEnoughRegs(SDNode *
N)
const {
3673 const X86RegisterInfo *RI = Subtarget->getRegisterInfo();
3677 if (Subtarget->is64Bit()) {
3680 ? &X86::GR64_TCW64RegClass
3681 : &X86::GR64_TCRegClass;
3689 ? &X86::GR32RegClass
3690 : &X86::GR32_TCRegClass;
3697 unsigned LoadGPRs = 2;
3699 assert(
N->getOpcode() == X86ISD::TC_RETURN);
3702 if (Subtarget->is32Bit()) {
3708 }
else if (
BasePtr.getOpcode() == X86ISD::Wrapper &&
3710 if (getTargetMachine().isPositionIndependent())
3718 for (
unsigned I = 3,
E =
N->getNumOperands();
I !=
E; ++
I) {
3720 if (!RI->isGeneralPurposeRegister(*MF,
RN->getReg()))
3722 if (++
ArgGPRs + LoadGPRs > AvailGPRs)
3738 if (StoredVal.
getResNo() != 0)
return false;
3755 if (!
Load.hasOneUse())
3763 bool FoundLoad =
false;
3767 const unsigned int Max = 1024;
3809 if (Chain ==
Load.getValue(1)) {
3815 if (
Op ==
Load.getValue(1)) {
3831 if (
Op.getNode() != LoadNode)
3863bool X86DAGToDAGISel::foldLoadStoreIntoMemOperand(SDNode *Node) {
3865 SDValue StoredVal = StoreNode->getOperand(1);
3871 EVT MemVT = StoreNode->getMemoryVT();
3872 if (MemVT != MVT::i64 && MemVT != MVT::i32 && MemVT != MVT::i16 &&
3876 bool IsCommutable =
false;
3877 bool IsNegate =
false;
3891 IsCommutable =
true;
3895 unsigned LoadOpNo = IsNegate ? 1 : 0;
3896 LoadSDNode *LoadNode =
nullptr;
3899 LoadNode, InputChain)) {
3906 LoadNode, InputChain))
3911 if (!selectAddr(LoadNode, LoadNode->
getBasePtr(),
Base, Scale, Index, Disp,
3915 auto SelectOpcode = [&](
unsigned Opc64,
unsigned Opc32,
unsigned Opc16,
3936 unsigned NewOpc = SelectOpcode(X86::NEG64m, X86::NEG32m, X86::NEG16m,
3939 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32,
3946 if (!Subtarget->slowIncDec() || CurDAG->shouldOptForSize()) {
3950 if ((IsOne || IsNegOne) && hasNoCarryFlagUses(StoredVal.
getValue(1))) {
3952 ((
Opc == X86ISD::ADD) == IsOne)
3953 ? SelectOpcode(X86::INC64m, X86::INC32m, X86::INC16m, X86::INC8m)
3954 : SelectOpcode(X86::DEC64m, X86::DEC32m, X86::DEC16m, X86::DEC8m);
3956 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32,
3967 auto SelectRegOpcode = [SelectOpcode](
unsigned Opc) {
3970 return SelectOpcode(X86::ADD64mr, X86::ADD32mr, X86::ADD16mr,
3973 return SelectOpcode(X86::ADC64mr, X86::ADC32mr, X86::ADC16mr,
3976 return SelectOpcode(X86::SUB64mr, X86::SUB32mr, X86::SUB16mr,
3979 return SelectOpcode(X86::SBB64mr, X86::SBB32mr, X86::SBB16mr,
3982 return SelectOpcode(X86::AND64mr, X86::AND32mr, X86::AND16mr,
3985 return SelectOpcode(X86::OR64mr, X86::OR32mr, X86::OR16mr, X86::OR8mr);
3987 return SelectOpcode(X86::XOR64mr, X86::XOR32mr, X86::XOR16mr,
3993 auto SelectImmOpcode = [SelectOpcode](
unsigned Opc) {
3996 return SelectOpcode(X86::ADD64mi32, X86::ADD32mi, X86::ADD16mi,
3999 return SelectOpcode(X86::ADC64mi32, X86::ADC32mi, X86::ADC16mi,
4002 return SelectOpcode(X86::SUB64mi32, X86::SUB32mi, X86::SUB16mi,
4005 return SelectOpcode(X86::SBB64mi32, X86::SBB32mi, X86::SBB16mi,
4008 return SelectOpcode(X86::AND64mi32, X86::AND32mi, X86::AND16mi,
4011 return SelectOpcode(X86::OR64mi32, X86::OR32mi, X86::OR16mi,
4014 return SelectOpcode(X86::XOR64mi32, X86::XOR32mi, X86::XOR16mi,
4021 unsigned NewOpc = SelectRegOpcode(
Opc);
4027 int64_t OperandV = OperandC->getSExtValue();
4032 if ((
Opc == X86ISD::ADD ||
Opc == X86ISD::SUB) &&
4034 (MemVT == MVT::i64 && !
isInt<32>(OperandV) &&
4036 hasNoCarryFlagUses(StoredVal.
getValue(1))) {
4037 OperandV = -OperandV;
4038 Opc =
Opc == X86ISD::ADD ? X86ISD::SUB : X86ISD::ADD;
4041 if (MemVT != MVT::i64 ||
isInt<32>(OperandV)) {
4042 Operand = CurDAG->getSignedTargetConstant(OperandV, SDLoc(Node), MemVT);
4043 NewOpc = SelectImmOpcode(
Opc);
4047 if (
Opc == X86ISD::ADC ||
Opc == X86ISD::SBB) {
4049 CurDAG->getCopyToReg(InputChain, SDLoc(Node), X86::EFLAGS,
4053 Segment, Operand, CopyTo, CopyTo.
getValue(1)};
4054 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other,
4058 Segment, Operand, InputChain};
4059 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other,
4068 MachineMemOperand *MemOps[] = {StoreNode->getMemOperand(),
4070 CurDAG->setNodeMemRefs(Result, MemOps);
4076 CurDAG->RemoveDeadNode(Node);
4087bool X86DAGToDAGISel::matchBitExtract(SDNode *Node) {
4091 "Should be either an and-mask, or right-shift after clearing high bits.");
4094 if (!Subtarget->hasBMI() && !Subtarget->hasBMI2())
4097 MVT NVT =
Node->getSimpleValueType(0);
4100 if (NVT != MVT::i32 && NVT != MVT::i64)
4108 const bool AllowExtraUsesByDefault = Subtarget->hasBMI2();
4109 auto checkUses = [AllowExtraUsesByDefault](
4111 std::optional<bool> AllowExtraUses) {
4112 return AllowExtraUses.value_or(AllowExtraUsesByDefault) ||
4113 Op.getNode()->hasNUsesOfValue(NUses,
Op.getResNo());
4115 auto checkOneUse = [checkUses](
SDValue Op,
4116 std::optional<bool> AllowExtraUses =
4118 return checkUses(
Op, 1, AllowExtraUses);
4120 auto checkTwoUse = [checkUses](
SDValue Op,
4121 std::optional<bool> AllowExtraUses =
4123 return checkUses(
Op, 2, AllowExtraUses);
4126 auto peekThroughOneUseTruncation = [checkOneUse](
SDValue V) {
4128 assert(
V.getSimpleValueType() == MVT::i32 &&
4129 V.getOperand(0).getSimpleValueType() == MVT::i64 &&
4130 "Expected i64 -> i32 truncation");
4131 V =
V.getOperand(0);
4137 auto matchPatternA = [checkOneUse, peekThroughOneUseTruncation, &NBits,
4140 if (
Mask->getOpcode() !=
ISD::ADD || !checkOneUse(Mask))
4146 SDValue M0 = peekThroughOneUseTruncation(
Mask->getOperand(0));
4151 NBits =
M0->getOperand(1);
4152 NegateNBits =
false;
4156 auto isAllOnes = [
this, peekThroughOneUseTruncation, NVT](
SDValue V) {
4157 V = peekThroughOneUseTruncation(V);
4158 return CurDAG->MaskedValueIsAllOnes(
4164 auto matchPatternB = [checkOneUse, isAllOnes, peekThroughOneUseTruncation,
4167 if (
Mask.getOpcode() !=
ISD::XOR || !checkOneUse(Mask))
4170 if (!isAllOnes(
Mask->getOperand(1)))
4173 SDValue M0 = peekThroughOneUseTruncation(
Mask->getOperand(0));
4177 if (!isAllOnes(
M0->getOperand(0)))
4179 NBits =
M0->getOperand(1);
4180 NegateNBits =
false;
4186 auto canonicalizeShiftAmt = [&NBits, &NegateNBits](
SDValue ShiftAmt,
4187 unsigned Bitwidth) {
4192 NBits = NBits.getOperand(0);
4198 if (!V0 || V0->getZExtValue() != Bitwidth)
4200 NBits = NBits.getOperand(1);
4201 NegateNBits =
false;
4207 auto matchPatternC = [checkOneUse, peekThroughOneUseTruncation, &NegateNBits,
4210 Mask = peekThroughOneUseTruncation(Mask);
4211 unsigned Bitwidth =
Mask.getSimpleValueType().getSizeInBits();
4213 if (
Mask.getOpcode() !=
ISD::SRL || !checkOneUse(Mask))
4220 if (!checkOneUse(
M1))
4222 canonicalizeShiftAmt(
M1, Bitwidth);
4227 return !NegateNBits;
4235 auto matchPatternD = [checkOneUse, checkTwoUse, canonicalizeShiftAmt,
4236 AllowExtraUsesByDefault, &NegateNBits,
4237 &
X](SDNode *
Node) ->
bool {
4249 canonicalizeShiftAmt(N1, Bitwidth);
4253 const bool AllowExtraUses = AllowExtraUsesByDefault && !NegateNBits;
4254 if (!checkOneUse(N0, AllowExtraUses) || !checkTwoUse(N1, AllowExtraUses))
4260 auto matchLowBitMask = [matchPatternA, matchPatternB,
4262 return matchPatternA(Mask) || matchPatternB(Mask) || matchPatternC(Mask);
4266 X =
Node->getOperand(0);
4269 if (matchLowBitMask(Mask)) {
4273 if (!matchLowBitMask(Mask))
4276 }
else if (matchLowBitMask(
SDValue(Node, 0))) {
4277 X = CurDAG->getAllOnesConstant(SDLoc(Node), NVT);
4278 }
else if (!matchPatternD(Node))
4283 if (NegateNBits && !Subtarget->hasBMI2())
4288 if (NBits.getSimpleValueType() != MVT::i8) {
4295 ConstantSDNode *
Imm =
nullptr;
4296 if (NBits->getOpcode() ==
ISD::AND)
4298 NBits = NBits->getOperand(0);
4303 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, MVT::i32), 0);
4306 SDValue SRIdxVal = CurDAG->getTargetConstant(X86::sub_8bit,
DL, MVT::i32);
4308 NBits =
SDValue(CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG,
DL,
4309 MVT::i32, ImplDef, NBits, SRIdxVal),
4315 CurDAG->getNode(
ISD::AND,
DL, MVT::i32, NBits,
4316 CurDAG->getConstant(
Imm->getZExtValue(),
DL, MVT::i32));
4326 NBits = CurDAG->getNode(
ISD::SUB,
DL, MVT::i32, BitWidthC, NBits);
4330 if (Subtarget->hasBMI2()) {
4332 if (NVT != MVT::i32) {
4338 SDValue Extract = CurDAG->getNode(X86ISD::BZHI,
DL, NVT,
X, NBits);
4339 ReplaceNode(Node, Extract.
getNode());
4340 SelectCode(Extract.
getNode());
4349 SDValue RealX = peekThroughOneUseTruncation(
X);
4355 MVT XVT =
X.getSimpleValueType();
4365 SDValue C8 = CurDAG->getConstant(8,
DL, MVT::i8);
4373 SDValue ShiftAmt =
X.getOperand(1);
4374 X =
X.getOperand(0);
4377 "Expected shift amount to be i8");
4381 SDValue OrigShiftAmt = ShiftAmt;
4386 Control = CurDAG->getNode(
ISD::OR,
DL, MVT::i32, Control, ShiftAmt);
4391 if (XVT != MVT::i32) {
4397 SDValue Extract = CurDAG->getNode(X86ISD::BEXTR,
DL, XVT,
X, Control);
4405 ReplaceNode(Node, Extract.
getNode());
4406 SelectCode(Extract.
getNode());
4412MachineSDNode *X86DAGToDAGISel::matchBEXTRFromAndImm(SDNode *Node) {
4413 MVT NVT =
Node->getSimpleValueType(0);
4426 Subtarget->hasTBM() || (Subtarget->hasBMI() && Subtarget->hasFastBEXTR());
4427 if (!PreferBEXTR && !Subtarget->hasBMI2())
4439 if (NVT != MVT::i32 && NVT != MVT::i64)
4445 if (!MaskCst || !ShiftCst)
4453 uint64_t Shift = ShiftCst->getZExtValue();
4458 if (Shift == 8 && MaskSize == 8)
4469 if (!PreferBEXTR && MaskSize <= 32)
4473 unsigned ROpc, MOpc;
4475#define GET_EGPR_IF_ENABLED(OPC) (Subtarget->hasEGPR() ? OPC##_EVEX : OPC)
4477 assert(Subtarget->hasBMI2() &&
"We must have BMI2's BZHI then.");
4481 Control = CurDAG->getTargetConstant(Shift + MaskSize, dl, NVT);
4486 unsigned NewOpc = NVT == MVT::i64 ? X86::MOV32ri64 : X86::MOV32ri;
4487 Control =
SDValue(CurDAG->getMachineNode(NewOpc, dl, NVT, Control), 0);
4493 Control = CurDAG->getTargetConstant(Shift | (MaskSize << 8), dl, NVT);
4494 if (Subtarget->hasTBM()) {
4495 ROpc = NVT == MVT::i64 ? X86::BEXTRI64ri : X86::BEXTRI32ri;
4496 MOpc = NVT == MVT::i64 ? X86::BEXTRI64mi : X86::BEXTRI32mi;
4498 assert(Subtarget->hasBMI() &&
"We must have BMI1's BEXTR then.");
4504 unsigned NewOpc = NVT == MVT::i64 ? X86::MOV32ri64 : X86::MOV32ri;
4505 Control =
SDValue(CurDAG->getMachineNode(NewOpc, dl, NVT, Control), 0);
4509 MachineSDNode *NewNode;
4511 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4512 if (tryFoldLoad(Node, N0.
getNode(), Input, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4514 Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Control, Input.
getOperand(0)};
4515 SDVTList VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
4516 NewNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4520 CurDAG->setNodeMemRefs(NewNode, {
cast<LoadSDNode>(Input)->getMemOperand()});
4522 NewNode = CurDAG->getMachineNode(ROpc, dl, NVT, MVT::i32, Input, Control);
4527 SDValue ShAmt = CurDAG->getTargetConstant(Shift, dl, NVT);
4531 CurDAG->getMachineNode(NewOpc, dl, NVT,
SDValue(NewNode, 0), ShAmt);
4538MachineSDNode *X86DAGToDAGISel::emitPCMPISTR(
unsigned ROpc,
unsigned MOpc,
4539 bool MayFoldLoad,
const SDLoc &dl,
4540 MVT VT, SDNode *Node) {
4545 Imm = CurDAG->getTargetConstant(*Val, SDLoc(Node),
Imm.getValueType());
4548 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4549 if (MayFoldLoad && tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4552 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Other);
4553 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4562 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32);
4563 MachineSDNode *CNode = CurDAG->getMachineNode(ROpc, dl, VTs,
Ops);
4570MachineSDNode *X86DAGToDAGISel::emitPCMPESTR(
unsigned ROpc,
unsigned MOpc,
4571 bool MayFoldLoad,
const SDLoc &dl,
4572 MVT VT, SDNode *Node,
4578 Imm = CurDAG->getTargetConstant(*Val, SDLoc(Node),
Imm.getValueType());
4581 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4582 if (MayFoldLoad && tryFoldLoad(Node, N2, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4585 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Other, MVT::Glue);
4586 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4596 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Glue);
4597 MachineSDNode *CNode = CurDAG->getMachineNode(ROpc, dl, VTs,
Ops);
4602bool X86DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
4603 EVT VT =
N->getValueType(0);
4610 unsigned Size = VT == MVT::i64 ? 64 : 32;
4613 SDValue ShiftAmt = OrigShiftAmt;
4632 if (Add1C && Add1C->getAPIntValue().urem(
Size) == 0) {
4636 ((Add0C && Add0C->getAPIntValue().urem(
Size) ==
Size - 1) ||
4637 (Add1C && Add1C->getAPIntValue().urem(
Size) ==
Size - 1))) {
4641 assert(Add0C ==
nullptr || Add1C ==
nullptr);
4650 NewShiftAmt = CurDAG->getNode(
ISD::XOR,
DL, OpVT,
4651 Add0C ==
nullptr ? Add0 : Add1,
AllOnes);
4657 Add0C->getZExtValue() != 0) {
4660 if (Add0C->getZExtValue() %
Size == 0)
4663 Add0C->getZExtValue() % 32 == 0) {
4671 Add0 = CurDAG->getZExtOrTrunc(Add0,
DL, SubVT);
4675 X = CurDAG->getNode(
ISD::ADD,
DL, SubVT, Add1, Add0);
4697 NewShiftAmt = CurDAG->getNode(
ISD::TRUNCATE,
DL, MVT::i8, NewShiftAmt);
4704 NewShiftAmt = CurDAG->getNode(
ISD::AND,
DL, MVT::i8, NewShiftAmt,
4705 CurDAG->getConstant(
Size - 1,
DL, MVT::i8));
4709 SDNode *UpdatedNode = CurDAG->UpdateNodeOperands(
N,
N->getOperand(0),
4711 if (UpdatedNode !=
N) {
4714 ReplaceNode(
N, UpdatedNode);
4721 CurDAG->RemoveDeadNode(OrigShiftAmt.
getNode());
4729bool X86DAGToDAGISel::tryShrinkShlLogicImm(SDNode *
N) {
4730 MVT NVT =
N->getSimpleValueType(0);
4731 unsigned Opcode =
N->getOpcode();
4743 int64_t Val = Cst->getSExtValue();
4748 bool FoundAnyExtend =
false;
4752 FoundAnyExtend =
true;
4760 if (NVT != MVT::i32 && NVT != MVT::i64)
4767 uint64_t ShAmt = ShlCst->getZExtValue();
4771 uint64_t RemovedBitsMask = (1ULL << ShAmt) - 1;
4772 if (Opcode !=
ISD::AND && (Val & RemovedBitsMask) != 0)
4777 auto CanShrinkImmediate = [&](int64_t &ShiftedVal) {
4781 ShiftedVal = (
uint64_t)Val >> ShAmt;
4785 if (ShiftedVal == UINT8_MAX || ShiftedVal == UINT16_MAX)
4788 ShiftedVal = Val >> ShAmt;
4794 ShiftedVal = (
uint64_t)Val >> ShAmt;
4802 if (!CanShrinkImmediate(ShiftedVal))
4812 unsigned ZExtWidth = Cst->getAPIntValue().getActiveBits();
4818 NeededMask &= ~Cst->getAPIntValue();
4820 if (CurDAG->MaskedValueIsZero(
N->getOperand(0), NeededMask))
4825 if (FoundAnyExtend) {
4831 SDValue NewCst = CurDAG->getSignedConstant(ShiftedVal, dl, NVT);
4833 SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT,
X, NewCst);
4842bool X86DAGToDAGISel::matchVPTERNLOG(SDNode *Root, SDNode *ParentA,
4843 SDNode *ParentB, SDNode *ParentC,
4846 assert(
A.isOperandOf(ParentA) &&
B.isOperandOf(ParentB) &&
4847 C.isOperandOf(ParentC) &&
"Incorrect parent node");
4849 auto tryFoldLoadOrBCast =
4852 if (tryFoldLoad(Root,
P, L,
Base, Scale, Index, Disp, Segment))
4858 L =
L.getOperand(0);
4861 if (
L.getOpcode() != X86ISD::VBROADCAST_LOAD)
4866 unsigned Size = MemIntr->getMemoryVT().getSizeInBits();
4870 return tryFoldBroadcast(Root,
P, L,
Base, Scale, Index, Disp, Segment);
4873 bool FoldedLoad =
false;
4874 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4875 if (tryFoldLoadOrBCast(Root, ParentC,
C, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4877 }
else if (tryFoldLoadOrBCast(Root, ParentA,
A, Tmp0, Tmp1, Tmp2, Tmp3,
4882 uint8_t OldImm =
Imm;
4883 Imm = OldImm & 0xa5;
4884 if (OldImm & 0x02)
Imm |= 0x10;
4885 if (OldImm & 0x10)
Imm |= 0x02;
4886 if (OldImm & 0x08)
Imm |= 0x40;
4887 if (OldImm & 0x40)
Imm |= 0x08;
4888 }
else if (tryFoldLoadOrBCast(Root, ParentB,
B, Tmp0, Tmp1, Tmp2, Tmp3,
4893 uint8_t OldImm =
Imm;
4894 Imm = OldImm & 0x99;
4895 if (OldImm & 0x02)
Imm |= 0x04;
4896 if (OldImm & 0x04)
Imm |= 0x02;
4897 if (OldImm & 0x20)
Imm |= 0x40;
4898 if (OldImm & 0x40)
Imm |= 0x20;
4903 SDValue TImm = CurDAG->getTargetConstant(
Imm,
DL, MVT::i8);
4907 MachineSDNode *MNode;
4909 SDVTList VTs = CurDAG->getVTList(NVT, MVT::Other);
4912 if (
C.getOpcode() == X86ISD::VBROADCAST_LOAD) {
4914 unsigned EltSize = MemIntr->getMemoryVT().getSizeInBits();
4915 assert((EltSize == 32 || EltSize == 64) &&
"Unexpected broadcast size!");
4917 bool UseD = EltSize == 32;
4919 Opc = UseD ? X86::VPTERNLOGDZ128rmbi : X86::VPTERNLOGQZ128rmbi;
4921 Opc = UseD ? X86::VPTERNLOGDZ256rmbi : X86::VPTERNLOGQZ256rmbi;
4923 Opc = UseD ? X86::VPTERNLOGDZrmbi : X86::VPTERNLOGQZrmbi;
4929 Opc = UseD ? X86::VPTERNLOGDZ128rmi : X86::VPTERNLOGQZ128rmi;
4931 Opc = UseD ? X86::VPTERNLOGDZ256rmi : X86::VPTERNLOGQZ256rmi;
4933 Opc = UseD ? X86::VPTERNLOGDZrmi : X86::VPTERNLOGQZrmi;
4939 MNode = CurDAG->getMachineNode(
Opc,
DL, VTs,
Ops);
4942 ReplaceUses(
C.getValue(1),
SDValue(MNode, 1));
4949 Opc = UseD ? X86::VPTERNLOGDZ128rri : X86::VPTERNLOGQZ128rri;
4951 Opc = UseD ? X86::VPTERNLOGDZ256rri : X86::VPTERNLOGQZ256rri;
4953 Opc = UseD ? X86::VPTERNLOGDZrri : X86::VPTERNLOGQZrri;
4957 MNode = CurDAG->getMachineNode(
Opc,
DL, NVT, {
A,
B,
C, TImm});
4961 CurDAG->RemoveDeadNode(Root);
4967bool X86DAGToDAGISel::tryVPTERNLOG(SDNode *
N) {
4968 MVT NVT =
N->getSimpleValueType(0);
4971 if (!NVT.
isVector() || !Subtarget->hasAVX512() ||
4979 auto getFoldableLogicOp = [](
SDValue Op) {
4982 Op =
Op.getOperand(0);
4984 if (!
Op.hasOneUse())
4987 unsigned Opc =
Op.getOpcode();
4989 Opc == X86ISD::ANDNP)
4998 auto tryPeelOuterNotWrappingLogic = [&](SDNode *
Op) {
5001 SDValue InnerOp = getFoldableLogicOp(
Op->getOperand(0));
5008 if ((FoldableOp = getFoldableLogicOp(N1))) {
5012 if ((FoldableOp = getFoldableLogicOp(N0))) {
5020 bool PeeledOuterNot =
false;
5022 if (
SDValue InnerOp = tryPeelOuterNotWrappingLogic(
N)) {
5023 PeeledOuterNot =
true;
5029 if ((FoldableOp = getFoldableLogicOp(N1)))
5031 else if ((FoldableOp = getFoldableLogicOp(N0)))
5039 SDNode *ParentA =
N;
5040 SDNode *ParentB = FoldableOp.
getNode();
5041 SDNode *ParentC = FoldableOp.
getNode();
5045 uint8_t TernlogMagicA = 0xf0;
5046 uint8_t TernlogMagicB = 0xcc;
5047 uint8_t TernlogMagicC = 0xaa;
5052 auto PeekThroughNot = [](
SDValue &
Op, SDNode *&Parent, uint8_t &
Magic) {
5056 Parent =
Op.getNode();
5057 Op =
Op.getOperand(0);
5061 PeekThroughNot(
A, ParentA, TernlogMagicA);
5062 PeekThroughNot(
B, ParentB, TernlogMagicB);
5063 PeekThroughNot(
C, ParentC, TernlogMagicC);
5068 case ISD::AND:
Imm = TernlogMagicB & TernlogMagicC;
break;
5069 case ISD::OR:
Imm = TernlogMagicB | TernlogMagicC;
break;
5070 case ISD::XOR:
Imm = TernlogMagicB ^ TernlogMagicC;
break;
5071 case X86ISD::ANDNP:
Imm = ~(TernlogMagicB) & TernlogMagicC;
break;
5074 switch (
N->getOpcode()) {
5078 Imm &= ~TernlogMagicA;
5080 Imm = ~(
Imm) & TernlogMagicA;
5090 return matchVPTERNLOG(OriN, ParentA, ParentB, ParentC,
A,
B,
C,
Imm);
5100bool X86DAGToDAGISel::shrinkAndImmediate(SDNode *
And) {
5103 MVT VT =
And->getSimpleValueType(0);
5104 if (VT != MVT::i32 && VT != MVT::i64)
5116 APInt MaskVal = And1C->getAPIntValue();
5118 if (!MaskLZ || (VT == MVT::i64 && MaskLZ == 32))
5122 if (VT == MVT::i64 && MaskLZ >= 32) {
5124 MaskVal = MaskVal.
trunc(32);
5129 APInt NegMaskVal = MaskVal | HighZeros;
5138 if (VT == MVT::i64 && MaskVal.
getBitWidth() < 64) {
5139 NegMaskVal = NegMaskVal.
zext(64);
5140 HighZeros = HighZeros.
zext(64);
5146 KnownBits Known0 = CurDAG->computeKnownBits(And0);
5158 SDValue NewMask = CurDAG->getConstant(NegMaskVal, SDLoc(
And), VT);
5167 bool FoldedBCast,
bool Masked) {
5168#define VPTESTM_CASE(VT, SUFFIX) \
5171 return IsTestN ? X86::VPTESTNM##SUFFIX##k: X86::VPTESTM##SUFFIX##k; \
5172 return IsTestN ? X86::VPTESTNM##SUFFIX : X86::VPTESTM##SUFFIX;
5175#define VPTESTM_BROADCAST_CASES(SUFFIX) \
5176default: llvm_unreachable("Unexpected VT!"); \
5177VPTESTM_CASE(v4i32, DZ128##SUFFIX) \
5178VPTESTM_CASE(v2i64, QZ128##SUFFIX) \
5179VPTESTM_CASE(v8i32, DZ256##SUFFIX) \
5180VPTESTM_CASE(v4i64, QZ256##SUFFIX) \
5181VPTESTM_CASE(v16i32, DZ##SUFFIX) \
5182VPTESTM_CASE(v8i64, QZ##SUFFIX)
5184#define VPTESTM_FULL_CASES(SUFFIX) \
5185VPTESTM_BROADCAST_CASES(SUFFIX) \
5186VPTESTM_CASE(v16i8, BZ128##SUFFIX) \
5187VPTESTM_CASE(v8i16, WZ128##SUFFIX) \
5188VPTESTM_CASE(v32i8, BZ256##SUFFIX) \
5189VPTESTM_CASE(v16i16, WZ256##SUFFIX) \
5190VPTESTM_CASE(v64i8, BZ##SUFFIX) \
5191VPTESTM_CASE(v32i16, WZ##SUFFIX)
5209#undef VPTESTM_FULL_CASES
5210#undef VPTESTM_BROADCAST_CASES
5220 if (
Reg.isVirtual())
5225 if (GetPhysReg(N1) == LoReg && GetPhysReg(N0) != LoReg)
5231bool X86DAGToDAGISel::tryVPTESTM(SDNode *Root,
SDValue Setcc,
5233 assert(Subtarget->hasAVX512() &&
"Expected AVX512!");
5278 auto tryFoldLoadOrBCast = [&](SDNode *Root, SDNode *
P,
SDValue &
L,
5283 if (tryFoldLoad(Root,
P, L,
Base, Scale, Index, Disp, Segment))
5288 if (CmpSVT != MVT::i32 && CmpSVT != MVT::i64)
5294 L =
L.getOperand(0);
5297 if (
L.getOpcode() != X86ISD::VBROADCAST_LOAD)
5301 if (MemIntr->getMemoryVT().getSizeInBits() != CmpSVT.
getSizeInBits())
5304 return tryFoldBroadcast(Root,
P, L,
Base, Scale, Index, Disp, Segment);
5308 bool CanFoldLoads = Src0 != Src1;
5310 bool FoldedLoad =
false;
5311 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5313 FoldedLoad = tryFoldLoadOrBCast(Root, N0.
getNode(), Src1, Tmp0, Tmp1, Tmp2,
5317 FoldedLoad = tryFoldLoadOrBCast(Root, N0.
getNode(), Src0, Tmp0, Tmp1,
5324 bool FoldedBCast = FoldedLoad && Src1.
getOpcode() == X86ISD::VBROADCAST_LOAD;
5326 bool IsMasked = InMask.
getNode() !=
nullptr;
5335 unsigned SubReg = CmpVT.
is128BitVector() ? X86::sub_xmm : X86::sub_ymm;
5339 SDValue ImplDef =
SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF, dl,
5341 Src0 = CurDAG->getTargetInsertSubreg(SubReg, dl, CmpVT, ImplDef, Src0);
5344 Src1 = CurDAG->getTargetInsertSubreg(SubReg, dl, CmpVT, ImplDef, Src1);
5349 SDValue RC = CurDAG->getTargetConstant(RegClass, dl, MVT::i32);
5350 InMask =
SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
5351 dl, MaskVT, InMask, RC), 0);
5359 MachineSDNode *CNode;
5361 SDVTList VTs = CurDAG->getVTList(MaskVT, MVT::Other);
5364 SDValue Ops[] = { InMask, Src0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
5366 CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5368 SDValue Ops[] = { Src0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
5370 CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5376 CurDAG->setNodeMemRefs(CNode, {
cast<MemSDNode>(Src1)->getMemOperand()});
5379 CNode = CurDAG->getMachineNode(
Opc, dl, MaskVT, InMask, Src0, Src1);
5381 CNode = CurDAG->getMachineNode(
Opc, dl, MaskVT, Src0, Src1);
5387 SDValue RC = CurDAG->getTargetConstant(RegClass, dl, MVT::i32);
5388 CNode = CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
5389 dl, ResVT,
SDValue(CNode, 0), RC);
5393 CurDAG->RemoveDeadNode(Root);
5399bool X86DAGToDAGISel::tryMatchBitSelect(SDNode *
N) {
5402 MVT NVT =
N->getSimpleValueType(0);
5405 if (!NVT.
isVector() || !Subtarget->hasAVX512())
5439 SDValue Imm = CurDAG->getTargetConstant(0xCA, dl, MVT::i8);
5440 SDValue Ternlog = CurDAG->getNode(X86ISD::VPTERNLOG, dl, NVT,
A,
B,
C,
Imm);
5447void X86DAGToDAGISel::Select(SDNode *Node) {
5448 MVT NVT =
Node->getSimpleValueType(0);
5449 unsigned Opcode =
Node->getOpcode();
5452 if (
Node->isMachineOpcode()) {
5454 Node->setNodeId(-1);
5461 unsigned IntNo =
Node->getConstantOperandVal(1);
5464 case Intrinsic::x86_encodekey128:
5465 case Intrinsic::x86_encodekey256: {
5466 if (!Subtarget->hasKL())
5472 case Intrinsic::x86_encodekey128:
5473 Opcode = X86::ENCODEKEY128;
5475 case Intrinsic::x86_encodekey256:
5476 Opcode = X86::ENCODEKEY256;
5481 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM0,
Node->getOperand(3),
5483 if (Opcode == X86::ENCODEKEY256)
5484 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM1,
Node->getOperand(4),
5487 MachineSDNode *Res = CurDAG->getMachineNode(
5488 Opcode, dl,
Node->getVTList(),
5489 {Node->getOperand(2), Chain, Chain.getValue(1)});
5490 ReplaceNode(Node, Res);
5493 case Intrinsic::x86_tileloaddrs64_internal:
5494 case Intrinsic::x86_tileloaddrst164_internal:
5495 if (!Subtarget->hasAMXMOVRS())
5498 case Intrinsic::x86_tileloadd64_internal:
5499 case Intrinsic::x86_tileloaddt164_internal: {
5500 if (!Subtarget->hasAMXTILE())
5503 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5504 MFI->setAMXProgModel(AMXProgModelEnum::ManagedRA);
5509 case Intrinsic::x86_tileloaddrs64_internal:
5510 Opc = X86::PTILELOADDRSV;
5512 case Intrinsic::x86_tileloaddrst164_internal:
5513 Opc = X86::PTILELOADDRST1V;
5515 case Intrinsic::x86_tileloadd64_internal:
5516 Opc = X86::PTILELOADDV;
5518 case Intrinsic::x86_tileloaddt164_internal:
5519 Opc = X86::PTILELOADDT1V;
5524 SDValue Scale = getI8Imm(1, dl);
5526 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5527 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5529 MachineSDNode *CNode;
5531 Node->getOperand(3),
5538 CNode = CurDAG->getMachineNode(
Opc, dl, {MVT::x86amx, MVT::Other},
Ops);
5539 ReplaceNode(Node, CNode);
5546 unsigned IntNo =
Node->getConstantOperandVal(1);
5549 case Intrinsic::x86_sse3_monitor:
5550 case Intrinsic::x86_monitorx:
5551 case Intrinsic::x86_clzero: {
5552 bool Use64BitPtr =
Node->getOperand(2).getValueType() == MVT::i64;
5557 case Intrinsic::x86_sse3_monitor:
5558 if (!Subtarget->hasSSE3())
5560 Opc = Use64BitPtr ? X86::MONITOR64rrr : X86::MONITOR32rrr;
5562 case Intrinsic::x86_monitorx:
5563 if (!Subtarget->hasMWAITX())
5565 Opc = Use64BitPtr ? X86::MONITORX64rrr : X86::MONITORX32rrr;
5567 case Intrinsic::x86_clzero:
5568 if (!Subtarget->hasCLZERO())
5570 Opc = Use64BitPtr ? X86::CLZERO64r : X86::CLZERO32r;
5575 unsigned PtrReg = Use64BitPtr ? X86::RAX : X86::EAX;
5576 SDValue Chain = CurDAG->getCopyToReg(
Node->getOperand(0), dl, PtrReg,
5580 if (IntNo == Intrinsic::x86_sse3_monitor ||
5581 IntNo == Intrinsic::x86_monitorx) {
5583 Chain = CurDAG->getCopyToReg(Chain, dl, X86::ECX,
Node->getOperand(3),
5586 Chain = CurDAG->getCopyToReg(Chain, dl, X86::EDX,
Node->getOperand(4),
5591 MachineSDNode *CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
5593 ReplaceNode(Node, CNode);
5599 case Intrinsic::x86_tilestored64_internal: {
5601 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5602 MFI->setAMXProgModel(AMXProgModelEnum::ManagedRA);
5603 unsigned Opc = X86::PTILESTOREDV;
5606 SDValue Scale = getI8Imm(1, dl);
5608 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5609 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5611 MachineSDNode *CNode;
5613 Node->getOperand(3),
5619 Node->getOperand(6),
5621 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5622 ReplaceNode(Node, CNode);
5625 case Intrinsic::x86_tileloaddrs64:
5626 case Intrinsic::x86_tileloaddrst164:
5627 if (!Subtarget->hasAMXMOVRS())
5630 case Intrinsic::x86_tileloadd64:
5631 case Intrinsic::x86_tileloaddt164:
5632 case Intrinsic::x86_tilestored64: {
5633 if (!Subtarget->hasAMXTILE())
5636 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5637 MFI->setAMXProgModel(AMXProgModelEnum::DirectReg);
5641 case Intrinsic::x86_tileloadd64:
Opc = X86::PTILELOADD;
break;
5642 case Intrinsic::x86_tileloaddrs64:
5643 Opc = X86::PTILELOADDRS;
5645 case Intrinsic::x86_tileloaddt164:
Opc = X86::PTILELOADDT1;
break;
5646 case Intrinsic::x86_tileloaddrst164:
5647 Opc = X86::PTILELOADDRST1;
5649 case Intrinsic::x86_tilestored64:
Opc = X86::PTILESTORED;
break;
5652 unsigned TIndex =
Node->getConstantOperandVal(2);
5655 SDValue Scale = getI8Imm(1, dl);
5657 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5658 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5660 MachineSDNode *CNode;
5661 if (
Opc == X86::PTILESTORED) {
5663 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5666 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5668 ReplaceNode(Node, CNode);
5675 case X86ISD::NT_BRIND: {
5676 if (Subtarget->isTarget64BitILP32()) {
5681 assert(
Target.getValueType() == MVT::i32 &&
"Unexpected VT!");
5682 SDValue ZextTarget = CurDAG->getZExtOrTrunc(Target, dl, MVT::i64);
5683 SDValue Brind = CurDAG->getNode(Opcode, dl, MVT::Other,
5684 Node->getOperand(0), ZextTarget);
5685 ReplaceNode(Node, Brind.
getNode());
5686 SelectCode(ZextTarget.
getNode());
5693 ReplaceNode(Node, getGlobalBaseReg());
5700 ReplaceUses(
SDValue(Node, 0),
Node->getOperand(0));
5701 CurDAG->RemoveDeadNode(Node);
5707 if (matchBitExtract(Node))
5712 if (tryShiftAmountMod(Node))
5716 case X86ISD::VPTERNLOG: {
5717 uint8_t
Imm =
Node->getConstantOperandVal(3);
5718 if (matchVPTERNLOG(Node, Node, Node, Node,
Node->getOperand(0),
5725 if (tryVPTERNLOG(Node))
5735 tryVPTESTM(Node, N0, N1))
5738 tryVPTESTM(Node, N1, N0))
5742 if (MachineSDNode *NewNode = matchBEXTRFromAndImm(Node)) {
5744 CurDAG->RemoveDeadNode(Node);
5747 if (matchBitExtract(Node))
5755 if (tryShrinkShlLogicImm(Node))
5757 if (Opcode ==
ISD::OR && tryMatchBitSelect(Node))
5759 if (tryVPTERNLOG(Node))
5764 if (Opcode ==
ISD::ADD && matchBitExtract(Node))
5774 if (!CurDAG->shouldOptForSize())
5778 if (NVT != MVT::i8 && NVT != MVT::i16 && NVT != MVT::i32 && NVT != MVT::i64)
5788 int64_t Val = Cst->getSExtValue();
5796 if (Opcode ==
ISD::ADD && (Val == 1 || Val == -1))
5800 if (!shouldAvoidImmediateInstFormsForSize(N1.
getNode()))
5804 unsigned ROpc, MOpc;
5913 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5914 if (tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
5916 SDVTList VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
5917 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
5923 CurDAG->RemoveDeadNode(Node);
5928 CurDAG->SelectNodeTo(Node, ROpc, NVT, MVT::i32, N0, N1);
5937 case X86ISD::UMUL: {
5941 unsigned LoReg, ROpc, MOpc;
5946 ROpc = Opcode == X86ISD::SMUL ? X86::IMUL8r : X86::MUL8r;
5947 MOpc = Opcode == X86ISD::SMUL ? X86::IMUL8m : X86::MUL8m;
5966 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5967 bool FoldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
5970 FoldedLoad = tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
5978 orderRegForMul(N0, N1, LoReg, CurDAG->getMachineFunction().getRegInfo());
5980 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg,
5983 MachineSDNode *CNode;
5989 VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
5991 VTs = CurDAG->getVTList(NVT, NVT, MVT::i32, MVT::Other);
5995 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6006 VTs = CurDAG->getVTList(NVT, MVT::i32);
6008 VTs = CurDAG->getVTList(NVT, NVT, MVT::i32);
6010 CNode = CurDAG->getMachineNode(ROpc, dl, VTs, {N1, InGlue});
6014 ReplaceUses(
SDValue(Node, 1),
SDValue(CNode, NVT == MVT::i8 ? 1 : 2));
6015 CurDAG->RemoveDeadNode(Node);
6025 unsigned LoReg, HiReg;
6027 bool UseMULX = !IsSigned && Subtarget->hasBMI2();
6028 bool UseMULXHi = UseMULX &&
SDValue(Node, 0).use_empty();
6032 Opc = UseMULXHi ? X86::MULX32Hrr
6034 : IsSigned ?
X86::IMUL32r
6036 MOpc = UseMULXHi ? X86::MULX32Hrm
6038 : IsSigned ?
X86::IMUL32m
6040 LoReg = UseMULX ? X86::EDX : X86::EAX;
6044 Opc = UseMULXHi ? X86::MULX64Hrr
6046 : IsSigned ?
X86::IMUL64r
6048 MOpc = UseMULXHi ? X86::MULX64Hrm
6050 : IsSigned ?
X86::IMUL64m
6052 LoReg = UseMULX ? X86::RDX : X86::RAX;
6057 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6058 bool foldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6061 foldedLoad = tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6069 orderRegForMul(N0, N1, LoReg, CurDAG->getMachineFunction().getRegInfo());
6071 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg,
6076 MachineSDNode *CNode =
nullptr;
6080 SDVTList VTs = CurDAG->getVTList(NVT, MVT::Other);
6081 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6084 }
else if (UseMULX) {
6085 SDVTList VTs = CurDAG->getVTList(NVT, NVT, MVT::Other);
6086 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6091 SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue);
6092 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6098 ReplaceUses(N1.
getValue(1), Chain);
6104 SDVTList VTs = CurDAG->getVTList(NVT);
6105 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6107 }
else if (UseMULX) {
6108 SDVTList VTs = CurDAG->getVTList(NVT, NVT);
6109 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6113 SDVTList VTs = CurDAG->getVTList(MVT::Glue);
6114 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6120 if (!
SDValue(Node, 0).use_empty()) {
6122 assert(LoReg &&
"Register for low half is not defined!");
6123 ResLo = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, LoReg,
6127 ReplaceUses(
SDValue(Node, 0), ResLo);
6132 if (!
SDValue(Node, 1).use_empty()) {
6134 assert(HiReg &&
"Register for high half is not defined!");
6135 ResHi = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, HiReg,
6139 ReplaceUses(
SDValue(Node, 1), ResHi);
6144 CurDAG->RemoveDeadNode(Node);
6153 unsigned ROpc, MOpc;
6158 case MVT::i8: ROpc = X86::DIV8r; MOpc = X86::DIV8m;
break;
6159 case MVT::i16: ROpc = X86::DIV16r; MOpc = X86::DIV16m;
break;
6160 case MVT::i32: ROpc = X86::DIV32r; MOpc = X86::DIV32m;
break;
6161 case MVT::i64: ROpc = X86::DIV64r; MOpc = X86::DIV64m;
break;
6166 case MVT::i8: ROpc = X86::IDIV8r; MOpc = X86::IDIV8m;
break;
6167 case MVT::i16: ROpc = X86::IDIV16r; MOpc = X86::IDIV16m;
break;
6168 case MVT::i32: ROpc = X86::IDIV32r; MOpc = X86::IDIV32m;
break;
6169 case MVT::i64: ROpc = X86::IDIV64r; MOpc = X86::IDIV64m;
break;
6173 unsigned LoReg, HiReg, ClrReg;
6174 unsigned SExtOpcode;
6178 LoReg = X86::AL; ClrReg = HiReg = X86::AH;
6182 LoReg = X86::AX; HiReg = X86::DX;
6184 SExtOpcode = X86::CWD;
6187 LoReg = X86::EAX; ClrReg = HiReg = X86::EDX;
6188 SExtOpcode = X86::CDQ;
6191 LoReg = X86::RAX; ClrReg = HiReg = X86::RDX;
6192 SExtOpcode = X86::CQO;
6196 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6197 bool foldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6198 bool signBitIsZero = CurDAG->SignBitIsZero(N0);
6201 if (NVT == MVT::i8) {
6204 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Chain;
6205 MachineSDNode *Move;
6206 if (tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
6208 unsigned Opc = (
isSigned && !signBitIsZero) ? X86::MOVSX16rm8
6210 Move = CurDAG->getMachineNode(
Opc, dl, MVT::i16, MVT::Other,
Ops);
6212 ReplaceUses(N0.
getValue(1), Chain);
6216 unsigned Opc = (
isSigned && !signBitIsZero) ? X86::MOVSX16rr8
6218 Move = CurDAG->getMachineNode(
Opc, dl, MVT::i16, N0);
6219 Chain = CurDAG->getEntryNode();
6221 Chain = CurDAG->getCopyToReg(Chain, dl, X86::AX,
SDValue(Move, 0),
6226 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl,
6227 LoReg, N0,
SDValue()).getValue(1);
6231 SDValue(CurDAG->getMachineNode(SExtOpcode, dl, MVT::Glue, InGlue),0);
6234 SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::i32);
6236 SDValue(CurDAG->getMachineNode(X86::MOV32r0, dl, VTs, {}), 0);
6240 SDValue(CurDAG->getMachineNode(
6241 TargetOpcode::EXTRACT_SUBREG, dl, MVT::i16, ClrNode,
6242 CurDAG->getTargetConstant(X86::sub_16bit, dl,
6250 CurDAG->getMachineNode(
6251 TargetOpcode::SUBREG_TO_REG, dl, MVT::i64, ClrNode,
6252 CurDAG->getTargetConstant(X86::sub_32bit, dl, MVT::i32)),
6259 InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, ClrReg,
6260 ClrNode, InGlue).getValue(1);
6267 MachineSDNode *CNode =
6268 CurDAG->getMachineNode(MOpc, dl, MVT::Other, MVT::Glue,
Ops);
6276 SDValue(CurDAG->getMachineNode(ROpc, dl, MVT::Glue, N1, InGlue), 0);
6286 if (HiReg == X86::AH && !
SDValue(Node, 1).use_empty()) {
6287 SDValue AHCopy = CurDAG->getRegister(X86::AH, MVT::i8);
6288 unsigned AHExtOpcode =
6289 isSigned ? X86::MOVSX32rr8_NOREX : X86::MOVZX32rr8_NOREX;
6291 SDNode *RNode = CurDAG->getMachineNode(AHExtOpcode, dl, MVT::i32,
6292 MVT::Glue, AHCopy, InGlue);
6297 CurDAG->getTargetExtractSubreg(X86::sub_8bit, dl, MVT::i8, Result);
6299 ReplaceUses(
SDValue(Node, 1), Result);
6304 if (!
SDValue(Node, 0).use_empty()) {
6305 SDValue Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
6306 LoReg, NVT, InGlue);
6307 InGlue =
Result.getValue(2);
6308 ReplaceUses(
SDValue(Node, 0), Result);
6313 if (!
SDValue(Node, 1).use_empty()) {
6314 SDValue Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
6315 HiReg, NVT, InGlue);
6316 InGlue =
Result.getValue(2);
6317 ReplaceUses(
SDValue(Node, 1), Result);
6321 CurDAG->RemoveDeadNode(Node);
6326 case X86ISD::STRICT_FCMP:
6327 case X86ISD::STRICT_FCMPS: {
6328 bool IsStrictCmp =
Node->getOpcode() == X86ISD::STRICT_FCMP ||
6329 Node->getOpcode() == X86ISD::STRICT_FCMPS;
6330 SDValue N0 =
Node->getOperand(IsStrictCmp ? 1 : 0);
6331 SDValue N1 =
Node->getOperand(IsStrictCmp ? 2 : 1);
6337 if (Subtarget->canUseCMOV())
6340 bool IsSignaling =
Node->getOpcode() == X86ISD::STRICT_FCMPS;
6346 Opc = IsSignaling ? X86::COM_Fpr32 : X86::UCOM_Fpr32;
6349 Opc = IsSignaling ? X86::COM_Fpr64 : X86::UCOM_Fpr64;
6352 Opc = IsSignaling ? X86::COM_Fpr80 : X86::UCOM_Fpr80;
6357 IsStrictCmp ?
Node->getOperand(0) : CurDAG->getEntryNode();
6360 SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue);
6361 Chain =
SDValue(CurDAG->getMachineNode(
Opc, dl, VTs, {N0, N1, Chain}), 0);
6364 Glue =
SDValue(CurDAG->getMachineNode(
Opc, dl, MVT::Glue, N0, N1), 0);
6369 SDValue(CurDAG->getMachineNode(X86::FNSTSW16r, dl, MVT::i16, Glue), 0);
6373 CurDAG->getTargetExtractSubreg(X86::sub_8bit_hi, dl, MVT::i8, FNSTSW);
6377 assert(Subtarget->canUseLAHFSAHF() &&
6378 "Target doesn't support SAHF or FCOMI?");
6379 SDValue AH = CurDAG->getCopyToReg(Chain, dl, X86::AH, Extract,
SDValue());
6382 CurDAG->getMachineNode(X86::SAHF, dl, MVT::i32, AH.
getValue(1)), 0);
6385 ReplaceUses(
SDValue(Node, 1), Chain);
6387 ReplaceUses(
SDValue(Node, 0), SAHF);
6388 CurDAG->RemoveDeadNode(Node);
6408 if (MachineSDNode *NewNode = matchBEXTRFromAndImm(N0.
getNode())) {
6409 unsigned TestOpc = CmpVT == MVT::i64 ? X86::TEST64rr
6412 NewNode = CurDAG->getMachineNode(TestOpc, dl, MVT::i32, BEXTR, BEXTR);
6414 CurDAG->RemoveDeadNode(Node);
6441 onlyUsesZeroFlag(
SDValue(Node, 0))) {
6446 unsigned TestOpcode;
6454 if (LeadingZeros == 0 && SavesBytes) {
6459 ShiftAmt = TrailingZeros;
6461 TestOpcode = X86::TEST64rr;
6462 }
else if (TrailingZeros == 0 && SavesBytes) {
6467 ShiftAmt = LeadingZeros;
6469 TestOpcode = X86::TEST64rr;
6470 }
else if (MaskC->hasOneUse() && !
isInt<32>(Mask)) {
6473 unsigned PopCount = 64 - LeadingZeros - TrailingZeros;
6474 if (PopCount == 8) {
6476 ShiftAmt = TrailingZeros;
6477 SubRegIdx = X86::sub_8bit;
6479 TestOpcode = X86::TEST8rr;
6480 }
else if (PopCount == 16) {
6482 ShiftAmt = TrailingZeros;
6483 SubRegIdx = X86::sub_16bit;
6484 SubRegVT = MVT::i16;
6485 TestOpcode = X86::TEST16rr;
6486 }
else if (PopCount == 32) {
6488 ShiftAmt = TrailingZeros;
6489 SubRegIdx = X86::sub_32bit;
6490 SubRegVT = MVT::i32;
6491 TestOpcode = X86::TEST32rr;
6495 SDValue ShiftC = CurDAG->getTargetConstant(ShiftAmt, dl, MVT::i64);
6497 CurDAG->getMachineNode(ShiftOpcode, dl, MVT::i64, MVT::i32,
6500 if (SubRegIdx != 0) {
6502 CurDAG->getTargetExtractSubreg(SubRegIdx, dl, SubRegVT, Shift);
6504 MachineSDNode *
Test =
6505 CurDAG->getMachineNode(TestOpcode, dl, MVT::i32, Shift, Shift);
6506 ReplaceNode(Node,
Test);
6513 unsigned ROpc, MOpc;
6521 (!(Mask & 0x80) || CmpVT == MVT::i8 ||
6522 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6525 SubRegOp = X86::sub_8bit;
6526 ROpc = X86::TEST8ri;
6527 MOpc = X86::TEST8mi;
6528 }
else if (OptForMinSize &&
isUInt<16>(Mask) &&
6529 (!(Mask & 0x8000) || CmpVT == MVT::i16 ||
6530 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6536 SubRegOp = X86::sub_16bit;
6537 ROpc = X86::TEST16ri;
6538 MOpc = X86::TEST16mi;
6540 ((!(Mask & 0x80000000) &&
6543 (CmpVT != MVT::i16 || !(Mask & 0x8000))) ||
6544 CmpVT == MVT::i32 ||
6545 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6552 SubRegOp = X86::sub_32bit;
6553 ROpc = X86::TEST32ri;
6554 MOpc = X86::TEST32mi;
6560 SDValue Imm = CurDAG->getTargetConstant(Mask, dl, VT);
6564 MachineSDNode *NewNode;
6565 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6566 if (tryFoldLoad(Node, N0.
getNode(),
Reg, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
6568 if (!LoadN->isSimple()) {
6569 unsigned NumVolBits = LoadN->getValueType(0).getSizeInBits();
6570 if ((MOpc == X86::TEST8mi && NumVolBits != 8) ||
6571 (MOpc == X86::TEST16mi && NumVolBits != 16) ||
6572 (MOpc == X86::TEST32mi && NumVolBits != 32))
6577 Reg.getOperand(0) };
6578 NewNode = CurDAG->getMachineNode(MOpc, dl, MVT::i32, MVT::Other,
Ops);
6580 ReplaceUses(
Reg.getValue(1),
SDValue(NewNode, 1));
6582 CurDAG->setNodeMemRefs(NewNode,
6587 Reg = CurDAG->getTargetExtractSubreg(SubRegOp, dl, VT,
Reg);
6589 NewNode = CurDAG->getMachineNode(ROpc, dl, MVT::i32,
Reg,
Imm);
6592 ReplaceNode(Node, NewNode);
6598 if (!Subtarget->hasSSE42())
6601 bool NeedIndex = !
SDValue(Node, 0).use_empty();
6602 bool NeedMask = !
SDValue(Node, 1).use_empty();
6604 bool MayFoldLoad = !NeedIndex || !NeedMask;
6606 MachineSDNode *CNode;
6609 Subtarget->hasAVX() ? X86::VPCMPISTRMrri : X86::PCMPISTRMrri;
6611 Subtarget->hasAVX() ? X86::VPCMPISTRMrmi : X86::PCMPISTRMrmi;
6612 CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node);
6615 if (NeedIndex || !NeedMask) {
6617 Subtarget->hasAVX() ? X86::VPCMPISTRIrri : X86::PCMPISTRIrri;
6619 Subtarget->hasAVX() ? X86::VPCMPISTRIrmi : X86::PCMPISTRIrmi;
6620 CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node);
6626 CurDAG->RemoveDeadNode(Node);
6630 if (!Subtarget->hasSSE42())
6634 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EAX,
6635 Node->getOperand(1),
6637 InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EDX,
6638 Node->getOperand(3), InGlue).getValue(1);
6640 bool NeedIndex = !
SDValue(Node, 0).use_empty();
6641 bool NeedMask = !
SDValue(Node, 1).use_empty();
6643 bool MayFoldLoad = !NeedIndex || !NeedMask;
6645 MachineSDNode *CNode;
6648 Subtarget->hasAVX() ? X86::VPCMPESTRMrri : X86::PCMPESTRMrri;
6650 Subtarget->hasAVX() ? X86::VPCMPESTRMrmi : X86::PCMPESTRMrmi;
6652 emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node, InGlue);
6655 if (NeedIndex || !NeedMask) {
6657 Subtarget->hasAVX() ? X86::VPCMPESTRIrri : X86::PCMPESTRIrri;
6659 Subtarget->hasAVX() ? X86::VPCMPESTRIrmi : X86::PCMPESTRIrmi;
6660 CNode = emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node, InGlue);
6665 CurDAG->RemoveDeadNode(Node);
6677 if (foldLoadStoreIntoMemOperand(Node))
6681 case X86ISD::SETCC_CARRY: {
6682 MVT VT =
Node->getSimpleValueType(0);
6684 if (Subtarget->hasSBBDepBreaking()) {
6689 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EFLAGS,
6694 unsigned Opc = VT == MVT::i64 ? X86::SETB_C64r : X86::SETB_C32r;
6695 MVT SetVT = VT == MVT::i64 ? MVT::i64 : MVT::i32;
6697 CurDAG->getMachineNode(
Opc, dl, SetVT, EFLAGS, EFLAGS.
getValue(1)),
6702 Result = getSBBZero(Node);
6706 if (VT == MVT::i8 || VT == MVT::i16) {
6707 int SubIndex = VT == MVT::i16 ? X86::sub_16bit : X86::sub_8bit;
6708 Result = CurDAG->getTargetExtractSubreg(SubIndex, dl, VT, Result);
6711 ReplaceUses(
SDValue(Node, 0), Result);
6712 CurDAG->RemoveDeadNode(Node);
6724 if (!
SDValue(Node, 0).use_empty()) {
6726 MVT VT =
Node->getSimpleValueType(0);
6727 if (VT == MVT::i8 || VT == MVT::i16) {
6728 int SubIndex = VT == MVT::i16 ? X86::sub_16bit : X86::sub_8bit;
6729 Result = CurDAG->getTargetExtractSubreg(SubIndex, dl, VT, Result);
6731 ReplaceUses(
SDValue(Node, 0), Result);
6734 CurDAG->RemoveDeadNode(Node);
6741 SDValue IndexOp = Mgt->getIndex();
6744 MVT ValueVT =
Node->getSimpleValueType(0);
6745 MVT MaskVT =
Mask.getSimpleValueType();
6762 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6763 Opc = IsFP ? X86::VGATHERDPSZ128rm : X86::VPGATHERDDZ128rm;
6764 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6765 Opc = IsFP ? X86::VGATHERDPSZ256rm : X86::VPGATHERDDZ256rm;
6766 else if (IndexVT == MVT::v16i32 && NumElts == 16 && EltSize == 32)
6767 Opc = IsFP ? X86::VGATHERDPSZrm : X86::VPGATHERDDZrm;
6768 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6769 Opc = IsFP ? X86::VGATHERDPDZ128rm : X86::VPGATHERDQZ128rm;
6770 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6771 Opc = IsFP ? X86::VGATHERDPDZ256rm : X86::VPGATHERDQZ256rm;
6772 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 64)
6773 Opc = IsFP ? X86::VGATHERDPDZrm : X86::VPGATHERDQZrm;
6774 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6775 Opc = IsFP ? X86::VGATHERQPSZ128rm : X86::VPGATHERQDZ128rm;
6776 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6777 Opc = IsFP ? X86::VGATHERQPSZ256rm : X86::VPGATHERQDZ256rm;
6778 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 32)
6779 Opc = IsFP ? X86::VGATHERQPSZrm : X86::VPGATHERQDZrm;
6780 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6781 Opc = IsFP ? X86::VGATHERQPDZ128rm : X86::VPGATHERQQZ128rm;
6782 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6783 Opc = IsFP ? X86::VGATHERQPDZ256rm : X86::VPGATHERQQZ256rm;
6784 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 64)
6785 Opc = IsFP ? X86::VGATHERQPDZrm : X86::VPGATHERQQZrm;
6787 assert(EVT(MaskVT) == EVT(ValueVT).changeVectorElementTypeToInteger() &&
6788 "Unexpected mask VT!");
6789 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6790 Opc = IsFP ? X86::VGATHERDPSrm : X86::VPGATHERDDrm;
6791 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6792 Opc = IsFP ? X86::VGATHERDPSYrm : X86::VPGATHERDDYrm;
6793 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6794 Opc = IsFP ? X86::VGATHERDPDrm : X86::VPGATHERDQrm;
6795 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6796 Opc = IsFP ? X86::VGATHERDPDYrm : X86::VPGATHERDQYrm;
6797 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6798 Opc = IsFP ? X86::VGATHERQPSrm : X86::VPGATHERQDrm;
6799 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6800 Opc = IsFP ? X86::VGATHERQPSYrm : X86::VPGATHERQDYrm;
6801 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6802 Opc = IsFP ? X86::VGATHERQPDrm : X86::VPGATHERQQrm;
6803 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6804 Opc = IsFP ? X86::VGATHERQPDYrm : X86::VPGATHERQQYrm;
6811 if (!selectVectorAddr(Mgt, Mgt->getBasePtr(), IndexOp, Mgt->getScale(),
6812 Base, Scale, Index, Disp, Segment))
6815 SDValue PassThru = Mgt->getPassThru();
6816 SDValue Chain = Mgt->getChain();
6818 SDVTList VTs = CurDAG->getVTList(ValueVT, MaskVT, MVT::Other);
6820 MachineSDNode *NewNode;
6823 Index, Disp, Segment, Chain};
6824 NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6827 Disp, Segment,
Mask, Chain};
6828 NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6830 CurDAG->setNodeMemRefs(NewNode, {Mgt->getMemOperand()});
6833 CurDAG->RemoveDeadNode(Node);
6839 SDValue IndexOp = Sc->getIndex();
6841 MVT ValueVT =
Value.getSimpleValueType();
6856 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6857 Opc = IsFP ? X86::VSCATTERDPSZ128mr : X86::VPSCATTERDDZ128mr;
6858 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6859 Opc = IsFP ? X86::VSCATTERDPSZ256mr : X86::VPSCATTERDDZ256mr;
6860 else if (IndexVT == MVT::v16i32 && NumElts == 16 && EltSize == 32)
6861 Opc = IsFP ? X86::VSCATTERDPSZmr : X86::VPSCATTERDDZmr;
6862 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6863 Opc = IsFP ? X86::VSCATTERDPDZ128mr : X86::VPSCATTERDQZ128mr;
6864 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6865 Opc = IsFP ? X86::VSCATTERDPDZ256mr : X86::VPSCATTERDQZ256mr;
6866 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 64)
6867 Opc = IsFP ? X86::VSCATTERDPDZmr : X86::VPSCATTERDQZmr;
6868 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6869 Opc = IsFP ? X86::VSCATTERQPSZ128mr : X86::VPSCATTERQDZ128mr;
6870 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6871 Opc = IsFP ? X86::VSCATTERQPSZ256mr : X86::VPSCATTERQDZ256mr;
6872 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 32)
6873 Opc = IsFP ? X86::VSCATTERQPSZmr : X86::VPSCATTERQDZmr;
6874 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6875 Opc = IsFP ? X86::VSCATTERQPDZ128mr : X86::VPSCATTERQQZ128mr;
6876 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6877 Opc = IsFP ? X86::VSCATTERQPDZ256mr : X86::VPSCATTERQQZ256mr;
6878 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 64)
6879 Opc = IsFP ? X86::VSCATTERQPDZmr : X86::VPSCATTERQQZmr;
6884 if (!selectVectorAddr(Sc, Sc->getBasePtr(), IndexOp, Sc->getScale(),
6885 Base, Scale, Index, Disp, Segment))
6889 SDValue Chain = Sc->getChain();
6891 SDVTList VTs = CurDAG->getVTList(
Mask.getValueType(), MVT::Other);
6894 MachineSDNode *NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6895 CurDAG->setNodeMemRefs(NewNode, {Sc->getMemOperand()});
6897 CurDAG->RemoveDeadNode(Node);
6901 auto *MFI = CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
6902 auto CallId = MFI->getPreallocatedIdForCallSite(
6905 SDValue CallIdValue = CurDAG->getTargetConstant(CallId, dl, MVT::i32);
6906 MachineSDNode *
New = CurDAG->getMachineNode(
6907 TargetOpcode::PREALLOCATED_SETUP, dl, MVT::Other, CallIdValue, Chain);
6909 CurDAG->RemoveDeadNode(Node);
6913 auto *MFI = CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
6917 SDValue CallIdValue = CurDAG->getTargetConstant(CallId, dl, MVT::i32);
6920 Ops[0] = CallIdValue;
6923 MachineSDNode *
New = CurDAG->getMachineNode(
6924 TargetOpcode::PREALLOCATED_ARG, dl,
6925 CurDAG->getVTList(TLI->
getPointerTy(CurDAG->getDataLayout()),
6930 CurDAG->RemoveDeadNode(Node);
6937 if (!Subtarget->hasWIDEKL())
6941 switch (
Node->getOpcode()) {
6945 Opcode = X86::AESENCWIDE128KL;
6948 Opcode = X86::AESDECWIDE128KL;
6951 Opcode = X86::AESENCWIDE256KL;
6954 Opcode = X86::AESDECWIDE256KL;
6962 if (!selectAddr(Node, Addr,
Base, Scale, Index, Disp, Segment))
6965 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM0,
Node->getOperand(2),
6967 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM1,
Node->getOperand(3),
6969 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM2,
Node->getOperand(4),
6971 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM3,
Node->getOperand(5),
6973 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM4,
Node->getOperand(6),
6975 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM5,
Node->getOperand(7),
6977 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM6,
Node->getOperand(8),
6979 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM7,
Node->getOperand(9),
6982 MachineSDNode *Res = CurDAG->getMachineNode(
6983 Opcode, dl,
Node->getVTList(),
6984 {Base, Scale, Index, Disp, Segment, Chain, Chain.getValue(1)});
6986 ReplaceNode(Node, Res);
6993 if (
Node->getNumValues() == 3)
6994 Glue =
Node->getOperand(2);
6996 CurDAG->getCopyFromReg(Chain, dl,
Reg,
Node->getValueType(0), Glue);
6997 ReplaceNode(Node,
Copy.getNode());
7005bool X86DAGToDAGISel::SelectInlineAsmMemoryOperand(
7007 std::vector<SDValue> &OutOps) {
7008 SDValue Op0, Op1, Op2, Op3, Op4;
7009 switch (ConstraintID) {
7012 case InlineAsm::ConstraintCode::o:
7013 case InlineAsm::ConstraintCode::v:
7014 case InlineAsm::ConstraintCode::m:
7015 case InlineAsm::ConstraintCode::X:
7016 case InlineAsm::ConstraintCode::p:
7017 if (!selectAddr(
nullptr,
Op, Op0, Op1, Op2, Op3, Op4))
7022 OutOps.push_back(Op0);
7023 OutOps.push_back(Op1);
7024 OutOps.push_back(Op2);
7025 OutOps.push_back(Op3);
7026 OutOps.push_back(Op4);
7032 std::make_unique<X86DAGToDAGISel>(TM, TM.getOptLevel())) {}
7038 return new X86DAGToDAGISelLegacy(TM, OptLevel);
static SDValue Widen(SelectionDAG *CurDAG, SDValue N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis false
#define CASE(ATTRNAME, AANAME,...)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
const MCPhysReg ArgGPRs[]
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool isFusableLoadOpStorePattern(StoreSDNode *StoreNode, SDValue StoredVal, SelectionDAG *CurDAG, LoadSDNode *&LoadNode, SDValue &InputChain)
static void insertDAGNode(SelectionDAG *DAG, SDNode *Pos, SDValue N)
static bool isRIPRelative(const MCInst &MI, const MCInstrInfo &MCII)
Check if the instruction uses RIP relative addressing.
#define FROM_TO(FROM, TO)
#define GET_EGPR_IF_ENABLED(OPC)
static bool isLegalMaskCompare(SDNode *N, const X86Subtarget *Subtarget)
static bool foldMaskAndShiftToScale(SelectionDAG &DAG, SDValue N, uint64_t Mask, SDValue Shift, SDValue X, X86ISelAddressMode &AM)
static bool foldMaskAndShiftToExtract(SelectionDAG &DAG, SDValue N, uint64_t Mask, SDValue Shift, SDValue X, X86ISelAddressMode &AM)
static bool needBWI(MVT VT)
static unsigned getVPTESTMOpc(MVT TestVT, bool IsTestN, bool FoldedLoad, bool FoldedBCast, bool Masked)
#define GET_NDM_IF_ENABLED(OPC)
static bool foldMaskedShiftToBEXTR(SelectionDAG &DAG, SDValue N, uint64_t Mask, SDValue Shift, SDValue X, X86ISelAddressMode &AM, const X86Subtarget &Subtarget)
static bool mayUseCarryFlag(X86::CondCode CC)
static cl::opt< bool > EnablePromoteAnyextLoad("x86-promote-anyext-load", cl::init(true), cl::desc("Enable promoting aligned anyext load to wider load"), cl::Hidden)
static void moveBelowOrigChain(SelectionDAG *CurDAG, SDValue Load, SDValue Call, SDValue OrigChain)
Replace the original chain operand of the call with load's chain operand and move load below the call...
#define GET_ND_IF_ENABLED(OPC)
#define VPTESTM_BROADCAST_CASES(SUFFIX)
static cl::opt< bool > AndImmShrink("x86-and-imm-shrink", cl::init(true), cl::desc("Enable setting constant bits to reduce size of mask immediates"), cl::Hidden)
static bool foldMaskedShiftToScaledMask(SelectionDAG &DAG, SDValue N, X86ISelAddressMode &AM)
#define VPTESTM_FULL_CASES(SUFFIX)
static bool isCalleeLoad(SDValue Callee, SDValue &Chain, bool HasCallSeq)
Return true if call address is a load and it can be moved below CALLSEQ_START and the chains leading ...
static bool isDispSafeForFrameIndexOrRegBase(int64_t Val)
static bool isEndbrImm64(uint64_t Imm)
static void orderRegForMul(SDValue &N0, SDValue &N1, const unsigned LoReg, const MachineRegisterInfo &MRI)
cl::opt< bool > IndirectBranchTracking("x86-indirect-branch-tracking", cl::init(false), cl::Hidden, cl::desc("Enable X86 indirect branch tracking pass."))
#define GET_ND_IF_ENABLED(OPC)
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countl_zero() const
The APInt version of std::countl_zero.
unsigned getSignificantBits() const
Get the minimum bit size for this signed APInt.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
bool isOne() const
Determine if this is a value of 1.
unsigned countr_one() const
Count the number of trailing one bits.
FunctionPass class - This class is used to implement most global optimizations.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI std::optional< ConstantRange > getAbsoluteSymbolRange() const
If this is an absolute symbol reference, returns the range of the symbol, otherwise returns std::null...
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
unsigned getID() const
getID() - Return the register class ID number.
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
bool isVectorOf(MVT EltVT) const
Return true if this is a vector with matching element type.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool is512BitVector() const
Return true if this is a 512-bit vector type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MCRegister getLiveInPhysReg(Register VReg) const
getLiveInPhysReg - If VReg is a live-in virtual register, return the corresponding live-in physical r...
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
bool isNonTemporal() const
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
ArrayRef< SDUse > ops() const
int getNodeId() const
Return the unique node id.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
SDNodeFlags getFlags() const
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
const SDValue & getOperand(unsigned Num) const
bool hasNUsesOfValue(unsigned NUses, unsigned Value) const
Return true if there are exactly NUSES uses of the indicated value.
iterator_range< user_iterator > users()
op_iterator op_end() const
op_iterator op_begin() const
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
bool isMachineOpcode() const
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getMachineOpcode() const
unsigned getOpcode() const
unsigned getNumOperands() const
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
static int getUninvalidatedNodeId(SDNode *N)
virtual bool runOnMachineFunction(MachineFunction &mf)
static void InvalidateNodeId(SDNode *N)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
static constexpr unsigned MaxRecursionDepth
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
void RepositionNode(allnodes_iterator Position, SDNode *N)
Move node N in the AllNodes list to be immediately before the given iterator Position.
ilist< SDNode >::iterator allnodes_iterator
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool hasOneUse() const
Return true if there is exactly one use of this value.
X86ISelDAGToDAGPass(X86TargetMachine &TM)
size_t getPreallocatedIdForCallSite(const Value *CS)
bool isScalarFPTypeInSSEReg(EVT VT) const
Return true if the specified scalar FP type is computed in an SSE register, not on the X87 floating p...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ 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...
@ PREALLOCATED_SETUP
PREALLOCATED_SETUP - This has 2 operands: an input chain and a SRCVALUE with the preallocated call Va...
@ PREALLOCATED_ARG
PREALLOCATED_ARG - This has 3 operands: an input chain, a SRCVALUE with the preallocated call Value,...
@ BRIND
BRIND - Indirect branch.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ SHL
Shift and rotation operations.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ LOCAL_RECOVER
LOCAL_RECOVER - Represents the llvm.localrecover intrinsic.
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ CALLSEQ_START
CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end of a call sequence,...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
LLVM_ABI bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
@ GlobalBaseReg
The result of the mflr at function entry, used for PIC code.
@ X86
Windows x64, Windows Itanium (IA-64)
@ MO_NO_FLAG
MO_NO_FLAG - No flag for the operand.
@ EVEX
EVEX - Specifies that this instruction use EVEX form which provides syntax support up to 32 512-bit r...
@ VEX
VEX - encoding using 0xC4/0xC5.
@ XOP
XOP - Opcode prefix used by XOP instructions.
int getMemoryOperandNo(uint64_t TSFlags)
@ GlobalBaseReg
On Darwin, this node represents the result of the popl at function entry, used for PIC code.
@ POP_FROM_X87_REG
The same as ISD::CopyFromReg except that this node makes it explicit that it may lower to an x87 FPU ...
int getCondSrcNoFromDesc(const MCInstrDesc &MCID)
Return the source operand # for condition code by MCID.
bool mayFoldLoad(SDValue Op, const X86Subtarget &Subtarget, bool AssumeSingleUse=false, bool IgnoreAlignment=false)
Check if Op is a load operation that could be folded into some other x86 instruction as a memory oper...
bool isOffsetSuitableForCodeModel(int64_t Offset, CodeModel::Model M, bool hasSymbolicDisplacement)
Returns true of the given offset can be fit into displacement field of the instruction.
bool isConstantSplat(SDValue Op, APInt &SplatVal, bool AllowPartialUndefs)
If Op is a constant whose elements are all the same constant or undefined, return true and return the...
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool isa_and_nonnull(const Y &Val)
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
unsigned M1(unsigned Val)
auto dyn_cast_or_null(const Y &Val)
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
FunctionPass * createX86ISelDag(X86TargetMachine &TM, CodeGenOptLevel OptLevel)
This pass converts a legalized DAG into a X86-specific DAG, ready for instruction scheduling.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
MCRegisterClass TargetRegisterClass
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
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.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
bool isVector() const
Return true if this is a vector value type.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
bool isConstant() const
Returns true if we know the value of all bits.
LLVM_ABI unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
bool hasNoUnsignedWrap() const