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;
111 void setBaseReg(SDValue
Reg) {
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;
217 SDValue matchIndexRecursively(SDValue
N, X86ISelAddressMode &AM,
219 bool matchAddressRecursively(SDValue
N, X86ISelAddressMode &AM,
221 bool matchVectorAddressRecursively(SDValue
N, X86ISelAddressMode &AM,
223 bool matchAddressBase(SDValue
N, X86ISelAddressMode &AM);
224 bool selectAddr(SDNode *Parent, SDValue
N, SDValue &
Base, SDValue &Scale,
225 SDValue &Index, SDValue &Disp, SDValue &Segment,
226 bool HasNDDM =
true);
227 bool selectNDDAddr(SDNode *Parent, SDValue
N, SDValue &
Base, SDValue &Scale,
228 SDValue &Index, SDValue &Disp, SDValue &Segment);
229 bool selectVectorAddr(MemSDNode *Parent, SDValue BasePtr, SDValue IndexOp,
230 SDValue ScaleOp, SDValue &
Base, SDValue &Scale,
231 SDValue &Index, SDValue &Disp, SDValue &Segment);
232 bool selectMOV64Imm32(SDValue
N, SDValue &
Imm);
233 bool selectLEAAddr(SDValue
N, SDValue &
Base,
234 SDValue &Scale, SDValue &Index, SDValue &Disp,
236 bool selectLEA64_Addr(SDValue
N, SDValue &
Base, SDValue &Scale,
237 SDValue &Index, SDValue &Disp, SDValue &Segment);
238 bool selectTLSADDRAddr(SDValue
N, SDValue &
Base,
239 SDValue &Scale, SDValue &Index, SDValue &Disp,
241 bool selectRelocImm(SDValue
N, SDValue &
Op);
243 bool tryFoldLoad(SDNode *Root, SDNode *
P, SDValue
N,
244 SDValue &
Base, SDValue &Scale,
245 SDValue &Index, SDValue &Disp,
249 bool tryFoldLoad(SDNode *
P, SDValue
N,
250 SDValue &
Base, SDValue &Scale,
251 SDValue &Index, SDValue &Disp,
253 return tryFoldLoad(
P,
P,
N,
Base, Scale, Index, Disp, Segment);
256 bool tryFoldBroadcast(SDNode *Root, SDNode *
P, SDValue
N,
257 SDValue &
Base, SDValue &Scale,
258 SDValue &Index, SDValue &Disp,
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,
271 MVT VT, SDValue &
Base, SDValue &Scale,
272 SDValue &Index, SDValue &Disp,
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) {
306 SDValue Neg = SDValue(CurDAG->getMachineNode(NegOpc,
DL, VT, MVT::i32,
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) {
358 SDValue
Op =
N->getOperand(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 ||
424 SDValue OtherOp =
User->getOperand(0);
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);
489 SDValue getSBBZero(SDNode *
N) {
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;
544 bool isDef32(SDNode *
N)
const {
545 unsigned Opc =
N->getOpcode();
550 !((
Opc == X86ISD::BSF ||
Opc == X86ISD::BSR) &&
558 SDNode *getGlobalBaseReg();
562 const X86TargetMachine &getTargetMachine()
const {
563 return static_cast<const X86TargetMachine &
>(TM);
568 const X86InstrInfo *getInstrInfo()
const {
569 return Subtarget->getInstrInfo();
578 bool ComplexPatternFuncMutatesDAG()
const override {
582 bool isSExtAbsoluteSymbolRef(
unsigned Width, SDNode *
N)
const;
585 bool useNonTemporalLoad(LoadSDNode *
N)
const {
586 if (!
N->isNonTemporal())
589 unsigned StoreSize =
N->getMemoryVT().getStoreSize();
591 if (
N->getAlign().value() < StoreSize)
600 return Subtarget->hasSSE41();
602 return Subtarget->hasAVX2();
604 return Subtarget->hasAVX512();
608 bool foldLoadStoreIntoMemOperand(SDNode *Node);
609 MachineSDNode *matchBEXTRFromAndImm(SDNode *Node);
610 bool matchBitExtract(SDNode *Node);
611 bool shrinkAndImmediate(SDNode *
N);
612 bool isMaskZeroExtended(SDNode *
N)
const;
613 bool tryShiftAmountMod(SDNode *
N);
614 bool tryShrinkShlLogicImm(SDNode *
N);
615 bool tryVPTERNLOG(SDNode *
N);
616 bool matchVPTERNLOG(SDNode *Root, SDNode *ParentA, SDNode *ParentB,
617 SDNode *ParentC, SDValue
A, SDValue
B, SDValue
C,
619 bool tryVPTESTM(SDNode *Root, SDValue Setcc, SDValue Mask);
620 bool tryMatchBitSelect(SDNode *
N);
622 MachineSDNode *emitPCMPISTR(
unsigned ROpc,
unsigned MOpc,
bool MayFoldLoad,
623 const SDLoc &dl, MVT VT, SDNode *Node);
624 MachineSDNode *emitPCMPESTR(
unsigned ROpc,
unsigned MOpc,
bool MayFoldLoad,
625 const SDLoc &dl, MVT VT, SDNode *Node,
628 bool tryOptimizeRem8Extend(SDNode *
N);
630 bool onlyUsesZeroFlag(SDValue Flags)
const;
631 bool hasNoSignFlagUses(SDValue Flags)
const;
632 bool hasNoCarryFlagUses(SDValue Flags)
const;
633 bool checkTCRetEnoughRegs(SDNode *
N)
const;
639 explicit X86DAGToDAGISelLegacy(X86TargetMachine &tm,
641 : SelectionDAGISelLegacy(
642 ID, std::make_unique<X86DAGToDAGISel>(tm, OptLevel)) {}
646char X86DAGToDAGISelLegacy::ID = 0;
653 unsigned Opcode =
N->getOpcode();
654 if (Opcode == X86ISD::CMPM || Opcode == X86ISD::CMPMM ||
655 Opcode == X86ISD::STRICT_CMPM || Opcode ==
ISD::SETCC ||
656 Opcode == X86ISD::CMPMM_SAE || Opcode == X86ISD::VFPCLASS) {
660 EVT OpVT =
N->getOperand(0).getValueType();
663 if (Opcode == X86ISD::STRICT_CMPM)
664 OpVT =
N->getOperand(1).getValueType();
666 return Subtarget->hasVLX();
671 if (Opcode == X86ISD::VFPCLASSS || Opcode == X86ISD::FSETCCM ||
672 Opcode == X86ISD::FSETCCM_SAE)
680bool X86DAGToDAGISel::isMaskZeroExtended(
SDNode *
N)
const {
692X86DAGToDAGISel::IsProfitableToFold(SDValue
N, SDNode *U, SDNode *Root)
const {
693 if (OptLevel == CodeGenOptLevel::None)
708 switch (
U->getOpcode()) {
722 SDValue Op1 =
U->getOperand(1);
735 if (
Imm->getAPIntValue().isSignedIntN(8))
744 Imm->getAPIntValue().getBitWidth() == 64 &&
745 Imm->getAPIntValue().isIntN(32))
752 (
Imm->getAPIntValue() == UINT8_MAX ||
753 Imm->getAPIntValue() == UINT16_MAX ||
754 Imm->getAPIntValue() == UINT32_MAX))
760 (-
Imm->getAPIntValue()).isSignedIntN(8))
763 if ((
U->getOpcode() == X86ISD::ADD ||
U->getOpcode() == X86ISD::SUB) &&
764 (-
Imm->getAPIntValue()).isSignedIntN(8) &&
765 hasNoCarryFlagUses(SDValue(U, 1)))
779 if (Op1.
getOpcode() == X86ISD::Wrapper) {
790 if (
U->getOperand(0).getOpcode() ==
ISD::SHL &&
794 if (
U->getOperand(1).getOpcode() ==
ISD::SHL &&
799 SDValue U0 =
U->getOperand(0);
800 SDValue U1 =
U->getOperand(1);
803 if (
C &&
C->getSExtValue() == -2)
809 if (
C &&
C->getSExtValue() == -2)
844bool X86DAGToDAGISel::isProfitableToFormMaskedOp(SDNode *
N)
const {
846 (
N->getOpcode() ==
ISD::VSELECT ||
N->getOpcode() == X86ISD::SELECTS) &&
847 "Unexpected opcode!");
852 return N->getOperand(1).hasOneUse();
862 Ops.push_back(
Load.getOperand(0));
865 "Unexpected chain operand");
868 Ops.push_back(
Load.getOperand(0));
874 Ops.push_back(NewChain);
879 Load.getOperand(1),
Load.getOperand(2));
897 if (Callee.getNode() == Chain.
getNode() || !Callee.hasOneUse())
909 if (!Callee.getValue(1).hasOneUse())
940 Callee.getValue(1).hasOneUse())
958 const unsigned NumBytes =
BitWidth / 8;
962 const uint8_t OptionalPrefixBytes[] = {0x26, 0x2e, 0x36, 0x3e, 0x64,
963 0x65, 0x66, 0x67, 0xf0, 0xf2};
965 for (
unsigned I = 0;
I != NumBytes; ++
I)
966 Bytes[
I] = (
Imm >> (
I * 8)) & 0xFF;
968 for (
unsigned I = 0;
I + 3 < NumBytes; ++
I) {
969 if (Bytes[
I] != 0xf3)
976 if (J + 2 < NumBytes && Bytes[J] == 0x0f && Bytes[J + 1] == 0x1e &&
977 (Bytes[J + 2] == 0xfa || Bytes[J + 2] == 0xfb))
985 return (VT == MVT::v32i16 || VT == MVT::v32f16 || VT == MVT::v64i8);
988void X86DAGToDAGISel::PreprocessISelDAG() {
989 bool MadeChange =
false;
991 E = CurDAG->allnodes_end();
I !=
E; ) {
1009 MVT VT =
N->getSimpleValueType(0);
1011 "ISD::Constant must have a scalar integer type");
1020 "cf-protection-branch");
1025 SDValue Complement =
1026 CurDAG->getConstant(ComplementImm, dl, VT,
false,
true);
1027 Complement = CurDAG->getNOT(dl, Complement, VT);
1029 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), Complement);
1039 if (
N->getOpcode() == X86ISD::AND && !
N->hasAnyUseOfValue(1)) {
1040 SDValue Res = CurDAG->getNode(
ISD::AND, SDLoc(
N),
N->getValueType(0),
1041 N->getOperand(0),
N->getOperand(1));
1043 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), Res);
1067 auto mayPreventLoadFold = [&]() {
1069 N->getOpcode() ==
ISD::ADD && Subtarget->hasAVX() &&
1070 !
N->getOperand(1).hasOneUse();
1073 N->getSimpleValueType(0).isVector() && !mayPreventLoadFold()) {
1081 MVT VT =
N->getSimpleValueType(0);
1089 CurDAG->getNode(NewOpcode,
DL, VT,
N->getOperand(0),
AllOnes);
1091 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1098 switch (
N->getOpcode()) {
1099 case X86ISD::VBROADCAST: {
1100 MVT VT =
N->getSimpleValueType(0);
1102 if (!Subtarget->hasBWI() &&
needBWI(VT)) {
1105 SDValue NarrowBCast =
1106 CurDAG->getNode(X86ISD::VBROADCAST, dl, NarrowVT,
N->getOperand(0));
1109 NarrowBCast, CurDAG->getIntPtrConstant(0, dl));
1112 CurDAG->getIntPtrConstant(Index, dl));
1115 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1123 case X86ISD::VBROADCAST_LOAD: {
1124 MVT VT =
N->getSimpleValueType(0);
1126 if (!Subtarget->hasBWI() &&
needBWI(VT)) {
1130 SDVTList VTs = CurDAG->getVTList(NarrowVT, MVT::Other);
1131 SDValue
Ops[] = {MemNode->getChain(), MemNode->getBasePtr()};
1132 SDValue NarrowBCast = CurDAG->getMemIntrinsicNode(
1133 X86ISD::VBROADCAST_LOAD, dl, VTs,
Ops, MemNode->getMemoryVT(),
1134 MemNode->getMemOperand());
1137 NarrowBCast, CurDAG->getIntPtrConstant(0, dl));
1140 CurDAG->getIntPtrConstant(Index, dl));
1143 SDValue To[] = {Res, NarrowBCast.
getValue(1)};
1144 CurDAG->ReplaceAllUsesWith(
N, To);
1156 MVT VT =
N->getSimpleValueType(0);
1162 SDNode *MaxLd =
nullptr;
1163 SDValue Ptr = Ld->getBasePtr();
1164 SDValue Chain = Ld->getChain();
1165 for (SDNode *User : Ptr->
users()) {
1167 MVT UserVT =
User->getSimpleValueType(0);
1169 UserLd->getBasePtr() == Ptr && UserLd->getChain() == Chain &&
1170 !
User->hasAnyUseOfValue(1) &&
1184 CurDAG->getIntPtrConstant(0, dl));
1185 SDValue Res = CurDAG->getBitcast(VT, Extract);
1188 SDValue To[] = {Res, SDValue(MaxLd, 1)};
1189 CurDAG->ReplaceAllUsesWith(
N, To);
1198 EVT EleVT =
N->getOperand(0).getValueType().getVectorElementType();
1199 if (EleVT == MVT::i1)
1202 assert(Subtarget->hasSSE41() &&
"Expected SSE4.1 support!");
1203 assert(
N->getValueType(0).getVectorElementType() != MVT::i16 &&
1204 "We can't replace VSELECT with BLENDV in vXi16!");
1206 if (Subtarget->hasVLX() && CurDAG->ComputeNumSignBits(
N->getOperand(0)) ==
1208 R = CurDAG->getNode(X86ISD::VPTERNLOG, SDLoc(
N),
N->getValueType(0),
1209 N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
1210 CurDAG->getTargetConstant(0xCA, SDLoc(
N), MVT::i8));
1212 R = CurDAG->getNode(X86ISD::BLENDV, SDLoc(
N),
N->getValueType(0),
1213 N->getOperand(0),
N->getOperand(1),
1217 CurDAG->ReplaceAllUsesWith(
N,
R.getNode());
1230 if (!
N->getSimpleValueType(0).isVector())
1234 switch (
N->getOpcode()) {
1244 if (
N->isStrictFPOpcode())
1246 CurDAG->getNode(NewOpc, SDLoc(
N), {
N->getValueType(0), MVT::Other},
1247 {
N->getOperand(0),
N->getOperand(1)});
1250 CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1253 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1263 if (!
N->getValueType(0).isVector())
1267 switch (
N->getOpcode()) {
1269 case ISD::SHL: NewOpc = X86ISD::VSHLV;
break;
1270 case ISD::SRA: NewOpc = X86ISD::VSRAV;
break;
1271 case ISD::SRL: NewOpc = X86ISD::VSRLV;
break;
1273 SDValue Res = CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1274 N->getOperand(0),
N->getOperand(1));
1276 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), Res);
1285 if (!
N->getValueType(0).isVector())
1289 if (
N->getOperand(0).getScalarValueSizeInBits() == 1) {
1291 "Unexpected opcode for mask vector!");
1299 SDValue Res = CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1302 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), Res);
1322 switch (
N->getOpcode()) {
1338 bool IsStrict =
N->isStrictFPOpcode();
1341 Res = CurDAG->getNode(X86ISD::STRICT_VRNDSCALE, dl,
1342 {
N->getValueType(0), MVT::Other},
1343 {
N->getOperand(0),
N->getOperand(1),
1344 CurDAG->getTargetConstant(
Imm, dl, MVT::i32)});
1346 Res = CurDAG->getNode(X86ISD::VRNDSCALE, dl,
N->getValueType(0),
1348 CurDAG->getTargetConstant(
Imm, dl, MVT::i32));
1350 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1358 case X86ISD::FXOR: {
1361 MVT VT =
N->getSimpleValueType(0);
1362 if (VT.
isVector() || VT == MVT::f128)
1365 MVT VecVT = VT == MVT::f64 ? MVT::v2f64
1366 : VT == MVT::f32 ? MVT::v4f32
1376 if (Subtarget->hasSSE2()) {
1377 EVT IntVT = EVT(VecVT).changeVectorElementTypeToInteger();
1381 switch (
N->getOpcode()) {
1383 case X86ISD::FANDN:
Opc = X86ISD::ANDNP;
break;
1388 Res = CurDAG->getNode(
Opc, dl, IntVT, Op0, Op1);
1391 Res = CurDAG->getNode(
N->getOpcode(), dl, VecVT, Op0, Op1);
1394 CurDAG->getIntPtrConstant(0, dl));
1396 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), Res);
1403 if (OptLevel != CodeGenOptLevel::None &&
1406 !Subtarget->useIndirectThunkCalls() &&
1407 ((
N->getOpcode() == X86ISD::CALL && !Subtarget->slowTwoMemOps() &&
1408 !Subtarget->slowIndirectCall()) ||
1409 (
N->getOpcode() == X86ISD::TC_RETURN &&
1410 (Subtarget->is64Bit() ||
1411 !getTargetMachine().isPositionIndependent())))) {
1431 bool HasCallSeq =
N->getOpcode() == X86ISD::CALL;
1436 if (
N->getOpcode() == X86ISD::TC_RETURN && !checkTCRetEnoughRegs(
N))
1452 switch (
N->getOpcode()) {
1457 MVT SrcVT =
N->getOperand(0).getSimpleValueType();
1458 MVT DstVT =
N->getSimpleValueType(0);
1466 const X86TargetLowering *X86Lowering =
1467 static_cast<const X86TargetLowering *
>(TLI);
1470 if (SrcIsSSE && DstIsSSE)
1473 if (!SrcIsSSE && !DstIsSSE) {
1478 if (
N->getConstantOperandVal(1))
1486 SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
1488 MachinePointerInfo MPI =
1494 SDValue
Store = CurDAG->getTruncStore(
1495 CurDAG->getEntryNode(), dl,
N->getOperand(0), MemTmp, MPI, MemVT);
1497 MemTmp, MPI, MemVT);
1504 CurDAG->ReplaceAllUsesOfValueWith(SDValue(
N, 0), Result);
1513 MVT SrcVT =
N->getOperand(1).getSimpleValueType();
1514 MVT DstVT =
N->getSimpleValueType(0);
1522 const X86TargetLowering *X86Lowering =
1523 static_cast<const X86TargetLowering *
>(TLI);
1526 if (SrcIsSSE && DstIsSSE)
1529 if (!SrcIsSSE && !DstIsSSE) {
1534 if (
N->getConstantOperandVal(2))
1542 SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
1544 MachinePointerInfo MPI =
1553 SDVTList VTs = CurDAG->getVTList(MVT::Other);
1554 SDValue
Ops[] = {
N->getOperand(0),
N->getOperand(1), MemTmp};
1555 Store = CurDAG->getMemIntrinsicNode(X86ISD::FST, dl, VTs,
Ops, MemVT,
1558 if (
N->getFlags().hasNoFPExcept()) {
1560 Flags.setNoFPExcept(
true);
1561 Store->setFlags(Flags);
1564 assert(SrcVT == MemVT &&
"Unexpected VT!");
1565 Store = CurDAG->getStore(
N->getOperand(0), dl,
N->getOperand(1), MemTmp,
1570 SDVTList VTs = CurDAG->getVTList(DstVT, MVT::Other);
1572 Result = CurDAG->getMemIntrinsicNode(
1573 X86ISD::FLD, dl, VTs,
Ops, MemVT, MPI,
1575 if (
N->getFlags().hasNoFPExcept()) {
1577 Flags.setNoFPExcept(
true);
1581 assert(DstVT == MemVT &&
"Unexpected VT!");
1582 Result = CurDAG->getLoad(DstVT, dl,
Store, MemTmp, MPI);
1590 CurDAG->ReplaceAllUsesWith(
N,
Result.getNode());
1604 CurDAG->RemoveDeadNodes();
1608bool X86DAGToDAGISel::tryOptimizeRem8Extend(SDNode *
N) {
1609 unsigned Opc =
N->getMachineOpcode();
1610 if (
Opc != X86::MOVZX32rr8 &&
Opc != X86::MOVSX32rr8 &&
1611 Opc != X86::MOVSX64rr8)
1614 SDValue N0 =
N->getOperand(0);
1623 unsigned ExpectedOpc =
Opc == X86::MOVZX32rr8 ? X86::MOVZX32rr8_NOREX
1624 : X86::MOVSX32rr8_NOREX;
1629 if (
Opc == X86::MOVSX64rr8) {
1632 MachineSDNode *Extend = CurDAG->getMachineNode(X86::MOVSX64rr32, SDLoc(
N),
1634 ReplaceUses(
N, Extend);
1643void X86DAGToDAGISel::PostprocessISelDAG() {
1645 if (TM.getOptLevel() == CodeGenOptLevel::None)
1650 bool MadeChange =
false;
1651 while (Position != CurDAG->allnodes_begin()) {
1652 SDNode *
N = &*--Position;
1654 if (
N->use_empty() || !
N->isMachineOpcode())
1657 if (tryOptimizeRem8Extend(
N)) {
1662 unsigned Opc =
N->getMachineOpcode();
1673 case X86::CTEST16rr:
1674 case X86::CTEST32rr:
1675 case X86::CTEST64rr: {
1681#define CASE_ND(OP) \
1684 switch (
And.getMachineOpcode()) {
1691 if (
And->hasAnyUseOfValue(1))
1694 Ops[0] =
And.getOperand(0);
1695 Ops[1] =
And.getOperand(1);
1696 MachineSDNode *
Test =
1697 CurDAG->getMachineNode(
Opc, SDLoc(
N), MVT::i32,
Ops);
1698 ReplaceUses(
N,
Test);
1706 if (
And->hasAnyUseOfValue(1))
1709 bool IsCTESTCC = X86::isCTESTCC(
Opc);
1710#define FROM_TO(A, B) \
1711 CASE_ND(A) NewOpc = IsCTESTCC ? X86::C##B : X86::B; \
1713 switch (
And.getMachineOpcode()) {
1723 And.getOperand(3),
And.getOperand(4),
1724 And.getOperand(5),
And.getOperand(0)};
1727 Ops.push_back(
N->getOperand(2));
1728 Ops.push_back(
N->getOperand(3));
1731 Ops.push_back(
And.getOperand(6));
1734 Ops.push_back(
N->getOperand(4));
1736 MachineSDNode *
Test = CurDAG->getMachineNode(
1737 NewOpc, SDLoc(
N), MVT::i32, MVT::Other,
Ops);
1738 CurDAG->setNodeMemRefs(
1740 ReplaceUses(
And.getValue(2), SDValue(
Test, 1));
1741 ReplaceUses(SDValue(
N, 0), SDValue(
Test, 0));
1751 case X86::KORTESTBkk:
1752 case X86::KORTESTWkk:
1753 case X86::KORTESTDkk:
1754 case X86::KORTESTQkk: {
1756 if (Op0 !=
N->getOperand(1) || !
N->isOnlyUserOf(Op0.
getNode()) ||
1771#define FROM_TO(A, B) \
1783 if (NewOpc == X86::KTESTWkk && !Subtarget->hasDQI())
1786 MachineSDNode *KTest = CurDAG->getMachineNode(
1788 ReplaceUses(
N, KTest);
1793 case TargetOpcode::SUBREG_TO_REG: {
1794 unsigned SubRegIdx =
N->getConstantOperandVal(1);
1795 if (SubRegIdx != X86::sub_xmm && SubRegIdx != X86::sub_ymm)
1798 SDValue Move =
N->getOperand(0);
1812 CASE(VMOVAPDZ128rr)
CASE(VMOVUPDZ128rr)
1813 CASE(VMOVAPSZ128rr)
CASE(VMOVUPSZ128rr)
1814 CASE(VMOVDQA32Z128rr)
CASE(VMOVDQU32Z128rr)
1815 CASE(VMOVDQA64Z128rr)
CASE(VMOVDQU64Z128rr)
1816 CASE(VMOVAPDZ256rr)
CASE(VMOVUPDZ256rr)
1817 CASE(VMOVAPSZ256rr)
CASE(VMOVUPSZ256rr)
1818 CASE(VMOVDQA32Z256rr)
CASE(VMOVDQU32Z256rr)
1819 CASE(VMOVDQA64Z256rr)
CASE(VMOVDQU64Z256rr)
1824 if (!
In.isMachineOpcode() ||
1825 In.getMachineOpcode() <= TargetOpcode::GENERIC_OP_END)
1830 uint64_t TSFlags = getInstrInfo()->get(
In.getMachineOpcode()).TSFlags;
1838 CurDAG->UpdateNodeOperands(
N, In,
N->getOperand(1));
1845 CurDAG->RemoveDeadNodes();
1850void X86DAGToDAGISel::emitSpecialCodeForMain() {
1851 if (Subtarget->isTargetCygMing()) {
1852 TargetLowering::ArgListTy
Args;
1853 auto &
DL = CurDAG->getDataLayout();
1855 TargetLowering::CallLoweringInfo CLI(*CurDAG);
1856 CLI.setChain(CurDAG->getRoot())
1857 .setCallee(CallingConv::C, Type::getVoidTy(*CurDAG->getContext()),
1858 CurDAG->getExternalSymbol(
"__main", TLI->getPointerTy(
DL)),
1860 const TargetLowering &TLI = CurDAG->getTargetLoweringInfo();
1862 CurDAG->setRoot(
Result.second);
1866void X86DAGToDAGISel::emitFunctionEntryCode() {
1869 if (
F.hasExternalLinkage() &&
F.getName() ==
"main")
1870 emitSpecialCodeForMain();
1884 X86ISelAddressMode &AM) {
1889 int64_t Val = AM.Disp +
Offset;
1892 if (Val != 0 && (AM.ES || AM.MCSym))
1896 if (Subtarget->is64Bit()) {
1899 AM.hasSymbolicDisplacement()))
1903 if (AM.BaseType == X86ISelAddressMode::FrameIndexBase &&
1922 if (Subtarget->isTarget64BitILP32() &&
1924 !AM.hasBaseOrIndexReg())
1926 }
else if (Subtarget->is16Bit()) {
1929 if (Val < -(int64_t)UINT16_MAX || Val > (int64_t)UINT16_MAX)
1939bool X86DAGToDAGISel::matchLoadInAddress(LoadSDNode *
N, X86ISelAddressMode &AM,
1940 bool AllowSegmentRegForX32) {
1941 SDValue
Address =
N->getOperand(1);
1953 !IndirectTlsSegRefs &&
1954 (Subtarget->isTargetGlibc() || Subtarget->isTargetMusl() ||
1955 Subtarget->isTargetAndroid() || Subtarget->isTargetFuchsia())) {
1956 if (Subtarget->isTarget64BitILP32() && !AllowSegmentRegForX32)
1958 switch (
N->getPointerInfo().getAddrSpace()) {
1960 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
1963 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
1976bool X86DAGToDAGISel::matchWrapper(SDValue
N, X86ISelAddressMode &AM) {
1979 if (AM.hasSymbolicDisplacement())
1982 bool IsRIPRelTLS =
false;
1983 bool IsRIPRel =
N.getOpcode() == X86ISD::WrapperRIP;
1985 SDValue Val =
N.getOperand(0);
2000 if (IsRIPRel && AM.hasBaseOrIndexReg())
2004 X86ISelAddressMode Backup = AM;
2009 AM.GV =
G->getGlobal();
2010 AM.SymbolFlags =
G->getTargetFlags();
2013 AM.CP = CP->getConstVal();
2014 AM.Alignment = CP->getAlign();
2015 AM.SymbolFlags = CP->getTargetFlags();
2016 Offset = CP->getOffset();
2018 AM.ES = S->getSymbol();
2019 AM.SymbolFlags = S->getTargetFlags();
2021 AM.MCSym = S->getMCSymbol();
2023 AM.JT = J->getIndex();
2024 AM.SymbolFlags = J->getTargetFlags();
2026 AM.BlockAddr = BA->getBlockAddress();
2027 AM.SymbolFlags = BA->getTargetFlags();
2028 Offset = BA->getOffset();
2033 if (Subtarget->is64Bit() && !IsRIPRel && AM.GV &&
2034 TM.isLargeGlobalValue(AM.GV)) {
2039 if (foldOffsetIntoAddress(
Offset, AM)) {
2045 AM.setBaseReg(CurDAG->getRegister(X86::RIP, MVT::i64));
2053bool X86DAGToDAGISel::matchAddress(SDValue
N, X86ISelAddressMode &AM) {
2054 if (matchAddressRecursively(
N, AM, 0))
2061 if (Subtarget->isTarget64BitILP32() &&
2062 AM.BaseType == X86ISelAddressMode::RegBase &&
2063 AM.Base_Reg.
getNode() !=
nullptr && AM.IndexReg.
getNode() ==
nullptr) {
2064 SDValue Save_Base_Reg = AM.Base_Reg;
2066 AM.Base_Reg = SDValue();
2067 if (matchLoadInAddress(LoadN, AM,
true))
2068 AM.Base_Reg = Save_Base_Reg;
2077 if (AM.Scale == 2 && !AM.NegateIndex &&
2078 AM.BaseType == X86ISelAddressMode::RegBase &&
2079 AM.Base_Reg.
getNode() ==
nullptr) {
2080 AM.Base_Reg = AM.IndexReg;
2087 (!AM.GV || !TM.isLargeGlobalValue(AM.GV)) && Subtarget->is64Bit() &&
2088 AM.Scale == 1 && AM.BaseType == X86ISelAddressMode::RegBase &&
2089 AM.Base_Reg.
getNode() ==
nullptr && AM.IndexReg.
getNode() ==
nullptr &&
2101 AM.Base_Reg = CurDAG->getRegister(X86::RIP, MVT::i64);
2114bool X86DAGToDAGISel::hasMaterializingUse(SDValue V)
const {
2115 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
2116 for (SDUse &U :
V->uses()) {
2117 if (
U.getResNo() !=
V.getResNo())
2119 SDNode *
User =
U.getUser();
2125 if (St->getValue() == V)
2136 if (!
User->isMachineOpcode())
2138 const MCInstrDesc &
Desc =
TII->get(
User->getMachineOpcode());
2139 if (!
Desc.mayStore())
2142 if (MemRefBegin < 0)
2145 for (
unsigned I = 0,
E =
User->getNumOperands();
I !=
E; ++
I) {
2146 if (
I >=
static_cast<unsigned>(MemRefBegin) &&
I < MemRefEnd)
2148 SDValue Opnd =
User->getOperand(
I);
2158bool X86DAGToDAGISel::matchAdd(SDValue &
N, X86ISelAddressMode &AM,
2162 HandleSDNode Handle(
N);
2164 auto IsAddOrAddLike = [&](SDValue
V) {
2165 return V.getOpcode() ==
ISD::ADD || CurDAG->isADDLike(V);
2174 auto SplitsMaterializedValue = [&](SDValue
Op) {
2175 if (!AM.IsForLEA || !hasMaterializingUse(
Op))
2179 if (IsAddOrAddLike(
Op))
2180 return IsAddOrAddLike(
Op.getOperand(0)) ||
2181 IsAddOrAddLike(
Op.getOperand(1));
2186 return C->getZExtValue() >= 1 &&
C->getZExtValue() <= 3 &&
2187 IsAddOrAddLike(
Op.getOperand(0));
2197 auto MatchOperand = [&](SDValue
Op) {
2207 if (SplitsMaterializedValue(
Op) && !AM.isRIPRelative())
2208 return matchAddressBase(
Op, AM);
2209 return matchAddressRecursively(
Op, AM,
Depth + 1);
2212 X86ISelAddressMode Backup = AM;
2213 if (!MatchOperand(
N.getOperand(0)) &&
2214 !MatchOperand(Handle.getValue().getOperand(1)))
2219 if (!MatchOperand(Handle.getValue().getOperand(1)) &&
2220 !MatchOperand(Handle.getValue().getOperand(0)))
2227 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2230 N = Handle.getValue();
2236 N = Handle.getValue();
2246 if (
N->getNodeId() == -1 ||
2266 X86ISelAddressMode &AM) {
2273 if (ScaleLog <= 0 || ScaleLog >= 4 ||
2274 Mask != (0xffu << ScaleLog))
2277 MVT XVT =
X.getSimpleValueType();
2278 MVT VT =
N.getSimpleValueType();
2303 AM.Scale = (1 << ScaleLog);
2311 X86ISelAddressMode &AM) {
2322 bool FoundAnyExtend =
false;
2326 FoundAnyExtend =
true;
2344 if (ShiftAmt != 1 && ShiftAmt != 2 && ShiftAmt != 3)
2347 MVT VT =
N.getSimpleValueType();
2349 if (FoundAnyExtend) {
2370 AM.Scale = 1 << ShiftAmt;
2371 AM.IndexReg = NewAnd;
2405 X86ISelAddressMode &AM) {
2411 unsigned MaskIdx, MaskLen;
2414 unsigned MaskLZ = 64 - (MaskIdx + MaskLen);
2420 unsigned AMShiftAmt = MaskIdx;
2424 if (AMShiftAmt == 0 || AMShiftAmt > 3)
return true;
2428 unsigned ScaleDown = (64 -
X.getSimpleValueType().getSizeInBits()) + ShiftAmt;
2429 if (MaskLZ < ScaleDown)
2431 MaskLZ -= ScaleDown;
2439 bool ReplacingAnyExtend =
false;
2441 unsigned ExtendBits =
X.getSimpleValueType().getSizeInBits() -
2442 X.getOperand(0).getSimpleValueType().getSizeInBits();
2445 X =
X.getOperand(0);
2446 MaskLZ = ExtendBits > MaskLZ ? 0 : MaskLZ - ExtendBits;
2447 ReplacingAnyExtend =
true;
2449 APInt MaskedHighBits =
2456 MVT VT =
N.getSimpleValueType();
2457 if (ReplacingAnyExtend) {
2458 assert(
X.getValueType() != VT);
2465 MVT XVT =
X.getSimpleValueType();
2486 AM.Scale = 1 << AMShiftAmt;
2487 AM.IndexReg = NewExt;
2497 X86ISelAddressMode &AM,
2505 if (!Subtarget.hasTBM() &&
2506 !(Subtarget.hasBMI() && Subtarget.hasFastBEXTR()))
2510 unsigned MaskIdx, MaskLen;
2518 unsigned AMShiftAmt = MaskIdx;
2522 if (AMShiftAmt == 0 || AMShiftAmt > 3)
return true;
2524 MVT XVT =
X.getSimpleValueType();
2525 MVT VT =
N.getSimpleValueType();
2550 AM.Scale = 1 << AMShiftAmt;
2551 AM.IndexReg = NewExt;
2557SDValue X86DAGToDAGISel::matchIndexRecursively(SDValue
N,
2558 X86ISelAddressMode &AM,
2560 assert(AM.IndexReg.
getNode() ==
nullptr &&
"IndexReg already matched");
2561 assert((AM.Scale == 1 || AM.Scale == 2 || AM.Scale == 4 || AM.Scale == 8) &&
2562 "Illegal index scale");
2568 EVT VT =
N.getValueType();
2569 unsigned Opc =
N.getOpcode();
2572 if (CurDAG->isBaseWithConstantOffset(
N)) {
2575 if (!foldOffsetIntoAddress(
Offset, AM))
2576 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2580 if (
Opc ==
ISD::ADD &&
N.getOperand(0) ==
N.getOperand(1)) {
2581 if (AM.Scale <= 4) {
2583 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2588 if (
Opc == X86ISD::VSHLI) {
2589 uint64_t ShiftAmt =
N.getConstantOperandVal(1);
2590 uint64_t ScaleAmt = 1ULL << ShiftAmt;
2591 if ((AM.Scale * ScaleAmt) <= 8) {
2592 AM.Scale *= ScaleAmt;
2593 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2600 SDValue Src =
N.getOperand(0);
2601 if (Src.getOpcode() ==
ISD::ADD && Src->getFlags().hasNoSignedWrap() &&
2603 if (CurDAG->isBaseWithConstantOffset(Src)) {
2604 SDValue AddSrc = Src.getOperand(0);
2606 int64_t
Offset = AddVal->getSExtValue();
2609 SDValue ExtSrc = CurDAG->getNode(
Opc,
DL, VT, AddSrc);
2610 SDValue ExtVal = CurDAG->getSignedConstant(
Offset,
DL, VT);
2611 SDValue ExtAdd = CurDAG->getNode(
ISD::ADD,
DL, VT, ExtSrc, ExtVal);
2615 CurDAG->ReplaceAllUsesWith(
N, ExtAdd);
2616 CurDAG->RemoveDeadNode(
N.getNode());
2627 SDValue Src =
N.getOperand(0);
2628 unsigned SrcOpc = Src.getOpcode();
2629 if (((SrcOpc ==
ISD::ADD && Src->getFlags().hasNoUnsignedWrap()) ||
2630 CurDAG->isADDLike(Src,
true)) &&
2632 if (CurDAG->isBaseWithConstantOffset(Src)) {
2633 SDValue AddSrc = Src.getOperand(0);
2635 if (!foldOffsetIntoAddress(
Offset * AM.Scale, AM)) {
2646 if ((AM.Scale * ScaleAmt) <= 8 &&
2648 CurDAG->MaskedValueIsZero(ShVal, HiBits))) {
2649 AM.Scale *= ScaleAmt;
2650 SDValue ExtShVal = CurDAG->getNode(
Opc,
DL, VT, ShVal);
2651 SDValue ExtShift = CurDAG->getNode(
ISD::SHL,
DL, VT, ExtShVal,
2659 SDValue ExtSrc = CurDAG->getNode(
Opc,
DL, VT, AddSrc);
2660 SDValue ExtVal = CurDAG->getConstant(
Offset,
DL, VT);
2661 SDValue ExtAdd = CurDAG->getNode(SrcOpc,
DL, VT, ExtSrc, ExtVal);
2665 CurDAG->ReplaceAllUsesWith(
N, ExtAdd);
2666 CurDAG->RemoveDeadNode(
N.getNode());
2667 return Res ? Res : ExtSrc;
2677bool X86DAGToDAGISel::matchAddressRecursively(SDValue
N, X86ISelAddressMode &AM,
2680 dbgs() <<
"MatchAddress: ";
2685 return matchAddressBase(
N, AM);
2690 if (AM.isRIPRelative()) {
2694 if (!(AM.ES || AM.MCSym) && AM.JT != -1)
2698 if (!foldOffsetIntoAddress(Cst->getSExtValue(), AM))
2703 switch (
N.getOpcode()) {
2706 if (!AM.hasSymbolicDisplacement() && AM.Disp == 0)
2709 AM.MCSym = ESNode->getMCSymbol();
2716 if (!foldOffsetIntoAddress(Val, AM))
2721 case X86ISD::Wrapper:
2722 case X86ISD::WrapperRIP:
2723 if (!matchWrapper(
N, AM))
2733 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2734 AM.Base_Reg.
getNode() ==
nullptr &&
2736 AM.BaseType = X86ISelAddressMode::FrameIndexBase;
2743 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
2747 unsigned Val = CN->getZExtValue();
2752 if (Val == 1 || Val == 2 || Val == 3) {
2754 AM.Scale = 1 << Val;
2755 AM.IndexReg = matchIndexRecursively(ShVal, AM,
Depth + 1);
2763 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
break;
2767 assert(
N.getSimpleValueType().getSizeInBits() <= 64 &&
2768 "Unexpected value size!");
2770 SDValue
And =
N.getOperand(0);
2772 SDValue
X =
And.getOperand(0);
2780 uint64_t Mask =
And.getConstantOperandVal(1) >>
N.getConstantOperandVal(1);
2792 if (
N.getResNo() != 0)
break;
2795 case X86ISD::MUL_IMM:
2797 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2798 AM.Base_Reg.
getNode() ==
nullptr &&
2799 AM.IndexReg.
getNode() ==
nullptr) {
2801 if (CN->getZExtValue() == 3 || CN->getZExtValue() == 5 ||
2802 CN->getZExtValue() == 9) {
2803 AM.Scale = unsigned(CN->getZExtValue())-1;
2805 SDValue MulVal =
N.getOperand(0);
2815 uint64_t Disp = AddVal->getSExtValue() * CN->getZExtValue();
2816 if (foldOffsetIntoAddress(Disp, AM))
2817 Reg =
N.getOperand(0);
2819 Reg =
N.getOperand(0);
2822 AM.IndexReg = AM.Base_Reg =
Reg;
2840 HandleSDNode Handle(
N);
2843 X86ISelAddressMode Backup = AM;
2844 if (matchAddressRecursively(
N.getOperand(0), AM,
Depth+1)) {
2845 N = Handle.getValue();
2849 N = Handle.getValue();
2851 if (AM.IndexReg.
getNode() || AM.isRIPRelative()) {
2857 SDValue
RHS =
N.getOperand(1);
2870 std::optional<unsigned> NegScale;
2873 uint64_t ShVal = ShAmt->getZExtValue();
2874 if (ShVal >= 1 && ShVal <= 3) {
2875 NegScale = 1u << ShVal;
2893 RHS.getOperand(0).getValueType() == MVT::i32))
2896 bool BaseIsNegatedValue = NegScale &&
2897 AM.BaseType == X86ISelAddressMode::RegBase &&
2904 if (((AM.BaseType == X86ISelAddressMode::RegBase && AM.Base_Reg.
getNode() &&
2906 AM.BaseType == X86ISelAddressMode::FrameIndexBase) &&
2907 !BaseIsNegatedValue)
2911 if ((AM.hasSymbolicDisplacement() && !Backup.hasSymbolicDisplacement()) +
2912 ((AM.Disp != 0) && (Backup.Disp == 0)) +
2925 AM.NegateIndex =
true;
2926 AM.Scale = NegScale.value_or(1);
2933 if (!CurDAG->isADDLike(
N))
2937 if (!matchAdd(
N, AM,
Depth))
2946 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
break;
2950 assert(
N.getSimpleValueType().getSizeInBits() <= 64 &&
2951 "Unexpected value size!");
2956 if (
N.getOperand(0).getOpcode() ==
ISD::SRL) {
2957 SDValue Shift =
N.getOperand(0);
2985 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
2988 SDValue Src =
N.getOperand(0);
2993 if (SDValue Index = matchIndexRecursively(
N, AM,
Depth + 1))
2995 AM.IndexReg =
Index;
3001 if (Src.getOpcode() ==
ISD::AND && Src.hasOneUse())
3003 Mask = MaskC->getAPIntValue();
3004 Src = Src.getOperand(0);
3007 if (Src.getOpcode() ==
ISD::SHL && Src.hasOneUse() &&
N->hasOneUse()) {
3009 SDValue ShlSrc = Src.getOperand(0);
3010 SDValue ShlAmt = Src.getOperand(1);
3014 unsigned ShAmtV = ShAmtC->getZExtValue();
3022 if (!Src->getFlags().hasNoUnsignedWrap() &&
3023 !CurDAG->MaskedValueIsZero(ShlSrc, HighZeros & Mask))
3031 MVT VT =
N.getSimpleValueType();
3034 SDValue Res = ShlSrc;
3035 if (!
Mask.isAllOnes()) {
3036 Res = CurDAG->getConstant(
Mask.lshr(ShAmtV),
DL, SrcVT);
3038 Res = CurDAG->getNode(
ISD::AND,
DL, SrcVT, ShlSrc, Res);
3043 SDValue NewShl = CurDAG->getNode(
ISD::SHL,
DL, VT, Zext, ShlAmt);
3045 CurDAG->ReplaceAllUsesWith(
N, NewShl);
3046 CurDAG->RemoveDeadNode(
N.getNode());
3049 AM.Scale = 1 << ShAmtV;
3053 AM.IndexReg = matchIndexRecursively(Zext, AM,
Depth + 1);
3057 if (Src.getOpcode() ==
ISD::SRL && !
Mask.isAllOnes()) {
3060 Src.getOperand(0), AM))
3065 Src.getOperand(0), AM))
3070 Src.getOperand(0), AM, *Subtarget))
3078 return matchAddressBase(
N, AM);
3083bool X86DAGToDAGISel::matchAddressBase(SDValue
N, X86ISelAddressMode &AM) {
3085 if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base_Reg.
getNode()) {
3098 AM.BaseType = X86ISelAddressMode::RegBase;
3103bool X86DAGToDAGISel::matchVectorAddressRecursively(SDValue
N,
3104 X86ISelAddressMode &AM,
3107 dbgs() <<
"MatchVectorAddress: ";
3112 return matchAddressBase(
N, AM);
3115 switch (
N.getOpcode()) {
3118 if (!foldOffsetIntoAddress(Val, AM))
3122 case X86ISD::Wrapper:
3123 if (!matchWrapper(
N, AM))
3129 HandleSDNode Handle(
N);
3131 X86ISelAddressMode Backup = AM;
3132 if (!matchVectorAddressRecursively(
N.getOperand(0), AM,
Depth + 1) &&
3133 !matchVectorAddressRecursively(Handle.getValue().getOperand(1), AM,
3139 if (!matchVectorAddressRecursively(Handle.getValue().getOperand(1), AM,
3141 !matchVectorAddressRecursively(Handle.getValue().getOperand(0), AM,
3146 N = Handle.getValue();
3151 return matchAddressBase(
N, AM);
3157bool X86DAGToDAGISel::matchVectorAddress(SDValue
N, X86ISelAddressMode &AM) {
3158 return matchVectorAddressRecursively(
N, AM, 0);
3161bool X86DAGToDAGISel::selectVectorAddr(MemSDNode *Parent, SDValue BasePtr,
3162 SDValue IndexOp, SDValue ScaleOp,
3163 SDValue &
Base, SDValue &Scale,
3164 SDValue &Index, SDValue &Disp,
3166 X86ISelAddressMode AM;
3172 AM.IndexReg = matchIndexRecursively(IndexOp, AM, 0);
3174 AM.IndexReg = IndexOp;
3178 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
3180 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
3182 AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16);
3185 MVT VT =
BasePtr.getSimpleValueType();
3188 if (matchVectorAddress(BasePtr, AM))
3191 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3202bool X86DAGToDAGISel::selectAddr(SDNode *Parent, SDValue
N, SDValue &
Base,
3203 SDValue &Scale, SDValue &Index, SDValue &Disp,
3204 SDValue &Segment,
bool HasNDDM) {
3205 X86ISelAddressMode AM;
3212 Parent->
getOpcode() != X86ISD::TLSCALL &&
3213 Parent->
getOpcode() != X86ISD::ENQCMD &&
3214 Parent->
getOpcode() != X86ISD::ENQCMDS &&
3215 Parent->
getOpcode() != X86ISD::EH_SJLJ_SETJMP &&
3216 Parent->
getOpcode() != X86ISD::EH_SJLJ_LONGJMP) {
3217 unsigned AddrSpace =
3220 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
3222 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
3224 AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16);
3229 MVT VT =
N.getSimpleValueType();
3231 if (matchAddress(
N, AM))
3234 if (!HasNDDM && !AM.isRIPRelative())
3237 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3241bool X86DAGToDAGISel::selectNDDAddr(SDNode *Parent, SDValue
N, SDValue &
Base,
3242 SDValue &Scale, SDValue &Index,
3243 SDValue &Disp, SDValue &Segment) {
3244 return selectAddr(Parent,
N,
Base, Scale, Index, Disp, Segment,
3245 Subtarget->hasNDDM());
3248bool X86DAGToDAGISel::selectMOV64Imm32(SDValue
N, SDValue &
Imm) {
3257 if (
N->getOpcode() != X86ISD::Wrapper)
3260 N =
N.getOperand(0);
3277 return CR->getUnsignedMax().ult(1ull << 32);
3279 return !TM.isLargeGlobalValue(GV);
3282bool X86DAGToDAGISel::selectLEA64_Addr(SDValue
N, SDValue &
Base, SDValue &Scale,
3283 SDValue &Index, SDValue &Disp,
3288 if (!selectLEAAddr(
N,
Base, Scale, Index, Disp, Segment))
3294 SubReg = X86::sub_8bit;
3296 SubReg = X86::sub_16bit;
3298 SubReg = X86::sub_32bit;
3301 if (RN &&
RN->getReg() == 0)
3302 Base = CurDAG->getRegister(0, MVT::i64);
3307 SDValue ImplDef = SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF,
DL,
3309 Base = CurDAG->getTargetInsertSubreg(SubReg,
DL, MVT::i64, ImplDef,
Base);
3312 [[maybe_unused]] EVT IndexType =
Index.getValueType();
3314 if (RN &&
RN->getReg() == 0)
3315 Index = CurDAG->getRegister(0, MVT::i64);
3318 "Expect to be extending 8/16/32-bit registers for use in LEA");
3319 SDValue ImplDef = SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF,
DL,
3321 Index = CurDAG->getTargetInsertSubreg(SubReg,
DL, MVT::i64, ImplDef, Index);
3329bool X86DAGToDAGISel::selectLEAAddr(SDValue
N,
3330 SDValue &
Base, SDValue &Scale,
3331 SDValue &Index, SDValue &Disp,
3333 X86ISelAddressMode AM;
3338 MVT VT =
N.getSimpleValueType();
3342 SDValue
Copy = AM.Segment;
3343 SDValue
T = CurDAG->getRegister(0, MVT::i32);
3345 if (matchAddress(
N, AM))
3350 unsigned Complexity = 0;
3351 if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base_Reg.
getNode())
3353 else if (AM.BaseType == X86ISelAddressMode::FrameIndexBase)
3369 if (AM.hasSymbolicDisplacement()) {
3371 if (Subtarget->is64Bit())
3381 auto isMathWithFlags = [](SDValue
V) {
3382 switch (
V.getOpcode()) {
3396 return !SDValue(
V.getNode(), 1).use_empty();
3403 if (isMathWithFlags(
N.getOperand(0)) || isMathWithFlags(
N.getOperand(1)))
3411 if (Complexity <= 2)
3414 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3419bool X86DAGToDAGISel::selectTLSADDRAddr(SDValue
N, SDValue &
Base,
3420 SDValue &Scale, SDValue &Index,
3421 SDValue &Disp, SDValue &Segment) {
3425 X86ISelAddressMode AM;
3427 AM.GV = GA->getGlobal();
3428 AM.Disp += GA->getOffset();
3429 AM.SymbolFlags = GA->getTargetFlags();
3432 AM.ES = SA->getSymbol();
3433 AM.SymbolFlags = SA->getTargetFlags();
3436 if (Subtarget->is32Bit()) {
3438 AM.IndexReg = CurDAG->getRegister(X86::EBX, MVT::i32);
3441 MVT VT =
N.getSimpleValueType();
3442 getAddressOperands(AM, SDLoc(
N), VT,
Base, Scale, Index, Disp, Segment);
3446bool X86DAGToDAGISel::selectRelocImm(SDValue
N, SDValue &
Op) {
3450 EVT VT =
N.getValueType();
3451 bool WasTruncated =
false;
3453 WasTruncated =
true;
3454 N =
N.getOperand(0);
3457 if (
N.getOpcode() != X86ISD::Wrapper)
3463 unsigned Opc =
N.getOperand(0)->getOpcode();
3465 Op =
N.getOperand(0);
3468 return !WasTruncated;
3473 std::optional<ConstantRange> CR = GA->getGlobal()->getAbsoluteSymbolRange();
3474 if (!CR || CR->getUnsignedMax().uge(1ull << VT.
getSizeInBits()))
3478 Op = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(
N), VT,
3479 GA->getOffset(), GA->getTargetFlags());
3483bool X86DAGToDAGISel::tryFoldLoad(SDNode *Root, SDNode *
P, SDValue
N,
3484 SDValue &
Base, SDValue &Scale,
3485 SDValue &Index, SDValue &Disp,
3487 assert(Root &&
P &&
"Unknown root/parent nodes");
3489 !IsProfitableToFold(
N,
P, Root) ||
3490 !IsLegalToFold(
N,
P, Root, OptLevel))
3493 return selectAddr(
N.getNode(),
3494 N.getOperand(1),
Base, Scale, Index, Disp, Segment);
3497bool X86DAGToDAGISel::tryFoldBroadcast(SDNode *Root, SDNode *
P, SDValue
N,
3498 SDValue &
Base, SDValue &Scale,
3499 SDValue &Index, SDValue &Disp,
3501 assert(Root &&
P &&
"Unknown root/parent nodes");
3502 if (
N->getOpcode() != X86ISD::VBROADCAST_LOAD ||
3503 !IsProfitableToFold(
N,
P, Root) ||
3504 !IsLegalToFold(
N,
P, Root, OptLevel))
3507 return selectAddr(
N.getNode(),
3508 N.getOperand(1),
Base, Scale, Index, Disp, Segment);
3514SDNode *X86DAGToDAGISel::getGlobalBaseReg() {
3517 return CurDAG->getRegister(GlobalBaseReg, TLI->
getPointerTy(
DL)).getNode();
3520bool X86DAGToDAGISel::isSExtAbsoluteSymbolRef(
unsigned Width, SDNode *
N)
const {
3522 N =
N->getOperand(0).getNode();
3523 if (
N->getOpcode() != X86ISD::Wrapper)
3530 auto *GV = GA->getGlobal();
3533 return CR->getSignedMin().sge(-1ull << Width) &&
3534 CR->getSignedMax().slt(1ull << Width);
3540 !TM.isLargeGlobalValue(GV);
3544 assert(
N->isMachineOpcode() &&
"Unexpected node");
3545 unsigned Opc =
N->getMachineOpcode();
3546 const MCInstrDesc &MCID = getInstrInfo()->get(
Opc);
3551 return static_cast<X86::CondCode>(
N->getConstantOperandVal(CondNo));
3556bool X86DAGToDAGISel::onlyUsesZeroFlag(SDValue Flags)
const {
3558 for (SDUse &Use :
Flags->uses()) {
3560 if (
Use.getResNo() !=
Flags.getResNo())
3568 for (SDUse &FlagUse :
User->uses()) {
3570 if (FlagUse.getResNo() != 1)
3573 if (!FlagUse.getUser()->isMachineOpcode())
3593bool X86DAGToDAGISel::hasNoSignFlagUses(SDValue Flags)
const {
3595 for (SDUse &Use :
Flags->uses()) {
3597 if (
Use.getResNo() !=
Flags.getResNo())
3605 for (SDUse &FlagUse :
User->uses()) {
3607 if (FlagUse.getResNo() != 1)
3610 if (!FlagUse.getUser()->isMachineOpcode())
3650 bool X86DAGToDAGISel::hasNoCarryFlagUses(SDValue Flags)
const {
3652 for (SDUse &Use :
Flags->uses()) {
3654 if (
Use.getResNo() !=
Flags.getResNo())
3658 unsigned UserOpc =
User->getOpcode();
3665 for (SDUse &FlagUse :
User->uses()) {
3667 if (FlagUse.getResNo() != 1)
3670 if (!FlagUse.getUser()->isMachineOpcode())
3690 case X86ISD::SETCC: CCOpNo = 0;
break;
3691 case X86ISD::SETCC_CARRY: CCOpNo = 0;
break;
3692 case X86ISD::CMOV: CCOpNo = 2;
break;
3693 case X86ISD::BRCOND: CCOpNo = 2;
break;
3706 unsigned Depth = 0) {
3727bool X86DAGToDAGISel::checkTCRetEnoughRegs(SDNode *
N)
const {
3728 assert(
N->getOpcode() == X86ISD::TC_RETURN);
3739 const X86RegisterInfo *RI = Subtarget->getRegisterInfo();
3743 if (Subtarget->is64Bit()) {
3746 ? &X86::GR64_TCW64RegClass
3747 : &X86::GR64_TCRegClass;
3755 ? &X86::GR32RegClass
3756 : &X86::GR32_TCRegClass;
3763 unsigned LoadGPRs = 2;
3765 if (Subtarget->is32Bit()) {
3770 }
else if (
BasePtr.getOpcode() == X86ISD::Wrapper &&
3772 if (getTargetMachine().isPositionIndependent())
3780 for (
unsigned I = 3,
E =
N->getNumOperands();
I !=
E; ++
I) {
3782 if (!RI->isGeneralPurposeRegister(*MF,
RN->getReg()))
3784 if (++
ArgGPRs + LoadGPRs > AvailGPRs)
3800 if (StoredVal.
getResNo() != 0)
return false;
3817 if (!
Load.hasOneUse())
3825 bool FoundLoad =
false;
3829 const unsigned int Max = 1024;
3871 if (Chain ==
Load.getValue(1)) {
3877 if (
Op ==
Load.getValue(1)) {
3893 if (
Op.getNode() != LoadNode)
3925bool X86DAGToDAGISel::foldLoadStoreIntoMemOperand(SDNode *Node) {
3927 SDValue StoredVal = StoreNode->getOperand(1);
3933 EVT MemVT = StoreNode->getMemoryVT();
3934 if (MemVT != MVT::i64 && MemVT != MVT::i32 && MemVT != MVT::i16 &&
3938 bool IsCommutable =
false;
3939 bool IsNegate =
false;
3953 IsCommutable =
true;
3957 unsigned LoadOpNo = IsNegate ? 1 : 0;
3958 LoadSDNode *LoadNode =
nullptr;
3961 LoadNode, InputChain)) {
3968 LoadNode, InputChain))
3972 SDValue
Base, Scale,
Index, Disp, Segment;
3973 if (!selectAddr(LoadNode, LoadNode->
getBasePtr(),
Base, Scale, Index, Disp,
3977 auto SelectOpcode = [&](
unsigned Opc64,
unsigned Opc32,
unsigned Opc16,
3998 unsigned NewOpc = SelectOpcode(X86::NEG64m, X86::NEG32m, X86::NEG16m,
4000 const SDValue
Ops[] = {
Base, Scale,
Index, Disp, Segment, InputChain};
4001 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32,
4008 if (!Subtarget->slowIncDec() || CurDAG->shouldOptForSize()) {
4012 if ((IsOne || IsNegOne) && hasNoCarryFlagUses(StoredVal.
getValue(1))) {
4014 ((
Opc == X86ISD::ADD) == IsOne)
4015 ? SelectOpcode(X86::INC64m, X86::INC32m, X86::INC16m, X86::INC8m)
4016 : SelectOpcode(X86::DEC64m, X86::DEC32m, X86::DEC16m, X86::DEC8m);
4017 const SDValue
Ops[] = {
Base, Scale,
Index, Disp, Segment, InputChain};
4018 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32,
4029 auto SelectRegOpcode = [SelectOpcode](
unsigned Opc) {
4032 return SelectOpcode(X86::ADD64mr, X86::ADD32mr, X86::ADD16mr,
4035 return SelectOpcode(X86::ADC64mr, X86::ADC32mr, X86::ADC16mr,
4038 return SelectOpcode(X86::SUB64mr, X86::SUB32mr, X86::SUB16mr,
4041 return SelectOpcode(X86::SBB64mr, X86::SBB32mr, X86::SBB16mr,
4044 return SelectOpcode(X86::AND64mr, X86::AND32mr, X86::AND16mr,
4047 return SelectOpcode(X86::OR64mr, X86::OR32mr, X86::OR16mr, X86::OR8mr);
4049 return SelectOpcode(X86::XOR64mr, X86::XOR32mr, X86::XOR16mr,
4055 auto SelectImmOpcode = [SelectOpcode](
unsigned Opc) {
4058 return SelectOpcode(X86::ADD64mi32, X86::ADD32mi, X86::ADD16mi,
4061 return SelectOpcode(X86::ADC64mi32, X86::ADC32mi, X86::ADC16mi,
4064 return SelectOpcode(X86::SUB64mi32, X86::SUB32mi, X86::SUB16mi,
4067 return SelectOpcode(X86::SBB64mi32, X86::SBB32mi, X86::SBB16mi,
4070 return SelectOpcode(X86::AND64mi32, X86::AND32mi, X86::AND16mi,
4073 return SelectOpcode(X86::OR64mi32, X86::OR32mi, X86::OR16mi,
4076 return SelectOpcode(X86::XOR64mi32, X86::XOR32mi, X86::XOR16mi,
4083 unsigned NewOpc = SelectRegOpcode(
Opc);
4084 SDValue Operand = StoredVal->
getOperand(1-LoadOpNo);
4089 int64_t OperandV = OperandC->getSExtValue();
4094 if ((
Opc == X86ISD::ADD ||
Opc == X86ISD::SUB) &&
4096 (MemVT == MVT::i64 && !
isInt<32>(OperandV) &&
4098 hasNoCarryFlagUses(StoredVal.
getValue(1))) {
4099 OperandV = -OperandV;
4100 Opc =
Opc == X86ISD::ADD ? X86ISD::SUB : X86ISD::ADD;
4103 if (MemVT != MVT::i64 ||
isInt<32>(OperandV)) {
4104 Operand = CurDAG->getSignedTargetConstant(OperandV, SDLoc(Node), MemVT);
4105 NewOpc = SelectImmOpcode(
Opc);
4109 if (
Opc == X86ISD::ADC ||
Opc == X86ISD::SBB) {
4111 CurDAG->getCopyToReg(InputChain, SDLoc(Node), X86::EFLAGS,
4115 Segment, Operand, CopyTo, CopyTo.
getValue(1)};
4116 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other,
4120 Segment, Operand, InputChain};
4121 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other,
4130 MachineMemOperand *MemOps[] = {StoreNode->getMemOperand(),
4132 CurDAG->setNodeMemRefs(Result, MemOps);
4135 ReplaceUses(SDValue(LoadNode, 1), SDValue(Result, 1));
4136 ReplaceUses(SDValue(StoreNode, 0), SDValue(Result, 1));
4137 ReplaceUses(SDValue(StoredVal.
getNode(), 1), SDValue(Result, 0));
4138 CurDAG->RemoveDeadNode(Node);
4150bool X86DAGToDAGISel::matchBitExtract(SDNode *Node) {
4153 "Should be either an and-mask, a standalone low-bits mask, or "
4154 "right-shift after clearing high bits.");
4157 if (!Subtarget->hasBMI() && !Subtarget->hasBMI2())
4160 MVT NVT =
Node->getSimpleValueType(0);
4163 if (NVT != MVT::i32 && NVT != MVT::i64)
4171 const bool AllowExtraUsesByDefault = Subtarget->hasBMI2();
4172 auto checkUses = [AllowExtraUsesByDefault](
4173 SDValue
Op,
unsigned NUses,
4174 std::optional<bool> AllowExtraUses) {
4175 return AllowExtraUses.value_or(AllowExtraUsesByDefault) ||
4176 Op.getNode()->hasNUsesOfValue(NUses,
Op.getResNo());
4178 auto checkOneUse = [checkUses](SDValue
Op,
4179 std::optional<bool> AllowExtraUses =
4181 return checkUses(
Op, 1, AllowExtraUses);
4183 auto checkTwoUse = [checkUses](SDValue
Op,
4184 std::optional<bool> AllowExtraUses =
4186 return checkUses(
Op, 2, AllowExtraUses);
4189 auto peekThroughOneUseTruncation = [checkOneUse](SDValue
V) {
4191 assert(
V.getSimpleValueType() == MVT::i32 &&
4192 V.getOperand(0).getSimpleValueType() == MVT::i64 &&
4193 "Expected i64 -> i32 truncation");
4194 V =
V.getOperand(0);
4200 auto matchPatternA = [checkOneUse, peekThroughOneUseTruncation, &NBits,
4201 &NegateNBits](SDValue
Mask) ->
bool {
4203 if (
Mask->getOpcode() !=
ISD::ADD || !checkOneUse(Mask))
4209 SDValue
M0 = peekThroughOneUseTruncation(
Mask->getOperand(0));
4214 NBits =
M0->getOperand(1);
4215 NegateNBits =
false;
4219 auto isAllOnes = [
this, peekThroughOneUseTruncation, NVT](SDValue
V) {
4220 V = peekThroughOneUseTruncation(V);
4221 return CurDAG->MaskedValueIsAllOnes(
4227 auto matchPatternB = [checkOneUse, isAllOnes, peekThroughOneUseTruncation,
4228 &NBits, &NegateNBits](SDValue
Mask) ->
bool {
4230 if (
Mask.getOpcode() !=
ISD::XOR || !checkOneUse(Mask))
4233 if (!isAllOnes(
Mask->getOperand(1)))
4236 SDValue
M0 = peekThroughOneUseTruncation(
Mask->getOperand(0));
4240 if (!isAllOnes(
M0->getOperand(0)))
4242 NBits =
M0->getOperand(1);
4243 NegateNBits =
false;
4249 auto canonicalizeShiftAmt = [&NBits, &NegateNBits](SDValue ShiftAmt,
4250 unsigned Bitwidth) {
4255 NBits = NBits.getOperand(0);
4261 if (!V0 ||
V0->getZExtValue() != Bitwidth)
4263 NBits = NBits.getOperand(1);
4264 NegateNBits =
false;
4270 auto matchPatternC = [checkOneUse, peekThroughOneUseTruncation, &NegateNBits,
4271 canonicalizeShiftAmt](SDValue
Mask) ->
bool {
4273 Mask = peekThroughOneUseTruncation(Mask);
4274 unsigned Bitwidth =
Mask.getSimpleValueType().getSizeInBits();
4276 if (
Mask.getOpcode() !=
ISD::SRL || !checkOneUse(Mask))
4281 SDValue
M1 =
Mask.getOperand(1);
4283 if (!checkOneUse(
M1))
4285 canonicalizeShiftAmt(
M1, Bitwidth);
4290 return !NegateNBits;
4298 auto matchPatternD = [checkOneUse, checkTwoUse, canonicalizeShiftAmt,
4299 AllowExtraUsesByDefault, &NegateNBits,
4300 &
X](SDNode *
Node) ->
bool {
4303 SDValue N0 =
Node->getOperand(0);
4307 SDValue N1 =
Node->getOperand(1);
4312 canonicalizeShiftAmt(N1, Bitwidth);
4316 const bool AllowExtraUses = AllowExtraUsesByDefault && !NegateNBits;
4317 if (!checkOneUse(N0, AllowExtraUses) || !checkTwoUse(N1, AllowExtraUses))
4323 auto matchLowBitMask = [matchPatternA, matchPatternB,
4324 matchPatternC](SDValue
Mask) ->
bool {
4325 return matchPatternA(Mask) || matchPatternB(Mask) || matchPatternC(Mask);
4329 X =
Node->getOperand(0);
4330 SDValue
Mask =
Node->getOperand(1);
4332 if (matchLowBitMask(Mask)) {
4336 if (!matchLowBitMask(Mask))
4339 }
else if (matchLowBitMask(SDValue(Node, 0))) {
4340 X = CurDAG->getAllOnesConstant(SDLoc(Node), NVT);
4341 }
else if (!matchPatternD(Node))
4346 if (NegateNBits && !Subtarget->hasBMI2())
4351 if (NBits.getSimpleValueType() != MVT::i8) {
4358 ConstantSDNode *
Imm =
nullptr;
4359 if (NBits->getOpcode() ==
ISD::AND)
4361 NBits = NBits->getOperand(0);
4365 SDValue ImplDef = SDValue(
4366 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, MVT::i32), 0);
4369 SDValue SRIdxVal = CurDAG->getTargetConstant(X86::sub_8bit,
DL, MVT::i32);
4371 NBits = SDValue(CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG,
DL,
4372 MVT::i32, ImplDef, NBits, SRIdxVal),
4378 CurDAG->getNode(
ISD::AND,
DL, MVT::i32, NBits,
4379 CurDAG->getConstant(
Imm->getZExtValue(),
DL, MVT::i32));
4386 SDValue BitWidthC = CurDAG->getConstant(NVT.
getSizeInBits(),
DL, MVT::i32);
4389 NBits = CurDAG->getNode(
ISD::SUB,
DL, MVT::i32, BitWidthC, NBits);
4393 if (Subtarget->hasBMI2()) {
4395 if (NVT != MVT::i32) {
4401 SDValue Extract = CurDAG->getNode(X86ISD::BZHI,
DL, NVT,
X, NBits);
4402 ReplaceNode(Node, Extract.
getNode());
4403 SelectCode(Extract.
getNode());
4412 SDValue RealX = peekThroughOneUseTruncation(
X);
4418 MVT XVT =
X.getSimpleValueType();
4428 SDValue C8 = CurDAG->getConstant(8,
DL, MVT::i8);
4430 SDValue Control = CurDAG->getNode(
ISD::SHL,
DL, MVT::i32, NBits, C8);
4436 SDValue ShiftAmt =
X.getOperand(1);
4437 X =
X.getOperand(0);
4440 "Expected shift amount to be i8");
4444 SDValue OrigShiftAmt = ShiftAmt;
4449 Control = CurDAG->getNode(
ISD::OR,
DL, MVT::i32, Control, ShiftAmt);
4454 if (XVT != MVT::i32) {
4460 SDValue Extract = CurDAG->getNode(X86ISD::BEXTR,
DL, XVT,
X, Control);
4468 ReplaceNode(Node, Extract.
getNode());
4469 SelectCode(Extract.
getNode());
4475MachineSDNode *X86DAGToDAGISel::matchBEXTRFromAndImm(SDNode *Node) {
4476 MVT NVT =
Node->getSimpleValueType(0);
4479 SDValue N0 =
Node->getOperand(0);
4480 SDValue N1 =
Node->getOperand(1);
4489 Subtarget->hasTBM() || (Subtarget->hasBMI() && Subtarget->hasFastBEXTR());
4490 if (!PreferBEXTR && !Subtarget->hasBMI2())
4502 if (NVT != MVT::i32 && NVT != MVT::i64)
4508 if (!MaskCst || !ShiftCst)
4516 uint64_t Shift = ShiftCst->getZExtValue();
4521 if (Shift == 8 && MaskSize == 8)
4532 if (!PreferBEXTR && MaskSize <= 32)
4536 unsigned ROpc, MOpc;
4538#define GET_EGPR_IF_ENABLED(OPC) (Subtarget->hasEGPR() ? OPC##_EVEX : OPC)
4540 assert(Subtarget->hasBMI2() &&
"We must have BMI2's BZHI then.");
4544 Control = CurDAG->getTargetConstant(Shift + MaskSize, dl, NVT);
4549 unsigned NewOpc = NVT == MVT::i64 ? X86::MOV32ri64 : X86::MOV32ri;
4550 Control = SDValue(CurDAG->getMachineNode(NewOpc, dl, NVT, Control), 0);
4556 Control = CurDAG->getTargetConstant(Shift | (MaskSize << 8), dl, NVT);
4557 if (Subtarget->hasTBM()) {
4558 ROpc = NVT == MVT::i64 ? X86::BEXTRI64ri : X86::BEXTRI32ri;
4559 MOpc = NVT == MVT::i64 ? X86::BEXTRI64mi : X86::BEXTRI32mi;
4561 assert(Subtarget->hasBMI() &&
"We must have BMI1's BEXTR then.");
4567 unsigned NewOpc = NVT == MVT::i64 ? X86::MOV32ri64 : X86::MOV32ri;
4568 Control = SDValue(CurDAG->getMachineNode(NewOpc, dl, NVT, Control), 0);
4572 MachineSDNode *NewNode;
4574 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4575 if (tryFoldLoad(Node, N0.
getNode(), Input, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4577 Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Control, Input.
getOperand(0)};
4578 SDVTList VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
4579 NewNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4581 ReplaceUses(Input.
getValue(1), SDValue(NewNode, 2));
4583 CurDAG->setNodeMemRefs(NewNode, {
cast<LoadSDNode>(Input)->getMemOperand()});
4585 NewNode = CurDAG->getMachineNode(ROpc, dl, NVT, MVT::i32, Input, Control);
4590 SDValue ShAmt = CurDAG->getTargetConstant(Shift, dl, NVT);
4594 CurDAG->getMachineNode(NewOpc, dl, NVT, SDValue(NewNode, 0), ShAmt);
4601MachineSDNode *X86DAGToDAGISel::emitPCMPISTR(
unsigned ROpc,
unsigned MOpc,
4602 bool MayFoldLoad,
const SDLoc &dl,
4603 MVT VT, SDNode *Node) {
4604 SDValue N0 =
Node->getOperand(0);
4605 SDValue N1 =
Node->getOperand(1);
4606 SDValue
Imm =
Node->getOperand(2);
4608 Imm = CurDAG->getTargetConstant(*Val, SDLoc(Node),
Imm.getValueType());
4611 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4612 if (MayFoldLoad && tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4613 SDValue
Ops[] = { N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
Imm,
4615 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Other);
4616 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4618 ReplaceUses(N1.
getValue(1), SDValue(CNode, 2));
4624 SDValue
Ops[] = { N0, N1,
Imm };
4625 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32);
4626 MachineSDNode *CNode = CurDAG->getMachineNode(ROpc, dl, VTs,
Ops);
4633MachineSDNode *X86DAGToDAGISel::emitPCMPESTR(
unsigned ROpc,
unsigned MOpc,
4634 bool MayFoldLoad,
const SDLoc &dl,
4635 MVT VT, SDNode *Node,
4637 SDValue N0 =
Node->getOperand(0);
4638 SDValue N2 =
Node->getOperand(2);
4639 SDValue
Imm =
Node->getOperand(4);
4641 Imm = CurDAG->getTargetConstant(*Val, SDLoc(Node),
Imm.getValueType());
4644 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4645 if (MayFoldLoad && tryFoldLoad(Node, N2, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4646 SDValue
Ops[] = { N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
Imm,
4648 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Other, MVT::Glue);
4649 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4650 InGlue = SDValue(CNode, 3);
4652 ReplaceUses(N2.
getValue(1), SDValue(CNode, 2));
4658 SDValue
Ops[] = { N0, N2,
Imm, InGlue };
4659 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Glue);
4660 MachineSDNode *CNode = CurDAG->getMachineNode(ROpc, dl, VTs,
Ops);
4661 InGlue = SDValue(CNode, 2);
4665bool X86DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
4666 EVT VT =
N->getValueType(0);
4673 unsigned Size = VT == MVT::i64 ? 64 : 32;
4676 SDValue ShiftAmt = OrigShiftAmt;
4686 SDValue NewShiftAmt;
4695 if (Add1C && Add1C->getAPIntValue().urem(
Size) == 0) {
4699 ((Add0C && Add0C->getAPIntValue().urem(
Size) ==
Size - 1) ||
4700 (Add1C && Add1C->getAPIntValue().urem(
Size) ==
Size - 1))) {
4704 assert(Add0C ==
nullptr || Add1C ==
nullptr);
4712 SDValue
AllOnes = CurDAG->getAllOnesConstant(
DL, OpVT);
4713 NewShiftAmt = CurDAG->getNode(
ISD::XOR,
DL, OpVT,
4714 Add0C ==
nullptr ? Add0 : Add1,
AllOnes);
4720 Add0C->getZExtValue() != 0) {
4723 if (Add0C->getZExtValue() %
Size == 0)
4726 Add0C->getZExtValue() % 32 == 0) {
4734 Add0 = CurDAG->getZExtOrTrunc(Add0,
DL, SubVT);
4738 X = CurDAG->getNode(
ISD::ADD,
DL, SubVT, Add1, Add0);
4745 SDValue
Zero = CurDAG->getConstant(0,
DL, SubVT);
4746 SDValue Neg = CurDAG->getNode(
ISD::SUB,
DL, SubVT, Zero,
X);
4760 NewShiftAmt = CurDAG->getNode(
ISD::TRUNCATE,
DL, MVT::i8, NewShiftAmt);
4767 NewShiftAmt = CurDAG->getNode(
ISD::AND,
DL, MVT::i8, NewShiftAmt,
4768 CurDAG->getConstant(
Size - 1,
DL, MVT::i8));
4772 SDNode *UpdatedNode = CurDAG->UpdateNodeOperands(
N,
N->getOperand(0),
4774 if (UpdatedNode !=
N) {
4777 ReplaceNode(
N, UpdatedNode);
4784 CurDAG->RemoveDeadNode(OrigShiftAmt.
getNode());
4792bool X86DAGToDAGISel::tryShrinkShlLogicImm(SDNode *
N) {
4793 MVT NVT =
N->getSimpleValueType(0);
4794 unsigned Opcode =
N->getOpcode();
4799 SDValue Shift =
N->getOperand(0);
4806 int64_t Val = Cst->getSExtValue();
4811 bool FoundAnyExtend =
false;
4815 FoundAnyExtend =
true;
4823 if (NVT != MVT::i32 && NVT != MVT::i64)
4830 uint64_t ShAmt = ShlCst->getZExtValue();
4834 uint64_t RemovedBitsMask = (1ULL << ShAmt) - 1;
4835 if (Opcode !=
ISD::AND && (Val & RemovedBitsMask) != 0)
4840 auto CanShrinkImmediate = [&](int64_t &ShiftedVal) {
4844 ShiftedVal = (
uint64_t)Val >> ShAmt;
4848 if (ShiftedVal == UINT8_MAX || ShiftedVal == UINT16_MAX)
4851 ShiftedVal = Val >> ShAmt;
4857 ShiftedVal = (
uint64_t)Val >> ShAmt;
4865 if (!CanShrinkImmediate(ShiftedVal))
4875 unsigned ZExtWidth = Cst->getAPIntValue().getActiveBits();
4881 NeededMask &= ~Cst->getAPIntValue();
4883 if (CurDAG->MaskedValueIsZero(
N->getOperand(0), NeededMask))
4888 if (FoundAnyExtend) {
4894 SDValue NewCst = CurDAG->getSignedConstant(ShiftedVal, dl, NVT);
4896 SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT,
X, NewCst);
4898 SDValue NewSHL = CurDAG->getNode(
ISD::SHL, dl, NVT, NewBinOp,
4905bool X86DAGToDAGISel::matchVPTERNLOG(SDNode *Root, SDNode *ParentA,
4906 SDNode *ParentB, SDNode *ParentC,
4907 SDValue
A, SDValue
B, SDValue
C,
4909 assert(
A.isOperandOf(ParentA) &&
B.isOperandOf(ParentB) &&
4910 C.isOperandOf(ParentC) &&
"Incorrect parent node");
4912 auto tryFoldLoadOrBCast =
4913 [
this](SDNode *Root, SDNode *
P, SDValue &
L, SDValue &
Base, SDValue &Scale,
4914 SDValue &
Index, SDValue &Disp, SDValue &Segment) {
4915 if (tryFoldLoad(Root,
P, L,
Base, Scale, Index, Disp, Segment))
4921 L =
L.getOperand(0);
4924 if (
L.getOpcode() != X86ISD::VBROADCAST_LOAD)
4929 unsigned Size = MemIntr->getMemoryVT().getSizeInBits();
4933 return tryFoldBroadcast(Root,
P, L,
Base, Scale, Index, Disp, Segment);
4936 bool FoldedLoad =
false;
4937 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4938 if (tryFoldLoadOrBCast(Root, ParentC,
C, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4940 }
else if (tryFoldLoadOrBCast(Root, ParentA,
A, Tmp0, Tmp1, Tmp2, Tmp3,
4945 uint8_t OldImm =
Imm;
4946 Imm = OldImm & 0xa5;
4947 if (OldImm & 0x02)
Imm |= 0x10;
4948 if (OldImm & 0x10)
Imm |= 0x02;
4949 if (OldImm & 0x08)
Imm |= 0x40;
4950 if (OldImm & 0x40)
Imm |= 0x08;
4951 }
else if (tryFoldLoadOrBCast(Root, ParentB,
B, Tmp0, Tmp1, Tmp2, Tmp3,
4956 uint8_t OldImm =
Imm;
4957 Imm = OldImm & 0x99;
4958 if (OldImm & 0x02)
Imm |= 0x04;
4959 if (OldImm & 0x04)
Imm |= 0x02;
4960 if (OldImm & 0x20)
Imm |= 0x40;
4961 if (OldImm & 0x40)
Imm |= 0x20;
4966 SDValue TImm = CurDAG->getTargetConstant(
Imm,
DL, MVT::i8);
4970 MachineSDNode *MNode;
4972 SDVTList VTs = CurDAG->getVTList(NVT, MVT::Other);
4975 if (
C.getOpcode() == X86ISD::VBROADCAST_LOAD) {
4977 unsigned EltSize = MemIntr->getMemoryVT().getSizeInBits();
4978 assert((EltSize == 32 || EltSize == 64) &&
"Unexpected broadcast size!");
4980 bool UseD = EltSize == 32;
4982 Opc = UseD ? X86::VPTERNLOGDZ128rmbi : X86::VPTERNLOGQZ128rmbi;
4984 Opc = UseD ? X86::VPTERNLOGDZ256rmbi : X86::VPTERNLOGQZ256rmbi;
4986 Opc = UseD ? X86::VPTERNLOGDZrmbi : X86::VPTERNLOGQZrmbi;
4992 Opc = UseD ? X86::VPTERNLOGDZ128rmi : X86::VPTERNLOGQZ128rmi;
4994 Opc = UseD ? X86::VPTERNLOGDZ256rmi : X86::VPTERNLOGQZ256rmi;
4996 Opc = UseD ? X86::VPTERNLOGDZrmi : X86::VPTERNLOGQZrmi;
5001 SDValue
Ops[] = {
A,
B, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, TImm,
C.
getOperand(0)};
5002 MNode = CurDAG->getMachineNode(
Opc,
DL, VTs,
Ops);
5005 ReplaceUses(
C.getValue(1), SDValue(MNode, 1));
5012 Opc = UseD ? X86::VPTERNLOGDZ128rri : X86::VPTERNLOGQZ128rri;
5014 Opc = UseD ? X86::VPTERNLOGDZ256rri : X86::VPTERNLOGQZ256rri;
5016 Opc = UseD ? X86::VPTERNLOGDZrri : X86::VPTERNLOGQZrri;
5020 MNode = CurDAG->getMachineNode(
Opc,
DL, NVT, {
A,
B,
C, TImm});
5023 ReplaceUses(SDValue(Root, 0), SDValue(MNode, 0));
5024 CurDAG->RemoveDeadNode(Root);
5030bool X86DAGToDAGISel::tryVPTERNLOG(SDNode *
N) {
5031 MVT NVT =
N->getSimpleValueType(0);
5034 if (!NVT.
isVector() || !Subtarget->hasAVX512() ||
5042 auto getFoldableLogicOp = [](SDValue
Op) {
5045 Op =
Op.getOperand(0);
5047 if (!
Op.hasOneUse())
5050 unsigned Opc =
Op.getOpcode();
5052 Opc == X86ISD::ANDNP)
5058 SDValue N0, N1,
A, FoldableOp;
5061 auto tryPeelOuterNotWrappingLogic = [&](SDNode *
Op) {
5064 SDValue InnerOp = getFoldableLogicOp(
Op->getOperand(0));
5071 if ((FoldableOp = getFoldableLogicOp(N1))) {
5075 if ((FoldableOp = getFoldableLogicOp(N0))) {
5083 bool PeeledOuterNot =
false;
5085 if (SDValue InnerOp = tryPeelOuterNotWrappingLogic(
N)) {
5086 PeeledOuterNot =
true;
5092 if ((FoldableOp = getFoldableLogicOp(N1)))
5094 else if ((FoldableOp = getFoldableLogicOp(N0)))
5102 SDNode *ParentA =
N;
5103 SDNode *ParentB = FoldableOp.
getNode();
5104 SDNode *ParentC = FoldableOp.
getNode();
5108 uint8_t TernlogMagicA = 0xf0;
5109 uint8_t TernlogMagicB = 0xcc;
5110 uint8_t TernlogMagicC = 0xaa;
5115 auto PeekThroughNot = [](SDValue &
Op, SDNode *&Parent, uint8_t &
Magic) {
5119 Parent =
Op.getNode();
5120 Op =
Op.getOperand(0);
5124 PeekThroughNot(
A, ParentA, TernlogMagicA);
5125 PeekThroughNot(
B, ParentB, TernlogMagicB);
5126 PeekThroughNot(
C, ParentC, TernlogMagicC);
5131 case ISD::AND:
Imm = TernlogMagicB & TernlogMagicC;
break;
5132 case ISD::OR:
Imm = TernlogMagicB | TernlogMagicC;
break;
5133 case ISD::XOR:
Imm = TernlogMagicB ^ TernlogMagicC;
break;
5134 case X86ISD::ANDNP:
Imm = ~(TernlogMagicB) & TernlogMagicC;
break;
5137 switch (
N->getOpcode()) {
5141 Imm &= ~TernlogMagicA;
5143 Imm = ~(
Imm) & TernlogMagicA;
5153 return matchVPTERNLOG(OriN, ParentA, ParentB, ParentC,
A,
B,
C,
Imm);
5163bool X86DAGToDAGISel::shrinkAndImmediate(SDNode *
And) {
5166 MVT VT =
And->getSimpleValueType(0);
5167 if (VT != MVT::i32 && VT != MVT::i64)
5179 APInt MaskVal = And1C->getAPIntValue();
5181 if (!MaskLZ || (VT == MVT::i64 && MaskLZ == 32))
5185 if (VT == MVT::i64 && MaskLZ >= 32) {
5187 MaskVal = MaskVal.
trunc(32);
5190 SDValue And0 =
And->getOperand(0);
5192 APInt NegMaskVal = MaskVal | HighZeros;
5201 if (VT == MVT::i64 && MaskVal.
getBitWidth() < 64) {
5202 NegMaskVal = NegMaskVal.
zext(64);
5203 HighZeros = HighZeros.
zext(64);
5209 KnownBits Known0 = CurDAG->computeKnownBits(And0);
5218 if (VT == MVT::i32 && !isDef32(And0.
getNode()))
5225 SDValue NewMask = CurDAG->getConstant(NegMaskVal, SDLoc(
And), VT);
5227 SDValue NewAnd = CurDAG->getNode(
ISD::AND, SDLoc(
And), VT, And0, NewMask);
5234 bool FoldedBCast,
bool Masked) {
5235#define VPTESTM_CASE(VT, SUFFIX) \
5238 return IsTestN ? X86::VPTESTNM##SUFFIX##k: X86::VPTESTM##SUFFIX##k; \
5239 return IsTestN ? X86::VPTESTNM##SUFFIX : X86::VPTESTM##SUFFIX;
5242#define VPTESTM_BROADCAST_CASES(SUFFIX) \
5243default: llvm_unreachable("Unexpected VT!"); \
5244VPTESTM_CASE(v4i32, DZ128##SUFFIX) \
5245VPTESTM_CASE(v2i64, QZ128##SUFFIX) \
5246VPTESTM_CASE(v8i32, DZ256##SUFFIX) \
5247VPTESTM_CASE(v4i64, QZ256##SUFFIX) \
5248VPTESTM_CASE(v16i32, DZ##SUFFIX) \
5249VPTESTM_CASE(v8i64, QZ##SUFFIX)
5251#define VPTESTM_FULL_CASES(SUFFIX) \
5252VPTESTM_BROADCAST_CASES(SUFFIX) \
5253VPTESTM_CASE(v16i8, BZ128##SUFFIX) \
5254VPTESTM_CASE(v8i16, WZ128##SUFFIX) \
5255VPTESTM_CASE(v32i8, BZ256##SUFFIX) \
5256VPTESTM_CASE(v16i16, WZ256##SUFFIX) \
5257VPTESTM_CASE(v64i8, BZ##SUFFIX) \
5258VPTESTM_CASE(v32i16, WZ##SUFFIX)
5276#undef VPTESTM_FULL_CASES
5277#undef VPTESTM_BROADCAST_CASES
5287 if (
Reg.isVirtual())
5292 if (GetPhysReg(N1) == LoReg && GetPhysReg(N0) != LoReg)
5298bool X86DAGToDAGISel::tryVPTESTM(SDNode *Root, SDValue Setcc,
5300 assert(Subtarget->hasAVX512() &&
"Expected AVX512!");
5320 SDValue N0 = SetccOp0;
5331 SDValue N0Temp = N0;
5345 auto tryFoldLoadOrBCast = [&](SDNode *Root, SDNode *
P, SDValue &
L,
5346 SDValue &
Base, SDValue &Scale, SDValue &
Index,
5347 SDValue &Disp, SDValue &Segment) {
5350 if (tryFoldLoad(Root,
P, L,
Base, Scale, Index, Disp, Segment))
5355 if (CmpSVT != MVT::i32 && CmpSVT != MVT::i64)
5361 L =
L.getOperand(0);
5364 if (
L.getOpcode() != X86ISD::VBROADCAST_LOAD)
5368 if (MemIntr->getMemoryVT().getSizeInBits() != CmpSVT.
getSizeInBits())
5371 return tryFoldBroadcast(Root,
P, L,
Base, Scale, Index, Disp, Segment);
5375 bool CanFoldLoads = Src0 != Src1;
5377 bool FoldedLoad =
false;
5378 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5380 FoldedLoad = tryFoldLoadOrBCast(Root, N0.
getNode(), Src1, Tmp0, Tmp1, Tmp2,
5384 FoldedLoad = tryFoldLoadOrBCast(Root, N0.
getNode(), Src0, Tmp0, Tmp1,
5391 bool FoldedBCast = FoldedLoad && Src1.
getOpcode() == X86ISD::VBROADCAST_LOAD;
5393 bool IsMasked = InMask.
getNode() !=
nullptr;
5402 unsigned SubReg = CmpVT.
is128BitVector() ? X86::sub_xmm : X86::sub_ymm;
5406 SDValue ImplDef = SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF, dl,
5408 Src0 = CurDAG->getTargetInsertSubreg(SubReg, dl, CmpVT, ImplDef, Src0);
5411 Src1 = CurDAG->getTargetInsertSubreg(SubReg, dl, CmpVT, ImplDef, Src1);
5416 SDValue RC = CurDAG->getTargetConstant(RegClass, dl, MVT::i32);
5417 InMask = SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
5418 dl, MaskVT, InMask, RC), 0);
5426 MachineSDNode *CNode;
5428 SDVTList VTs = CurDAG->getVTList(MaskVT, MVT::Other);
5431 SDValue
Ops[] = { InMask, Src0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
5433 CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5435 SDValue
Ops[] = { Src0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
5437 CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5441 ReplaceUses(Src1.
getValue(1), SDValue(CNode, 1));
5443 CurDAG->setNodeMemRefs(CNode, {
cast<MemSDNode>(Src1)->getMemOperand()});
5446 CNode = CurDAG->getMachineNode(
Opc, dl, MaskVT, InMask, Src0, Src1);
5448 CNode = CurDAG->getMachineNode(
Opc, dl, MaskVT, Src0, Src1);
5454 SDValue RC = CurDAG->getTargetConstant(RegClass, dl, MVT::i32);
5455 CNode = CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
5456 dl, ResVT, SDValue(CNode, 0), RC);
5459 ReplaceUses(SDValue(Root, 0), SDValue(CNode, 0));
5460 CurDAG->RemoveDeadNode(Root);
5466bool X86DAGToDAGISel::tryMatchBitSelect(SDNode *
N) {
5469 MVT NVT =
N->getSimpleValueType(0);
5472 if (!NVT.
isVector() || !Subtarget->hasAVX512())
5506 SDValue
Imm = CurDAG->getTargetConstant(0xCA, dl, MVT::i8);
5507 SDValue Ternlog = CurDAG->getNode(X86ISD::VPTERNLOG, dl, NVT,
A,
B,
C,
Imm);
5514void X86DAGToDAGISel::Select(SDNode *Node) {
5515 MVT NVT =
Node->getSimpleValueType(0);
5516 unsigned Opcode =
Node->getOpcode();
5519 if (
Node->isMachineOpcode()) {
5521 Node->setNodeId(-1);
5528 unsigned IntNo =
Node->getConstantOperandVal(1);
5531 case Intrinsic::x86_encodekey128:
5532 case Intrinsic::x86_encodekey256: {
5533 if (!Subtarget->hasKL())
5539 case Intrinsic::x86_encodekey128:
5540 Opcode = X86::ENCODEKEY128;
5542 case Intrinsic::x86_encodekey256:
5543 Opcode = X86::ENCODEKEY256;
5547 SDValue Chain =
Node->getOperand(0);
5548 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM0,
Node->getOperand(3),
5550 if (Opcode == X86::ENCODEKEY256)
5551 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM1,
Node->getOperand(4),
5554 MachineSDNode *Res = CurDAG->getMachineNode(
5555 Opcode, dl,
Node->getVTList(),
5556 {Node->getOperand(2), Chain, Chain.getValue(1)});
5557 ReplaceNode(Node, Res);
5560 case Intrinsic::x86_tileloaddrs64_internal:
5561 case Intrinsic::x86_tileloaddrst164_internal:
5562 if (!Subtarget->hasAMXMOVRS())
5565 case Intrinsic::x86_tileloadd64_internal:
5566 case Intrinsic::x86_tileloaddt164_internal: {
5567 if (!Subtarget->hasAMXTILE())
5570 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5571 MFI->setAMXProgModel(AMXProgModelEnum::ManagedRA);
5576 case Intrinsic::x86_tileloaddrs64_internal:
5577 Opc = X86::PTILELOADDRSV;
5579 case Intrinsic::x86_tileloaddrst164_internal:
5580 Opc = X86::PTILELOADDRST1V;
5582 case Intrinsic::x86_tileloadd64_internal:
5583 Opc = X86::PTILELOADDV;
5585 case Intrinsic::x86_tileloaddt164_internal:
5586 Opc = X86::PTILELOADDT1V;
5590 SDValue
Base =
Node->getOperand(4);
5591 SDValue Scale = getI8Imm(1, dl);
5593 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5594 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5595 SDValue Chain =
Node->getOperand(0);
5596 MachineSDNode *CNode;
5597 SDValue
Ops[] = {
Node->getOperand(2),
5598 Node->getOperand(3),
5605 CNode = CurDAG->getMachineNode(
Opc, dl, {MVT::x86amx, MVT::Other},
Ops);
5606 ReplaceNode(Node, CNode);
5613 unsigned IntNo =
Node->getConstantOperandVal(1);
5616 case Intrinsic::x86_sse3_monitor:
5617 case Intrinsic::x86_monitorx:
5618 case Intrinsic::x86_clzero: {
5619 bool Use64BitPtr =
Node->getOperand(2).getValueType() == MVT::i64;
5624 case Intrinsic::x86_sse3_monitor:
5625 if (!Subtarget->hasSSE3())
5627 Opc = Use64BitPtr ? X86::MONITOR64rrr : X86::MONITOR32rrr;
5629 case Intrinsic::x86_monitorx:
5630 if (!Subtarget->hasMWAITX())
5632 Opc = Use64BitPtr ? X86::MONITORX64rrr : X86::MONITORX32rrr;
5634 case Intrinsic::x86_clzero:
5635 if (!Subtarget->hasCLZERO())
5637 Opc = Use64BitPtr ? X86::CLZERO64r : X86::CLZERO32r;
5642 unsigned PtrReg = Use64BitPtr ? X86::RAX : X86::EAX;
5643 SDValue Chain = CurDAG->getCopyToReg(
Node->getOperand(0), dl, PtrReg,
5644 Node->getOperand(2), SDValue());
5645 SDValue InGlue = Chain.
getValue(1);
5647 if (IntNo == Intrinsic::x86_sse3_monitor ||
5648 IntNo == Intrinsic::x86_monitorx) {
5650 Chain = CurDAG->getCopyToReg(Chain, dl, X86::ECX,
Node->getOperand(3),
5653 Chain = CurDAG->getCopyToReg(Chain, dl, X86::EDX,
Node->getOperand(4),
5658 MachineSDNode *CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
5660 ReplaceNode(Node, CNode);
5666 case Intrinsic::x86_tilestored64_internal: {
5668 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5669 MFI->setAMXProgModel(AMXProgModelEnum::ManagedRA);
5670 unsigned Opc = X86::PTILESTOREDV;
5672 SDValue
Base =
Node->getOperand(4);
5673 SDValue Scale = getI8Imm(1, dl);
5675 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5676 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5677 SDValue Chain =
Node->getOperand(0);
5678 MachineSDNode *CNode;
5679 SDValue
Ops[] = {
Node->getOperand(2),
5680 Node->getOperand(3),
5686 Node->getOperand(6),
5688 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5689 ReplaceNode(Node, CNode);
5692 case Intrinsic::x86_tileloaddrs64:
5693 case Intrinsic::x86_tileloaddrst164:
5694 if (!Subtarget->hasAMXMOVRS())
5697 case Intrinsic::x86_tileloadd64:
5698 case Intrinsic::x86_tileloaddt164:
5699 case Intrinsic::x86_tilestored64: {
5700 if (!Subtarget->hasAMXTILE())
5703 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5704 MFI->setAMXProgModel(AMXProgModelEnum::DirectReg);
5708 case Intrinsic::x86_tileloadd64:
Opc = X86::PTILELOADD;
break;
5709 case Intrinsic::x86_tileloaddrs64:
5710 Opc = X86::PTILELOADDRS;
5712 case Intrinsic::x86_tileloaddt164:
Opc = X86::PTILELOADDT1;
break;
5713 case Intrinsic::x86_tileloaddrst164:
5714 Opc = X86::PTILELOADDRST1;
5716 case Intrinsic::x86_tilestored64:
Opc = X86::PTILESTORED;
break;
5719 unsigned TIndex =
Node->getConstantOperandVal(2);
5720 SDValue
TReg = getI8Imm(TIndex, dl);
5721 SDValue
Base =
Node->getOperand(3);
5722 SDValue Scale = getI8Imm(1, dl);
5724 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5725 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5726 SDValue Chain =
Node->getOperand(0);
5727 MachineSDNode *CNode;
5728 if (
Opc == X86::PTILESTORED) {
5730 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5733 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5735 ReplaceNode(Node, CNode);
5742 case X86ISD::NT_BRIND: {
5743 if (Subtarget->isTarget64BitILP32()) {
5748 assert(
Target.getValueType() == MVT::i32 &&
"Unexpected VT!");
5749 SDValue ZextTarget = CurDAG->getZExtOrTrunc(Target, dl, MVT::i64);
5750 SDValue Brind = CurDAG->getNode(Opcode, dl, MVT::Other,
5751 Node->getOperand(0), ZextTarget);
5752 ReplaceNode(Node, Brind.
getNode());
5753 SelectCode(ZextTarget.
getNode());
5760 ReplaceNode(Node, getGlobalBaseReg());
5767 ReplaceUses(SDValue(Node, 0),
Node->getOperand(0));
5768 CurDAG->RemoveDeadNode(Node);
5774 if (matchBitExtract(Node))
5779 if (tryShiftAmountMod(Node))
5783 case X86ISD::VPTERNLOG: {
5784 uint8_t
Imm =
Node->getConstantOperandVal(3);
5785 if (matchVPTERNLOG(Node, Node, Node, Node,
Node->getOperand(0),
5792 if (tryVPTERNLOG(Node))
5799 SDValue N0 =
Node->getOperand(0);
5800 SDValue N1 =
Node->getOperand(1);
5802 tryVPTESTM(Node, N0, N1))
5805 tryVPTESTM(Node, N1, N0))
5809 if (MachineSDNode *NewNode = matchBEXTRFromAndImm(Node)) {
5810 ReplaceUses(SDValue(Node, 0), SDValue(NewNode, 0));
5811 CurDAG->RemoveDeadNode(Node);
5814 if (matchBitExtract(Node))
5823 if (Opcode ==
ISD::XOR && Subtarget->hasBMI2() && matchBitExtract(Node))
5827 if (tryShrinkShlLogicImm(Node))
5829 if (Opcode ==
ISD::OR && tryMatchBitSelect(Node))
5831 if (tryVPTERNLOG(Node))
5836 if (Opcode ==
ISD::ADD && matchBitExtract(Node))
5846 if (!CurDAG->shouldOptForSize())
5850 if (NVT != MVT::i8 && NVT != MVT::i16 && NVT != MVT::i32 && NVT != MVT::i64)
5853 SDValue N0 =
Node->getOperand(0);
5854 SDValue N1 =
Node->getOperand(1);
5860 int64_t Val = Cst->getSExtValue();
5868 if (Opcode ==
ISD::ADD && (Val == 1 || Val == -1))
5872 if (!shouldAvoidImmediateInstFormsForSize(N1.
getNode()))
5876 unsigned ROpc, MOpc;
5985 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5986 if (tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
5987 SDValue
Ops[] = { N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, N0.
getOperand(0) };
5988 SDVTList VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
5989 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
5991 ReplaceUses(N0.
getValue(1), SDValue(CNode, 2));
5994 ReplaceUses(SDValue(Node, 0), SDValue(CNode, 0));
5995 CurDAG->RemoveDeadNode(Node);
6000 CurDAG->SelectNodeTo(Node, ROpc, NVT, MVT::i32, N0, N1);
6009 case X86ISD::UMUL: {
6010 SDValue N0 =
Node->getOperand(0);
6011 SDValue N1 =
Node->getOperand(1);
6013 unsigned LoReg, ROpc, MOpc;
6018 ROpc = Opcode == X86ISD::SMUL ? X86::IMUL8r : X86::MUL8r;
6019 MOpc = Opcode == X86ISD::SMUL ? X86::IMUL8m : X86::MUL8m;
6038 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6039 bool FoldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6042 FoldedLoad = tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6050 orderRegForMul(N0, N1, LoReg, CurDAG->getMachineFunction().getRegInfo());
6052 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg,
6053 N0, SDValue()).getValue(1);
6055 MachineSDNode *CNode;
6061 VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
6063 VTs = CurDAG->getVTList(NVT, NVT, MVT::i32, MVT::Other);
6065 SDValue
Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, N1.
getOperand(0),
6067 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6070 ReplaceUses(N1.
getValue(1), SDValue(CNode, NVT == MVT::i8 ? 2 : 3));
6078 VTs = CurDAG->getVTList(NVT, MVT::i32);
6080 VTs = CurDAG->getVTList(NVT, NVT, MVT::i32);
6082 CNode = CurDAG->getMachineNode(ROpc, dl, VTs, {N1, InGlue});
6085 ReplaceUses(SDValue(Node, 0), SDValue(CNode, 0));
6086 ReplaceUses(SDValue(Node, 1), SDValue(CNode, NVT == MVT::i8 ? 1 : 2));
6087 CurDAG->RemoveDeadNode(Node);
6093 SDValue N0 =
Node->getOperand(0);
6094 SDValue N1 =
Node->getOperand(1);
6097 unsigned LoReg, HiReg;
6099 bool UseMULX = !IsSigned && Subtarget->hasBMI2();
6100 bool UseMULXHi = UseMULX && SDValue(Node, 0).use_empty();
6104 Opc = UseMULXHi ? X86::MULX32Hrr
6106 : IsSigned ?
X86::IMUL32r
6108 MOpc = UseMULXHi ? X86::MULX32Hrm
6110 : IsSigned ?
X86::IMUL32m
6112 LoReg = UseMULX ? X86::EDX : X86::EAX;
6116 Opc = UseMULXHi ? X86::MULX64Hrr
6118 : IsSigned ?
X86::IMUL64r
6120 MOpc = UseMULXHi ? X86::MULX64Hrm
6122 : IsSigned ?
X86::IMUL64m
6124 LoReg = UseMULX ? X86::RDX : X86::RAX;
6129 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6130 bool foldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6133 foldedLoad = tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6141 orderRegForMul(N0, N1, LoReg, CurDAG->getMachineFunction().getRegInfo());
6143 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg,
6144 N0, SDValue()).getValue(1);
6145 SDValue ResHi, ResLo;
6148 MachineSDNode *CNode =
nullptr;
6149 SDValue
Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, N1.
getOperand(0),
6152 SDVTList VTs = CurDAG->getVTList(NVT, MVT::Other);
6153 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6154 ResHi = SDValue(CNode, 0);
6155 Chain = SDValue(CNode, 1);
6156 }
else if (UseMULX) {
6157 SDVTList VTs = CurDAG->getVTList(NVT, NVT, MVT::Other);
6158 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6159 ResHi = SDValue(CNode, 0);
6160 ResLo = SDValue(CNode, 1);
6161 Chain = SDValue(CNode, 2);
6163 SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue);
6164 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6165 Chain = SDValue(CNode, 0);
6166 InGlue = SDValue(CNode, 1);
6170 ReplaceUses(N1.
getValue(1), Chain);
6174 SDValue
Ops[] = { N1, InGlue };
6176 SDVTList VTs = CurDAG->getVTList(NVT);
6177 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6178 ResHi = SDValue(CNode, 0);
6179 }
else if (UseMULX) {
6180 SDVTList VTs = CurDAG->getVTList(NVT, NVT);
6181 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6182 ResHi = SDValue(CNode, 0);
6183 ResLo = SDValue(CNode, 1);
6185 SDVTList VTs = CurDAG->getVTList(MVT::Glue);
6186 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6187 InGlue = SDValue(CNode, 0);
6192 if (!SDValue(Node, 0).use_empty()) {
6194 assert(LoReg &&
"Register for low half is not defined!");
6195 ResLo = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, LoReg,
6199 ReplaceUses(SDValue(Node, 0), ResLo);
6204 if (!SDValue(Node, 1).use_empty()) {
6206 assert(HiReg &&
"Register for high half is not defined!");
6207 ResHi = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, HiReg,
6211 ReplaceUses(SDValue(Node, 1), ResHi);
6216 CurDAG->RemoveDeadNode(Node);
6222 SDValue N0 =
Node->getOperand(0);
6223 SDValue N1 =
Node->getOperand(1);
6225 unsigned ROpc, MOpc;
6230 case MVT::i8: ROpc = X86::DIV8r; MOpc = X86::DIV8m;
break;
6231 case MVT::i16: ROpc = X86::DIV16r; MOpc = X86::DIV16m;
break;
6232 case MVT::i32: ROpc = X86::DIV32r; MOpc = X86::DIV32m;
break;
6233 case MVT::i64: ROpc = X86::DIV64r; MOpc = X86::DIV64m;
break;
6238 case MVT::i8: ROpc = X86::IDIV8r; MOpc = X86::IDIV8m;
break;
6239 case MVT::i16: ROpc = X86::IDIV16r; MOpc = X86::IDIV16m;
break;
6240 case MVT::i32: ROpc = X86::IDIV32r; MOpc = X86::IDIV32m;
break;
6241 case MVT::i64: ROpc = X86::IDIV64r; MOpc = X86::IDIV64m;
break;
6245 unsigned LoReg, HiReg, ClrReg;
6246 unsigned SExtOpcode;
6250 LoReg = X86::AL; ClrReg = HiReg = X86::AH;
6254 LoReg = X86::AX; HiReg = X86::DX;
6256 SExtOpcode = X86::CWD;
6259 LoReg = X86::EAX; ClrReg = HiReg = X86::EDX;
6260 SExtOpcode = X86::CDQ;
6263 LoReg = X86::RAX; ClrReg = HiReg = X86::RDX;
6264 SExtOpcode = X86::CQO;
6268 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6269 bool foldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6270 bool signBitIsZero = CurDAG->SignBitIsZero(N0);
6273 if (NVT == MVT::i8) {
6276 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Chain;
6277 MachineSDNode *Move;
6278 if (tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
6279 SDValue
Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, N0.
getOperand(0) };
6280 unsigned Opc = (
isSigned && !signBitIsZero) ? X86::MOVSX16rm8
6282 Move = CurDAG->getMachineNode(
Opc, dl, MVT::i16, MVT::Other,
Ops);
6283 Chain = SDValue(Move, 1);
6284 ReplaceUses(N0.
getValue(1), Chain);
6288 unsigned Opc = (
isSigned && !signBitIsZero) ? X86::MOVSX16rr8
6290 Move = CurDAG->getMachineNode(
Opc, dl, MVT::i16, N0);
6291 Chain = CurDAG->getEntryNode();
6293 Chain = CurDAG->getCopyToReg(Chain, dl, X86::AX, SDValue(Move, 0),
6298 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl,
6299 LoReg, N0, SDValue()).getValue(1);
6303 SDValue(CurDAG->getMachineNode(SExtOpcode, dl, MVT::Glue, InGlue),0);
6306 SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::i32);
6308 SDValue(CurDAG->getMachineNode(X86::MOV32r0, dl, VTs, {}), 0);
6312 SDValue(CurDAG->getMachineNode(
6313 TargetOpcode::EXTRACT_SUBREG, dl, MVT::i16, ClrNode,
6314 CurDAG->getTargetConstant(X86::sub_16bit, dl,
6322 CurDAG->getMachineNode(
6323 TargetOpcode::SUBREG_TO_REG, dl, MVT::i64, ClrNode,
6324 CurDAG->getTargetConstant(X86::sub_32bit, dl, MVT::i32)),
6331 InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, ClrReg,
6332 ClrNode, InGlue).getValue(1);
6337 SDValue
Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, N1.
getOperand(0),
6339 MachineSDNode *CNode =
6340 CurDAG->getMachineNode(MOpc, dl, MVT::Other, MVT::Glue,
Ops);
6341 InGlue = SDValue(CNode, 1);
6343 ReplaceUses(N1.
getValue(1), SDValue(CNode, 0));
6348 SDValue(CurDAG->getMachineNode(ROpc, dl, MVT::Glue, N1, InGlue), 0);
6358 if (HiReg == X86::AH && !SDValue(Node, 1).use_empty()) {
6359 SDValue AHCopy = CurDAG->getRegister(X86::AH, MVT::i8);
6360 unsigned AHExtOpcode =
6361 isSigned ? X86::MOVSX32rr8_NOREX : X86::MOVZX32rr8_NOREX;
6363 SDNode *RNode = CurDAG->getMachineNode(AHExtOpcode, dl, MVT::i32,
6364 MVT::Glue, AHCopy, InGlue);
6365 SDValue
Result(RNode, 0);
6366 InGlue = SDValue(RNode, 1);
6369 CurDAG->getTargetExtractSubreg(X86::sub_8bit, dl, MVT::i8, Result);
6371 ReplaceUses(SDValue(Node, 1), Result);
6376 if (!SDValue(Node, 0).use_empty()) {
6377 SDValue
Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
6378 LoReg, NVT, InGlue);
6379 InGlue =
Result.getValue(2);
6380 ReplaceUses(SDValue(Node, 0), Result);
6385 if (!SDValue(Node, 1).use_empty()) {
6386 SDValue
Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
6387 HiReg, NVT, InGlue);
6388 InGlue =
Result.getValue(2);
6389 ReplaceUses(SDValue(Node, 1), Result);
6393 CurDAG->RemoveDeadNode(Node);
6398 case X86ISD::STRICT_FCMP:
6399 case X86ISD::STRICT_FCMPS: {
6400 bool IsStrictCmp =
Node->getOpcode() == X86ISD::STRICT_FCMP ||
6401 Node->getOpcode() == X86ISD::STRICT_FCMPS;
6402 SDValue N0 =
Node->getOperand(IsStrictCmp ? 1 : 0);
6403 SDValue N1 =
Node->getOperand(IsStrictCmp ? 2 : 1);
6409 if (Subtarget->canUseCMOV())
6412 bool IsSignaling =
Node->getOpcode() == X86ISD::STRICT_FCMPS;
6418 Opc = IsSignaling ? X86::COM_Fpr32 : X86::UCOM_Fpr32;
6421 Opc = IsSignaling ? X86::COM_Fpr64 : X86::UCOM_Fpr64;
6424 Opc = IsSignaling ? X86::COM_Fpr80 : X86::UCOM_Fpr80;
6429 IsStrictCmp ?
Node->getOperand(0) : CurDAG->getEntryNode();
6432 SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue);
6433 Chain = SDValue(CurDAG->getMachineNode(
Opc, dl, VTs, {N0, N1, Chain}), 0);
6436 Glue = SDValue(CurDAG->getMachineNode(
Opc, dl, MVT::Glue, N0, N1), 0);
6441 SDValue(CurDAG->getMachineNode(X86::FNSTSW16r, dl, MVT::i16, Glue), 0);
6445 CurDAG->getTargetExtractSubreg(X86::sub_8bit_hi, dl, MVT::i8, FNSTSW);
6449 assert(Subtarget->canUseLAHFSAHF() &&
6450 "Target doesn't support SAHF or FCOMI?");
6451 SDValue AH = CurDAG->getCopyToReg(Chain, dl, X86::AH, Extract, SDValue());
6453 SDValue SAHF = SDValue(
6454 CurDAG->getMachineNode(X86::SAHF, dl, MVT::i32, AH.
getValue(1)), 0);
6457 ReplaceUses(SDValue(Node, 1), Chain);
6459 ReplaceUses(SDValue(Node, 0), SAHF);
6460 CurDAG->RemoveDeadNode(Node);
6465 SDValue N0 =
Node->getOperand(0);
6466 SDValue N1 =
Node->getOperand(1);
6480 if (MachineSDNode *NewNode = matchBEXTRFromAndImm(N0.
getNode())) {
6481 unsigned TestOpc = CmpVT == MVT::i64 ? X86::TEST64rr
6483 SDValue BEXTR = SDValue(NewNode, 0);
6484 NewNode = CurDAG->getMachineNode(TestOpc, dl, MVT::i32, BEXTR, BEXTR);
6485 ReplaceUses(SDValue(Node, 0), SDValue(NewNode, 0));
6486 CurDAG->RemoveDeadNode(Node);
6513 onlyUsesZeroFlag(SDValue(Node, 0))) {
6518 unsigned TestOpcode;
6526 if (LeadingZeros == 0 && SavesBytes) {
6531 ShiftAmt = TrailingZeros;
6533 TestOpcode = X86::TEST64rr;
6534 }
else if (TrailingZeros == 0 && SavesBytes) {
6540 if (LeadingZeros == 1) {
6544 MachineSDNode *
Add = CurDAG->getMachineNode(
6547 MachineSDNode *
Test = CurDAG->getMachineNode(
6548 X86::TEST64rr, dl, MVT::i32, SDValue(
Add, 0), SDValue(
Add, 0));
6549 ReplaceNode(Node,
Test);
6553 ShiftAmt = LeadingZeros;
6555 TestOpcode = X86::TEST64rr;
6556 }
else if (MaskC->hasOneUse() && !
isInt<32>(Mask)) {
6559 unsigned PopCount = 64 - LeadingZeros - TrailingZeros;
6560 if (PopCount == 8) {
6562 ShiftAmt = TrailingZeros;
6563 SubRegIdx = X86::sub_8bit;
6565 TestOpcode = X86::TEST8rr;
6566 }
else if (PopCount == 16) {
6568 ShiftAmt = TrailingZeros;
6569 SubRegIdx = X86::sub_16bit;
6570 SubRegVT = MVT::i16;
6571 TestOpcode = X86::TEST16rr;
6572 }
else if (PopCount == 32) {
6574 ShiftAmt = TrailingZeros;
6575 SubRegIdx = X86::sub_32bit;
6576 SubRegVT = MVT::i32;
6577 TestOpcode = X86::TEST32rr;
6581 SDValue ShiftC = CurDAG->getTargetConstant(ShiftAmt, dl, MVT::i64);
6582 SDValue Shift = SDValue(
6583 CurDAG->getMachineNode(ShiftOpcode, dl, MVT::i64, MVT::i32,
6586 if (SubRegIdx != 0) {
6588 CurDAG->getTargetExtractSubreg(SubRegIdx, dl, SubRegVT, Shift);
6590 MachineSDNode *
Test =
6591 CurDAG->getMachineNode(TestOpcode, dl, MVT::i32, Shift, Shift);
6592 ReplaceNode(Node,
Test);
6599 unsigned ROpc, MOpc;
6607 (!(Mask & 0x80) || CmpVT == MVT::i8 ||
6608 hasNoSignFlagUses(SDValue(Node, 0)))) {
6611 SubRegOp = X86::sub_8bit;
6612 ROpc = X86::TEST8ri;
6613 MOpc = X86::TEST8mi;
6614 }
else if (OptForMinSize &&
isUInt<16>(Mask) &&
6615 (!(Mask & 0x8000) || CmpVT == MVT::i16 ||
6616 hasNoSignFlagUses(SDValue(Node, 0)))) {
6622 SubRegOp = X86::sub_16bit;
6623 ROpc = X86::TEST16ri;
6624 MOpc = X86::TEST16mi;
6626 ((!(Mask & 0x80000000) &&
6629 (CmpVT != MVT::i16 || !(Mask & 0x8000))) ||
6630 CmpVT == MVT::i32 ||
6631 hasNoSignFlagUses(SDValue(Node, 0)))) {
6638 SubRegOp = X86::sub_32bit;
6639 ROpc = X86::TEST32ri;
6640 MOpc = X86::TEST32mi;
6646 SDValue
Imm = CurDAG->getTargetConstant(Mask, dl, VT);
6650 MachineSDNode *NewNode;
6651 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6652 if (tryFoldLoad(Node, N0.
getNode(),
Reg, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
6654 if (!LoadN->isSimple()) {
6655 unsigned NumVolBits = LoadN->getValueType(0).getSizeInBits();
6656 if ((MOpc == X86::TEST8mi && NumVolBits != 8) ||
6657 (MOpc == X86::TEST16mi && NumVolBits != 16) ||
6658 (MOpc == X86::TEST32mi && NumVolBits != 32))
6662 SDValue
Ops[] = { Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
Imm,
6663 Reg.getOperand(0) };
6664 NewNode = CurDAG->getMachineNode(MOpc, dl, MVT::i32, MVT::Other,
Ops);
6666 ReplaceUses(
Reg.getValue(1), SDValue(NewNode, 1));
6668 CurDAG->setNodeMemRefs(NewNode,
6673 Reg = CurDAG->getTargetExtractSubreg(SubRegOp, dl, VT,
Reg);
6675 NewNode = CurDAG->getMachineNode(ROpc, dl, MVT::i32,
Reg,
Imm);
6678 ReplaceNode(Node, NewNode);
6684 if (!Subtarget->hasSSE42())
6687 bool NeedIndex = !SDValue(Node, 0).use_empty();
6688 bool NeedMask = !SDValue(Node, 1).use_empty();
6690 bool MayFoldLoad = !NeedIndex || !
NeedMask;
6692 MachineSDNode *CNode;
6695 Subtarget->hasAVX() ? X86::VPCMPISTRMrri : X86::PCMPISTRMrri;
6697 Subtarget->hasAVX() ? X86::VPCMPISTRMrmi : X86::PCMPISTRMrmi;
6698 CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node);
6699 ReplaceUses(SDValue(Node, 1), SDValue(CNode, 0));
6701 if (NeedIndex || !NeedMask) {
6703 Subtarget->hasAVX() ? X86::VPCMPISTRIrri : X86::PCMPISTRIrri;
6705 Subtarget->hasAVX() ? X86::VPCMPISTRIrmi : X86::PCMPISTRIrmi;
6706 CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node);
6707 ReplaceUses(SDValue(Node, 0), SDValue(CNode, 0));
6711 ReplaceUses(SDValue(Node, 2), SDValue(CNode, 1));
6712 CurDAG->RemoveDeadNode(Node);
6716 if (!Subtarget->hasSSE42())
6720 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EAX,
6721 Node->getOperand(1),
6722 SDValue()).getValue(1);
6723 InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EDX,
6724 Node->getOperand(3), InGlue).getValue(1);
6726 bool NeedIndex = !SDValue(Node, 0).use_empty();
6727 bool NeedMask = !SDValue(Node, 1).use_empty();
6729 bool MayFoldLoad = !NeedIndex || !
NeedMask;
6731 MachineSDNode *CNode;
6734 Subtarget->hasAVX() ? X86::VPCMPESTRMrri : X86::PCMPESTRMrri;
6736 Subtarget->hasAVX() ? X86::VPCMPESTRMrmi : X86::PCMPESTRMrmi;
6738 emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node, InGlue);
6739 ReplaceUses(SDValue(Node, 1), SDValue(CNode, 0));
6741 if (NeedIndex || !NeedMask) {
6743 Subtarget->hasAVX() ? X86::VPCMPESTRIrri : X86::PCMPESTRIrri;
6745 Subtarget->hasAVX() ? X86::VPCMPESTRIrmi : X86::PCMPESTRIrmi;
6746 CNode = emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node, InGlue);
6747 ReplaceUses(SDValue(Node, 0), SDValue(CNode, 0));
6750 ReplaceUses(SDValue(Node, 2), SDValue(CNode, 1));
6751 CurDAG->RemoveDeadNode(Node);
6756 if (NVT.
isVector() && tryVPTESTM(Node, SDValue(Node, 0), SDValue()))
6763 if (foldLoadStoreIntoMemOperand(Node))
6767 case X86ISD::SETCC_CARRY: {
6768 MVT VT =
Node->getSimpleValueType(0);
6770 if (Subtarget->hasSBBDepBreaking()) {
6775 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EFLAGS,
6776 Node->getOperand(1), SDValue());
6780 unsigned Opc = VT == MVT::i64 ? X86::SETB_C64r : X86::SETB_C32r;
6781 MVT SetVT = VT == MVT::i64 ? MVT::i64 : MVT::i32;
6783 CurDAG->getMachineNode(
Opc, dl, SetVT, EFLAGS, EFLAGS.
getValue(1)),
6788 Result = getSBBZero(Node);
6792 if (VT == MVT::i8 || VT == MVT::i16) {
6793 int SubIndex = VT == MVT::i16 ? X86::sub_16bit : X86::sub_8bit;
6794 Result = CurDAG->getTargetExtractSubreg(SubIndex, dl, VT, Result);
6797 ReplaceUses(SDValue(Node, 0), Result);
6798 CurDAG->RemoveDeadNode(Node);
6804 SDValue
Result = getSBBZero(Node);
6807 ReplaceUses(SDValue(Node, 1),
Result.getValue(1));
6810 if (!SDValue(Node, 0).use_empty()) {
6812 MVT VT =
Node->getSimpleValueType(0);
6813 if (VT == MVT::i8 || VT == MVT::i16) {
6814 int SubIndex = VT == MVT::i16 ? X86::sub_16bit : X86::sub_8bit;
6815 Result = CurDAG->getTargetExtractSubreg(SubIndex, dl, VT, Result);
6817 ReplaceUses(SDValue(Node, 0), Result);
6820 CurDAG->RemoveDeadNode(Node);
6827 SDValue IndexOp = Mgt->getIndex();
6828 SDValue
Mask = Mgt->getMask();
6830 MVT ValueVT =
Node->getSimpleValueType(0);
6831 MVT MaskVT =
Mask.getSimpleValueType();
6848 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6849 Opc = IsFP ? X86::VGATHERDPSZ128rm : X86::VPGATHERDDZ128rm;
6850 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6851 Opc = IsFP ? X86::VGATHERDPSZ256rm : X86::VPGATHERDDZ256rm;
6852 else if (IndexVT == MVT::v16i32 && NumElts == 16 && EltSize == 32)
6853 Opc = IsFP ? X86::VGATHERDPSZrm : X86::VPGATHERDDZrm;
6854 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6855 Opc = IsFP ? X86::VGATHERDPDZ128rm : X86::VPGATHERDQZ128rm;
6856 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6857 Opc = IsFP ? X86::VGATHERDPDZ256rm : X86::VPGATHERDQZ256rm;
6858 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 64)
6859 Opc = IsFP ? X86::VGATHERDPDZrm : X86::VPGATHERDQZrm;
6860 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6861 Opc = IsFP ? X86::VGATHERQPSZ128rm : X86::VPGATHERQDZ128rm;
6862 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6863 Opc = IsFP ? X86::VGATHERQPSZ256rm : X86::VPGATHERQDZ256rm;
6864 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 32)
6865 Opc = IsFP ? X86::VGATHERQPSZrm : X86::VPGATHERQDZrm;
6866 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6867 Opc = IsFP ? X86::VGATHERQPDZ128rm : X86::VPGATHERQQZ128rm;
6868 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6869 Opc = IsFP ? X86::VGATHERQPDZ256rm : X86::VPGATHERQQZ256rm;
6870 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 64)
6871 Opc = IsFP ? X86::VGATHERQPDZrm : X86::VPGATHERQQZrm;
6873 assert(EVT(MaskVT) == EVT(ValueVT).changeVectorElementTypeToInteger() &&
6874 "Unexpected mask VT!");
6875 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6876 Opc = IsFP ? X86::VGATHERDPSrm : X86::VPGATHERDDrm;
6877 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6878 Opc = IsFP ? X86::VGATHERDPSYrm : X86::VPGATHERDDYrm;
6879 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6880 Opc = IsFP ? X86::VGATHERDPDrm : X86::VPGATHERDQrm;
6881 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6882 Opc = IsFP ? X86::VGATHERDPDYrm : X86::VPGATHERDQYrm;
6883 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6884 Opc = IsFP ? X86::VGATHERQPSrm : X86::VPGATHERQDrm;
6885 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6886 Opc = IsFP ? X86::VGATHERQPSYrm : X86::VPGATHERQDYrm;
6887 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6888 Opc = IsFP ? X86::VGATHERQPDrm : X86::VPGATHERQQrm;
6889 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6890 Opc = IsFP ? X86::VGATHERQPDYrm : X86::VPGATHERQQYrm;
6896 SDValue
Base, Scale,
Index, Disp, Segment;
6897 if (!selectVectorAddr(Mgt, Mgt->getBasePtr(), IndexOp, Mgt->getScale(),
6898 Base, Scale, Index, Disp, Segment))
6901 SDValue PassThru = Mgt->getPassThru();
6902 SDValue Chain = Mgt->getChain();
6904 SDVTList VTs = CurDAG->getVTList(ValueVT, MaskVT, MVT::Other);
6906 MachineSDNode *NewNode;
6909 Index, Disp, Segment, Chain};
6910 NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6913 Disp, Segment,
Mask, Chain};
6914 NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6916 CurDAG->setNodeMemRefs(NewNode, {Mgt->getMemOperand()});
6917 ReplaceUses(SDValue(Node, 0), SDValue(NewNode, 0));
6918 ReplaceUses(SDValue(Node, 1), SDValue(NewNode, 2));
6919 CurDAG->RemoveDeadNode(Node);
6924 SDValue
Value = Sc->getValue();
6925 SDValue IndexOp = Sc->getIndex();
6927 MVT ValueVT =
Value.getSimpleValueType();
6942 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6943 Opc = IsFP ? X86::VSCATTERDPSZ128mr : X86::VPSCATTERDDZ128mr;
6944 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6945 Opc = IsFP ? X86::VSCATTERDPSZ256mr : X86::VPSCATTERDDZ256mr;
6946 else if (IndexVT == MVT::v16i32 && NumElts == 16 && EltSize == 32)
6947 Opc = IsFP ? X86::VSCATTERDPSZmr : X86::VPSCATTERDDZmr;
6948 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6949 Opc = IsFP ? X86::VSCATTERDPDZ128mr : X86::VPSCATTERDQZ128mr;
6950 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6951 Opc = IsFP ? X86::VSCATTERDPDZ256mr : X86::VPSCATTERDQZ256mr;
6952 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 64)
6953 Opc = IsFP ? X86::VSCATTERDPDZmr : X86::VPSCATTERDQZmr;
6954 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6955 Opc = IsFP ? X86::VSCATTERQPSZ128mr : X86::VPSCATTERQDZ128mr;
6956 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6957 Opc = IsFP ? X86::VSCATTERQPSZ256mr : X86::VPSCATTERQDZ256mr;
6958 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 32)
6959 Opc = IsFP ? X86::VSCATTERQPSZmr : X86::VPSCATTERQDZmr;
6960 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6961 Opc = IsFP ? X86::VSCATTERQPDZ128mr : X86::VPSCATTERQQZ128mr;
6962 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6963 Opc = IsFP ? X86::VSCATTERQPDZ256mr : X86::VPSCATTERQQZ256mr;
6964 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 64)
6965 Opc = IsFP ? X86::VSCATTERQPDZmr : X86::VPSCATTERQQZmr;
6969 SDValue
Base, Scale,
Index, Disp, Segment;
6970 if (!selectVectorAddr(Sc, Sc->getBasePtr(), IndexOp, Sc->getScale(),
6971 Base, Scale, Index, Disp, Segment))
6974 SDValue
Mask = Sc->getMask();
6975 SDValue Chain = Sc->getChain();
6977 SDVTList VTs = CurDAG->getVTList(
Mask.getValueType(), MVT::Other);
6980 MachineSDNode *NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6981 CurDAG->setNodeMemRefs(NewNode, {Sc->getMemOperand()});
6982 ReplaceUses(SDValue(Node, 0), SDValue(NewNode, 1));
6983 CurDAG->RemoveDeadNode(Node);
6987 auto *MFI = CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
6988 auto CallId = MFI->getPreallocatedIdForCallSite(
6990 SDValue Chain =
Node->getOperand(0);
6991 SDValue CallIdValue = CurDAG->getTargetConstant(CallId, dl, MVT::i32);
6992 MachineSDNode *
New = CurDAG->getMachineNode(
6993 TargetOpcode::PREALLOCATED_SETUP, dl, MVT::Other, CallIdValue, Chain);
6994 ReplaceUses(SDValue(Node, 0), SDValue(New, 0));
6995 CurDAG->RemoveDeadNode(Node);
6999 auto *MFI = CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
7002 SDValue Chain =
Node->getOperand(0);
7003 SDValue CallIdValue = CurDAG->getTargetConstant(CallId, dl, MVT::i32);
7004 SDValue ArgIndex =
Node->getOperand(2);
7006 Ops[0] = CallIdValue;
7009 MachineSDNode *
New = CurDAG->getMachineNode(
7010 TargetOpcode::PREALLOCATED_ARG, dl,
7011 CurDAG->getVTList(TLI->
getPointerTy(CurDAG->getDataLayout()),
7014 ReplaceUses(SDValue(Node, 0), SDValue(New, 0));
7015 ReplaceUses(SDValue(Node, 1), SDValue(New, 1));
7016 CurDAG->RemoveDeadNode(Node);
7023 if (!Subtarget->hasWIDEKL())
7027 switch (
Node->getOpcode()) {
7031 Opcode = X86::AESENCWIDE128KL;
7034 Opcode = X86::AESDECWIDE128KL;
7037 Opcode = X86::AESENCWIDE256KL;
7040 Opcode = X86::AESDECWIDE256KL;
7044 SDValue Chain =
Node->getOperand(0);
7045 SDValue Addr =
Node->getOperand(1);
7047 SDValue
Base, Scale,
Index, Disp, Segment;
7048 if (!selectAddr(Node, Addr,
Base, Scale, Index, Disp, Segment))
7051 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM0,
Node->getOperand(2),
7053 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM1,
Node->getOperand(3),
7055 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM2,
Node->getOperand(4),
7057 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM3,
Node->getOperand(5),
7059 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM4,
Node->getOperand(6),
7061 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM5,
Node->getOperand(7),
7063 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM6,
Node->getOperand(8),
7065 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM7,
Node->getOperand(9),
7068 MachineSDNode *Res = CurDAG->getMachineNode(
7069 Opcode, dl,
Node->getVTList(),
7070 {Base, Scale, Index, Disp, Segment, Chain, Chain.getValue(1)});
7072 ReplaceNode(Node, Res);
7076 SDValue Chain =
Node->getOperand(0);
7079 if (
Node->getNumValues() == 3)
7080 Glue =
Node->getOperand(2);
7082 CurDAG->getCopyFromReg(Chain, dl,
Reg,
Node->getValueType(0), Glue);
7083 ReplaceNode(Node,
Copy.getNode());
7091bool X86DAGToDAGISel::SelectInlineAsmMemoryOperand(
7093 std::vector<SDValue> &OutOps) {
7094 SDValue Op0, Op1, Op2, Op3, Op4;
7095 switch (ConstraintID) {
7098 case InlineAsm::ConstraintCode::o:
7099 case InlineAsm::ConstraintCode::v:
7100 case InlineAsm::ConstraintCode::m:
7101 case InlineAsm::ConstraintCode::X:
7102 case InlineAsm::ConstraintCode::p:
7103 if (!selectAddr(
nullptr,
Op, Op0, Op1, Op2, Op3, Op4))
7108 OutOps.push_back(Op0);
7109 OutOps.push_back(Op1);
7110 OutOps.push_back(Op2);
7111 OutOps.push_back(Op3);
7112 OutOps.push_back(Op4);
7118 std::make_unique<X86DAGToDAGISel>(TM, TM.getOptLevel())) {}
7124 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[]
static bool isUndef(const MachineInstr &MI)
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.
@ AssertAlign
AssertAlign - These nodes record if a register contains a value that has a known alignment and the tr...
@ 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.
@ FREEZE
FREEZE - FREEZE(VAL) returns an arbitrary value if VAL is UNDEF (or is evaluated to UNDEF),...
@ 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.
@ AssertSext
AssertSext, AssertZext - These nodes record if a register contains a value that has already been zero...
@ 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