22#include "llvm/Config/llvm-config.h"
27#include "llvm/IR/IntrinsicsX86.h"
39#define DEBUG_TYPE "x86-isel"
40#define PASS_NAME "X86 DAG->DAG Instruction Selection"
42STATISTIC(NumLoadMoved,
"Number of loads moved below TokenFactor");
45 cl::desc(
"Enable setting constant bits to reduce size of mask immediates"),
49 "x86-promote-anyext-load",
cl::init(
true),
61 struct X86ISelAddressMode {
69 int Base_FrameIndex = 0;
75 const GlobalValue *GV =
nullptr;
78 const char *ES =
nullptr;
83 bool NegateIndex =
false;
88 bool IsForLEA =
false;
90 X86ISelAddressMode() =
default;
92 bool hasSymbolicDisplacement()
const {
93 return GV !=
nullptr || CP !=
nullptr || ES !=
nullptr ||
94 MCSym !=
nullptr || JT != -1 || BlockAddr !=
nullptr;
97 bool hasBaseOrIndexReg()
const {
98 return BaseType == FrameIndexBase ||
99 IndexReg.getNode() !=
nullptr || Base_Reg.getNode() !=
nullptr;
104 if (BaseType != RegBase)
return false;
105 if (RegisterSDNode *RegNode =
107 return RegNode->getReg() == X86::RIP;
116#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
117 void dump(SelectionDAG *DAG =
nullptr) {
118 dbgs() <<
"X86ISelAddressMode " <<
this <<
'\n';
119 dbgs() <<
"Base_Reg ";
120 if (Base_Reg.getNode())
121 Base_Reg.getNode()->dump(DAG);
124 if (BaseType == FrameIndexBase)
125 dbgs() <<
" Base.FrameIndex " << Base_FrameIndex <<
'\n';
126 dbgs() <<
" Scale " << Scale <<
'\n'
130 if (IndexReg.getNode())
131 IndexReg.getNode()->dump(DAG);
134 dbgs() <<
" Disp " << Disp <<
'\n'
156 dbgs() <<
" JT" << JT <<
" Align" << Alignment.value() <<
'\n';
170 const X86Subtarget *Subtarget;
176 bool IndirectTlsSegRefs;
179 X86DAGToDAGISel() =
delete;
181 explicit X86DAGToDAGISel(X86TargetMachine &tm,
CodeGenOptLevel OptLevel)
182 : SelectionDAGISel(tm, OptLevel), Subtarget(nullptr),
183 OptForMinSize(
false), IndirectTlsSegRefs(
false) {}
189 "indirect-tls-seg-refs");
196 void emitFunctionEntryCode()
override;
198 bool IsProfitableToFold(
SDValue N, SDNode *U, SDNode *Root)
const override;
200 void PreprocessISelDAG()
override;
201 void PostprocessISelDAG()
override;
204#include "X86GenDAGISel.inc"
207 void Select(SDNode *
N)
override;
209 bool foldOffsetIntoAddress(
uint64_t Offset, X86ISelAddressMode &AM);
210 bool matchLoadInAddress(LoadSDNode *
N, X86ISelAddressMode &AM,
211 bool AllowSegmentRegForX32 =
false);
212 bool matchWrapper(
SDValue N, X86ISelAddressMode &AM);
213 bool matchAddress(
SDValue N, X86ISelAddressMode &AM);
214 bool matchVectorAddress(
SDValue N, X86ISelAddressMode &AM);
215 bool matchAdd(
SDValue &
N, X86ISelAddressMode &AM,
unsigned Depth);
216 bool hasMaterializingUse(
SDValue V)
const;
219 bool matchAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
221 bool matchVectorAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
223 bool matchAddressBase(
SDValue N, X86ISelAddressMode &AM);
226 bool HasNDDM =
true);
229 bool selectVectorAddr(MemSDNode *Parent,
SDValue BasePtr,
SDValue IndexOp,
243 bool tryFoldLoad(SDNode *Root, SDNode *
P,
SDValue N,
253 return tryFoldLoad(
P,
P,
N,
Base, Scale, Index, Disp, Segment);
256 bool tryFoldBroadcast(SDNode *Root, SDNode *
P,
SDValue N,
261 bool isProfitableToFormMaskedOp(SDNode *
N)
const;
264 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
266 std::vector<SDValue> &OutOps)
override;
268 void emitSpecialCodeForMain();
270 inline void getAddressOperands(X86ISelAddressMode &AM,
const SDLoc &
DL,
274 if (AM.BaseType == X86ISelAddressMode::FrameIndexBase)
275 Base = CurDAG->getTargetFrameIndex(
276 AM.Base_FrameIndex, TLI->getPointerTy(CurDAG->getDataLayout()));
277 else if (AM.Base_Reg.
getNode())
280 Base = CurDAG->getRegister(0, VT);
282 Scale = getI8Imm(AM.Scale,
DL);
284#define GET_ND_IF_ENABLED(OPC) (Subtarget->hasNDD() ? OPC##_ND : OPC)
285#define GET_NDM_IF_ENABLED(OPC) \
286 (Subtarget->hasNDD() && Subtarget->hasNDDM() ? OPC##_ND : OPC)
288 if (AM.NegateIndex) {
314 Index = CurDAG->getRegister(0, VT);
319 Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(),
323 Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, AM.Alignment,
324 AM.Disp, AM.SymbolFlags);
326 assert(!AM.Disp &&
"Non-zero displacement is ignored with ES.");
327 Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags);
328 }
else if (AM.MCSym) {
329 assert(!AM.Disp &&
"Non-zero displacement is ignored with MCSym.");
330 assert(AM.SymbolFlags == 0 &&
"oo");
331 Disp = CurDAG->getMCSymbol(AM.MCSym, MVT::i32);
332 }
else if (AM.JT != -1) {
333 assert(!AM.Disp &&
"Non-zero displacement is ignored with JT.");
334 Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags);
335 }
else if (AM.BlockAddr)
336 Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, AM.Disp,
339 Disp = CurDAG->getSignedTargetConstant(AM.Disp,
DL, MVT::i32);
342 Segment = AM.Segment;
344 Segment = CurDAG->getRegister(0, MVT::i16);
349 bool isAMXSDNode(SDNode *
N)
const {
353 for (
unsigned Idx = 0,
E =
N->getNumValues(); Idx !=
E; ++Idx) {
354 if (
N->getValueType(Idx) == MVT::x86amx)
357 for (
unsigned Idx = 0,
E =
N->getNumOperands(); Idx !=
E; ++Idx) {
359 if (
Op.getValueType() == MVT::x86amx)
371 bool shouldAvoidImmediateInstFormsForSize(SDNode *
N)
const {
372 uint32_t UseCount = 0;
377 if (!CurDAG->shouldOptForSize())
381 for (
const SDNode *User :
N->users()) {
387 if (
User->isMachineOpcode()) {
394 User->getOperand(1).getNode() ==
N) {
405 if (
User->getNumOperands() != 2)
418 if (
User->getOpcode() == X86ISD::ADD ||
420 User->getOpcode() == X86ISD::SUB ||
426 OtherOp =
User->getOperand(1);
429 RegisterSDNode *RegNode;
433 if ((RegNode->
getReg() == X86::ESP) ||
434 (RegNode->
getReg() == X86::RSP))
443 return (UseCount > 1);
447 inline SDValue getI8Imm(
unsigned Imm,
const SDLoc &
DL) {
448 return CurDAG->getTargetConstant(
Imm,
DL, MVT::i8);
452 inline SDValue getI32Imm(
unsigned Imm,
const SDLoc &
DL) {
453 return CurDAG->getTargetConstant(
Imm,
DL, MVT::i32);
458 return CurDAG->getTargetConstant(
Imm,
DL, MVT::i64);
461 SDValue getExtractVEXTRACTImmediate(SDNode *
N,
unsigned VecWidth,
463 assert((VecWidth == 128 || VecWidth == 256) &&
"Unexpected vector width");
465 MVT VecVT =
N->getOperand(0).getSimpleValueType();
469 SDValue getInsertVINSERTImmediate(SDNode *
N,
unsigned VecWidth,
471 assert((VecWidth == 128 || VecWidth == 256) &&
"Unexpected vector width");
473 MVT VecVT =
N->getSimpleValueType(0);
477 SDValue getPermuteVINSERTCommutedImmediate(SDNode *
N,
unsigned VecWidth,
479 assert(VecWidth == 128 &&
"Unexpected vector width");
481 MVT VecVT =
N->getSimpleValueType(0);
483 assert((InsertIdx == 0 || InsertIdx == 1) &&
"Bad insertf128 index");
486 return getI8Imm(InsertIdx ? 0x02 : 0x30,
DL);
491 MVT VT =
N->getSimpleValueType(0);
494 SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::i32);
496 SDValue(CurDAG->getMachineNode(X86::MOV32r0, dl, VTs, {}), 0);
497 if (VT == MVT::i64) {
499 CurDAG->getMachineNode(
500 TargetOpcode::SUBREG_TO_REG, dl, MVT::i64, Zero,
501 CurDAG->getTargetConstant(X86::sub_32bit, dl, MVT::i32)),
506 unsigned Opcode =
N->getOpcode();
507 assert((Opcode == X86ISD::SBB || Opcode == X86ISD::SETCC_CARRY) &&
508 "Unexpected opcode for SBB materialization");
509 unsigned FlagOpIndex = Opcode == X86ISD::SBB ? 2 : 1;
511 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EFLAGS,
512 N->getOperand(FlagOpIndex),
SDValue());
516 unsigned Opc = VT == MVT::i64 ? X86::SBB64rr : X86::SBB32rr;
517 MVT SBBVT = VT == MVT::i64 ? MVT::i64 : MVT::i32;
518 VTs = CurDAG->getVTList(SBBVT, MVT::i32);
520 CurDAG->getMachineNode(
Opc, dl, VTs,
521 {Zero, Zero, EFLAGS, EFLAGS.getValue(1)}),
527 bool isUnneededShiftMask(SDNode *
N,
unsigned Width)
const {
529 const APInt &Val =
N->getConstantOperandAPInt(1);
534 APInt
Mask = Val | CurDAG->computeKnownBits(
N->getOperand(0)).Zero;
535 return Mask.countr_one() >= Width;
541 SDNode *getGlobalBaseReg();
545 const X86TargetMachine &getTargetMachine()
const {
546 return static_cast<const X86TargetMachine &
>(TM);
551 const X86InstrInfo *getInstrInfo()
const {
552 return Subtarget->getInstrInfo();
561 bool ComplexPatternFuncMutatesDAG()
const override {
565 bool isSExtAbsoluteSymbolRef(
unsigned Width, SDNode *
N)
const;
568 bool useNonTemporalLoad(LoadSDNode *
N)
const {
569 if (!
N->isNonTemporal())
572 unsigned StoreSize =
N->getMemoryVT().getStoreSize();
574 if (
N->getAlign().value() < StoreSize)
583 return Subtarget->hasSSE41();
585 return Subtarget->hasAVX2();
587 return Subtarget->hasAVX512();
591 bool foldLoadStoreIntoMemOperand(SDNode *Node);
592 MachineSDNode *matchBEXTRFromAndImm(SDNode *Node);
593 bool matchBitExtract(SDNode *Node);
594 bool shrinkAndImmediate(SDNode *
N);
595 bool isMaskZeroExtended(SDNode *
N)
const;
596 bool tryShiftAmountMod(SDNode *
N);
597 bool tryShrinkShlLogicImm(SDNode *
N);
598 bool tryVPTERNLOG(SDNode *
N);
599 bool matchVPTERNLOG(SDNode *Root, SDNode *ParentA, SDNode *ParentB,
603 bool tryMatchBitSelect(SDNode *
N);
605 MachineSDNode *emitPCMPISTR(
unsigned ROpc,
unsigned MOpc,
bool MayFoldLoad,
606 const SDLoc &dl, MVT VT, SDNode *Node);
607 MachineSDNode *emitPCMPESTR(
unsigned ROpc,
unsigned MOpc,
bool MayFoldLoad,
608 const SDLoc &dl, MVT VT, SDNode *Node,
611 bool tryOptimizeRem8Extend(SDNode *
N);
613 bool onlyUsesZeroFlag(
SDValue Flags)
const;
614 bool hasNoSignFlagUses(
SDValue Flags)
const;
615 bool hasNoCarryFlagUses(
SDValue Flags)
const;
616 bool checkTCRetEnoughRegs(SDNode *
N)
const;
622 explicit X86DAGToDAGISelLegacy(X86TargetMachine &tm,
624 : SelectionDAGISelLegacy(
625 ID, std::make_unique<X86DAGToDAGISel>(tm, OptLevel)) {}
629char X86DAGToDAGISelLegacy::ID = 0;
636 unsigned Opcode =
N->getOpcode();
637 if (Opcode == X86ISD::CMPM || Opcode == X86ISD::CMPMM ||
638 Opcode == X86ISD::STRICT_CMPM || Opcode ==
ISD::SETCC ||
639 Opcode == X86ISD::CMPMM_SAE || Opcode == X86ISD::VFPCLASS) {
643 EVT OpVT =
N->getOperand(0).getValueType();
646 if (Opcode == X86ISD::STRICT_CMPM)
647 OpVT =
N->getOperand(1).getValueType();
649 return Subtarget->hasVLX();
654 if (Opcode == X86ISD::VFPCLASSS || Opcode == X86ISD::FSETCCM ||
655 Opcode == X86ISD::FSETCCM_SAE)
663bool X86DAGToDAGISel::isMaskZeroExtended(
SDNode *
N)
const {
675X86DAGToDAGISel::IsProfitableToFold(
SDValue N, SDNode *U, SDNode *Root)
const {
676 if (OptLevel == CodeGenOptLevel::None)
691 switch (
U->getOpcode()) {
718 if (
Imm->getAPIntValue().isSignedIntN(8))
727 Imm->getAPIntValue().getBitWidth() == 64 &&
728 Imm->getAPIntValue().isIntN(32))
735 (
Imm->getAPIntValue() == UINT8_MAX ||
736 Imm->getAPIntValue() == UINT16_MAX ||
737 Imm->getAPIntValue() == UINT32_MAX))
743 (-
Imm->getAPIntValue()).isSignedIntN(8))
746 if ((
U->getOpcode() == X86ISD::ADD ||
U->getOpcode() == X86ISD::SUB) &&
747 (-
Imm->getAPIntValue()).isSignedIntN(8) &&
748 hasNoCarryFlagUses(
SDValue(U, 1)))
762 if (Op1.
getOpcode() == X86ISD::Wrapper) {
773 if (
U->getOperand(0).getOpcode() ==
ISD::SHL &&
777 if (
U->getOperand(1).getOpcode() ==
ISD::SHL &&
786 if (
C &&
C->getSExtValue() == -2)
792 if (
C &&
C->getSExtValue() == -2)
827bool X86DAGToDAGISel::isProfitableToFormMaskedOp(SDNode *
N)
const {
829 (
N->getOpcode() ==
ISD::VSELECT ||
N->getOpcode() == X86ISD::SELECTS) &&
830 "Unexpected opcode!");
835 return N->getOperand(1).hasOneUse();
845 Ops.push_back(
Load.getOperand(0));
848 "Unexpected chain operand");
851 Ops.push_back(
Load.getOperand(0));
857 Ops.push_back(NewChain);
862 Load.getOperand(1),
Load.getOperand(2));
880 if (Callee.getNode() == Chain.
getNode() || !Callee.hasOneUse())
892 if (!Callee.getValue(1).hasOneUse())
923 Callee.getValue(1).hasOneUse())
941 const unsigned NumBytes =
BitWidth / 8;
945 const uint8_t OptionalPrefixBytes[] = {0x26, 0x2e, 0x36, 0x3e, 0x64,
946 0x65, 0x66, 0x67, 0xf0, 0xf2};
948 for (
unsigned I = 0;
I != NumBytes; ++
I)
949 Bytes[
I] = (
Imm >> (
I * 8)) & 0xFF;
951 for (
unsigned I = 0;
I + 3 < NumBytes; ++
I) {
952 if (Bytes[
I] != 0xf3)
959 if (J + 2 < NumBytes && Bytes[J] == 0x0f && Bytes[J + 1] == 0x1e &&
960 (Bytes[J + 2] == 0xfa || Bytes[J + 2] == 0xfb))
968 return (VT == MVT::v32i16 || VT == MVT::v32f16 || VT == MVT::v64i8);
971void X86DAGToDAGISel::PreprocessISelDAG() {
972 bool MadeChange =
false;
974 E = CurDAG->allnodes_end();
I !=
E; ) {
992 MVT VT =
N->getSimpleValueType(0);
994 "ISD::Constant must have a scalar integer type");
1003 "cf-protection-branch");
1009 CurDAG->getConstant(ComplementImm, dl, VT,
false,
true);
1010 Complement = CurDAG->getNOT(dl, Complement, VT);
1012 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Complement);
1022 if (
N->getOpcode() == X86ISD::AND && !
N->hasAnyUseOfValue(1)) {
1024 N->getOperand(0),
N->getOperand(1));
1026 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1050 auto mayPreventLoadFold = [&]() {
1052 N->getOpcode() ==
ISD::ADD && Subtarget->hasAVX() &&
1053 !
N->getOperand(1).hasOneUse();
1056 N->getSimpleValueType(0).isVector() && !mayPreventLoadFold()) {
1064 MVT VT =
N->getSimpleValueType(0);
1072 CurDAG->getNode(NewOpcode,
DL, VT,
N->getOperand(0),
AllOnes);
1074 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1081 switch (
N->getOpcode()) {
1082 case X86ISD::VBROADCAST: {
1083 MVT VT =
N->getSimpleValueType(0);
1085 if (!Subtarget->hasBWI() &&
needBWI(VT)) {
1089 CurDAG->getNode(X86ISD::VBROADCAST, dl, NarrowVT,
N->getOperand(0));
1092 NarrowBCast, CurDAG->getIntPtrConstant(0, dl));
1095 CurDAG->getIntPtrConstant(Index, dl));
1098 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1106 case X86ISD::VBROADCAST_LOAD: {
1107 MVT VT =
N->getSimpleValueType(0);
1109 if (!Subtarget->hasBWI() &&
needBWI(VT)) {
1113 SDVTList VTs = CurDAG->getVTList(NarrowVT, MVT::Other);
1114 SDValue Ops[] = {MemNode->getChain(), MemNode->getBasePtr()};
1115 SDValue NarrowBCast = CurDAG->getMemIntrinsicNode(
1116 X86ISD::VBROADCAST_LOAD, dl, VTs,
Ops, MemNode->getMemoryVT(),
1117 MemNode->getMemOperand());
1120 NarrowBCast, CurDAG->getIntPtrConstant(0, dl));
1123 CurDAG->getIntPtrConstant(Index, dl));
1127 CurDAG->ReplaceAllUsesWith(
N, To);
1139 MVT VT =
N->getSimpleValueType(0);
1145 SDNode *MaxLd =
nullptr;
1146 SDValue Ptr = Ld->getBasePtr();
1147 SDValue Chain = Ld->getChain();
1148 for (SDNode *User : Ptr->
users()) {
1150 MVT UserVT =
User->getSimpleValueType(0);
1152 UserLd->getBasePtr() == Ptr && UserLd->getChain() == Chain &&
1153 !
User->hasAnyUseOfValue(1) &&
1167 CurDAG->getIntPtrConstant(0, dl));
1168 SDValue Res = CurDAG->getBitcast(VT, Extract);
1172 CurDAG->ReplaceAllUsesWith(
N, To);
1181 EVT EleVT =
N->getOperand(0).getValueType().getVectorElementType();
1182 if (EleVT == MVT::i1)
1185 assert(Subtarget->hasSSE41() &&
"Expected SSE4.1 support!");
1186 assert(
N->getValueType(0).getVectorElementType() != MVT::i16 &&
1187 "We can't replace VSELECT with BLENDV in vXi16!");
1189 if (Subtarget->hasVLX() && CurDAG->ComputeNumSignBits(
N->getOperand(0)) ==
1191 R = CurDAG->getNode(X86ISD::VPTERNLOG, SDLoc(
N),
N->getValueType(0),
1192 N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
1193 CurDAG->getTargetConstant(0xCA, SDLoc(
N), MVT::i8));
1195 R = CurDAG->getNode(X86ISD::BLENDV, SDLoc(
N),
N->getValueType(0),
1196 N->getOperand(0),
N->getOperand(1),
1200 CurDAG->ReplaceAllUsesWith(
N,
R.getNode());
1213 if (!
N->getSimpleValueType(0).isVector())
1217 switch (
N->getOpcode()) {
1227 if (
N->isStrictFPOpcode())
1229 CurDAG->getNode(NewOpc, SDLoc(
N), {
N->getValueType(0), MVT::Other},
1230 {
N->getOperand(0),
N->getOperand(1)});
1233 CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1236 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1246 if (!
N->getValueType(0).isVector())
1250 switch (
N->getOpcode()) {
1252 case ISD::SHL: NewOpc = X86ISD::VSHLV;
break;
1253 case ISD::SRA: NewOpc = X86ISD::VSRAV;
break;
1254 case ISD::SRL: NewOpc = X86ISD::VSRLV;
break;
1256 SDValue Res = CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1257 N->getOperand(0),
N->getOperand(1));
1259 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1268 if (!
N->getValueType(0).isVector())
1272 if (
N->getOperand(0).getScalarValueSizeInBits() == 1) {
1274 "Unexpected opcode for mask vector!");
1282 SDValue Res = CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1285 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1305 switch (
N->getOpcode()) {
1321 bool IsStrict =
N->isStrictFPOpcode();
1324 Res = CurDAG->getNode(X86ISD::STRICT_VRNDSCALE, dl,
1325 {
N->getValueType(0), MVT::Other},
1326 {
N->getOperand(0),
N->getOperand(1),
1327 CurDAG->getTargetConstant(
Imm, dl, MVT::i32)});
1329 Res = CurDAG->getNode(X86ISD::VRNDSCALE, dl,
N->getValueType(0),
1331 CurDAG->getTargetConstant(
Imm, dl, MVT::i32));
1333 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1341 case X86ISD::FXOR: {
1344 MVT VT =
N->getSimpleValueType(0);
1345 if (VT.
isVector() || VT == MVT::f128)
1348 MVT VecVT = VT == MVT::f64 ? MVT::v2f64
1349 : VT == MVT::f32 ? MVT::v4f32
1359 if (Subtarget->hasSSE2()) {
1360 EVT IntVT = EVT(VecVT).changeVectorElementTypeToInteger();
1364 switch (
N->getOpcode()) {
1366 case X86ISD::FANDN:
Opc = X86ISD::ANDNP;
break;
1371 Res = CurDAG->getNode(
Opc, dl, IntVT, Op0, Op1);
1374 Res = CurDAG->getNode(
N->getOpcode(), dl, VecVT, Op0, Op1);
1377 CurDAG->getIntPtrConstant(0, dl));
1379 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1386 if (OptLevel != CodeGenOptLevel::None &&
1389 !Subtarget->useIndirectThunkCalls() &&
1390 ((
N->getOpcode() == X86ISD::CALL && !Subtarget->slowTwoMemOps() &&
1391 !Subtarget->slowIndirectCall()) ||
1392 (
N->getOpcode() == X86ISD::TC_RETURN &&
1393 (Subtarget->is64Bit() ||
1394 !getTargetMachine().isPositionIndependent())))) {
1414 bool HasCallSeq =
N->getOpcode() == X86ISD::CALL;
1419 if (
N->getOpcode() == X86ISD::TC_RETURN && !checkTCRetEnoughRegs(
N))
1435 switch (
N->getOpcode()) {
1440 MVT SrcVT =
N->getOperand(0).getSimpleValueType();
1441 MVT DstVT =
N->getSimpleValueType(0);
1449 const X86TargetLowering *X86Lowering =
1450 static_cast<const X86TargetLowering *
>(TLI);
1453 if (SrcIsSSE && DstIsSSE)
1456 if (!SrcIsSSE && !DstIsSSE) {
1461 if (
N->getConstantOperandVal(1))
1469 SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
1471 MachinePointerInfo MPI =
1478 CurDAG->getEntryNode(), dl,
N->getOperand(0), MemTmp, MPI, MemVT);
1480 MemTmp, MPI, MemVT);
1487 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Result);
1496 MVT SrcVT =
N->getOperand(1).getSimpleValueType();
1497 MVT DstVT =
N->getSimpleValueType(0);
1505 const X86TargetLowering *X86Lowering =
1506 static_cast<const X86TargetLowering *
>(TLI);
1509 if (SrcIsSSE && DstIsSSE)
1512 if (!SrcIsSSE && !DstIsSSE) {
1517 if (
N->getConstantOperandVal(2))
1525 SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
1527 MachinePointerInfo MPI =
1536 SDVTList VTs = CurDAG->getVTList(MVT::Other);
1537 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), MemTmp};
1538 Store = CurDAG->getMemIntrinsicNode(X86ISD::FST, dl, VTs,
Ops, MemVT,
1541 if (
N->getFlags().hasNoFPExcept()) {
1543 Flags.setNoFPExcept(
true);
1544 Store->setFlags(Flags);
1547 assert(SrcVT == MemVT &&
"Unexpected VT!");
1548 Store = CurDAG->getStore(
N->getOperand(0), dl,
N->getOperand(1), MemTmp,
1553 SDVTList VTs = CurDAG->getVTList(DstVT, MVT::Other);
1555 Result = CurDAG->getMemIntrinsicNode(
1556 X86ISD::FLD, dl, VTs,
Ops, MemVT, MPI,
1558 if (
N->getFlags().hasNoFPExcept()) {
1560 Flags.setNoFPExcept(
true);
1564 assert(DstVT == MemVT &&
"Unexpected VT!");
1565 Result = CurDAG->getLoad(DstVT, dl,
Store, MemTmp, MPI);
1573 CurDAG->ReplaceAllUsesWith(
N,
Result.getNode());
1587 CurDAG->RemoveDeadNodes();
1591bool X86DAGToDAGISel::tryOptimizeRem8Extend(SDNode *
N) {
1592 unsigned Opc =
N->getMachineOpcode();
1593 if (
Opc != X86::MOVZX32rr8 &&
Opc != X86::MOVSX32rr8 &&
1594 Opc != X86::MOVSX64rr8)
1606 unsigned ExpectedOpc =
Opc == X86::MOVZX32rr8 ? X86::MOVZX32rr8_NOREX
1607 : X86::MOVSX32rr8_NOREX;
1612 if (
Opc == X86::MOVSX64rr8) {
1615 MachineSDNode *Extend = CurDAG->getMachineNode(X86::MOVSX64rr32, SDLoc(
N),
1617 ReplaceUses(
N, Extend);
1626void X86DAGToDAGISel::PostprocessISelDAG() {
1628 if (TM.getOptLevel() == CodeGenOptLevel::None)
1633 bool MadeChange =
false;
1634 while (Position != CurDAG->allnodes_begin()) {
1635 SDNode *
N = &*--Position;
1637 if (
N->use_empty() || !
N->isMachineOpcode())
1640 if (tryOptimizeRem8Extend(
N)) {
1645 unsigned Opc =
N->getMachineOpcode();
1656 case X86::CTEST16rr:
1657 case X86::CTEST32rr:
1658 case X86::CTEST64rr: {
1664#define CASE_ND(OP) \
1667 switch (
And.getMachineOpcode()) {
1674 if (
And->hasAnyUseOfValue(1))
1677 Ops[0] =
And.getOperand(0);
1678 Ops[1] =
And.getOperand(1);
1679 MachineSDNode *
Test =
1680 CurDAG->getMachineNode(
Opc, SDLoc(
N), MVT::i32,
Ops);
1681 ReplaceUses(
N,
Test);
1689 if (
And->hasAnyUseOfValue(1))
1692 bool IsCTESTCC = X86::isCTESTCC(
Opc);
1693#define FROM_TO(A, B) \
1694 CASE_ND(A) NewOpc = IsCTESTCC ? X86::C##B : X86::B; \
1696 switch (
And.getMachineOpcode()) {
1706 And.getOperand(3),
And.getOperand(4),
1707 And.getOperand(5),
And.getOperand(0)};
1710 Ops.push_back(
N->getOperand(2));
1711 Ops.push_back(
N->getOperand(3));
1714 Ops.push_back(
And.getOperand(6));
1717 Ops.push_back(
N->getOperand(4));
1719 MachineSDNode *
Test = CurDAG->getMachineNode(
1720 NewOpc, SDLoc(
N), MVT::i32, MVT::Other,
Ops);
1721 CurDAG->setNodeMemRefs(
1734 case X86::KORTESTBkk:
1735 case X86::KORTESTWkk:
1736 case X86::KORTESTDkk:
1737 case X86::KORTESTQkk: {
1739 if (Op0 !=
N->getOperand(1) || !
N->isOnlyUserOf(Op0.
getNode()) ||
1754#define FROM_TO(A, B) \
1766 if (NewOpc == X86::KTESTWkk && !Subtarget->hasDQI())
1769 MachineSDNode *KTest = CurDAG->getMachineNode(
1771 ReplaceUses(
N, KTest);
1776 case TargetOpcode::SUBREG_TO_REG: {
1777 unsigned SubRegIdx =
N->getConstantOperandVal(1);
1778 if (SubRegIdx != X86::sub_xmm && SubRegIdx != X86::sub_ymm)
1795 CASE(VMOVAPDZ128rr)
CASE(VMOVUPDZ128rr)
1796 CASE(VMOVAPSZ128rr)
CASE(VMOVUPSZ128rr)
1797 CASE(VMOVDQA32Z128rr)
CASE(VMOVDQU32Z128rr)
1798 CASE(VMOVDQA64Z128rr)
CASE(VMOVDQU64Z128rr)
1799 CASE(VMOVAPDZ256rr)
CASE(VMOVUPDZ256rr)
1800 CASE(VMOVAPSZ256rr)
CASE(VMOVUPSZ256rr)
1801 CASE(VMOVDQA32Z256rr)
CASE(VMOVDQU32Z256rr)
1802 CASE(VMOVDQA64Z256rr)
CASE(VMOVDQU64Z256rr)
1807 if (!
In.isMachineOpcode() ||
1808 In.getMachineOpcode() <= TargetOpcode::GENERIC_OP_END)
1813 uint64_t TSFlags = getInstrInfo()->get(
In.getMachineOpcode()).TSFlags;
1821 CurDAG->UpdateNodeOperands(
N, In,
N->getOperand(1));
1828 CurDAG->RemoveDeadNodes();
1833void X86DAGToDAGISel::emitSpecialCodeForMain() {
1834 if (Subtarget->isTargetCygMing()) {
1835 TargetLowering::ArgListTy
Args;
1836 auto &
DL = CurDAG->getDataLayout();
1838 TargetLowering::CallLoweringInfo CLI(*CurDAG);
1839 CLI.setChain(CurDAG->getRoot())
1840 .setCallee(CallingConv::C, Type::getVoidTy(*CurDAG->getContext()),
1841 CurDAG->getExternalSymbol(
"__main", TLI->getPointerTy(
DL)),
1843 const TargetLowering &TLI = CurDAG->getTargetLoweringInfo();
1845 CurDAG->setRoot(
Result.second);
1849void X86DAGToDAGISel::emitFunctionEntryCode() {
1852 if (
F.hasExternalLinkage() &&
F.getName() ==
"main")
1853 emitSpecialCodeForMain();
1867 X86ISelAddressMode &AM) {
1872 int64_t Val = AM.Disp +
Offset;
1875 if (Val != 0 && (AM.ES || AM.MCSym))
1879 if (Subtarget->is64Bit()) {
1882 AM.hasSymbolicDisplacement()))
1886 if (AM.BaseType == X86ISelAddressMode::FrameIndexBase &&
1905 if (Subtarget->isTarget64BitILP32() &&
1907 !AM.hasBaseOrIndexReg())
1909 }
else if (Subtarget->is16Bit()) {
1912 if (Val < -(int64_t)UINT16_MAX || Val > (int64_t)UINT16_MAX)
1922bool X86DAGToDAGISel::matchLoadInAddress(LoadSDNode *
N, X86ISelAddressMode &AM,
1923 bool AllowSegmentRegForX32) {
1936 !IndirectTlsSegRefs &&
1937 (Subtarget->isTargetGlibc() || Subtarget->isTargetMusl() ||
1938 Subtarget->isTargetAndroid() || Subtarget->isTargetFuchsia())) {
1939 if (Subtarget->isTarget64BitILP32() && !AllowSegmentRegForX32)
1941 switch (
N->getPointerInfo().getAddrSpace()) {
1943 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
1946 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
1959bool X86DAGToDAGISel::matchWrapper(
SDValue N, X86ISelAddressMode &AM) {
1962 if (AM.hasSymbolicDisplacement())
1965 bool IsRIPRelTLS =
false;
1966 bool IsRIPRel =
N.getOpcode() == X86ISD::WrapperRIP;
1983 if (IsRIPRel && AM.hasBaseOrIndexReg())
1987 X86ISelAddressMode Backup = AM;
1992 AM.GV =
G->getGlobal();
1993 AM.SymbolFlags =
G->getTargetFlags();
1996 AM.CP = CP->getConstVal();
1997 AM.Alignment = CP->getAlign();
1998 AM.SymbolFlags = CP->getTargetFlags();
1999 Offset = CP->getOffset();
2001 AM.ES = S->getSymbol();
2002 AM.SymbolFlags = S->getTargetFlags();
2004 AM.MCSym = S->getMCSymbol();
2006 AM.JT = J->getIndex();
2007 AM.SymbolFlags = J->getTargetFlags();
2009 AM.BlockAddr = BA->getBlockAddress();
2010 AM.SymbolFlags = BA->getTargetFlags();
2011 Offset = BA->getOffset();
2016 if (Subtarget->is64Bit() && !IsRIPRel && AM.GV &&
2017 TM.isLargeGlobalValue(AM.GV)) {
2022 if (foldOffsetIntoAddress(
Offset, AM)) {
2028 AM.setBaseReg(CurDAG->getRegister(X86::RIP, MVT::i64));
2036bool X86DAGToDAGISel::matchAddress(
SDValue N, X86ISelAddressMode &AM) {
2037 if (matchAddressRecursively(
N, AM, 0))
2044 if (Subtarget->isTarget64BitILP32() &&
2045 AM.BaseType == X86ISelAddressMode::RegBase &&
2046 AM.Base_Reg.
getNode() !=
nullptr && AM.IndexReg.
getNode() ==
nullptr) {
2047 SDValue Save_Base_Reg = AM.Base_Reg;
2050 if (matchLoadInAddress(LoadN, AM,
true))
2051 AM.Base_Reg = Save_Base_Reg;
2060 if (AM.Scale == 2 && !AM.NegateIndex &&
2061 AM.BaseType == X86ISelAddressMode::RegBase &&
2062 AM.Base_Reg.
getNode() ==
nullptr) {
2063 AM.Base_Reg = AM.IndexReg;
2070 (!AM.GV || !TM.isLargeGlobalValue(AM.GV)) && Subtarget->is64Bit() &&
2071 AM.Scale == 1 && AM.BaseType == X86ISelAddressMode::RegBase &&
2072 AM.Base_Reg.
getNode() ==
nullptr && AM.IndexReg.
getNode() ==
nullptr &&
2084 AM.Base_Reg = CurDAG->getRegister(X86::RIP, MVT::i64);
2097bool X86DAGToDAGISel::hasMaterializingUse(
SDValue V)
const {
2098 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
2099 for (SDUse &U :
V->uses()) {
2100 if (
U.getResNo() !=
V.getResNo())
2102 SDNode *
User =
U.getUser();
2108 if (St->getValue() == V)
2119 if (!
User->isMachineOpcode())
2121 const MCInstrDesc &
Desc =
TII->get(
User->getMachineOpcode());
2122 if (!
Desc.mayStore())
2125 if (MemRefBegin < 0)
2128 for (
unsigned I = 0,
E =
User->getNumOperands();
I !=
E; ++
I) {
2129 if (
I >=
static_cast<unsigned>(MemRefBegin) &&
I < MemRefEnd)
2141bool X86DAGToDAGISel::matchAdd(
SDValue &
N, X86ISelAddressMode &AM,
2145 HandleSDNode Handle(
N);
2147 auto IsAddOrAddLike = [&](
SDValue V) {
2148 return V.getOpcode() ==
ISD::ADD || CurDAG->isADDLike(V);
2157 auto SplitsMaterializedValue = [&](
SDValue Op) {
2158 if (!AM.IsForLEA || !hasMaterializingUse(
Op))
2162 if (IsAddOrAddLike(
Op))
2163 return IsAddOrAddLike(
Op.getOperand(0)) ||
2164 IsAddOrAddLike(
Op.getOperand(1));
2169 return C->getZExtValue() >= 1 &&
C->getZExtValue() <= 3 &&
2170 IsAddOrAddLike(
Op.getOperand(0));
2190 if (SplitsMaterializedValue(
Op) && !AM.isRIPRelative())
2191 return matchAddressBase(
Op, AM);
2192 return matchAddressRecursively(
Op, AM,
Depth + 1);
2195 X86ISelAddressMode Backup = AM;
2196 if (!MatchOperand(
N.getOperand(0)) &&
2197 !MatchOperand(Handle.getValue().getOperand(1)))
2202 if (!MatchOperand(Handle.getValue().getOperand(1)) &&
2203 !MatchOperand(Handle.getValue().getOperand(0)))
2210 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2213 N = Handle.getValue();
2219 N = Handle.getValue();
2229 if (
N->getNodeId() == -1 ||
2249 X86ISelAddressMode &AM) {
2256 if (ScaleLog <= 0 || ScaleLog >= 4 ||
2257 Mask != (0xffu << ScaleLog))
2260 MVT XVT =
X.getSimpleValueType();
2261 MVT VT =
N.getSimpleValueType();
2286 AM.Scale = (1 << ScaleLog);
2294 X86ISelAddressMode &AM) {
2305 bool FoundAnyExtend =
false;
2309 FoundAnyExtend =
true;
2327 if (ShiftAmt != 1 && ShiftAmt != 2 && ShiftAmt != 3)
2330 MVT VT =
N.getSimpleValueType();
2332 if (FoundAnyExtend) {
2353 AM.Scale = 1 << ShiftAmt;
2354 AM.IndexReg = NewAnd;
2388 X86ISelAddressMode &AM) {
2394 unsigned MaskIdx, MaskLen;
2397 unsigned MaskLZ = 64 - (MaskIdx + MaskLen);
2403 unsigned AMShiftAmt = MaskIdx;
2407 if (AMShiftAmt == 0 || AMShiftAmt > 3)
return true;
2411 unsigned ScaleDown = (64 -
X.getSimpleValueType().getSizeInBits()) + ShiftAmt;
2412 if (MaskLZ < ScaleDown)
2414 MaskLZ -= ScaleDown;
2422 bool ReplacingAnyExtend =
false;
2424 unsigned ExtendBits =
X.getSimpleValueType().getSizeInBits() -
2425 X.getOperand(0).getSimpleValueType().getSizeInBits();
2428 X =
X.getOperand(0);
2429 MaskLZ = ExtendBits > MaskLZ ? 0 : MaskLZ - ExtendBits;
2430 ReplacingAnyExtend =
true;
2432 APInt MaskedHighBits =
2439 MVT VT =
N.getSimpleValueType();
2440 if (ReplacingAnyExtend) {
2441 assert(
X.getValueType() != VT);
2448 MVT XVT =
X.getSimpleValueType();
2469 AM.Scale = 1 << AMShiftAmt;
2470 AM.IndexReg = NewExt;
2480 X86ISelAddressMode &AM,
2488 if (!Subtarget.hasTBM() &&
2489 !(Subtarget.hasBMI() && Subtarget.hasFastBEXTR()))
2493 unsigned MaskIdx, MaskLen;
2501 unsigned AMShiftAmt = MaskIdx;
2505 if (AMShiftAmt == 0 || AMShiftAmt > 3)
return true;
2507 MVT XVT =
X.getSimpleValueType();
2508 MVT VT =
N.getSimpleValueType();
2533 AM.Scale = 1 << AMShiftAmt;
2534 AM.IndexReg = NewExt;
2541 X86ISelAddressMode &AM,
2543 assert(AM.IndexReg.
getNode() ==
nullptr &&
"IndexReg already matched");
2544 assert((AM.Scale == 1 || AM.Scale == 2 || AM.Scale == 4 || AM.Scale == 8) &&
2545 "Illegal index scale");
2551 EVT VT =
N.getValueType();
2552 unsigned Opc =
N.getOpcode();
2555 if (CurDAG->isBaseWithConstantOffset(
N)) {
2558 if (!foldOffsetIntoAddress(
Offset, AM))
2559 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2563 if (
Opc ==
ISD::ADD &&
N.getOperand(0) ==
N.getOperand(1)) {
2564 if (AM.Scale <= 4) {
2566 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2571 if (
Opc == X86ISD::VSHLI) {
2572 uint64_t ShiftAmt =
N.getConstantOperandVal(1);
2573 uint64_t ScaleAmt = 1ULL << ShiftAmt;
2574 if ((AM.Scale * ScaleAmt) <= 8) {
2575 AM.Scale *= ScaleAmt;
2576 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2584 if (Src.getOpcode() ==
ISD::ADD && Src->getFlags().hasNoSignedWrap() &&
2586 if (CurDAG->isBaseWithConstantOffset(Src)) {
2587 SDValue AddSrc = Src.getOperand(0);
2589 int64_t
Offset = AddVal->getSExtValue();
2598 CurDAG->ReplaceAllUsesWith(
N, ExtAdd);
2599 CurDAG->RemoveDeadNode(
N.getNode());
2611 unsigned SrcOpc = Src.getOpcode();
2612 if (((SrcOpc ==
ISD::ADD && Src->getFlags().hasNoUnsignedWrap()) ||
2613 CurDAG->isADDLike(Src,
true)) &&
2615 if (CurDAG->isBaseWithConstantOffset(Src)) {
2616 SDValue AddSrc = Src.getOperand(0);
2618 if (!foldOffsetIntoAddress(
Offset * AM.Scale, AM)) {
2629 if ((AM.Scale * ScaleAmt) <= 8 &&
2631 CurDAG->MaskedValueIsZero(ShVal, HiBits))) {
2632 AM.Scale *= ScaleAmt;
2633 SDValue ExtShVal = CurDAG->getNode(
Opc,
DL, VT, ShVal);
2644 SDValue ExtAdd = CurDAG->getNode(SrcOpc,
DL, VT, ExtSrc, ExtVal);
2648 CurDAG->ReplaceAllUsesWith(
N, ExtAdd);
2649 CurDAG->RemoveDeadNode(
N.getNode());
2650 return Res ? Res : ExtSrc;
2660bool X86DAGToDAGISel::matchAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
2663 dbgs() <<
"MatchAddress: ";
2668 return matchAddressBase(
N, AM);
2673 if (AM.isRIPRelative()) {
2677 if (!(AM.ES || AM.MCSym) && AM.JT != -1)
2681 if (!foldOffsetIntoAddress(Cst->getSExtValue(), AM))
2686 switch (
N.getOpcode()) {
2689 if (!AM.hasSymbolicDisplacement() && AM.Disp == 0)
2692 AM.MCSym = ESNode->getMCSymbol();
2699 if (!foldOffsetIntoAddress(Val, AM))
2704 case X86ISD::Wrapper:
2705 case X86ISD::WrapperRIP:
2706 if (!matchWrapper(
N, AM))
2716 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2717 AM.Base_Reg.
getNode() ==
nullptr &&
2719 AM.BaseType = X86ISelAddressMode::FrameIndexBase;
2726 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
2730 unsigned Val = CN->getZExtValue();
2735 if (Val == 1 || Val == 2 || Val == 3) {
2737 AM.Scale = 1 << Val;
2738 AM.IndexReg = matchIndexRecursively(ShVal, AM,
Depth + 1);
2746 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
break;
2750 assert(
N.getSimpleValueType().getSizeInBits() <= 64 &&
2751 "Unexpected value size!");
2763 uint64_t Mask =
And.getConstantOperandVal(1) >>
N.getConstantOperandVal(1);
2775 if (
N.getResNo() != 0)
break;
2778 case X86ISD::MUL_IMM:
2780 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2781 AM.Base_Reg.
getNode() ==
nullptr &&
2782 AM.IndexReg.
getNode() ==
nullptr) {
2784 if (CN->getZExtValue() == 3 || CN->getZExtValue() == 5 ||
2785 CN->getZExtValue() == 9) {
2786 AM.Scale = unsigned(CN->getZExtValue())-1;
2798 uint64_t Disp = AddVal->getSExtValue() * CN->getZExtValue();
2799 if (foldOffsetIntoAddress(Disp, AM))
2800 Reg =
N.getOperand(0);
2802 Reg =
N.getOperand(0);
2805 AM.IndexReg = AM.Base_Reg =
Reg;
2823 HandleSDNode Handle(
N);
2826 X86ISelAddressMode Backup = AM;
2827 if (matchAddressRecursively(
N.getOperand(0), AM,
Depth+1)) {
2828 N = Handle.getValue();
2832 N = Handle.getValue();
2834 if (AM.IndexReg.
getNode() || AM.isRIPRelative()) {
2853 std::optional<unsigned> NegScale;
2856 uint64_t ShVal = ShAmt->getZExtValue();
2857 if (ShVal >= 1 && ShVal <= 3) {
2858 NegScale = 1u << ShVal;
2876 RHS.getOperand(0).getValueType() == MVT::i32))
2879 bool BaseIsNegatedValue = NegScale &&
2880 AM.BaseType == X86ISelAddressMode::RegBase &&
2887 if (((AM.BaseType == X86ISelAddressMode::RegBase && AM.Base_Reg.
getNode() &&
2889 AM.BaseType == X86ISelAddressMode::FrameIndexBase) &&
2890 !BaseIsNegatedValue)
2894 if ((AM.hasSymbolicDisplacement() && !Backup.hasSymbolicDisplacement()) +
2895 ((AM.Disp != 0) && (Backup.Disp == 0)) +
2908 AM.NegateIndex =
true;
2909 AM.Scale = NegScale.value_or(1);
2916 if (!CurDAG->isADDLike(
N))
2920 if (!matchAdd(
N, AM,
Depth))
2929 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
break;
2933 assert(
N.getSimpleValueType().getSizeInBits() <= 64 &&
2934 "Unexpected value size!");
2939 if (
N.getOperand(0).getOpcode() ==
ISD::SRL) {
2968 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
2976 if (
SDValue Index = matchIndexRecursively(
N, AM,
Depth + 1))
2978 AM.IndexReg =
Index;
2984 if (Src.getOpcode() ==
ISD::AND && Src.hasOneUse())
2986 Mask = MaskC->getAPIntValue();
2987 Src = Src.getOperand(0);
2990 if (Src.getOpcode() ==
ISD::SHL && Src.hasOneUse() &&
N->hasOneUse()) {
2992 SDValue ShlSrc = Src.getOperand(0);
2993 SDValue ShlAmt = Src.getOperand(1);
2997 unsigned ShAmtV = ShAmtC->getZExtValue();
3005 if (!Src->getFlags().hasNoUnsignedWrap() &&
3006 !CurDAG->MaskedValueIsZero(ShlSrc, HighZeros & Mask))
3014 MVT VT =
N.getSimpleValueType();
3018 if (!
Mask.isAllOnes()) {
3019 Res = CurDAG->getConstant(
Mask.lshr(ShAmtV),
DL, SrcVT);
3021 Res = CurDAG->getNode(
ISD::AND,
DL, SrcVT, ShlSrc, Res);
3028 CurDAG->ReplaceAllUsesWith(
N, NewShl);
3029 CurDAG->RemoveDeadNode(
N.getNode());
3032 AM.Scale = 1 << ShAmtV;
3036 AM.IndexReg = matchIndexRecursively(Zext, AM,
Depth + 1);
3040 if (Src.getOpcode() ==
ISD::SRL && !
Mask.isAllOnes()) {
3043 Src.getOperand(0), AM))
3048 Src.getOperand(0), AM))
3053 Src.getOperand(0), AM, *Subtarget))
3061 return matchAddressBase(
N, AM);
3066bool X86DAGToDAGISel::matchAddressBase(
SDValue N, X86ISelAddressMode &AM) {
3068 if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base_Reg.
getNode()) {
3081 AM.BaseType = X86ISelAddressMode::RegBase;
3086bool X86DAGToDAGISel::matchVectorAddressRecursively(
SDValue N,
3087 X86ISelAddressMode &AM,
3090 dbgs() <<
"MatchVectorAddress: ";
3095 return matchAddressBase(
N, AM);
3098 switch (
N.getOpcode()) {
3101 if (!foldOffsetIntoAddress(Val, AM))
3105 case X86ISD::Wrapper:
3106 if (!matchWrapper(
N, AM))
3112 HandleSDNode Handle(
N);
3114 X86ISelAddressMode Backup = AM;
3115 if (!matchVectorAddressRecursively(
N.getOperand(0), AM,
Depth + 1) &&
3116 !matchVectorAddressRecursively(Handle.getValue().getOperand(1), AM,
3122 if (!matchVectorAddressRecursively(Handle.getValue().getOperand(1), AM,
3124 !matchVectorAddressRecursively(Handle.getValue().getOperand(0), AM,
3129 N = Handle.getValue();
3134 return matchAddressBase(
N, AM);
3140bool X86DAGToDAGISel::matchVectorAddress(
SDValue N, X86ISelAddressMode &AM) {
3141 return matchVectorAddressRecursively(
N, AM, 0);
3144bool X86DAGToDAGISel::selectVectorAddr(MemSDNode *Parent,
SDValue BasePtr,
3149 X86ISelAddressMode AM;
3155 AM.IndexReg = matchIndexRecursively(IndexOp, AM, 0);
3157 AM.IndexReg = IndexOp;
3161 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
3163 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
3165 AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16);
3168 MVT VT =
BasePtr.getSimpleValueType();
3171 if (matchVectorAddress(BasePtr, AM))
3174 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3187 SDValue &Segment,
bool HasNDDM) {
3188 X86ISelAddressMode AM;
3195 Parent->
getOpcode() != X86ISD::TLSCALL &&
3196 Parent->
getOpcode() != X86ISD::ENQCMD &&
3197 Parent->
getOpcode() != X86ISD::ENQCMDS &&
3198 Parent->
getOpcode() != X86ISD::EH_SJLJ_SETJMP &&
3199 Parent->
getOpcode() != X86ISD::EH_SJLJ_LONGJMP) {
3200 unsigned AddrSpace =
3203 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
3205 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
3207 AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16);
3212 MVT VT =
N.getSimpleValueType();
3214 if (matchAddress(
N, AM))
3217 if (!HasNDDM && !AM.isRIPRelative())
3220 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3227 return selectAddr(Parent,
N,
Base, Scale, Index, Disp, Segment,
3228 Subtarget->hasNDDM());
3240 if (
N->getOpcode() != X86ISD::Wrapper)
3243 N =
N.getOperand(0);
3260 return CR->getUnsignedMax().ult(1ull << 32);
3262 return !TM.isLargeGlobalValue(GV);
3271 if (!selectLEAAddr(
N,
Base, Scale, Index, Disp, Segment))
3277 SubReg = X86::sub_8bit;
3279 SubReg = X86::sub_16bit;
3281 SubReg = X86::sub_32bit;
3284 if (RN &&
RN->getReg() == 0)
3285 Base = CurDAG->getRegister(0, MVT::i64);
3292 Base = CurDAG->getTargetInsertSubreg(SubReg,
DL, MVT::i64, ImplDef,
Base);
3295 [[maybe_unused]] EVT IndexType =
Index.getValueType();
3297 if (RN &&
RN->getReg() == 0)
3298 Index = CurDAG->getRegister(0, MVT::i64);
3301 "Expect to be extending 8/16/32-bit registers for use in LEA");
3304 Index = CurDAG->getTargetInsertSubreg(SubReg,
DL, MVT::i64, ImplDef, Index);
3312bool X86DAGToDAGISel::selectLEAAddr(
SDValue N,
3316 X86ISelAddressMode AM;
3321 MVT VT =
N.getSimpleValueType();
3326 SDValue T = CurDAG->getRegister(0, MVT::i32);
3328 if (matchAddress(
N, AM))
3333 unsigned Complexity = 0;
3334 if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base_Reg.
getNode())
3336 else if (AM.BaseType == X86ISelAddressMode::FrameIndexBase)
3352 if (AM.hasSymbolicDisplacement()) {
3354 if (Subtarget->is64Bit())
3364 auto isMathWithFlags = [](
SDValue V) {
3365 switch (
V.getOpcode()) {
3379 return !
SDValue(
V.getNode(), 1).use_empty();
3386 if (isMathWithFlags(
N.getOperand(0)) || isMathWithFlags(
N.getOperand(1)))
3394 if (Complexity <= 2)
3397 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3408 X86ISelAddressMode AM;
3410 AM.GV = GA->getGlobal();
3411 AM.Disp += GA->getOffset();
3412 AM.SymbolFlags = GA->getTargetFlags();
3415 AM.ES = SA->getSymbol();
3416 AM.SymbolFlags = SA->getTargetFlags();
3419 if (Subtarget->is32Bit()) {
3421 AM.IndexReg = CurDAG->getRegister(X86::EBX, MVT::i32);
3424 MVT VT =
N.getSimpleValueType();
3425 getAddressOperands(AM, SDLoc(
N), VT,
Base, Scale, Index, Disp, Segment);
3433 EVT VT =
N.getValueType();
3434 bool WasTruncated =
false;
3436 WasTruncated =
true;
3437 N =
N.getOperand(0);
3440 if (
N.getOpcode() != X86ISD::Wrapper)
3446 unsigned Opc =
N.getOperand(0)->getOpcode();
3448 Op =
N.getOperand(0);
3451 return !WasTruncated;
3456 std::optional<ConstantRange> CR = GA->getGlobal()->getAbsoluteSymbolRange();
3457 if (!CR || CR->getUnsignedMax().uge(1ull << VT.
getSizeInBits()))
3461 Op = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(
N), VT,
3462 GA->getOffset(), GA->getTargetFlags());
3466bool X86DAGToDAGISel::tryFoldLoad(SDNode *Root, SDNode *
P,
SDValue N,
3470 assert(Root &&
P &&
"Unknown root/parent nodes");
3472 !IsProfitableToFold(
N,
P, Root) ||
3473 !IsLegalToFold(
N,
P, Root, OptLevel))
3476 return selectAddr(
N.getNode(),
3477 N.getOperand(1),
Base, Scale, Index, Disp, Segment);
3480bool X86DAGToDAGISel::tryFoldBroadcast(SDNode *Root, SDNode *
P,
SDValue N,
3484 assert(Root &&
P &&
"Unknown root/parent nodes");
3485 if (
N->getOpcode() != X86ISD::VBROADCAST_LOAD ||
3486 !IsProfitableToFold(
N,
P, Root) ||
3487 !IsLegalToFold(
N,
P, Root, OptLevel))
3490 return selectAddr(
N.getNode(),
3491 N.getOperand(1),
Base, Scale, Index, Disp, Segment);
3497SDNode *X86DAGToDAGISel::getGlobalBaseReg() {
3500 return CurDAG->getRegister(GlobalBaseReg, TLI->
getPointerTy(
DL)).getNode();
3503bool X86DAGToDAGISel::isSExtAbsoluteSymbolRef(
unsigned Width, SDNode *
N)
const {
3505 N =
N->getOperand(0).getNode();
3506 if (
N->getOpcode() != X86ISD::Wrapper)
3513 auto *GV = GA->getGlobal();
3516 return CR->getSignedMin().sge(-1ull << Width) &&
3517 CR->getSignedMax().slt(1ull << Width);
3523 !TM.isLargeGlobalValue(GV);
3527 assert(
N->isMachineOpcode() &&
"Unexpected node");
3528 unsigned Opc =
N->getMachineOpcode();
3529 const MCInstrDesc &MCID = getInstrInfo()->get(
Opc);
3534 return static_cast<X86::CondCode>(
N->getConstantOperandVal(CondNo));
3539bool X86DAGToDAGISel::onlyUsesZeroFlag(
SDValue Flags)
const {
3541 for (SDUse &Use :
Flags->uses()) {
3543 if (
Use.getResNo() !=
Flags.getResNo())
3551 for (SDUse &FlagUse :
User->uses()) {
3553 if (FlagUse.getResNo() != 1)
3556 if (!FlagUse.getUser()->isMachineOpcode())
3576bool X86DAGToDAGISel::hasNoSignFlagUses(
SDValue Flags)
const {
3578 for (SDUse &Use :
Flags->uses()) {
3580 if (
Use.getResNo() !=
Flags.getResNo())
3588 for (SDUse &FlagUse :
User->uses()) {
3590 if (FlagUse.getResNo() != 1)
3593 if (!FlagUse.getUser()->isMachineOpcode())
3633 bool X86DAGToDAGISel::hasNoCarryFlagUses(
SDValue Flags)
const {
3635 for (SDUse &Use :
Flags->uses()) {
3637 if (
Use.getResNo() !=
Flags.getResNo())
3641 unsigned UserOpc =
User->getOpcode();
3648 for (SDUse &FlagUse :
User->uses()) {
3650 if (FlagUse.getResNo() != 1)
3653 if (!FlagUse.getUser()->isMachineOpcode())
3673 case X86ISD::SETCC: CCOpNo = 0;
break;
3674 case X86ISD::SETCC_CARRY: CCOpNo = 0;
break;
3675 case X86ISD::CMOV: CCOpNo = 2;
break;
3676 case X86ISD::BRCOND: CCOpNo = 2;
break;
3689 unsigned Depth = 0) {
3710bool X86DAGToDAGISel::checkTCRetEnoughRegs(SDNode *
N)
const {
3711 assert(
N->getOpcode() == X86ISD::TC_RETURN);
3722 const X86RegisterInfo *RI = Subtarget->getRegisterInfo();
3726 if (Subtarget->is64Bit()) {
3729 ? &X86::GR64_TCW64RegClass
3730 : &X86::GR64_TCRegClass;
3738 ? &X86::GR32RegClass
3739 : &X86::GR32_TCRegClass;
3746 unsigned LoadGPRs = 2;
3748 if (Subtarget->is32Bit()) {
3753 }
else if (
BasePtr.getOpcode() == X86ISD::Wrapper &&
3755 if (getTargetMachine().isPositionIndependent())
3763 for (
unsigned I = 3,
E =
N->getNumOperands();
I !=
E; ++
I) {
3765 if (!RI->isGeneralPurposeRegister(*MF,
RN->getReg()))
3767 if (++
ArgGPRs + LoadGPRs > AvailGPRs)
3783 if (StoredVal.
getResNo() != 0)
return false;
3800 if (!
Load.hasOneUse())
3808 bool FoundLoad =
false;
3812 const unsigned int Max = 1024;
3854 if (Chain ==
Load.getValue(1)) {
3860 if (
Op ==
Load.getValue(1)) {
3876 if (
Op.getNode() != LoadNode)
3908bool X86DAGToDAGISel::foldLoadStoreIntoMemOperand(SDNode *Node) {
3910 SDValue StoredVal = StoreNode->getOperand(1);
3916 EVT MemVT = StoreNode->getMemoryVT();
3917 if (MemVT != MVT::i64 && MemVT != MVT::i32 && MemVT != MVT::i16 &&
3921 bool IsCommutable =
false;
3922 bool IsNegate =
false;
3936 IsCommutable =
true;
3940 unsigned LoadOpNo = IsNegate ? 1 : 0;
3941 LoadSDNode *LoadNode =
nullptr;
3944 LoadNode, InputChain)) {
3951 LoadNode, InputChain))
3956 if (!selectAddr(LoadNode, LoadNode->
getBasePtr(),
Base, Scale, Index, Disp,
3960 auto SelectOpcode = [&](
unsigned Opc64,
unsigned Opc32,
unsigned Opc16,
3981 unsigned NewOpc = SelectOpcode(X86::NEG64m, X86::NEG32m, X86::NEG16m,
3984 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32,
3991 if (!Subtarget->slowIncDec() || CurDAG->shouldOptForSize()) {
3995 if ((IsOne || IsNegOne) && hasNoCarryFlagUses(StoredVal.
getValue(1))) {
3997 ((
Opc == X86ISD::ADD) == IsOne)
3998 ? SelectOpcode(X86::INC64m, X86::INC32m, X86::INC16m, X86::INC8m)
3999 : SelectOpcode(X86::DEC64m, X86::DEC32m, X86::DEC16m, X86::DEC8m);
4001 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32,
4012 auto SelectRegOpcode = [SelectOpcode](
unsigned Opc) {
4015 return SelectOpcode(X86::ADD64mr, X86::ADD32mr, X86::ADD16mr,
4018 return SelectOpcode(X86::ADC64mr, X86::ADC32mr, X86::ADC16mr,
4021 return SelectOpcode(X86::SUB64mr, X86::SUB32mr, X86::SUB16mr,
4024 return SelectOpcode(X86::SBB64mr, X86::SBB32mr, X86::SBB16mr,
4027 return SelectOpcode(X86::AND64mr, X86::AND32mr, X86::AND16mr,
4030 return SelectOpcode(X86::OR64mr, X86::OR32mr, X86::OR16mr, X86::OR8mr);
4032 return SelectOpcode(X86::XOR64mr, X86::XOR32mr, X86::XOR16mr,
4038 auto SelectImmOpcode = [SelectOpcode](
unsigned Opc) {
4041 return SelectOpcode(X86::ADD64mi32, X86::ADD32mi, X86::ADD16mi,
4044 return SelectOpcode(X86::ADC64mi32, X86::ADC32mi, X86::ADC16mi,
4047 return SelectOpcode(X86::SUB64mi32, X86::SUB32mi, X86::SUB16mi,
4050 return SelectOpcode(X86::SBB64mi32, X86::SBB32mi, X86::SBB16mi,
4053 return SelectOpcode(X86::AND64mi32, X86::AND32mi, X86::AND16mi,
4056 return SelectOpcode(X86::OR64mi32, X86::OR32mi, X86::OR16mi,
4059 return SelectOpcode(X86::XOR64mi32, X86::XOR32mi, X86::XOR16mi,
4066 unsigned NewOpc = SelectRegOpcode(
Opc);
4072 int64_t OperandV = OperandC->getSExtValue();
4077 if ((
Opc == X86ISD::ADD ||
Opc == X86ISD::SUB) &&
4079 (MemVT == MVT::i64 && !
isInt<32>(OperandV) &&
4081 hasNoCarryFlagUses(StoredVal.
getValue(1))) {
4082 OperandV = -OperandV;
4083 Opc =
Opc == X86ISD::ADD ? X86ISD::SUB : X86ISD::ADD;
4086 if (MemVT != MVT::i64 ||
isInt<32>(OperandV)) {
4087 Operand = CurDAG->getSignedTargetConstant(OperandV, SDLoc(Node), MemVT);
4088 NewOpc = SelectImmOpcode(
Opc);
4092 if (
Opc == X86ISD::ADC ||
Opc == X86ISD::SBB) {
4094 CurDAG->getCopyToReg(InputChain, SDLoc(Node), X86::EFLAGS,
4098 Segment, Operand, CopyTo, CopyTo.
getValue(1)};
4099 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other,
4103 Segment, Operand, InputChain};
4104 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other,
4113 MachineMemOperand *MemOps[] = {StoreNode->getMemOperand(),
4115 CurDAG->setNodeMemRefs(Result, MemOps);
4121 CurDAG->RemoveDeadNode(Node);
4132bool X86DAGToDAGISel::matchBitExtract(SDNode *Node) {
4136 "Should be either an and-mask, or right-shift after clearing high bits.");
4139 if (!Subtarget->hasBMI() && !Subtarget->hasBMI2())
4142 MVT NVT =
Node->getSimpleValueType(0);
4145 if (NVT != MVT::i32 && NVT != MVT::i64)
4153 const bool AllowExtraUsesByDefault = Subtarget->hasBMI2();
4154 auto checkUses = [AllowExtraUsesByDefault](
4156 std::optional<bool> AllowExtraUses) {
4157 return AllowExtraUses.value_or(AllowExtraUsesByDefault) ||
4158 Op.getNode()->hasNUsesOfValue(NUses,
Op.getResNo());
4160 auto checkOneUse = [checkUses](
SDValue Op,
4161 std::optional<bool> AllowExtraUses =
4163 return checkUses(
Op, 1, AllowExtraUses);
4165 auto checkTwoUse = [checkUses](
SDValue Op,
4166 std::optional<bool> AllowExtraUses =
4168 return checkUses(
Op, 2, AllowExtraUses);
4171 auto peekThroughOneUseTruncation = [checkOneUse](
SDValue V) {
4173 assert(
V.getSimpleValueType() == MVT::i32 &&
4174 V.getOperand(0).getSimpleValueType() == MVT::i64 &&
4175 "Expected i64 -> i32 truncation");
4176 V =
V.getOperand(0);
4182 auto matchPatternA = [checkOneUse, peekThroughOneUseTruncation, &NBits,
4185 if (
Mask->getOpcode() !=
ISD::ADD || !checkOneUse(Mask))
4191 SDValue M0 = peekThroughOneUseTruncation(
Mask->getOperand(0));
4196 NBits =
M0->getOperand(1);
4197 NegateNBits =
false;
4201 auto isAllOnes = [
this, peekThroughOneUseTruncation, NVT](
SDValue V) {
4202 V = peekThroughOneUseTruncation(V);
4203 return CurDAG->MaskedValueIsAllOnes(
4209 auto matchPatternB = [checkOneUse, isAllOnes, peekThroughOneUseTruncation,
4212 if (
Mask.getOpcode() !=
ISD::XOR || !checkOneUse(Mask))
4215 if (!isAllOnes(
Mask->getOperand(1)))
4218 SDValue M0 = peekThroughOneUseTruncation(
Mask->getOperand(0));
4222 if (!isAllOnes(
M0->getOperand(0)))
4224 NBits =
M0->getOperand(1);
4225 NegateNBits =
false;
4231 auto canonicalizeShiftAmt = [&NBits, &NegateNBits](
SDValue ShiftAmt,
4232 unsigned Bitwidth) {
4237 NBits = NBits.getOperand(0);
4243 if (!V0 || V0->getZExtValue() != Bitwidth)
4245 NBits = NBits.getOperand(1);
4246 NegateNBits =
false;
4252 auto matchPatternC = [checkOneUse, peekThroughOneUseTruncation, &NegateNBits,
4255 Mask = peekThroughOneUseTruncation(Mask);
4256 unsigned Bitwidth =
Mask.getSimpleValueType().getSizeInBits();
4258 if (
Mask.getOpcode() !=
ISD::SRL || !checkOneUse(Mask))
4265 if (!checkOneUse(
M1))
4267 canonicalizeShiftAmt(
M1, Bitwidth);
4272 return !NegateNBits;
4280 auto matchPatternD = [checkOneUse, checkTwoUse, canonicalizeShiftAmt,
4281 AllowExtraUsesByDefault, &NegateNBits,
4282 &
X](SDNode *
Node) ->
bool {
4294 canonicalizeShiftAmt(N1, Bitwidth);
4298 const bool AllowExtraUses = AllowExtraUsesByDefault && !NegateNBits;
4299 if (!checkOneUse(N0, AllowExtraUses) || !checkTwoUse(N1, AllowExtraUses))
4305 auto matchLowBitMask = [matchPatternA, matchPatternB,
4307 return matchPatternA(Mask) || matchPatternB(Mask) || matchPatternC(Mask);
4311 X =
Node->getOperand(0);
4314 if (matchLowBitMask(Mask)) {
4318 if (!matchLowBitMask(Mask))
4321 }
else if (matchLowBitMask(
SDValue(Node, 0))) {
4322 X = CurDAG->getAllOnesConstant(SDLoc(Node), NVT);
4323 }
else if (!matchPatternD(Node))
4328 if (NegateNBits && !Subtarget->hasBMI2())
4333 if (NBits.getSimpleValueType() != MVT::i8) {
4340 ConstantSDNode *
Imm =
nullptr;
4341 if (NBits->getOpcode() ==
ISD::AND)
4343 NBits = NBits->getOperand(0);
4348 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, MVT::i32), 0);
4351 SDValue SRIdxVal = CurDAG->getTargetConstant(X86::sub_8bit,
DL, MVT::i32);
4353 NBits =
SDValue(CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG,
DL,
4354 MVT::i32, ImplDef, NBits, SRIdxVal),
4360 CurDAG->getNode(
ISD::AND,
DL, MVT::i32, NBits,
4361 CurDAG->getConstant(
Imm->getZExtValue(),
DL, MVT::i32));
4371 NBits = CurDAG->getNode(
ISD::SUB,
DL, MVT::i32, BitWidthC, NBits);
4375 if (Subtarget->hasBMI2()) {
4377 if (NVT != MVT::i32) {
4383 SDValue Extract = CurDAG->getNode(X86ISD::BZHI,
DL, NVT,
X, NBits);
4384 ReplaceNode(Node, Extract.
getNode());
4385 SelectCode(Extract.
getNode());
4394 SDValue RealX = peekThroughOneUseTruncation(
X);
4400 MVT XVT =
X.getSimpleValueType();
4410 SDValue C8 = CurDAG->getConstant(8,
DL, MVT::i8);
4418 SDValue ShiftAmt =
X.getOperand(1);
4419 X =
X.getOperand(0);
4422 "Expected shift amount to be i8");
4426 SDValue OrigShiftAmt = ShiftAmt;
4431 Control = CurDAG->getNode(
ISD::OR,
DL, MVT::i32, Control, ShiftAmt);
4436 if (XVT != MVT::i32) {
4442 SDValue Extract = CurDAG->getNode(X86ISD::BEXTR,
DL, XVT,
X, Control);
4450 ReplaceNode(Node, Extract.
getNode());
4451 SelectCode(Extract.
getNode());
4457MachineSDNode *X86DAGToDAGISel::matchBEXTRFromAndImm(SDNode *Node) {
4458 MVT NVT =
Node->getSimpleValueType(0);
4471 Subtarget->hasTBM() || (Subtarget->hasBMI() && Subtarget->hasFastBEXTR());
4472 if (!PreferBEXTR && !Subtarget->hasBMI2())
4484 if (NVT != MVT::i32 && NVT != MVT::i64)
4490 if (!MaskCst || !ShiftCst)
4498 uint64_t Shift = ShiftCst->getZExtValue();
4503 if (Shift == 8 && MaskSize == 8)
4514 if (!PreferBEXTR && MaskSize <= 32)
4518 unsigned ROpc, MOpc;
4520#define GET_EGPR_IF_ENABLED(OPC) (Subtarget->hasEGPR() ? OPC##_EVEX : OPC)
4522 assert(Subtarget->hasBMI2() &&
"We must have BMI2's BZHI then.");
4526 Control = CurDAG->getTargetConstant(Shift + MaskSize, dl, NVT);
4531 unsigned NewOpc = NVT == MVT::i64 ? X86::MOV32ri64 : X86::MOV32ri;
4532 Control =
SDValue(CurDAG->getMachineNode(NewOpc, dl, NVT, Control), 0);
4538 Control = CurDAG->getTargetConstant(Shift | (MaskSize << 8), dl, NVT);
4539 if (Subtarget->hasTBM()) {
4540 ROpc = NVT == MVT::i64 ? X86::BEXTRI64ri : X86::BEXTRI32ri;
4541 MOpc = NVT == MVT::i64 ? X86::BEXTRI64mi : X86::BEXTRI32mi;
4543 assert(Subtarget->hasBMI() &&
"We must have BMI1's BEXTR then.");
4549 unsigned NewOpc = NVT == MVT::i64 ? X86::MOV32ri64 : X86::MOV32ri;
4550 Control =
SDValue(CurDAG->getMachineNode(NewOpc, dl, NVT, Control), 0);
4554 MachineSDNode *NewNode;
4556 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4557 if (tryFoldLoad(Node, N0.
getNode(), Input, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4559 Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Control, Input.
getOperand(0)};
4560 SDVTList VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
4561 NewNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4565 CurDAG->setNodeMemRefs(NewNode, {
cast<LoadSDNode>(Input)->getMemOperand()});
4567 NewNode = CurDAG->getMachineNode(ROpc, dl, NVT, MVT::i32, Input, Control);
4572 SDValue ShAmt = CurDAG->getTargetConstant(Shift, dl, NVT);
4576 CurDAG->getMachineNode(NewOpc, dl, NVT,
SDValue(NewNode, 0), ShAmt);
4583MachineSDNode *X86DAGToDAGISel::emitPCMPISTR(
unsigned ROpc,
unsigned MOpc,
4584 bool MayFoldLoad,
const SDLoc &dl,
4585 MVT VT, SDNode *Node) {
4590 Imm = CurDAG->getTargetConstant(*Val, SDLoc(Node),
Imm.getValueType());
4593 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4594 if (MayFoldLoad && tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4597 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Other);
4598 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4607 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32);
4608 MachineSDNode *CNode = CurDAG->getMachineNode(ROpc, dl, VTs,
Ops);
4615MachineSDNode *X86DAGToDAGISel::emitPCMPESTR(
unsigned ROpc,
unsigned MOpc,
4616 bool MayFoldLoad,
const SDLoc &dl,
4617 MVT VT, SDNode *Node,
4623 Imm = CurDAG->getTargetConstant(*Val, SDLoc(Node),
Imm.getValueType());
4626 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4627 if (MayFoldLoad && tryFoldLoad(Node, N2, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4630 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Other, MVT::Glue);
4631 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4641 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Glue);
4642 MachineSDNode *CNode = CurDAG->getMachineNode(ROpc, dl, VTs,
Ops);
4647bool X86DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
4648 EVT VT =
N->getValueType(0);
4655 unsigned Size = VT == MVT::i64 ? 64 : 32;
4658 SDValue ShiftAmt = OrigShiftAmt;
4677 if (Add1C && Add1C->getAPIntValue().urem(
Size) == 0) {
4681 ((Add0C && Add0C->getAPIntValue().urem(
Size) ==
Size - 1) ||
4682 (Add1C && Add1C->getAPIntValue().urem(
Size) ==
Size - 1))) {
4686 assert(Add0C ==
nullptr || Add1C ==
nullptr);
4695 NewShiftAmt = CurDAG->getNode(
ISD::XOR,
DL, OpVT,
4696 Add0C ==
nullptr ? Add0 : Add1,
AllOnes);
4702 Add0C->getZExtValue() != 0) {
4705 if (Add0C->getZExtValue() %
Size == 0)
4708 Add0C->getZExtValue() % 32 == 0) {
4716 Add0 = CurDAG->getZExtOrTrunc(Add0,
DL, SubVT);
4720 X = CurDAG->getNode(
ISD::ADD,
DL, SubVT, Add1, Add0);
4742 NewShiftAmt = CurDAG->getNode(
ISD::TRUNCATE,
DL, MVT::i8, NewShiftAmt);
4749 NewShiftAmt = CurDAG->getNode(
ISD::AND,
DL, MVT::i8, NewShiftAmt,
4750 CurDAG->getConstant(
Size - 1,
DL, MVT::i8));
4754 SDNode *UpdatedNode = CurDAG->UpdateNodeOperands(
N,
N->getOperand(0),
4756 if (UpdatedNode !=
N) {
4759 ReplaceNode(
N, UpdatedNode);
4766 CurDAG->RemoveDeadNode(OrigShiftAmt.
getNode());
4774bool X86DAGToDAGISel::tryShrinkShlLogicImm(SDNode *
N) {
4775 MVT NVT =
N->getSimpleValueType(0);
4776 unsigned Opcode =
N->getOpcode();
4788 int64_t Val = Cst->getSExtValue();
4793 bool FoundAnyExtend =
false;
4797 FoundAnyExtend =
true;
4805 if (NVT != MVT::i32 && NVT != MVT::i64)
4812 uint64_t ShAmt = ShlCst->getZExtValue();
4816 uint64_t RemovedBitsMask = (1ULL << ShAmt) - 1;
4817 if (Opcode !=
ISD::AND && (Val & RemovedBitsMask) != 0)
4822 auto CanShrinkImmediate = [&](int64_t &ShiftedVal) {
4826 ShiftedVal = (
uint64_t)Val >> ShAmt;
4830 if (ShiftedVal == UINT8_MAX || ShiftedVal == UINT16_MAX)
4833 ShiftedVal = Val >> ShAmt;
4839 ShiftedVal = (
uint64_t)Val >> ShAmt;
4847 if (!CanShrinkImmediate(ShiftedVal))
4857 unsigned ZExtWidth = Cst->getAPIntValue().getActiveBits();
4863 NeededMask &= ~Cst->getAPIntValue();
4865 if (CurDAG->MaskedValueIsZero(
N->getOperand(0), NeededMask))
4870 if (FoundAnyExtend) {
4876 SDValue NewCst = CurDAG->getSignedConstant(ShiftedVal, dl, NVT);
4878 SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT,
X, NewCst);
4887bool X86DAGToDAGISel::matchVPTERNLOG(SDNode *Root, SDNode *ParentA,
4888 SDNode *ParentB, SDNode *ParentC,
4891 assert(
A.isOperandOf(ParentA) &&
B.isOperandOf(ParentB) &&
4892 C.isOperandOf(ParentC) &&
"Incorrect parent node");
4894 auto tryFoldLoadOrBCast =
4897 if (tryFoldLoad(Root,
P, L,
Base, Scale, Index, Disp, Segment))
4903 L =
L.getOperand(0);
4906 if (
L.getOpcode() != X86ISD::VBROADCAST_LOAD)
4911 unsigned Size = MemIntr->getMemoryVT().getSizeInBits();
4915 return tryFoldBroadcast(Root,
P, L,
Base, Scale, Index, Disp, Segment);
4918 bool FoldedLoad =
false;
4919 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4920 if (tryFoldLoadOrBCast(Root, ParentC,
C, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4922 }
else if (tryFoldLoadOrBCast(Root, ParentA,
A, Tmp0, Tmp1, Tmp2, Tmp3,
4927 uint8_t OldImm =
Imm;
4928 Imm = OldImm & 0xa5;
4929 if (OldImm & 0x02)
Imm |= 0x10;
4930 if (OldImm & 0x10)
Imm |= 0x02;
4931 if (OldImm & 0x08)
Imm |= 0x40;
4932 if (OldImm & 0x40)
Imm |= 0x08;
4933 }
else if (tryFoldLoadOrBCast(Root, ParentB,
B, Tmp0, Tmp1, Tmp2, Tmp3,
4938 uint8_t OldImm =
Imm;
4939 Imm = OldImm & 0x99;
4940 if (OldImm & 0x02)
Imm |= 0x04;
4941 if (OldImm & 0x04)
Imm |= 0x02;
4942 if (OldImm & 0x20)
Imm |= 0x40;
4943 if (OldImm & 0x40)
Imm |= 0x20;
4948 SDValue TImm = CurDAG->getTargetConstant(
Imm,
DL, MVT::i8);
4952 MachineSDNode *MNode;
4954 SDVTList VTs = CurDAG->getVTList(NVT, MVT::Other);
4957 if (
C.getOpcode() == X86ISD::VBROADCAST_LOAD) {
4959 unsigned EltSize = MemIntr->getMemoryVT().getSizeInBits();
4960 assert((EltSize == 32 || EltSize == 64) &&
"Unexpected broadcast size!");
4962 bool UseD = EltSize == 32;
4964 Opc = UseD ? X86::VPTERNLOGDZ128rmbi : X86::VPTERNLOGQZ128rmbi;
4966 Opc = UseD ? X86::VPTERNLOGDZ256rmbi : X86::VPTERNLOGQZ256rmbi;
4968 Opc = UseD ? X86::VPTERNLOGDZrmbi : X86::VPTERNLOGQZrmbi;
4974 Opc = UseD ? X86::VPTERNLOGDZ128rmi : X86::VPTERNLOGQZ128rmi;
4976 Opc = UseD ? X86::VPTERNLOGDZ256rmi : X86::VPTERNLOGQZ256rmi;
4978 Opc = UseD ? X86::VPTERNLOGDZrmi : X86::VPTERNLOGQZrmi;
4984 MNode = CurDAG->getMachineNode(
Opc,
DL, VTs,
Ops);
4987 ReplaceUses(
C.getValue(1),
SDValue(MNode, 1));
4994 Opc = UseD ? X86::VPTERNLOGDZ128rri : X86::VPTERNLOGQZ128rri;
4996 Opc = UseD ? X86::VPTERNLOGDZ256rri : X86::VPTERNLOGQZ256rri;
4998 Opc = UseD ? X86::VPTERNLOGDZrri : X86::VPTERNLOGQZrri;
5002 MNode = CurDAG->getMachineNode(
Opc,
DL, NVT, {
A,
B,
C, TImm});
5006 CurDAG->RemoveDeadNode(Root);
5012bool X86DAGToDAGISel::tryVPTERNLOG(SDNode *
N) {
5013 MVT NVT =
N->getSimpleValueType(0);
5016 if (!NVT.
isVector() || !Subtarget->hasAVX512() ||
5024 auto getFoldableLogicOp = [](
SDValue Op) {
5027 Op =
Op.getOperand(0);
5029 if (!
Op.hasOneUse())
5032 unsigned Opc =
Op.getOpcode();
5034 Opc == X86ISD::ANDNP)
5043 auto tryPeelOuterNotWrappingLogic = [&](SDNode *
Op) {
5046 SDValue InnerOp = getFoldableLogicOp(
Op->getOperand(0));
5053 if ((FoldableOp = getFoldableLogicOp(N1))) {
5057 if ((FoldableOp = getFoldableLogicOp(N0))) {
5065 bool PeeledOuterNot =
false;
5067 if (
SDValue InnerOp = tryPeelOuterNotWrappingLogic(
N)) {
5068 PeeledOuterNot =
true;
5074 if ((FoldableOp = getFoldableLogicOp(N1)))
5076 else if ((FoldableOp = getFoldableLogicOp(N0)))
5084 SDNode *ParentA =
N;
5085 SDNode *ParentB = FoldableOp.
getNode();
5086 SDNode *ParentC = FoldableOp.
getNode();
5090 uint8_t TernlogMagicA = 0xf0;
5091 uint8_t TernlogMagicB = 0xcc;
5092 uint8_t TernlogMagicC = 0xaa;
5097 auto PeekThroughNot = [](
SDValue &
Op, SDNode *&Parent, uint8_t &
Magic) {
5101 Parent =
Op.getNode();
5102 Op =
Op.getOperand(0);
5106 PeekThroughNot(
A, ParentA, TernlogMagicA);
5107 PeekThroughNot(
B, ParentB, TernlogMagicB);
5108 PeekThroughNot(
C, ParentC, TernlogMagicC);
5113 case ISD::AND:
Imm = TernlogMagicB & TernlogMagicC;
break;
5114 case ISD::OR:
Imm = TernlogMagicB | TernlogMagicC;
break;
5115 case ISD::XOR:
Imm = TernlogMagicB ^ TernlogMagicC;
break;
5116 case X86ISD::ANDNP:
Imm = ~(TernlogMagicB) & TernlogMagicC;
break;
5119 switch (
N->getOpcode()) {
5123 Imm &= ~TernlogMagicA;
5125 Imm = ~(
Imm) & TernlogMagicA;
5135 return matchVPTERNLOG(OriN, ParentA, ParentB, ParentC,
A,
B,
C,
Imm);
5145bool X86DAGToDAGISel::shrinkAndImmediate(SDNode *
And) {
5148 MVT VT =
And->getSimpleValueType(0);
5149 if (VT != MVT::i32 && VT != MVT::i64)
5161 APInt MaskVal = And1C->getAPIntValue();
5163 if (!MaskLZ || (VT == MVT::i64 && MaskLZ == 32))
5167 if (VT == MVT::i64 && MaskLZ >= 32) {
5169 MaskVal = MaskVal.
trunc(32);
5174 APInt NegMaskVal = MaskVal | HighZeros;
5183 if (VT == MVT::i64 && MaskVal.
getBitWidth() < 64) {
5184 NegMaskVal = NegMaskVal.
zext(64);
5185 HighZeros = HighZeros.
zext(64);
5191 KnownBits Known0 = CurDAG->computeKnownBits(And0);
5203 SDValue NewMask = CurDAG->getConstant(NegMaskVal, SDLoc(
And), VT);
5212 bool FoldedBCast,
bool Masked) {
5213#define VPTESTM_CASE(VT, SUFFIX) \
5216 return IsTestN ? X86::VPTESTNM##SUFFIX##k: X86::VPTESTM##SUFFIX##k; \
5217 return IsTestN ? X86::VPTESTNM##SUFFIX : X86::VPTESTM##SUFFIX;
5220#define VPTESTM_BROADCAST_CASES(SUFFIX) \
5221default: llvm_unreachable("Unexpected VT!"); \
5222VPTESTM_CASE(v4i32, DZ128##SUFFIX) \
5223VPTESTM_CASE(v2i64, QZ128##SUFFIX) \
5224VPTESTM_CASE(v8i32, DZ256##SUFFIX) \
5225VPTESTM_CASE(v4i64, QZ256##SUFFIX) \
5226VPTESTM_CASE(v16i32, DZ##SUFFIX) \
5227VPTESTM_CASE(v8i64, QZ##SUFFIX)
5229#define VPTESTM_FULL_CASES(SUFFIX) \
5230VPTESTM_BROADCAST_CASES(SUFFIX) \
5231VPTESTM_CASE(v16i8, BZ128##SUFFIX) \
5232VPTESTM_CASE(v8i16, WZ128##SUFFIX) \
5233VPTESTM_CASE(v32i8, BZ256##SUFFIX) \
5234VPTESTM_CASE(v16i16, WZ256##SUFFIX) \
5235VPTESTM_CASE(v64i8, BZ##SUFFIX) \
5236VPTESTM_CASE(v32i16, WZ##SUFFIX)
5254#undef VPTESTM_FULL_CASES
5255#undef VPTESTM_BROADCAST_CASES
5265 if (
Reg.isVirtual())
5270 if (GetPhysReg(N1) == LoReg && GetPhysReg(N0) != LoReg)
5276bool X86DAGToDAGISel::tryVPTESTM(SDNode *Root,
SDValue Setcc,
5278 assert(Subtarget->hasAVX512() &&
"Expected AVX512!");
5323 auto tryFoldLoadOrBCast = [&](SDNode *Root, SDNode *
P,
SDValue &
L,
5328 if (tryFoldLoad(Root,
P, L,
Base, Scale, Index, Disp, Segment))
5333 if (CmpSVT != MVT::i32 && CmpSVT != MVT::i64)
5339 L =
L.getOperand(0);
5342 if (
L.getOpcode() != X86ISD::VBROADCAST_LOAD)
5346 if (MemIntr->getMemoryVT().getSizeInBits() != CmpSVT.
getSizeInBits())
5349 return tryFoldBroadcast(Root,
P, L,
Base, Scale, Index, Disp, Segment);
5353 bool CanFoldLoads = Src0 != Src1;
5355 bool FoldedLoad =
false;
5356 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5358 FoldedLoad = tryFoldLoadOrBCast(Root, N0.
getNode(), Src1, Tmp0, Tmp1, Tmp2,
5362 FoldedLoad = tryFoldLoadOrBCast(Root, N0.
getNode(), Src0, Tmp0, Tmp1,
5369 bool FoldedBCast = FoldedLoad && Src1.
getOpcode() == X86ISD::VBROADCAST_LOAD;
5371 bool IsMasked = InMask.
getNode() !=
nullptr;
5380 unsigned SubReg = CmpVT.
is128BitVector() ? X86::sub_xmm : X86::sub_ymm;
5384 SDValue ImplDef =
SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF, dl,
5386 Src0 = CurDAG->getTargetInsertSubreg(SubReg, dl, CmpVT, ImplDef, Src0);
5389 Src1 = CurDAG->getTargetInsertSubreg(SubReg, dl, CmpVT, ImplDef, Src1);
5394 SDValue RC = CurDAG->getTargetConstant(RegClass, dl, MVT::i32);
5395 InMask =
SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
5396 dl, MaskVT, InMask, RC), 0);
5404 MachineSDNode *CNode;
5406 SDVTList VTs = CurDAG->getVTList(MaskVT, MVT::Other);
5409 SDValue Ops[] = { InMask, Src0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
5411 CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5413 SDValue Ops[] = { Src0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
5415 CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5421 CurDAG->setNodeMemRefs(CNode, {
cast<MemSDNode>(Src1)->getMemOperand()});
5424 CNode = CurDAG->getMachineNode(
Opc, dl, MaskVT, InMask, Src0, Src1);
5426 CNode = CurDAG->getMachineNode(
Opc, dl, MaskVT, Src0, Src1);
5432 SDValue RC = CurDAG->getTargetConstant(RegClass, dl, MVT::i32);
5433 CNode = CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
5434 dl, ResVT,
SDValue(CNode, 0), RC);
5438 CurDAG->RemoveDeadNode(Root);
5444bool X86DAGToDAGISel::tryMatchBitSelect(SDNode *
N) {
5447 MVT NVT =
N->getSimpleValueType(0);
5450 if (!NVT.
isVector() || !Subtarget->hasAVX512())
5484 SDValue Imm = CurDAG->getTargetConstant(0xCA, dl, MVT::i8);
5485 SDValue Ternlog = CurDAG->getNode(X86ISD::VPTERNLOG, dl, NVT,
A,
B,
C,
Imm);
5492void X86DAGToDAGISel::Select(SDNode *Node) {
5493 MVT NVT =
Node->getSimpleValueType(0);
5494 unsigned Opcode =
Node->getOpcode();
5497 if (
Node->isMachineOpcode()) {
5499 Node->setNodeId(-1);
5506 unsigned IntNo =
Node->getConstantOperandVal(1);
5509 case Intrinsic::x86_encodekey128:
5510 case Intrinsic::x86_encodekey256: {
5511 if (!Subtarget->hasKL())
5517 case Intrinsic::x86_encodekey128:
5518 Opcode = X86::ENCODEKEY128;
5520 case Intrinsic::x86_encodekey256:
5521 Opcode = X86::ENCODEKEY256;
5526 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM0,
Node->getOperand(3),
5528 if (Opcode == X86::ENCODEKEY256)
5529 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM1,
Node->getOperand(4),
5532 MachineSDNode *Res = CurDAG->getMachineNode(
5533 Opcode, dl,
Node->getVTList(),
5534 {Node->getOperand(2), Chain, Chain.getValue(1)});
5535 ReplaceNode(Node, Res);
5538 case Intrinsic::x86_tileloaddrs64_internal:
5539 case Intrinsic::x86_tileloaddrst164_internal:
5540 if (!Subtarget->hasAMXMOVRS())
5543 case Intrinsic::x86_tileloadd64_internal:
5544 case Intrinsic::x86_tileloaddt164_internal: {
5545 if (!Subtarget->hasAMXTILE())
5548 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5549 MFI->setAMXProgModel(AMXProgModelEnum::ManagedRA);
5554 case Intrinsic::x86_tileloaddrs64_internal:
5555 Opc = X86::PTILELOADDRSV;
5557 case Intrinsic::x86_tileloaddrst164_internal:
5558 Opc = X86::PTILELOADDRST1V;
5560 case Intrinsic::x86_tileloadd64_internal:
5561 Opc = X86::PTILELOADDV;
5563 case Intrinsic::x86_tileloaddt164_internal:
5564 Opc = X86::PTILELOADDT1V;
5569 SDValue Scale = getI8Imm(1, dl);
5571 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5572 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5574 MachineSDNode *CNode;
5576 Node->getOperand(3),
5583 CNode = CurDAG->getMachineNode(
Opc, dl, {MVT::x86amx, MVT::Other},
Ops);
5584 ReplaceNode(Node, CNode);
5591 unsigned IntNo =
Node->getConstantOperandVal(1);
5594 case Intrinsic::x86_sse3_monitor:
5595 case Intrinsic::x86_monitorx:
5596 case Intrinsic::x86_clzero: {
5597 bool Use64BitPtr =
Node->getOperand(2).getValueType() == MVT::i64;
5602 case Intrinsic::x86_sse3_monitor:
5603 if (!Subtarget->hasSSE3())
5605 Opc = Use64BitPtr ? X86::MONITOR64rrr : X86::MONITOR32rrr;
5607 case Intrinsic::x86_monitorx:
5608 if (!Subtarget->hasMWAITX())
5610 Opc = Use64BitPtr ? X86::MONITORX64rrr : X86::MONITORX32rrr;
5612 case Intrinsic::x86_clzero:
5613 if (!Subtarget->hasCLZERO())
5615 Opc = Use64BitPtr ? X86::CLZERO64r : X86::CLZERO32r;
5620 unsigned PtrReg = Use64BitPtr ? X86::RAX : X86::EAX;
5621 SDValue Chain = CurDAG->getCopyToReg(
Node->getOperand(0), dl, PtrReg,
5625 if (IntNo == Intrinsic::x86_sse3_monitor ||
5626 IntNo == Intrinsic::x86_monitorx) {
5628 Chain = CurDAG->getCopyToReg(Chain, dl, X86::ECX,
Node->getOperand(3),
5631 Chain = CurDAG->getCopyToReg(Chain, dl, X86::EDX,
Node->getOperand(4),
5636 MachineSDNode *CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
5638 ReplaceNode(Node, CNode);
5644 case Intrinsic::x86_tilestored64_internal: {
5646 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5647 MFI->setAMXProgModel(AMXProgModelEnum::ManagedRA);
5648 unsigned Opc = X86::PTILESTOREDV;
5651 SDValue Scale = getI8Imm(1, dl);
5653 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5654 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5656 MachineSDNode *CNode;
5658 Node->getOperand(3),
5664 Node->getOperand(6),
5666 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5667 ReplaceNode(Node, CNode);
5670 case Intrinsic::x86_tileloaddrs64:
5671 case Intrinsic::x86_tileloaddrst164:
5672 if (!Subtarget->hasAMXMOVRS())
5675 case Intrinsic::x86_tileloadd64:
5676 case Intrinsic::x86_tileloaddt164:
5677 case Intrinsic::x86_tilestored64: {
5678 if (!Subtarget->hasAMXTILE())
5681 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5682 MFI->setAMXProgModel(AMXProgModelEnum::DirectReg);
5686 case Intrinsic::x86_tileloadd64:
Opc = X86::PTILELOADD;
break;
5687 case Intrinsic::x86_tileloaddrs64:
5688 Opc = X86::PTILELOADDRS;
5690 case Intrinsic::x86_tileloaddt164:
Opc = X86::PTILELOADDT1;
break;
5691 case Intrinsic::x86_tileloaddrst164:
5692 Opc = X86::PTILELOADDRST1;
5694 case Intrinsic::x86_tilestored64:
Opc = X86::PTILESTORED;
break;
5697 unsigned TIndex =
Node->getConstantOperandVal(2);
5700 SDValue Scale = getI8Imm(1, dl);
5702 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5703 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5705 MachineSDNode *CNode;
5706 if (
Opc == X86::PTILESTORED) {
5708 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5711 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5713 ReplaceNode(Node, CNode);
5720 case X86ISD::NT_BRIND: {
5721 if (Subtarget->isTarget64BitILP32()) {
5726 assert(
Target.getValueType() == MVT::i32 &&
"Unexpected VT!");
5727 SDValue ZextTarget = CurDAG->getZExtOrTrunc(Target, dl, MVT::i64);
5728 SDValue Brind = CurDAG->getNode(Opcode, dl, MVT::Other,
5729 Node->getOperand(0), ZextTarget);
5730 ReplaceNode(Node, Brind.
getNode());
5731 SelectCode(ZextTarget.
getNode());
5738 ReplaceNode(Node, getGlobalBaseReg());
5745 ReplaceUses(
SDValue(Node, 0),
Node->getOperand(0));
5746 CurDAG->RemoveDeadNode(Node);
5752 if (matchBitExtract(Node))
5757 if (tryShiftAmountMod(Node))
5761 case X86ISD::VPTERNLOG: {
5762 uint8_t
Imm =
Node->getConstantOperandVal(3);
5763 if (matchVPTERNLOG(Node, Node, Node, Node,
Node->getOperand(0),
5770 if (tryVPTERNLOG(Node))
5780 tryVPTESTM(Node, N0, N1))
5783 tryVPTESTM(Node, N1, N0))
5787 if (MachineSDNode *NewNode = matchBEXTRFromAndImm(Node)) {
5789 CurDAG->RemoveDeadNode(Node);
5792 if (matchBitExtract(Node))
5800 if (tryShrinkShlLogicImm(Node))
5802 if (Opcode ==
ISD::OR && tryMatchBitSelect(Node))
5804 if (tryVPTERNLOG(Node))
5809 if (Opcode ==
ISD::ADD && matchBitExtract(Node))
5819 if (!CurDAG->shouldOptForSize())
5823 if (NVT != MVT::i8 && NVT != MVT::i16 && NVT != MVT::i32 && NVT != MVT::i64)
5833 int64_t Val = Cst->getSExtValue();
5841 if (Opcode ==
ISD::ADD && (Val == 1 || Val == -1))
5845 if (!shouldAvoidImmediateInstFormsForSize(N1.
getNode()))
5849 unsigned ROpc, MOpc;
5958 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5959 if (tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
5961 SDVTList VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
5962 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
5968 CurDAG->RemoveDeadNode(Node);
5973 CurDAG->SelectNodeTo(Node, ROpc, NVT, MVT::i32, N0, N1);
5982 case X86ISD::UMUL: {
5986 unsigned LoReg, ROpc, MOpc;
5991 ROpc = Opcode == X86ISD::SMUL ? X86::IMUL8r : X86::MUL8r;
5992 MOpc = Opcode == X86ISD::SMUL ? X86::IMUL8m : X86::MUL8m;
6011 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6012 bool FoldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6015 FoldedLoad = tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6023 orderRegForMul(N0, N1, LoReg, CurDAG->getMachineFunction().getRegInfo());
6025 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg,
6028 MachineSDNode *CNode;
6034 VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
6036 VTs = CurDAG->getVTList(NVT, NVT, MVT::i32, MVT::Other);
6040 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6051 VTs = CurDAG->getVTList(NVT, MVT::i32);
6053 VTs = CurDAG->getVTList(NVT, NVT, MVT::i32);
6055 CNode = CurDAG->getMachineNode(ROpc, dl, VTs, {N1, InGlue});
6059 ReplaceUses(
SDValue(Node, 1),
SDValue(CNode, NVT == MVT::i8 ? 1 : 2));
6060 CurDAG->RemoveDeadNode(Node);
6070 unsigned LoReg, HiReg;
6072 bool UseMULX = !IsSigned && Subtarget->hasBMI2();
6073 bool UseMULXHi = UseMULX &&
SDValue(Node, 0).use_empty();
6077 Opc = UseMULXHi ? X86::MULX32Hrr
6079 : IsSigned ?
X86::IMUL32r
6081 MOpc = UseMULXHi ? X86::MULX32Hrm
6083 : IsSigned ?
X86::IMUL32m
6085 LoReg = UseMULX ? X86::EDX : X86::EAX;
6089 Opc = UseMULXHi ? X86::MULX64Hrr
6091 : IsSigned ?
X86::IMUL64r
6093 MOpc = UseMULXHi ? X86::MULX64Hrm
6095 : IsSigned ?
X86::IMUL64m
6097 LoReg = UseMULX ? X86::RDX : X86::RAX;
6102 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6103 bool foldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6106 foldedLoad = tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6114 orderRegForMul(N0, N1, LoReg, CurDAG->getMachineFunction().getRegInfo());
6116 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg,
6121 MachineSDNode *CNode =
nullptr;
6125 SDVTList VTs = CurDAG->getVTList(NVT, MVT::Other);
6126 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6129 }
else if (UseMULX) {
6130 SDVTList VTs = CurDAG->getVTList(NVT, NVT, MVT::Other);
6131 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6136 SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue);
6137 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6143 ReplaceUses(N1.
getValue(1), Chain);
6149 SDVTList VTs = CurDAG->getVTList(NVT);
6150 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6152 }
else if (UseMULX) {
6153 SDVTList VTs = CurDAG->getVTList(NVT, NVT);
6154 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6158 SDVTList VTs = CurDAG->getVTList(MVT::Glue);
6159 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6165 if (!
SDValue(Node, 0).use_empty()) {
6167 assert(LoReg &&
"Register for low half is not defined!");
6168 ResLo = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, LoReg,
6172 ReplaceUses(
SDValue(Node, 0), ResLo);
6177 if (!
SDValue(Node, 1).use_empty()) {
6179 assert(HiReg &&
"Register for high half is not defined!");
6180 ResHi = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, HiReg,
6184 ReplaceUses(
SDValue(Node, 1), ResHi);
6189 CurDAG->RemoveDeadNode(Node);
6198 unsigned ROpc, MOpc;
6203 case MVT::i8: ROpc = X86::DIV8r; MOpc = X86::DIV8m;
break;
6204 case MVT::i16: ROpc = X86::DIV16r; MOpc = X86::DIV16m;
break;
6205 case MVT::i32: ROpc = X86::DIV32r; MOpc = X86::DIV32m;
break;
6206 case MVT::i64: ROpc = X86::DIV64r; MOpc = X86::DIV64m;
break;
6211 case MVT::i8: ROpc = X86::IDIV8r; MOpc = X86::IDIV8m;
break;
6212 case MVT::i16: ROpc = X86::IDIV16r; MOpc = X86::IDIV16m;
break;
6213 case MVT::i32: ROpc = X86::IDIV32r; MOpc = X86::IDIV32m;
break;
6214 case MVT::i64: ROpc = X86::IDIV64r; MOpc = X86::IDIV64m;
break;
6218 unsigned LoReg, HiReg, ClrReg;
6219 unsigned SExtOpcode;
6223 LoReg = X86::AL; ClrReg = HiReg = X86::AH;
6227 LoReg = X86::AX; HiReg = X86::DX;
6229 SExtOpcode = X86::CWD;
6232 LoReg = X86::EAX; ClrReg = HiReg = X86::EDX;
6233 SExtOpcode = X86::CDQ;
6236 LoReg = X86::RAX; ClrReg = HiReg = X86::RDX;
6237 SExtOpcode = X86::CQO;
6241 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6242 bool foldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6243 bool signBitIsZero = CurDAG->SignBitIsZero(N0);
6246 if (NVT == MVT::i8) {
6249 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Chain;
6250 MachineSDNode *Move;
6251 if (tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
6253 unsigned Opc = (
isSigned && !signBitIsZero) ? X86::MOVSX16rm8
6255 Move = CurDAG->getMachineNode(
Opc, dl, MVT::i16, MVT::Other,
Ops);
6257 ReplaceUses(N0.
getValue(1), Chain);
6261 unsigned Opc = (
isSigned && !signBitIsZero) ? X86::MOVSX16rr8
6263 Move = CurDAG->getMachineNode(
Opc, dl, MVT::i16, N0);
6264 Chain = CurDAG->getEntryNode();
6266 Chain = CurDAG->getCopyToReg(Chain, dl, X86::AX,
SDValue(Move, 0),
6271 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl,
6272 LoReg, N0,
SDValue()).getValue(1);
6276 SDValue(CurDAG->getMachineNode(SExtOpcode, dl, MVT::Glue, InGlue),0);
6279 SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::i32);
6281 SDValue(CurDAG->getMachineNode(X86::MOV32r0, dl, VTs, {}), 0);
6285 SDValue(CurDAG->getMachineNode(
6286 TargetOpcode::EXTRACT_SUBREG, dl, MVT::i16, ClrNode,
6287 CurDAG->getTargetConstant(X86::sub_16bit, dl,
6295 CurDAG->getMachineNode(
6296 TargetOpcode::SUBREG_TO_REG, dl, MVT::i64, ClrNode,
6297 CurDAG->getTargetConstant(X86::sub_32bit, dl, MVT::i32)),
6304 InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, ClrReg,
6305 ClrNode, InGlue).getValue(1);
6312 MachineSDNode *CNode =
6313 CurDAG->getMachineNode(MOpc, dl, MVT::Other, MVT::Glue,
Ops);
6321 SDValue(CurDAG->getMachineNode(ROpc, dl, MVT::Glue, N1, InGlue), 0);
6331 if (HiReg == X86::AH && !
SDValue(Node, 1).use_empty()) {
6332 SDValue AHCopy = CurDAG->getRegister(X86::AH, MVT::i8);
6333 unsigned AHExtOpcode =
6334 isSigned ? X86::MOVSX32rr8_NOREX : X86::MOVZX32rr8_NOREX;
6336 SDNode *RNode = CurDAG->getMachineNode(AHExtOpcode, dl, MVT::i32,
6337 MVT::Glue, AHCopy, InGlue);
6342 CurDAG->getTargetExtractSubreg(X86::sub_8bit, dl, MVT::i8, Result);
6344 ReplaceUses(
SDValue(Node, 1), Result);
6349 if (!
SDValue(Node, 0).use_empty()) {
6350 SDValue Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
6351 LoReg, NVT, InGlue);
6352 InGlue =
Result.getValue(2);
6353 ReplaceUses(
SDValue(Node, 0), Result);
6358 if (!
SDValue(Node, 1).use_empty()) {
6359 SDValue Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
6360 HiReg, NVT, InGlue);
6361 InGlue =
Result.getValue(2);
6362 ReplaceUses(
SDValue(Node, 1), Result);
6366 CurDAG->RemoveDeadNode(Node);
6371 case X86ISD::STRICT_FCMP:
6372 case X86ISD::STRICT_FCMPS: {
6373 bool IsStrictCmp =
Node->getOpcode() == X86ISD::STRICT_FCMP ||
6374 Node->getOpcode() == X86ISD::STRICT_FCMPS;
6375 SDValue N0 =
Node->getOperand(IsStrictCmp ? 1 : 0);
6376 SDValue N1 =
Node->getOperand(IsStrictCmp ? 2 : 1);
6382 if (Subtarget->canUseCMOV())
6385 bool IsSignaling =
Node->getOpcode() == X86ISD::STRICT_FCMPS;
6391 Opc = IsSignaling ? X86::COM_Fpr32 : X86::UCOM_Fpr32;
6394 Opc = IsSignaling ? X86::COM_Fpr64 : X86::UCOM_Fpr64;
6397 Opc = IsSignaling ? X86::COM_Fpr80 : X86::UCOM_Fpr80;
6402 IsStrictCmp ?
Node->getOperand(0) : CurDAG->getEntryNode();
6405 SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue);
6406 Chain =
SDValue(CurDAG->getMachineNode(
Opc, dl, VTs, {N0, N1, Chain}), 0);
6409 Glue =
SDValue(CurDAG->getMachineNode(
Opc, dl, MVT::Glue, N0, N1), 0);
6414 SDValue(CurDAG->getMachineNode(X86::FNSTSW16r, dl, MVT::i16, Glue), 0);
6418 CurDAG->getTargetExtractSubreg(X86::sub_8bit_hi, dl, MVT::i8, FNSTSW);
6422 assert(Subtarget->canUseLAHFSAHF() &&
6423 "Target doesn't support SAHF or FCOMI?");
6424 SDValue AH = CurDAG->getCopyToReg(Chain, dl, X86::AH, Extract,
SDValue());
6427 CurDAG->getMachineNode(X86::SAHF, dl, MVT::i32, AH.
getValue(1)), 0);
6430 ReplaceUses(
SDValue(Node, 1), Chain);
6432 ReplaceUses(
SDValue(Node, 0), SAHF);
6433 CurDAG->RemoveDeadNode(Node);
6453 if (MachineSDNode *NewNode = matchBEXTRFromAndImm(N0.
getNode())) {
6454 unsigned TestOpc = CmpVT == MVT::i64 ? X86::TEST64rr
6457 NewNode = CurDAG->getMachineNode(TestOpc, dl, MVT::i32, BEXTR, BEXTR);
6459 CurDAG->RemoveDeadNode(Node);
6486 onlyUsesZeroFlag(
SDValue(Node, 0))) {
6491 unsigned TestOpcode;
6499 if (LeadingZeros == 0 && SavesBytes) {
6504 ShiftAmt = TrailingZeros;
6506 TestOpcode = X86::TEST64rr;
6507 }
else if (TrailingZeros == 0 && SavesBytes) {
6513 if (LeadingZeros == 1) {
6517 MachineSDNode *
Add = CurDAG->getMachineNode(
6520 MachineSDNode *
Test = CurDAG->getMachineNode(
6522 ReplaceNode(Node,
Test);
6526 ShiftAmt = LeadingZeros;
6528 TestOpcode = X86::TEST64rr;
6529 }
else if (MaskC->hasOneUse() && !
isInt<32>(Mask)) {
6532 unsigned PopCount = 64 - LeadingZeros - TrailingZeros;
6533 if (PopCount == 8) {
6535 ShiftAmt = TrailingZeros;
6536 SubRegIdx = X86::sub_8bit;
6538 TestOpcode = X86::TEST8rr;
6539 }
else if (PopCount == 16) {
6541 ShiftAmt = TrailingZeros;
6542 SubRegIdx = X86::sub_16bit;
6543 SubRegVT = MVT::i16;
6544 TestOpcode = X86::TEST16rr;
6545 }
else if (PopCount == 32) {
6547 ShiftAmt = TrailingZeros;
6548 SubRegIdx = X86::sub_32bit;
6549 SubRegVT = MVT::i32;
6550 TestOpcode = X86::TEST32rr;
6554 SDValue ShiftC = CurDAG->getTargetConstant(ShiftAmt, dl, MVT::i64);
6556 CurDAG->getMachineNode(ShiftOpcode, dl, MVT::i64, MVT::i32,
6559 if (SubRegIdx != 0) {
6561 CurDAG->getTargetExtractSubreg(SubRegIdx, dl, SubRegVT, Shift);
6563 MachineSDNode *
Test =
6564 CurDAG->getMachineNode(TestOpcode, dl, MVT::i32, Shift, Shift);
6565 ReplaceNode(Node,
Test);
6572 unsigned ROpc, MOpc;
6580 (!(Mask & 0x80) || CmpVT == MVT::i8 ||
6581 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6584 SubRegOp = X86::sub_8bit;
6585 ROpc = X86::TEST8ri;
6586 MOpc = X86::TEST8mi;
6587 }
else if (OptForMinSize &&
isUInt<16>(Mask) &&
6588 (!(Mask & 0x8000) || CmpVT == MVT::i16 ||
6589 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6595 SubRegOp = X86::sub_16bit;
6596 ROpc = X86::TEST16ri;
6597 MOpc = X86::TEST16mi;
6599 ((!(Mask & 0x80000000) &&
6602 (CmpVT != MVT::i16 || !(Mask & 0x8000))) ||
6603 CmpVT == MVT::i32 ||
6604 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6611 SubRegOp = X86::sub_32bit;
6612 ROpc = X86::TEST32ri;
6613 MOpc = X86::TEST32mi;
6619 SDValue Imm = CurDAG->getTargetConstant(Mask, dl, VT);
6623 MachineSDNode *NewNode;
6624 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6625 if (tryFoldLoad(Node, N0.
getNode(),
Reg, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
6627 if (!LoadN->isSimple()) {
6628 unsigned NumVolBits = LoadN->getValueType(0).getSizeInBits();
6629 if ((MOpc == X86::TEST8mi && NumVolBits != 8) ||
6630 (MOpc == X86::TEST16mi && NumVolBits != 16) ||
6631 (MOpc == X86::TEST32mi && NumVolBits != 32))
6636 Reg.getOperand(0) };
6637 NewNode = CurDAG->getMachineNode(MOpc, dl, MVT::i32, MVT::Other,
Ops);
6639 ReplaceUses(
Reg.getValue(1),
SDValue(NewNode, 1));
6641 CurDAG->setNodeMemRefs(NewNode,
6646 Reg = CurDAG->getTargetExtractSubreg(SubRegOp, dl, VT,
Reg);
6648 NewNode = CurDAG->getMachineNode(ROpc, dl, MVT::i32,
Reg,
Imm);
6651 ReplaceNode(Node, NewNode);
6657 if (!Subtarget->hasSSE42())
6660 bool NeedIndex = !
SDValue(Node, 0).use_empty();
6661 bool NeedMask = !
SDValue(Node, 1).use_empty();
6663 bool MayFoldLoad = !NeedIndex || !NeedMask;
6665 MachineSDNode *CNode;
6668 Subtarget->hasAVX() ? X86::VPCMPISTRMrri : X86::PCMPISTRMrri;
6670 Subtarget->hasAVX() ? X86::VPCMPISTRMrmi : X86::PCMPISTRMrmi;
6671 CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node);
6674 if (NeedIndex || !NeedMask) {
6676 Subtarget->hasAVX() ? X86::VPCMPISTRIrri : X86::PCMPISTRIrri;
6678 Subtarget->hasAVX() ? X86::VPCMPISTRIrmi : X86::PCMPISTRIrmi;
6679 CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node);
6685 CurDAG->RemoveDeadNode(Node);
6689 if (!Subtarget->hasSSE42())
6693 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EAX,
6694 Node->getOperand(1),
6696 InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EDX,
6697 Node->getOperand(3), InGlue).getValue(1);
6699 bool NeedIndex = !
SDValue(Node, 0).use_empty();
6700 bool NeedMask = !
SDValue(Node, 1).use_empty();
6702 bool MayFoldLoad = !NeedIndex || !NeedMask;
6704 MachineSDNode *CNode;
6707 Subtarget->hasAVX() ? X86::VPCMPESTRMrri : X86::PCMPESTRMrri;
6709 Subtarget->hasAVX() ? X86::VPCMPESTRMrmi : X86::PCMPESTRMrmi;
6711 emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node, InGlue);
6714 if (NeedIndex || !NeedMask) {
6716 Subtarget->hasAVX() ? X86::VPCMPESTRIrri : X86::PCMPESTRIrri;
6718 Subtarget->hasAVX() ? X86::VPCMPESTRIrmi : X86::PCMPESTRIrmi;
6719 CNode = emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node, InGlue);
6724 CurDAG->RemoveDeadNode(Node);
6736 if (foldLoadStoreIntoMemOperand(Node))
6740 case X86ISD::SETCC_CARRY: {
6741 MVT VT =
Node->getSimpleValueType(0);
6743 if (Subtarget->hasSBBDepBreaking()) {
6748 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EFLAGS,
6753 unsigned Opc = VT == MVT::i64 ? X86::SETB_C64r : X86::SETB_C32r;
6754 MVT SetVT = VT == MVT::i64 ? MVT::i64 : MVT::i32;
6756 CurDAG->getMachineNode(
Opc, dl, SetVT, EFLAGS, EFLAGS.
getValue(1)),
6761 Result = getSBBZero(Node);
6765 if (VT == MVT::i8 || VT == MVT::i16) {
6766 int SubIndex = VT == MVT::i16 ? X86::sub_16bit : X86::sub_8bit;
6767 Result = CurDAG->getTargetExtractSubreg(SubIndex, dl, VT, Result);
6770 ReplaceUses(
SDValue(Node, 0), Result);
6771 CurDAG->RemoveDeadNode(Node);
6783 if (!
SDValue(Node, 0).use_empty()) {
6785 MVT VT =
Node->getSimpleValueType(0);
6786 if (VT == MVT::i8 || VT == MVT::i16) {
6787 int SubIndex = VT == MVT::i16 ? X86::sub_16bit : X86::sub_8bit;
6788 Result = CurDAG->getTargetExtractSubreg(SubIndex, dl, VT, Result);
6790 ReplaceUses(
SDValue(Node, 0), Result);
6793 CurDAG->RemoveDeadNode(Node);
6800 SDValue IndexOp = Mgt->getIndex();
6803 MVT ValueVT =
Node->getSimpleValueType(0);
6804 MVT MaskVT =
Mask.getSimpleValueType();
6821 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6822 Opc = IsFP ? X86::VGATHERDPSZ128rm : X86::VPGATHERDDZ128rm;
6823 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6824 Opc = IsFP ? X86::VGATHERDPSZ256rm : X86::VPGATHERDDZ256rm;
6825 else if (IndexVT == MVT::v16i32 && NumElts == 16 && EltSize == 32)
6826 Opc = IsFP ? X86::VGATHERDPSZrm : X86::VPGATHERDDZrm;
6827 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6828 Opc = IsFP ? X86::VGATHERDPDZ128rm : X86::VPGATHERDQZ128rm;
6829 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6830 Opc = IsFP ? X86::VGATHERDPDZ256rm : X86::VPGATHERDQZ256rm;
6831 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 64)
6832 Opc = IsFP ? X86::VGATHERDPDZrm : X86::VPGATHERDQZrm;
6833 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6834 Opc = IsFP ? X86::VGATHERQPSZ128rm : X86::VPGATHERQDZ128rm;
6835 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6836 Opc = IsFP ? X86::VGATHERQPSZ256rm : X86::VPGATHERQDZ256rm;
6837 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 32)
6838 Opc = IsFP ? X86::VGATHERQPSZrm : X86::VPGATHERQDZrm;
6839 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6840 Opc = IsFP ? X86::VGATHERQPDZ128rm : X86::VPGATHERQQZ128rm;
6841 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6842 Opc = IsFP ? X86::VGATHERQPDZ256rm : X86::VPGATHERQQZ256rm;
6843 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 64)
6844 Opc = IsFP ? X86::VGATHERQPDZrm : X86::VPGATHERQQZrm;
6846 assert(EVT(MaskVT) == EVT(ValueVT).changeVectorElementTypeToInteger() &&
6847 "Unexpected mask VT!");
6848 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6849 Opc = IsFP ? X86::VGATHERDPSrm : X86::VPGATHERDDrm;
6850 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6851 Opc = IsFP ? X86::VGATHERDPSYrm : X86::VPGATHERDDYrm;
6852 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6853 Opc = IsFP ? X86::VGATHERDPDrm : X86::VPGATHERDQrm;
6854 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6855 Opc = IsFP ? X86::VGATHERDPDYrm : X86::VPGATHERDQYrm;
6856 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6857 Opc = IsFP ? X86::VGATHERQPSrm : X86::VPGATHERQDrm;
6858 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6859 Opc = IsFP ? X86::VGATHERQPSYrm : X86::VPGATHERQDYrm;
6860 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6861 Opc = IsFP ? X86::VGATHERQPDrm : X86::VPGATHERQQrm;
6862 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6863 Opc = IsFP ? X86::VGATHERQPDYrm : X86::VPGATHERQQYrm;
6870 if (!selectVectorAddr(Mgt, Mgt->getBasePtr(), IndexOp, Mgt->getScale(),
6871 Base, Scale, Index, Disp, Segment))
6874 SDValue PassThru = Mgt->getPassThru();
6875 SDValue Chain = Mgt->getChain();
6877 SDVTList VTs = CurDAG->getVTList(ValueVT, MaskVT, MVT::Other);
6879 MachineSDNode *NewNode;
6882 Index, Disp, Segment, Chain};
6883 NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6886 Disp, Segment,
Mask, Chain};
6887 NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6889 CurDAG->setNodeMemRefs(NewNode, {Mgt->getMemOperand()});
6892 CurDAG->RemoveDeadNode(Node);
6898 SDValue IndexOp = Sc->getIndex();
6900 MVT ValueVT =
Value.getSimpleValueType();
6915 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6916 Opc = IsFP ? X86::VSCATTERDPSZ128mr : X86::VPSCATTERDDZ128mr;
6917 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6918 Opc = IsFP ? X86::VSCATTERDPSZ256mr : X86::VPSCATTERDDZ256mr;
6919 else if (IndexVT == MVT::v16i32 && NumElts == 16 && EltSize == 32)
6920 Opc = IsFP ? X86::VSCATTERDPSZmr : X86::VPSCATTERDDZmr;
6921 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6922 Opc = IsFP ? X86::VSCATTERDPDZ128mr : X86::VPSCATTERDQZ128mr;
6923 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6924 Opc = IsFP ? X86::VSCATTERDPDZ256mr : X86::VPSCATTERDQZ256mr;
6925 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 64)
6926 Opc = IsFP ? X86::VSCATTERDPDZmr : X86::VPSCATTERDQZmr;
6927 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6928 Opc = IsFP ? X86::VSCATTERQPSZ128mr : X86::VPSCATTERQDZ128mr;
6929 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6930 Opc = IsFP ? X86::VSCATTERQPSZ256mr : X86::VPSCATTERQDZ256mr;
6931 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 32)
6932 Opc = IsFP ? X86::VSCATTERQPSZmr : X86::VPSCATTERQDZmr;
6933 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6934 Opc = IsFP ? X86::VSCATTERQPDZ128mr : X86::VPSCATTERQQZ128mr;
6935 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6936 Opc = IsFP ? X86::VSCATTERQPDZ256mr : X86::VPSCATTERQQZ256mr;
6937 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 64)
6938 Opc = IsFP ? X86::VSCATTERQPDZmr : X86::VPSCATTERQQZmr;
6943 if (!selectVectorAddr(Sc, Sc->getBasePtr(), IndexOp, Sc->getScale(),
6944 Base, Scale, Index, Disp, Segment))
6948 SDValue Chain = Sc->getChain();
6950 SDVTList VTs = CurDAG->getVTList(
Mask.getValueType(), MVT::Other);
6953 MachineSDNode *NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6954 CurDAG->setNodeMemRefs(NewNode, {Sc->getMemOperand()});
6956 CurDAG->RemoveDeadNode(Node);
6960 auto *MFI = CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
6961 auto CallId = MFI->getPreallocatedIdForCallSite(
6964 SDValue CallIdValue = CurDAG->getTargetConstant(CallId, dl, MVT::i32);
6965 MachineSDNode *
New = CurDAG->getMachineNode(
6966 TargetOpcode::PREALLOCATED_SETUP, dl, MVT::Other, CallIdValue, Chain);
6968 CurDAG->RemoveDeadNode(Node);
6972 auto *MFI = CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
6976 SDValue CallIdValue = CurDAG->getTargetConstant(CallId, dl, MVT::i32);
6979 Ops[0] = CallIdValue;
6982 MachineSDNode *
New = CurDAG->getMachineNode(
6983 TargetOpcode::PREALLOCATED_ARG, dl,
6984 CurDAG->getVTList(TLI->
getPointerTy(CurDAG->getDataLayout()),
6989 CurDAG->RemoveDeadNode(Node);
6996 if (!Subtarget->hasWIDEKL())
7000 switch (
Node->getOpcode()) {
7004 Opcode = X86::AESENCWIDE128KL;
7007 Opcode = X86::AESDECWIDE128KL;
7010 Opcode = X86::AESENCWIDE256KL;
7013 Opcode = X86::AESDECWIDE256KL;
7021 if (!selectAddr(Node, Addr,
Base, Scale, Index, Disp, Segment))
7024 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM0,
Node->getOperand(2),
7026 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM1,
Node->getOperand(3),
7028 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM2,
Node->getOperand(4),
7030 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM3,
Node->getOperand(5),
7032 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM4,
Node->getOperand(6),
7034 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM5,
Node->getOperand(7),
7036 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM6,
Node->getOperand(8),
7038 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM7,
Node->getOperand(9),
7041 MachineSDNode *Res = CurDAG->getMachineNode(
7042 Opcode, dl,
Node->getVTList(),
7043 {Base, Scale, Index, Disp, Segment, Chain, Chain.getValue(1)});
7045 ReplaceNode(Node, Res);
7052 if (
Node->getNumValues() == 3)
7053 Glue =
Node->getOperand(2);
7055 CurDAG->getCopyFromReg(Chain, dl,
Reg,
Node->getValueType(0), Glue);
7056 ReplaceNode(Node,
Copy.getNode());
7064bool X86DAGToDAGISel::SelectInlineAsmMemoryOperand(
7066 std::vector<SDValue> &OutOps) {
7067 SDValue Op0, Op1, Op2, Op3, Op4;
7068 switch (ConstraintID) {
7071 case InlineAsm::ConstraintCode::o:
7072 case InlineAsm::ConstraintCode::v:
7073 case InlineAsm::ConstraintCode::m:
7074 case InlineAsm::ConstraintCode::X:
7075 case InlineAsm::ConstraintCode::p:
7076 if (!selectAddr(
nullptr,
Op, Op0, Op1, Op2, Op3, Op4))
7081 OutOps.push_back(Op0);
7082 OutOps.push_back(Op1);
7083 OutOps.push_back(Op2);
7084 OutOps.push_back(Op3);
7085 OutOps.push_back(Op4);
7091 std::make_unique<X86DAGToDAGISel>(TM, TM.getOptLevel())) {}
7097 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 addrMayUseNonFixedFrameIndex(SDValue Addr, const MachineFrameInfo &MFI, unsigned Depth=0)
Return true if Addr may be matched with a non-fixed frame index as base.
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 bool isEndbrImm(uint64_t Imm, unsigned BitWidth)
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 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.
bool isScalarInteger() const
Return true if this is an integer, not including vectors.
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.
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
bool isFixedObjectIndex(int ObjectIdx) const
Returns true if the specified index corresponds to a fixed stack object.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
const 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)
constexpr unsigned BitWidth
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