21#include "llvm/Config/llvm-config.h"
26#include "llvm/IR/IntrinsicsX86.h"
38#define DEBUG_TYPE "x86-isel"
39#define PASS_NAME "X86 DAG->DAG Instruction Selection"
41STATISTIC(NumLoadMoved,
"Number of loads moved below TokenFactor");
44 cl::desc(
"Enable setting constant bits to reduce size of mask immediates"),
48 "x86-promote-anyext-load",
cl::init(
true),
60 struct X86ISelAddressMode {
68 int Base_FrameIndex = 0;
74 const GlobalValue *GV =
nullptr;
77 const char *ES =
nullptr;
82 bool NegateIndex =
false;
87 bool IsForLEA =
false;
89 X86ISelAddressMode() =
default;
91 bool hasSymbolicDisplacement()
const {
92 return GV !=
nullptr || CP !=
nullptr || ES !=
nullptr ||
93 MCSym !=
nullptr || JT != -1 || BlockAddr !=
nullptr;
96 bool hasBaseOrIndexReg()
const {
97 return BaseType == FrameIndexBase ||
98 IndexReg.getNode() !=
nullptr || Base_Reg.getNode() !=
nullptr;
103 if (BaseType != RegBase)
return false;
104 if (RegisterSDNode *RegNode =
106 return RegNode->getReg() == X86::RIP;
115#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
116 void dump(SelectionDAG *DAG =
nullptr) {
117 dbgs() <<
"X86ISelAddressMode " <<
this <<
'\n';
118 dbgs() <<
"Base_Reg ";
119 if (Base_Reg.getNode())
120 Base_Reg.getNode()->dump(DAG);
123 if (BaseType == FrameIndexBase)
124 dbgs() <<
" Base.FrameIndex " << Base_FrameIndex <<
'\n';
125 dbgs() <<
" Scale " << Scale <<
'\n'
129 if (IndexReg.getNode())
130 IndexReg.getNode()->dump(DAG);
133 dbgs() <<
" Disp " << Disp <<
'\n'
155 dbgs() <<
" JT" << JT <<
" Align" << Alignment.value() <<
'\n';
169 const X86Subtarget *Subtarget;
175 bool IndirectTlsSegRefs;
178 X86DAGToDAGISel() =
delete;
180 explicit X86DAGToDAGISel(X86TargetMachine &tm,
CodeGenOptLevel OptLevel)
181 : SelectionDAGISel(tm, OptLevel), Subtarget(nullptr),
182 OptForMinSize(
false), IndirectTlsSegRefs(
false) {}
188 "indirect-tls-seg-refs");
195 void emitFunctionEntryCode()
override;
197 bool IsProfitableToFold(
SDValue N, SDNode *U, SDNode *Root)
const override;
199 void PreprocessISelDAG()
override;
200 void PostprocessISelDAG()
override;
203#include "X86GenDAGISel.inc"
206 void Select(SDNode *
N)
override;
208 bool foldOffsetIntoAddress(
uint64_t Offset, X86ISelAddressMode &AM);
209 bool matchLoadInAddress(LoadSDNode *
N, X86ISelAddressMode &AM,
210 bool AllowSegmentRegForX32 =
false);
211 bool matchWrapper(
SDValue N, X86ISelAddressMode &AM);
212 bool matchAddress(
SDValue N, X86ISelAddressMode &AM);
213 bool matchVectorAddress(
SDValue N, X86ISelAddressMode &AM);
214 bool matchAdd(
SDValue &
N, X86ISelAddressMode &AM,
unsigned Depth);
215 bool hasMaterializingUse(
SDValue V)
const;
218 bool matchAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
220 bool matchVectorAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
222 bool matchAddressBase(
SDValue N, X86ISelAddressMode &AM);
225 bool HasNDDM =
true);
228 bool selectVectorAddr(MemSDNode *Parent,
SDValue BasePtr,
SDValue IndexOp,
242 bool tryFoldLoad(SDNode *Root, SDNode *
P,
SDValue N,
252 return tryFoldLoad(
P,
P,
N,
Base, Scale, Index, Disp, Segment);
255 bool tryFoldBroadcast(SDNode *Root, SDNode *
P,
SDValue N,
260 bool isProfitableToFormMaskedOp(SDNode *
N)
const;
263 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
265 std::vector<SDValue> &OutOps)
override;
267 void emitSpecialCodeForMain();
269 inline void getAddressOperands(X86ISelAddressMode &AM,
const SDLoc &
DL,
273 if (AM.BaseType == X86ISelAddressMode::FrameIndexBase)
274 Base = CurDAG->getTargetFrameIndex(
275 AM.Base_FrameIndex, TLI->getPointerTy(CurDAG->getDataLayout()));
276 else if (AM.Base_Reg.
getNode())
279 Base = CurDAG->getRegister(0, VT);
281 Scale = getI8Imm(AM.Scale,
DL);
283#define GET_ND_IF_ENABLED(OPC) (Subtarget->hasNDD() ? OPC##_ND : OPC)
284#define GET_NDM_IF_ENABLED(OPC) \
285 (Subtarget->hasNDD() && Subtarget->hasNDDM() ? OPC##_ND : OPC)
287 if (AM.NegateIndex) {
313 Index = CurDAG->getRegister(0, VT);
318 Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(),
322 Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, AM.Alignment,
323 AM.Disp, AM.SymbolFlags);
325 assert(!AM.Disp &&
"Non-zero displacement is ignored with ES.");
326 Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags);
327 }
else if (AM.MCSym) {
328 assert(!AM.Disp &&
"Non-zero displacement is ignored with MCSym.");
329 assert(AM.SymbolFlags == 0 &&
"oo");
330 Disp = CurDAG->getMCSymbol(AM.MCSym, MVT::i32);
331 }
else if (AM.JT != -1) {
332 assert(!AM.Disp &&
"Non-zero displacement is ignored with JT.");
333 Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags);
334 }
else if (AM.BlockAddr)
335 Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, AM.Disp,
338 Disp = CurDAG->getSignedTargetConstant(AM.Disp,
DL, MVT::i32);
341 Segment = AM.Segment;
343 Segment = CurDAG->getRegister(0, MVT::i16);
348 bool isAMXSDNode(SDNode *
N)
const {
352 for (
unsigned Idx = 0,
E =
N->getNumValues(); Idx !=
E; ++Idx) {
353 if (
N->getValueType(Idx) == MVT::x86amx)
356 for (
unsigned Idx = 0,
E =
N->getNumOperands(); Idx !=
E; ++Idx) {
358 if (
Op.getValueType() == MVT::x86amx)
370 bool shouldAvoidImmediateInstFormsForSize(SDNode *
N)
const {
371 uint32_t UseCount = 0;
376 if (!CurDAG->shouldOptForSize())
380 for (
const SDNode *User :
N->users()) {
386 if (
User->isMachineOpcode()) {
393 User->getOperand(1).getNode() ==
N) {
404 if (
User->getNumOperands() != 2)
417 if (
User->getOpcode() == X86ISD::ADD ||
419 User->getOpcode() == X86ISD::SUB ||
425 OtherOp =
User->getOperand(1);
428 RegisterSDNode *RegNode;
432 if ((RegNode->
getReg() == X86::ESP) ||
433 (RegNode->
getReg() == X86::RSP))
442 return (UseCount > 1);
446 inline SDValue getI8Imm(
unsigned Imm,
const SDLoc &
DL) {
447 return CurDAG->getTargetConstant(
Imm,
DL, MVT::i8);
451 inline SDValue getI32Imm(
unsigned Imm,
const SDLoc &
DL) {
452 return CurDAG->getTargetConstant(
Imm,
DL, MVT::i32);
457 return CurDAG->getTargetConstant(
Imm,
DL, MVT::i64);
460 SDValue getExtractVEXTRACTImmediate(SDNode *
N,
unsigned VecWidth,
462 assert((VecWidth == 128 || VecWidth == 256) &&
"Unexpected vector width");
464 MVT VecVT =
N->getOperand(0).getSimpleValueType();
468 SDValue getInsertVINSERTImmediate(SDNode *
N,
unsigned VecWidth,
470 assert((VecWidth == 128 || VecWidth == 256) &&
"Unexpected vector width");
472 MVT VecVT =
N->getSimpleValueType(0);
476 SDValue getPermuteVINSERTCommutedImmediate(SDNode *
N,
unsigned VecWidth,
478 assert(VecWidth == 128 &&
"Unexpected vector width");
480 MVT VecVT =
N->getSimpleValueType(0);
482 assert((InsertIdx == 0 || InsertIdx == 1) &&
"Bad insertf128 index");
485 return getI8Imm(InsertIdx ? 0x02 : 0x30,
DL);
490 MVT VT =
N->getSimpleValueType(0);
493 SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::i32);
495 SDValue(CurDAG->getMachineNode(X86::MOV32r0, dl, VTs, {}), 0);
496 if (VT == MVT::i64) {
498 CurDAG->getMachineNode(
499 TargetOpcode::SUBREG_TO_REG, dl, MVT::i64, Zero,
500 CurDAG->getTargetConstant(X86::sub_32bit, dl, MVT::i32)),
505 unsigned Opcode =
N->getOpcode();
506 assert((Opcode == X86ISD::SBB || Opcode == X86ISD::SETCC_CARRY) &&
507 "Unexpected opcode for SBB materialization");
508 unsigned FlagOpIndex = Opcode == X86ISD::SBB ? 2 : 1;
510 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EFLAGS,
511 N->getOperand(FlagOpIndex),
SDValue());
515 unsigned Opc = VT == MVT::i64 ? X86::SBB64rr : X86::SBB32rr;
516 MVT SBBVT = VT == MVT::i64 ? MVT::i64 : MVT::i32;
517 VTs = CurDAG->getVTList(SBBVT, MVT::i32);
519 CurDAG->getMachineNode(
Opc, dl, VTs,
520 {Zero, Zero, EFLAGS, EFLAGS.getValue(1)}),
526 bool isUnneededShiftMask(SDNode *
N,
unsigned Width)
const {
528 const APInt &Val =
N->getConstantOperandAPInt(1);
533 APInt
Mask = Val | CurDAG->computeKnownBits(
N->getOperand(0)).Zero;
534 return Mask.countr_one() >= Width;
540 SDNode *getGlobalBaseReg();
544 const X86TargetMachine &getTargetMachine()
const {
545 return static_cast<const X86TargetMachine &
>(TM);
550 const X86InstrInfo *getInstrInfo()
const {
551 return Subtarget->getInstrInfo();
560 bool ComplexPatternFuncMutatesDAG()
const override {
564 bool isSExtAbsoluteSymbolRef(
unsigned Width, SDNode *
N)
const;
567 bool useNonTemporalLoad(LoadSDNode *
N)
const {
568 if (!
N->isNonTemporal())
571 unsigned StoreSize =
N->getMemoryVT().getStoreSize();
573 if (
N->getAlign().value() < StoreSize)
582 return Subtarget->hasSSE41();
584 return Subtarget->hasAVX2();
586 return Subtarget->hasAVX512();
590 bool foldLoadStoreIntoMemOperand(SDNode *Node);
591 MachineSDNode *matchBEXTRFromAndImm(SDNode *Node);
592 bool matchBitExtract(SDNode *Node);
593 bool shrinkAndImmediate(SDNode *
N);
594 bool isMaskZeroExtended(SDNode *
N)
const;
595 bool tryShiftAmountMod(SDNode *
N);
596 bool tryShrinkShlLogicImm(SDNode *
N);
597 bool tryVPTERNLOG(SDNode *
N);
598 bool matchVPTERNLOG(SDNode *Root, SDNode *ParentA, SDNode *ParentB,
602 bool tryMatchBitSelect(SDNode *
N);
604 MachineSDNode *emitPCMPISTR(
unsigned ROpc,
unsigned MOpc,
bool MayFoldLoad,
605 const SDLoc &dl, MVT VT, SDNode *Node);
606 MachineSDNode *emitPCMPESTR(
unsigned ROpc,
unsigned MOpc,
bool MayFoldLoad,
607 const SDLoc &dl, MVT VT, SDNode *Node,
610 bool tryOptimizeRem8Extend(SDNode *
N);
612 bool onlyUsesZeroFlag(
SDValue Flags)
const;
613 bool hasNoSignFlagUses(
SDValue Flags)
const;
614 bool hasNoCarryFlagUses(
SDValue Flags)
const;
615 bool checkTCRetEnoughRegs(SDNode *
N)
const;
621 explicit X86DAGToDAGISelLegacy(X86TargetMachine &tm,
623 : SelectionDAGISelLegacy(
624 ID, std::make_unique<X86DAGToDAGISel>(tm, OptLevel)) {}
628char X86DAGToDAGISelLegacy::ID = 0;
635 unsigned Opcode =
N->getOpcode();
636 if (Opcode == X86ISD::CMPM || Opcode == X86ISD::CMPMM ||
637 Opcode == X86ISD::STRICT_CMPM || Opcode ==
ISD::SETCC ||
638 Opcode == X86ISD::CMPMM_SAE || Opcode == X86ISD::VFPCLASS) {
642 EVT OpVT =
N->getOperand(0).getValueType();
645 if (Opcode == X86ISD::STRICT_CMPM)
646 OpVT =
N->getOperand(1).getValueType();
648 return Subtarget->hasVLX();
653 if (Opcode == X86ISD::VFPCLASSS || Opcode == X86ISD::FSETCCM ||
654 Opcode == X86ISD::FSETCCM_SAE)
662bool X86DAGToDAGISel::isMaskZeroExtended(
SDNode *
N)
const {
674X86DAGToDAGISel::IsProfitableToFold(
SDValue N, SDNode *U, SDNode *Root)
const {
675 if (OptLevel == CodeGenOptLevel::None)
690 switch (
U->getOpcode()) {
717 if (
Imm->getAPIntValue().isSignedIntN(8))
726 Imm->getAPIntValue().getBitWidth() == 64 &&
727 Imm->getAPIntValue().isIntN(32))
734 (
Imm->getAPIntValue() == UINT8_MAX ||
735 Imm->getAPIntValue() == UINT16_MAX ||
736 Imm->getAPIntValue() == UINT32_MAX))
742 (-
Imm->getAPIntValue()).isSignedIntN(8))
745 if ((
U->getOpcode() == X86ISD::ADD ||
U->getOpcode() == X86ISD::SUB) &&
746 (-
Imm->getAPIntValue()).isSignedIntN(8) &&
747 hasNoCarryFlagUses(
SDValue(U, 1)))
761 if (Op1.
getOpcode() == X86ISD::Wrapper) {
772 if (
U->getOperand(0).getOpcode() ==
ISD::SHL &&
776 if (
U->getOperand(1).getOpcode() ==
ISD::SHL &&
785 if (
C &&
C->getSExtValue() == -2)
791 if (
C &&
C->getSExtValue() == -2)
826bool X86DAGToDAGISel::isProfitableToFormMaskedOp(SDNode *
N)
const {
828 (
N->getOpcode() ==
ISD::VSELECT ||
N->getOpcode() == X86ISD::SELECTS) &&
829 "Unexpected opcode!");
834 return N->getOperand(1).hasOneUse();
844 Ops.push_back(
Load.getOperand(0));
847 "Unexpected chain operand");
850 Ops.push_back(
Load.getOperand(0));
856 Ops.push_back(NewChain);
861 Load.getOperand(1),
Load.getOperand(2));
879 if (Callee.getNode() == Chain.
getNode() || !Callee.hasOneUse())
891 if (!Callee.getValue(1).hasOneUse())
922 Callee.getValue(1).hasOneUse())
940 const unsigned NumBytes =
BitWidth / 8;
944 const uint8_t OptionalPrefixBytes[] = {0x26, 0x2e, 0x36, 0x3e, 0x64,
945 0x65, 0x66, 0x67, 0xf0, 0xf2};
947 for (
unsigned I = 0;
I != NumBytes; ++
I)
948 Bytes[
I] = (
Imm >> (
I * 8)) & 0xFF;
950 for (
unsigned I = 0;
I + 3 < NumBytes; ++
I) {
951 if (Bytes[
I] != 0xf3)
958 if (J + 2 < NumBytes && Bytes[J] == 0x0f && Bytes[J + 1] == 0x1e &&
959 (Bytes[J + 2] == 0xfa || Bytes[J + 2] == 0xfb))
967 return (VT == MVT::v32i16 || VT == MVT::v32f16 || VT == MVT::v64i8);
970void X86DAGToDAGISel::PreprocessISelDAG() {
971 bool MadeChange =
false;
973 E = CurDAG->allnodes_end();
I !=
E; ) {
991 MVT VT =
N->getSimpleValueType(0);
993 "ISD::Constant must have a scalar integer type");
1002 "cf-protection-branch");
1008 CurDAG->getConstant(ComplementImm, dl, VT,
false,
true);
1009 Complement = CurDAG->getNOT(dl, Complement, VT);
1011 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Complement);
1021 if (
N->getOpcode() == X86ISD::AND && !
N->hasAnyUseOfValue(1)) {
1023 N->getOperand(0),
N->getOperand(1));
1025 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1049 auto mayPreventLoadFold = [&]() {
1051 N->getOpcode() ==
ISD::ADD && Subtarget->hasAVX() &&
1052 !
N->getOperand(1).hasOneUse();
1055 N->getSimpleValueType(0).isVector() && !mayPreventLoadFold()) {
1063 MVT VT =
N->getSimpleValueType(0);
1071 CurDAG->getNode(NewOpcode,
DL, VT,
N->getOperand(0),
AllOnes);
1073 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1080 switch (
N->getOpcode()) {
1081 case X86ISD::VBROADCAST: {
1082 MVT VT =
N->getSimpleValueType(0);
1084 if (!Subtarget->hasBWI() &&
needBWI(VT)) {
1088 CurDAG->getNode(X86ISD::VBROADCAST, dl, NarrowVT,
N->getOperand(0));
1091 NarrowBCast, CurDAG->getIntPtrConstant(0, dl));
1094 CurDAG->getIntPtrConstant(Index, dl));
1097 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1105 case X86ISD::VBROADCAST_LOAD: {
1106 MVT VT =
N->getSimpleValueType(0);
1108 if (!Subtarget->hasBWI() &&
needBWI(VT)) {
1112 SDVTList VTs = CurDAG->getVTList(NarrowVT, MVT::Other);
1113 SDValue Ops[] = {MemNode->getChain(), MemNode->getBasePtr()};
1114 SDValue NarrowBCast = CurDAG->getMemIntrinsicNode(
1115 X86ISD::VBROADCAST_LOAD, dl, VTs,
Ops, MemNode->getMemoryVT(),
1116 MemNode->getMemOperand());
1119 NarrowBCast, CurDAG->getIntPtrConstant(0, dl));
1122 CurDAG->getIntPtrConstant(Index, dl));
1126 CurDAG->ReplaceAllUsesWith(
N, To);
1138 MVT VT =
N->getSimpleValueType(0);
1144 SDNode *MaxLd =
nullptr;
1145 SDValue Ptr = Ld->getBasePtr();
1146 SDValue Chain = Ld->getChain();
1147 for (SDNode *User : Ptr->
users()) {
1149 MVT UserVT =
User->getSimpleValueType(0);
1151 UserLd->getBasePtr() == Ptr && UserLd->getChain() == Chain &&
1152 !
User->hasAnyUseOfValue(1) &&
1166 CurDAG->getIntPtrConstant(0, dl));
1167 SDValue Res = CurDAG->getBitcast(VT, Extract);
1171 CurDAG->ReplaceAllUsesWith(
N, To);
1180 EVT EleVT =
N->getOperand(0).getValueType().getVectorElementType();
1181 if (EleVT == MVT::i1)
1184 assert(Subtarget->hasSSE41() &&
"Expected SSE4.1 support!");
1185 assert(
N->getValueType(0).getVectorElementType() != MVT::i16 &&
1186 "We can't replace VSELECT with BLENDV in vXi16!");
1188 if (Subtarget->hasVLX() && CurDAG->ComputeNumSignBits(
N->getOperand(0)) ==
1190 R = CurDAG->getNode(X86ISD::VPTERNLOG, SDLoc(
N),
N->getValueType(0),
1191 N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
1192 CurDAG->getTargetConstant(0xCA, SDLoc(
N), MVT::i8));
1194 R = CurDAG->getNode(X86ISD::BLENDV, SDLoc(
N),
N->getValueType(0),
1195 N->getOperand(0),
N->getOperand(1),
1199 CurDAG->ReplaceAllUsesWith(
N,
R.getNode());
1212 if (!
N->getSimpleValueType(0).isVector())
1216 switch (
N->getOpcode()) {
1226 if (
N->isStrictFPOpcode())
1228 CurDAG->getNode(NewOpc, SDLoc(
N), {
N->getValueType(0), MVT::Other},
1229 {
N->getOperand(0),
N->getOperand(1)});
1232 CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1235 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1245 if (!
N->getValueType(0).isVector())
1249 switch (
N->getOpcode()) {
1251 case ISD::SHL: NewOpc = X86ISD::VSHLV;
break;
1252 case ISD::SRA: NewOpc = X86ISD::VSRAV;
break;
1253 case ISD::SRL: NewOpc = X86ISD::VSRLV;
break;
1255 SDValue Res = CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1256 N->getOperand(0),
N->getOperand(1));
1258 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1267 if (!
N->getValueType(0).isVector())
1271 if (
N->getOperand(0).getScalarValueSizeInBits() == 1) {
1273 "Unexpected opcode for mask vector!");
1281 SDValue Res = CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1284 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1304 switch (
N->getOpcode()) {
1320 bool IsStrict =
N->isStrictFPOpcode();
1323 Res = CurDAG->getNode(X86ISD::STRICT_VRNDSCALE, dl,
1324 {
N->getValueType(0), MVT::Other},
1325 {
N->getOperand(0),
N->getOperand(1),
1326 CurDAG->getTargetConstant(
Imm, dl, MVT::i32)});
1328 Res = CurDAG->getNode(X86ISD::VRNDSCALE, dl,
N->getValueType(0),
1330 CurDAG->getTargetConstant(
Imm, dl, MVT::i32));
1332 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1340 case X86ISD::FXOR: {
1343 MVT VT =
N->getSimpleValueType(0);
1344 if (VT.
isVector() || VT == MVT::f128)
1347 MVT VecVT = VT == MVT::f64 ? MVT::v2f64
1348 : VT == MVT::f32 ? MVT::v4f32
1358 if (Subtarget->hasSSE2()) {
1359 EVT IntVT = EVT(VecVT).changeVectorElementTypeToInteger();
1363 switch (
N->getOpcode()) {
1365 case X86ISD::FANDN:
Opc = X86ISD::ANDNP;
break;
1370 Res = CurDAG->getNode(
Opc, dl, IntVT, Op0, Op1);
1373 Res = CurDAG->getNode(
N->getOpcode(), dl, VecVT, Op0, Op1);
1376 CurDAG->getIntPtrConstant(0, dl));
1378 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1385 if (OptLevel != CodeGenOptLevel::None &&
1388 !Subtarget->useIndirectThunkCalls() &&
1389 ((
N->getOpcode() == X86ISD::CALL && !Subtarget->slowTwoMemOps() &&
1390 !Subtarget->slowIndirectCall()) ||
1391 (
N->getOpcode() == X86ISD::TC_RETURN &&
1392 (Subtarget->is64Bit() ||
1393 !getTargetMachine().isPositionIndependent())))) {
1413 bool HasCallSeq =
N->getOpcode() == X86ISD::CALL;
1418 if (
N->getOpcode() == X86ISD::TC_RETURN && !checkTCRetEnoughRegs(
N))
1434 switch (
N->getOpcode()) {
1439 MVT SrcVT =
N->getOperand(0).getSimpleValueType();
1440 MVT DstVT =
N->getSimpleValueType(0);
1448 const X86TargetLowering *X86Lowering =
1449 static_cast<const X86TargetLowering *
>(TLI);
1452 if (SrcIsSSE && DstIsSSE)
1455 if (!SrcIsSSE && !DstIsSSE) {
1460 if (
N->getConstantOperandVal(1))
1468 SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
1470 MachinePointerInfo MPI =
1477 CurDAG->getEntryNode(), dl,
N->getOperand(0), MemTmp, MPI, MemVT);
1479 MemTmp, MPI, MemVT);
1486 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Result);
1495 MVT SrcVT =
N->getOperand(1).getSimpleValueType();
1496 MVT DstVT =
N->getSimpleValueType(0);
1504 const X86TargetLowering *X86Lowering =
1505 static_cast<const X86TargetLowering *
>(TLI);
1508 if (SrcIsSSE && DstIsSSE)
1511 if (!SrcIsSSE && !DstIsSSE) {
1516 if (
N->getConstantOperandVal(2))
1524 SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
1526 MachinePointerInfo MPI =
1535 SDVTList VTs = CurDAG->getVTList(MVT::Other);
1536 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), MemTmp};
1537 Store = CurDAG->getMemIntrinsicNode(X86ISD::FST, dl, VTs,
Ops, MemVT,
1540 if (
N->getFlags().hasNoFPExcept()) {
1542 Flags.setNoFPExcept(
true);
1543 Store->setFlags(Flags);
1546 assert(SrcVT == MemVT &&
"Unexpected VT!");
1547 Store = CurDAG->getStore(
N->getOperand(0), dl,
N->getOperand(1), MemTmp,
1552 SDVTList VTs = CurDAG->getVTList(DstVT, MVT::Other);
1554 Result = CurDAG->getMemIntrinsicNode(
1555 X86ISD::FLD, dl, VTs,
Ops, MemVT, MPI,
1557 if (
N->getFlags().hasNoFPExcept()) {
1559 Flags.setNoFPExcept(
true);
1563 assert(DstVT == MemVT &&
"Unexpected VT!");
1564 Result = CurDAG->getLoad(DstVT, dl,
Store, MemTmp, MPI);
1572 CurDAG->ReplaceAllUsesWith(
N,
Result.getNode());
1586 CurDAG->RemoveDeadNodes();
1590bool X86DAGToDAGISel::tryOptimizeRem8Extend(SDNode *
N) {
1591 unsigned Opc =
N->getMachineOpcode();
1592 if (
Opc != X86::MOVZX32rr8 &&
Opc != X86::MOVSX32rr8 &&
1593 Opc != X86::MOVSX64rr8)
1605 unsigned ExpectedOpc =
Opc == X86::MOVZX32rr8 ? X86::MOVZX32rr8_NOREX
1606 : X86::MOVSX32rr8_NOREX;
1611 if (
Opc == X86::MOVSX64rr8) {
1614 MachineSDNode *Extend = CurDAG->getMachineNode(X86::MOVSX64rr32, SDLoc(
N),
1616 ReplaceUses(
N, Extend);
1625void X86DAGToDAGISel::PostprocessISelDAG() {
1627 if (TM.getOptLevel() == CodeGenOptLevel::None)
1632 bool MadeChange =
false;
1633 while (Position != CurDAG->allnodes_begin()) {
1634 SDNode *
N = &*--Position;
1636 if (
N->use_empty() || !
N->isMachineOpcode())
1639 if (tryOptimizeRem8Extend(
N)) {
1644 unsigned Opc =
N->getMachineOpcode();
1655 case X86::CTEST16rr:
1656 case X86::CTEST32rr:
1657 case X86::CTEST64rr: {
1663#define CASE_ND(OP) \
1666 switch (
And.getMachineOpcode()) {
1673 if (
And->hasAnyUseOfValue(1))
1676 Ops[0] =
And.getOperand(0);
1677 Ops[1] =
And.getOperand(1);
1678 MachineSDNode *
Test =
1679 CurDAG->getMachineNode(
Opc, SDLoc(
N), MVT::i32,
Ops);
1680 ReplaceUses(
N,
Test);
1688 if (
And->hasAnyUseOfValue(1))
1691 bool IsCTESTCC = X86::isCTESTCC(
Opc);
1692#define FROM_TO(A, B) \
1693 CASE_ND(A) NewOpc = IsCTESTCC ? X86::C##B : X86::B; \
1695 switch (
And.getMachineOpcode()) {
1705 And.getOperand(3),
And.getOperand(4),
1706 And.getOperand(5),
And.getOperand(0)};
1709 Ops.push_back(
N->getOperand(2));
1710 Ops.push_back(
N->getOperand(3));
1713 Ops.push_back(
And.getOperand(6));
1716 Ops.push_back(
N->getOperand(4));
1718 MachineSDNode *
Test = CurDAG->getMachineNode(
1719 NewOpc, SDLoc(
N), MVT::i32, MVT::Other,
Ops);
1720 CurDAG->setNodeMemRefs(
1733 case X86::KORTESTBkk:
1734 case X86::KORTESTWkk:
1735 case X86::KORTESTDkk:
1736 case X86::KORTESTQkk: {
1738 if (Op0 !=
N->getOperand(1) || !
N->isOnlyUserOf(Op0.
getNode()) ||
1753#define FROM_TO(A, B) \
1765 if (NewOpc == X86::KTESTWkk && !Subtarget->hasDQI())
1768 MachineSDNode *KTest = CurDAG->getMachineNode(
1770 ReplaceUses(
N, KTest);
1775 case TargetOpcode::SUBREG_TO_REG: {
1776 unsigned SubRegIdx =
N->getConstantOperandVal(1);
1777 if (SubRegIdx != X86::sub_xmm && SubRegIdx != X86::sub_ymm)
1794 CASE(VMOVAPDZ128rr)
CASE(VMOVUPDZ128rr)
1795 CASE(VMOVAPSZ128rr)
CASE(VMOVUPSZ128rr)
1796 CASE(VMOVDQA32Z128rr)
CASE(VMOVDQU32Z128rr)
1797 CASE(VMOVDQA64Z128rr)
CASE(VMOVDQU64Z128rr)
1798 CASE(VMOVAPDZ256rr)
CASE(VMOVUPDZ256rr)
1799 CASE(VMOVAPSZ256rr)
CASE(VMOVUPSZ256rr)
1800 CASE(VMOVDQA32Z256rr)
CASE(VMOVDQU32Z256rr)
1801 CASE(VMOVDQA64Z256rr)
CASE(VMOVDQU64Z256rr)
1806 if (!
In.isMachineOpcode() ||
1807 In.getMachineOpcode() <= TargetOpcode::GENERIC_OP_END)
1812 uint64_t TSFlags = getInstrInfo()->get(
In.getMachineOpcode()).TSFlags;
1820 CurDAG->UpdateNodeOperands(
N, In,
N->getOperand(1));
1827 CurDAG->RemoveDeadNodes();
1832void X86DAGToDAGISel::emitSpecialCodeForMain() {
1833 if (Subtarget->isTargetCygMing()) {
1834 TargetLowering::ArgListTy
Args;
1835 auto &
DL = CurDAG->getDataLayout();
1837 TargetLowering::CallLoweringInfo CLI(*CurDAG);
1838 CLI.setChain(CurDAG->getRoot())
1839 .setCallee(CallingConv::C, Type::getVoidTy(*CurDAG->getContext()),
1840 CurDAG->getExternalSymbol(
"__main", TLI->getPointerTy(
DL)),
1842 const TargetLowering &TLI = CurDAG->getTargetLoweringInfo();
1844 CurDAG->setRoot(
Result.second);
1848void X86DAGToDAGISel::emitFunctionEntryCode() {
1851 if (
F.hasExternalLinkage() &&
F.getName() ==
"main")
1852 emitSpecialCodeForMain();
1866 X86ISelAddressMode &AM) {
1871 int64_t Val = AM.Disp +
Offset;
1874 if (Val != 0 && (AM.ES || AM.MCSym))
1878 if (Subtarget->is64Bit()) {
1881 AM.hasSymbolicDisplacement()))
1885 if (AM.BaseType == X86ISelAddressMode::FrameIndexBase &&
1904 if (Subtarget->isTarget64BitILP32() &&
1906 !AM.hasBaseOrIndexReg())
1908 }
else if (Subtarget->is16Bit()) {
1911 if (Val < -(int64_t)UINT16_MAX || Val > (int64_t)UINT16_MAX)
1921bool X86DAGToDAGISel::matchLoadInAddress(LoadSDNode *
N, X86ISelAddressMode &AM,
1922 bool AllowSegmentRegForX32) {
1935 !IndirectTlsSegRefs &&
1936 (Subtarget->isTargetGlibc() || Subtarget->isTargetMusl() ||
1937 Subtarget->isTargetAndroid() || Subtarget->isTargetFuchsia())) {
1938 if (Subtarget->isTarget64BitILP32() && !AllowSegmentRegForX32)
1940 switch (
N->getPointerInfo().getAddrSpace()) {
1942 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
1945 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
1958bool X86DAGToDAGISel::matchWrapper(
SDValue N, X86ISelAddressMode &AM) {
1961 if (AM.hasSymbolicDisplacement())
1964 bool IsRIPRelTLS =
false;
1965 bool IsRIPRel =
N.getOpcode() == X86ISD::WrapperRIP;
1982 if (IsRIPRel && AM.hasBaseOrIndexReg())
1986 X86ISelAddressMode Backup = AM;
1991 AM.GV =
G->getGlobal();
1992 AM.SymbolFlags =
G->getTargetFlags();
1995 AM.CP = CP->getConstVal();
1996 AM.Alignment = CP->getAlign();
1997 AM.SymbolFlags = CP->getTargetFlags();
1998 Offset = CP->getOffset();
2000 AM.ES = S->getSymbol();
2001 AM.SymbolFlags = S->getTargetFlags();
2003 AM.MCSym = S->getMCSymbol();
2005 AM.JT = J->getIndex();
2006 AM.SymbolFlags = J->getTargetFlags();
2008 AM.BlockAddr = BA->getBlockAddress();
2009 AM.SymbolFlags = BA->getTargetFlags();
2010 Offset = BA->getOffset();
2015 if (Subtarget->is64Bit() && !IsRIPRel && AM.GV &&
2016 TM.isLargeGlobalValue(AM.GV)) {
2021 if (foldOffsetIntoAddress(
Offset, AM)) {
2027 AM.setBaseReg(CurDAG->getRegister(X86::RIP, MVT::i64));
2035bool X86DAGToDAGISel::matchAddress(
SDValue N, X86ISelAddressMode &AM) {
2036 if (matchAddressRecursively(
N, AM, 0))
2043 if (Subtarget->isTarget64BitILP32() &&
2044 AM.BaseType == X86ISelAddressMode::RegBase &&
2045 AM.Base_Reg.
getNode() !=
nullptr && AM.IndexReg.
getNode() ==
nullptr) {
2046 SDValue Save_Base_Reg = AM.Base_Reg;
2049 if (matchLoadInAddress(LoadN, AM,
true))
2050 AM.Base_Reg = Save_Base_Reg;
2059 if (AM.Scale == 2 && !AM.NegateIndex &&
2060 AM.BaseType == X86ISelAddressMode::RegBase &&
2061 AM.Base_Reg.
getNode() ==
nullptr) {
2062 AM.Base_Reg = AM.IndexReg;
2069 (!AM.GV || !TM.isLargeGlobalValue(AM.GV)) && Subtarget->is64Bit() &&
2070 AM.Scale == 1 && AM.BaseType == X86ISelAddressMode::RegBase &&
2071 AM.Base_Reg.
getNode() ==
nullptr && AM.IndexReg.
getNode() ==
nullptr &&
2083 AM.Base_Reg = CurDAG->getRegister(X86::RIP, MVT::i64);
2096bool X86DAGToDAGISel::hasMaterializingUse(
SDValue V)
const {
2097 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
2098 for (SDUse &U :
V->uses()) {
2099 if (
U.getResNo() !=
V.getResNo())
2101 SDNode *
User =
U.getUser();
2107 if (St->getValue() == V)
2118 if (!
User->isMachineOpcode())
2120 const MCInstrDesc &
Desc =
TII->get(
User->getMachineOpcode());
2121 if (!
Desc.mayStore())
2124 if (MemRefBegin < 0)
2127 for (
unsigned I = 0,
E =
User->getNumOperands();
I !=
E; ++
I) {
2128 if (
I >=
static_cast<unsigned>(MemRefBegin) &&
I < MemRefEnd)
2140bool X86DAGToDAGISel::matchAdd(
SDValue &
N, X86ISelAddressMode &AM,
2144 HandleSDNode Handle(
N);
2146 auto IsAddOrAddLike = [&](
SDValue V) {
2147 return V.getOpcode() ==
ISD::ADD || CurDAG->isADDLike(V);
2156 auto SplitsMaterializedValue = [&](
SDValue Op) {
2157 if (!AM.IsForLEA || !hasMaterializingUse(
Op))
2161 if (IsAddOrAddLike(
Op))
2162 return IsAddOrAddLike(
Op.getOperand(0)) ||
2163 IsAddOrAddLike(
Op.getOperand(1));
2168 return C->getZExtValue() >= 1 &&
C->getZExtValue() <= 3 &&
2169 IsAddOrAddLike(
Op.getOperand(0));
2189 if (SplitsMaterializedValue(
Op) && !AM.isRIPRelative())
2190 return matchAddressBase(
Op, AM);
2191 return matchAddressRecursively(
Op, AM,
Depth + 1);
2194 X86ISelAddressMode Backup = AM;
2195 if (!MatchOperand(
N.getOperand(0)) &&
2196 !MatchOperand(Handle.getValue().getOperand(1)))
2201 if (!MatchOperand(Handle.getValue().getOperand(1)) &&
2202 !MatchOperand(Handle.getValue().getOperand(0)))
2209 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2212 N = Handle.getValue();
2218 N = Handle.getValue();
2228 if (
N->getNodeId() == -1 ||
2248 X86ISelAddressMode &AM) {
2255 if (ScaleLog <= 0 || ScaleLog >= 4 ||
2256 Mask != (0xffu << ScaleLog))
2259 MVT XVT =
X.getSimpleValueType();
2260 MVT VT =
N.getSimpleValueType();
2285 AM.Scale = (1 << ScaleLog);
2293 X86ISelAddressMode &AM) {
2304 bool FoundAnyExtend =
false;
2308 FoundAnyExtend =
true;
2326 if (ShiftAmt != 1 && ShiftAmt != 2 && ShiftAmt != 3)
2329 MVT VT =
N.getSimpleValueType();
2331 if (FoundAnyExtend) {
2352 AM.Scale = 1 << ShiftAmt;
2353 AM.IndexReg = NewAnd;
2387 X86ISelAddressMode &AM) {
2393 unsigned MaskIdx, MaskLen;
2396 unsigned MaskLZ = 64 - (MaskIdx + MaskLen);
2402 unsigned AMShiftAmt = MaskIdx;
2406 if (AMShiftAmt == 0 || AMShiftAmt > 3)
return true;
2410 unsigned ScaleDown = (64 -
X.getSimpleValueType().getSizeInBits()) + ShiftAmt;
2411 if (MaskLZ < ScaleDown)
2413 MaskLZ -= ScaleDown;
2421 bool ReplacingAnyExtend =
false;
2423 unsigned ExtendBits =
X.getSimpleValueType().getSizeInBits() -
2424 X.getOperand(0).getSimpleValueType().getSizeInBits();
2427 X =
X.getOperand(0);
2428 MaskLZ = ExtendBits > MaskLZ ? 0 : MaskLZ - ExtendBits;
2429 ReplacingAnyExtend =
true;
2431 APInt MaskedHighBits =
2438 MVT VT =
N.getSimpleValueType();
2439 if (ReplacingAnyExtend) {
2440 assert(
X.getValueType() != VT);
2447 MVT XVT =
X.getSimpleValueType();
2468 AM.Scale = 1 << AMShiftAmt;
2469 AM.IndexReg = NewExt;
2479 X86ISelAddressMode &AM,
2487 if (!Subtarget.hasTBM() &&
2488 !(Subtarget.hasBMI() && Subtarget.hasFastBEXTR()))
2492 unsigned MaskIdx, MaskLen;
2500 unsigned AMShiftAmt = MaskIdx;
2504 if (AMShiftAmt == 0 || AMShiftAmt > 3)
return true;
2506 MVT XVT =
X.getSimpleValueType();
2507 MVT VT =
N.getSimpleValueType();
2532 AM.Scale = 1 << AMShiftAmt;
2533 AM.IndexReg = NewExt;
2540 X86ISelAddressMode &AM,
2542 assert(AM.IndexReg.
getNode() ==
nullptr &&
"IndexReg already matched");
2543 assert((AM.Scale == 1 || AM.Scale == 2 || AM.Scale == 4 || AM.Scale == 8) &&
2544 "Illegal index scale");
2550 EVT VT =
N.getValueType();
2551 unsigned Opc =
N.getOpcode();
2554 if (CurDAG->isBaseWithConstantOffset(
N)) {
2557 if (!foldOffsetIntoAddress(
Offset, AM))
2558 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2562 if (
Opc ==
ISD::ADD &&
N.getOperand(0) ==
N.getOperand(1)) {
2563 if (AM.Scale <= 4) {
2565 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2570 if (
Opc == X86ISD::VSHLI) {
2571 uint64_t ShiftAmt =
N.getConstantOperandVal(1);
2572 uint64_t ScaleAmt = 1ULL << ShiftAmt;
2573 if ((AM.Scale * ScaleAmt) <= 8) {
2574 AM.Scale *= ScaleAmt;
2575 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2583 if (Src.getOpcode() ==
ISD::ADD && Src->getFlags().hasNoSignedWrap() &&
2585 if (CurDAG->isBaseWithConstantOffset(Src)) {
2586 SDValue AddSrc = Src.getOperand(0);
2588 int64_t
Offset = AddVal->getSExtValue();
2597 CurDAG->ReplaceAllUsesWith(
N, ExtAdd);
2598 CurDAG->RemoveDeadNode(
N.getNode());
2610 unsigned SrcOpc = Src.getOpcode();
2611 if (((SrcOpc ==
ISD::ADD && Src->getFlags().hasNoUnsignedWrap()) ||
2612 CurDAG->isADDLike(Src,
true)) &&
2614 if (CurDAG->isBaseWithConstantOffset(Src)) {
2615 SDValue AddSrc = Src.getOperand(0);
2617 if (!foldOffsetIntoAddress(
Offset * AM.Scale, AM)) {
2628 if ((AM.Scale * ScaleAmt) <= 8 &&
2630 CurDAG->MaskedValueIsZero(ShVal, HiBits))) {
2631 AM.Scale *= ScaleAmt;
2632 SDValue ExtShVal = CurDAG->getNode(
Opc,
DL, VT, ShVal);
2643 SDValue ExtAdd = CurDAG->getNode(SrcOpc,
DL, VT, ExtSrc, ExtVal);
2647 CurDAG->ReplaceAllUsesWith(
N, ExtAdd);
2648 CurDAG->RemoveDeadNode(
N.getNode());
2649 return Res ? Res : ExtSrc;
2659bool X86DAGToDAGISel::matchAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
2662 dbgs() <<
"MatchAddress: ";
2667 return matchAddressBase(
N, AM);
2672 if (AM.isRIPRelative()) {
2676 if (!(AM.ES || AM.MCSym) && AM.JT != -1)
2680 if (!foldOffsetIntoAddress(Cst->getSExtValue(), AM))
2685 switch (
N.getOpcode()) {
2688 if (!AM.hasSymbolicDisplacement() && AM.Disp == 0)
2691 AM.MCSym = ESNode->getMCSymbol();
2698 if (!foldOffsetIntoAddress(Val, AM))
2703 case X86ISD::Wrapper:
2704 case X86ISD::WrapperRIP:
2705 if (!matchWrapper(
N, AM))
2715 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2716 AM.Base_Reg.
getNode() ==
nullptr &&
2718 AM.BaseType = X86ISelAddressMode::FrameIndexBase;
2725 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
2729 unsigned Val = CN->getZExtValue();
2734 if (Val == 1 || Val == 2 || Val == 3) {
2736 AM.Scale = 1 << Val;
2737 AM.IndexReg = matchIndexRecursively(ShVal, AM,
Depth + 1);
2745 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
break;
2749 assert(
N.getSimpleValueType().getSizeInBits() <= 64 &&
2750 "Unexpected value size!");
2762 uint64_t Mask =
And.getConstantOperandVal(1) >>
N.getConstantOperandVal(1);
2774 if (
N.getResNo() != 0)
break;
2777 case X86ISD::MUL_IMM:
2779 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2780 AM.Base_Reg.
getNode() ==
nullptr &&
2781 AM.IndexReg.
getNode() ==
nullptr) {
2783 if (CN->getZExtValue() == 3 || CN->getZExtValue() == 5 ||
2784 CN->getZExtValue() == 9) {
2785 AM.Scale = unsigned(CN->getZExtValue())-1;
2797 uint64_t Disp = AddVal->getSExtValue() * CN->getZExtValue();
2798 if (foldOffsetIntoAddress(Disp, AM))
2799 Reg =
N.getOperand(0);
2801 Reg =
N.getOperand(0);
2804 AM.IndexReg = AM.Base_Reg =
Reg;
2822 HandleSDNode Handle(
N);
2825 X86ISelAddressMode Backup = AM;
2826 if (matchAddressRecursively(
N.getOperand(0), AM,
Depth+1)) {
2827 N = Handle.getValue();
2831 N = Handle.getValue();
2833 if (AM.IndexReg.
getNode() || AM.isRIPRelative()) {
2852 std::optional<unsigned> NegScale;
2855 uint64_t ShVal = ShAmt->getZExtValue();
2856 if (ShVal >= 1 && ShVal <= 3) {
2857 NegScale = 1u << ShVal;
2875 RHS.getOperand(0).getValueType() == MVT::i32))
2878 bool BaseIsNegatedValue = NegScale &&
2879 AM.BaseType == X86ISelAddressMode::RegBase &&
2886 if (((AM.BaseType == X86ISelAddressMode::RegBase && AM.Base_Reg.
getNode() &&
2888 AM.BaseType == X86ISelAddressMode::FrameIndexBase) &&
2889 !BaseIsNegatedValue)
2893 if ((AM.hasSymbolicDisplacement() && !Backup.hasSymbolicDisplacement()) +
2894 ((AM.Disp != 0) && (Backup.Disp == 0)) +
2907 AM.NegateIndex =
true;
2908 AM.Scale = NegScale.value_or(1);
2915 if (!CurDAG->isADDLike(
N))
2919 if (!matchAdd(
N, AM,
Depth))
2928 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
break;
2932 assert(
N.getSimpleValueType().getSizeInBits() <= 64 &&
2933 "Unexpected value size!");
2938 if (
N.getOperand(0).getOpcode() ==
ISD::SRL) {
2967 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
2975 if (
SDValue Index = matchIndexRecursively(
N, AM,
Depth + 1))
2977 AM.IndexReg =
Index;
2983 if (Src.getOpcode() ==
ISD::AND && Src.hasOneUse())
2985 Mask = MaskC->getAPIntValue();
2986 Src = Src.getOperand(0);
2989 if (Src.getOpcode() ==
ISD::SHL && Src.hasOneUse() &&
N->hasOneUse()) {
2991 SDValue ShlSrc = Src.getOperand(0);
2992 SDValue ShlAmt = Src.getOperand(1);
2996 unsigned ShAmtV = ShAmtC->getZExtValue();
3004 if (!Src->getFlags().hasNoUnsignedWrap() &&
3005 !CurDAG->MaskedValueIsZero(ShlSrc, HighZeros & Mask))
3013 MVT VT =
N.getSimpleValueType();
3017 if (!
Mask.isAllOnes()) {
3018 Res = CurDAG->getConstant(
Mask.lshr(ShAmtV),
DL, SrcVT);
3020 Res = CurDAG->getNode(
ISD::AND,
DL, SrcVT, ShlSrc, Res);
3027 CurDAG->ReplaceAllUsesWith(
N, NewShl);
3028 CurDAG->RemoveDeadNode(
N.getNode());
3031 AM.Scale = 1 << ShAmtV;
3035 AM.IndexReg = matchIndexRecursively(Zext, AM,
Depth + 1);
3039 if (Src.getOpcode() ==
ISD::SRL && !
Mask.isAllOnes()) {
3042 Src.getOperand(0), AM))
3047 Src.getOperand(0), AM))
3052 Src.getOperand(0), AM, *Subtarget))
3060 return matchAddressBase(
N, AM);
3065bool X86DAGToDAGISel::matchAddressBase(
SDValue N, X86ISelAddressMode &AM) {
3067 if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base_Reg.
getNode()) {
3080 AM.BaseType = X86ISelAddressMode::RegBase;
3085bool X86DAGToDAGISel::matchVectorAddressRecursively(
SDValue N,
3086 X86ISelAddressMode &AM,
3089 dbgs() <<
"MatchVectorAddress: ";
3094 return matchAddressBase(
N, AM);
3097 switch (
N.getOpcode()) {
3100 if (!foldOffsetIntoAddress(Val, AM))
3104 case X86ISD::Wrapper:
3105 if (!matchWrapper(
N, AM))
3111 HandleSDNode Handle(
N);
3113 X86ISelAddressMode Backup = AM;
3114 if (!matchVectorAddressRecursively(
N.getOperand(0), AM,
Depth + 1) &&
3115 !matchVectorAddressRecursively(Handle.getValue().getOperand(1), AM,
3121 if (!matchVectorAddressRecursively(Handle.getValue().getOperand(1), AM,
3123 !matchVectorAddressRecursively(Handle.getValue().getOperand(0), AM,
3128 N = Handle.getValue();
3133 return matchAddressBase(
N, AM);
3139bool X86DAGToDAGISel::matchVectorAddress(
SDValue N, X86ISelAddressMode &AM) {
3140 return matchVectorAddressRecursively(
N, AM, 0);
3143bool X86DAGToDAGISel::selectVectorAddr(MemSDNode *Parent,
SDValue BasePtr,
3148 X86ISelAddressMode AM;
3154 AM.IndexReg = matchIndexRecursively(IndexOp, AM, 0);
3156 AM.IndexReg = IndexOp;
3160 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
3162 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
3164 AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16);
3167 MVT VT =
BasePtr.getSimpleValueType();
3170 if (matchVectorAddress(BasePtr, AM))
3173 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3186 SDValue &Segment,
bool HasNDDM) {
3187 X86ISelAddressMode AM;
3194 Parent->
getOpcode() != X86ISD::TLSCALL &&
3195 Parent->
getOpcode() != X86ISD::ENQCMD &&
3196 Parent->
getOpcode() != X86ISD::ENQCMDS &&
3197 Parent->
getOpcode() != X86ISD::EH_SJLJ_SETJMP &&
3198 Parent->
getOpcode() != X86ISD::EH_SJLJ_LONGJMP) {
3199 unsigned AddrSpace =
3202 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
3204 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
3206 AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16);
3211 MVT VT =
N.getSimpleValueType();
3213 if (matchAddress(
N, AM))
3216 if (!HasNDDM && !AM.isRIPRelative())
3219 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3226 return selectAddr(Parent,
N,
Base, Scale, Index, Disp, Segment,
3227 Subtarget->hasNDDM());
3239 if (
N->getOpcode() != X86ISD::Wrapper)
3242 N =
N.getOperand(0);
3259 return CR->getUnsignedMax().ult(1ull << 32);
3261 return !TM.isLargeGlobalValue(GV);
3270 if (!selectLEAAddr(
N,
Base, Scale, Index, Disp, Segment))
3276 SubReg = X86::sub_8bit;
3278 SubReg = X86::sub_16bit;
3280 SubReg = X86::sub_32bit;
3283 if (RN &&
RN->getReg() == 0)
3284 Base = CurDAG->getRegister(0, MVT::i64);
3291 Base = CurDAG->getTargetInsertSubreg(SubReg,
DL, MVT::i64, ImplDef,
Base);
3294 [[maybe_unused]] EVT IndexType =
Index.getValueType();
3296 if (RN &&
RN->getReg() == 0)
3297 Index = CurDAG->getRegister(0, MVT::i64);
3300 "Expect to be extending 8/16/32-bit registers for use in LEA");
3303 Index = CurDAG->getTargetInsertSubreg(SubReg,
DL, MVT::i64, ImplDef, Index);
3311bool X86DAGToDAGISel::selectLEAAddr(
SDValue N,
3315 X86ISelAddressMode AM;
3320 MVT VT =
N.getSimpleValueType();
3325 SDValue T = CurDAG->getRegister(0, MVT::i32);
3327 if (matchAddress(
N, AM))
3332 unsigned Complexity = 0;
3333 if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base_Reg.
getNode())
3335 else if (AM.BaseType == X86ISelAddressMode::FrameIndexBase)
3351 if (AM.hasSymbolicDisplacement()) {
3353 if (Subtarget->is64Bit())
3363 auto isMathWithFlags = [](
SDValue V) {
3364 switch (
V.getOpcode()) {
3378 return !
SDValue(
V.getNode(), 1).use_empty();
3385 if (isMathWithFlags(
N.getOperand(0)) || isMathWithFlags(
N.getOperand(1)))
3393 if (Complexity <= 2)
3396 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3407 X86ISelAddressMode AM;
3409 AM.GV = GA->getGlobal();
3410 AM.Disp += GA->getOffset();
3411 AM.SymbolFlags = GA->getTargetFlags();
3414 AM.ES = SA->getSymbol();
3415 AM.SymbolFlags = SA->getTargetFlags();
3418 if (Subtarget->is32Bit()) {
3420 AM.IndexReg = CurDAG->getRegister(X86::EBX, MVT::i32);
3423 MVT VT =
N.getSimpleValueType();
3424 getAddressOperands(AM, SDLoc(
N), VT,
Base, Scale, Index, Disp, Segment);
3432 EVT VT =
N.getValueType();
3433 bool WasTruncated =
false;
3435 WasTruncated =
true;
3436 N =
N.getOperand(0);
3439 if (
N.getOpcode() != X86ISD::Wrapper)
3445 unsigned Opc =
N.getOperand(0)->getOpcode();
3447 Op =
N.getOperand(0);
3450 return !WasTruncated;
3455 std::optional<ConstantRange> CR = GA->getGlobal()->getAbsoluteSymbolRange();
3456 if (!CR || CR->getUnsignedMax().uge(1ull << VT.
getSizeInBits()))
3460 Op = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(
N), VT,
3461 GA->getOffset(), GA->getTargetFlags());
3465bool X86DAGToDAGISel::tryFoldLoad(SDNode *Root, SDNode *
P,
SDValue N,
3469 assert(Root &&
P &&
"Unknown root/parent nodes");
3471 !IsProfitableToFold(
N,
P, Root) ||
3472 !IsLegalToFold(
N,
P, Root, OptLevel))
3475 return selectAddr(
N.getNode(),
3476 N.getOperand(1),
Base, Scale, Index, Disp, Segment);
3479bool X86DAGToDAGISel::tryFoldBroadcast(SDNode *Root, SDNode *
P,
SDValue N,
3483 assert(Root &&
P &&
"Unknown root/parent nodes");
3484 if (
N->getOpcode() != X86ISD::VBROADCAST_LOAD ||
3485 !IsProfitableToFold(
N,
P, Root) ||
3486 !IsLegalToFold(
N,
P, Root, OptLevel))
3489 return selectAddr(
N.getNode(),
3490 N.getOperand(1),
Base, Scale, Index, Disp, Segment);
3496SDNode *X86DAGToDAGISel::getGlobalBaseReg() {
3499 return CurDAG->getRegister(GlobalBaseReg, TLI->
getPointerTy(
DL)).getNode();
3502bool X86DAGToDAGISel::isSExtAbsoluteSymbolRef(
unsigned Width, SDNode *
N)
const {
3504 N =
N->getOperand(0).getNode();
3505 if (
N->getOpcode() != X86ISD::Wrapper)
3512 auto *GV = GA->getGlobal();
3515 return CR->getSignedMin().sge(-1ull << Width) &&
3516 CR->getSignedMax().slt(1ull << Width);
3522 !TM.isLargeGlobalValue(GV);
3526 assert(
N->isMachineOpcode() &&
"Unexpected node");
3527 unsigned Opc =
N->getMachineOpcode();
3528 const MCInstrDesc &MCID = getInstrInfo()->get(
Opc);
3533 return static_cast<X86::CondCode>(
N->getConstantOperandVal(CondNo));
3538bool X86DAGToDAGISel::onlyUsesZeroFlag(
SDValue Flags)
const {
3540 for (SDUse &Use :
Flags->uses()) {
3542 if (
Use.getResNo() !=
Flags.getResNo())
3550 for (SDUse &FlagUse :
User->uses()) {
3552 if (FlagUse.getResNo() != 1)
3555 if (!FlagUse.getUser()->isMachineOpcode())
3575bool X86DAGToDAGISel::hasNoSignFlagUses(
SDValue Flags)
const {
3577 for (SDUse &Use :
Flags->uses()) {
3579 if (
Use.getResNo() !=
Flags.getResNo())
3587 for (SDUse &FlagUse :
User->uses()) {
3589 if (FlagUse.getResNo() != 1)
3592 if (!FlagUse.getUser()->isMachineOpcode())
3632 bool X86DAGToDAGISel::hasNoCarryFlagUses(
SDValue Flags)
const {
3634 for (SDUse &Use :
Flags->uses()) {
3636 if (
Use.getResNo() !=
Flags.getResNo())
3640 unsigned UserOpc =
User->getOpcode();
3647 for (SDUse &FlagUse :
User->uses()) {
3649 if (FlagUse.getResNo() != 1)
3652 if (!FlagUse.getUser()->isMachineOpcode())
3672 case X86ISD::SETCC: CCOpNo = 0;
break;
3673 case X86ISD::SETCC_CARRY: CCOpNo = 0;
break;
3674 case X86ISD::CMOV: CCOpNo = 2;
break;
3675 case X86ISD::BRCOND: CCOpNo = 2;
break;
3685bool X86DAGToDAGISel::checkTCRetEnoughRegs(SDNode *
N)
const {
3688 const X86RegisterInfo *RI = Subtarget->getRegisterInfo();
3692 if (Subtarget->is64Bit()) {
3695 ? &X86::GR64_TCW64RegClass
3696 : &X86::GR64_TCRegClass;
3704 ? &X86::GR32RegClass
3705 : &X86::GR32_TCRegClass;
3712 unsigned LoadGPRs = 2;
3714 assert(
N->getOpcode() == X86ISD::TC_RETURN);
3717 if (Subtarget->is32Bit()) {
3723 }
else if (
BasePtr.getOpcode() == X86ISD::Wrapper &&
3725 if (getTargetMachine().isPositionIndependent())
3733 for (
unsigned I = 3,
E =
N->getNumOperands();
I !=
E; ++
I) {
3735 if (!RI->isGeneralPurposeRegister(*MF,
RN->getReg()))
3737 if (++
ArgGPRs + LoadGPRs > AvailGPRs)
3753 if (StoredVal.
getResNo() != 0)
return false;
3770 if (!
Load.hasOneUse())
3778 bool FoundLoad =
false;
3782 const unsigned int Max = 1024;
3824 if (Chain ==
Load.getValue(1)) {
3830 if (
Op ==
Load.getValue(1)) {
3846 if (
Op.getNode() != LoadNode)
3878bool X86DAGToDAGISel::foldLoadStoreIntoMemOperand(SDNode *Node) {
3880 SDValue StoredVal = StoreNode->getOperand(1);
3886 EVT MemVT = StoreNode->getMemoryVT();
3887 if (MemVT != MVT::i64 && MemVT != MVT::i32 && MemVT != MVT::i16 &&
3891 bool IsCommutable =
false;
3892 bool IsNegate =
false;
3906 IsCommutable =
true;
3910 unsigned LoadOpNo = IsNegate ? 1 : 0;
3911 LoadSDNode *LoadNode =
nullptr;
3914 LoadNode, InputChain)) {
3921 LoadNode, InputChain))
3926 if (!selectAddr(LoadNode, LoadNode->
getBasePtr(),
Base, Scale, Index, Disp,
3930 auto SelectOpcode = [&](
unsigned Opc64,
unsigned Opc32,
unsigned Opc16,
3951 unsigned NewOpc = SelectOpcode(X86::NEG64m, X86::NEG32m, X86::NEG16m,
3954 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32,
3961 if (!Subtarget->slowIncDec() || CurDAG->shouldOptForSize()) {
3965 if ((IsOne || IsNegOne) && hasNoCarryFlagUses(StoredVal.
getValue(1))) {
3967 ((
Opc == X86ISD::ADD) == IsOne)
3968 ? SelectOpcode(X86::INC64m, X86::INC32m, X86::INC16m, X86::INC8m)
3969 : SelectOpcode(X86::DEC64m, X86::DEC32m, X86::DEC16m, X86::DEC8m);
3971 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32,
3982 auto SelectRegOpcode = [SelectOpcode](
unsigned Opc) {
3985 return SelectOpcode(X86::ADD64mr, X86::ADD32mr, X86::ADD16mr,
3988 return SelectOpcode(X86::ADC64mr, X86::ADC32mr, X86::ADC16mr,
3991 return SelectOpcode(X86::SUB64mr, X86::SUB32mr, X86::SUB16mr,
3994 return SelectOpcode(X86::SBB64mr, X86::SBB32mr, X86::SBB16mr,
3997 return SelectOpcode(X86::AND64mr, X86::AND32mr, X86::AND16mr,
4000 return SelectOpcode(X86::OR64mr, X86::OR32mr, X86::OR16mr, X86::OR8mr);
4002 return SelectOpcode(X86::XOR64mr, X86::XOR32mr, X86::XOR16mr,
4008 auto SelectImmOpcode = [SelectOpcode](
unsigned Opc) {
4011 return SelectOpcode(X86::ADD64mi32, X86::ADD32mi, X86::ADD16mi,
4014 return SelectOpcode(X86::ADC64mi32, X86::ADC32mi, X86::ADC16mi,
4017 return SelectOpcode(X86::SUB64mi32, X86::SUB32mi, X86::SUB16mi,
4020 return SelectOpcode(X86::SBB64mi32, X86::SBB32mi, X86::SBB16mi,
4023 return SelectOpcode(X86::AND64mi32, X86::AND32mi, X86::AND16mi,
4026 return SelectOpcode(X86::OR64mi32, X86::OR32mi, X86::OR16mi,
4029 return SelectOpcode(X86::XOR64mi32, X86::XOR32mi, X86::XOR16mi,
4036 unsigned NewOpc = SelectRegOpcode(
Opc);
4042 int64_t OperandV = OperandC->getSExtValue();
4047 if ((
Opc == X86ISD::ADD ||
Opc == X86ISD::SUB) &&
4049 (MemVT == MVT::i64 && !
isInt<32>(OperandV) &&
4051 hasNoCarryFlagUses(StoredVal.
getValue(1))) {
4052 OperandV = -OperandV;
4053 Opc =
Opc == X86ISD::ADD ? X86ISD::SUB : X86ISD::ADD;
4056 if (MemVT != MVT::i64 ||
isInt<32>(OperandV)) {
4057 Operand = CurDAG->getSignedTargetConstant(OperandV, SDLoc(Node), MemVT);
4058 NewOpc = SelectImmOpcode(
Opc);
4062 if (
Opc == X86ISD::ADC ||
Opc == X86ISD::SBB) {
4064 CurDAG->getCopyToReg(InputChain, SDLoc(Node), X86::EFLAGS,
4068 Segment, Operand, CopyTo, CopyTo.
getValue(1)};
4069 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other,
4073 Segment, Operand, InputChain};
4074 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other,
4083 MachineMemOperand *MemOps[] = {StoreNode->getMemOperand(),
4085 CurDAG->setNodeMemRefs(Result, MemOps);
4091 CurDAG->RemoveDeadNode(Node);
4102bool X86DAGToDAGISel::matchBitExtract(SDNode *Node) {
4106 "Should be either an and-mask, or right-shift after clearing high bits.");
4109 if (!Subtarget->hasBMI() && !Subtarget->hasBMI2())
4112 MVT NVT =
Node->getSimpleValueType(0);
4115 if (NVT != MVT::i32 && NVT != MVT::i64)
4123 const bool AllowExtraUsesByDefault = Subtarget->hasBMI2();
4124 auto checkUses = [AllowExtraUsesByDefault](
4126 std::optional<bool> AllowExtraUses) {
4127 return AllowExtraUses.value_or(AllowExtraUsesByDefault) ||
4128 Op.getNode()->hasNUsesOfValue(NUses,
Op.getResNo());
4130 auto checkOneUse = [checkUses](
SDValue Op,
4131 std::optional<bool> AllowExtraUses =
4133 return checkUses(
Op, 1, AllowExtraUses);
4135 auto checkTwoUse = [checkUses](
SDValue Op,
4136 std::optional<bool> AllowExtraUses =
4138 return checkUses(
Op, 2, AllowExtraUses);
4141 auto peekThroughOneUseTruncation = [checkOneUse](
SDValue V) {
4143 assert(
V.getSimpleValueType() == MVT::i32 &&
4144 V.getOperand(0).getSimpleValueType() == MVT::i64 &&
4145 "Expected i64 -> i32 truncation");
4146 V =
V.getOperand(0);
4152 auto matchPatternA = [checkOneUse, peekThroughOneUseTruncation, &NBits,
4155 if (
Mask->getOpcode() !=
ISD::ADD || !checkOneUse(Mask))
4161 SDValue M0 = peekThroughOneUseTruncation(
Mask->getOperand(0));
4166 NBits =
M0->getOperand(1);
4167 NegateNBits =
false;
4171 auto isAllOnes = [
this, peekThroughOneUseTruncation, NVT](
SDValue V) {
4172 V = peekThroughOneUseTruncation(V);
4173 return CurDAG->MaskedValueIsAllOnes(
4179 auto matchPatternB = [checkOneUse, isAllOnes, peekThroughOneUseTruncation,
4182 if (
Mask.getOpcode() !=
ISD::XOR || !checkOneUse(Mask))
4185 if (!isAllOnes(
Mask->getOperand(1)))
4188 SDValue M0 = peekThroughOneUseTruncation(
Mask->getOperand(0));
4192 if (!isAllOnes(
M0->getOperand(0)))
4194 NBits =
M0->getOperand(1);
4195 NegateNBits =
false;
4201 auto canonicalizeShiftAmt = [&NBits, &NegateNBits](
SDValue ShiftAmt,
4202 unsigned Bitwidth) {
4207 NBits = NBits.getOperand(0);
4213 if (!V0 || V0->getZExtValue() != Bitwidth)
4215 NBits = NBits.getOperand(1);
4216 NegateNBits =
false;
4222 auto matchPatternC = [checkOneUse, peekThroughOneUseTruncation, &NegateNBits,
4225 Mask = peekThroughOneUseTruncation(Mask);
4226 unsigned Bitwidth =
Mask.getSimpleValueType().getSizeInBits();
4228 if (
Mask.getOpcode() !=
ISD::SRL || !checkOneUse(Mask))
4235 if (!checkOneUse(
M1))
4237 canonicalizeShiftAmt(
M1, Bitwidth);
4242 return !NegateNBits;
4250 auto matchPatternD = [checkOneUse, checkTwoUse, canonicalizeShiftAmt,
4251 AllowExtraUsesByDefault, &NegateNBits,
4252 &
X](SDNode *
Node) ->
bool {
4264 canonicalizeShiftAmt(N1, Bitwidth);
4268 const bool AllowExtraUses = AllowExtraUsesByDefault && !NegateNBits;
4269 if (!checkOneUse(N0, AllowExtraUses) || !checkTwoUse(N1, AllowExtraUses))
4275 auto matchLowBitMask = [matchPatternA, matchPatternB,
4277 return matchPatternA(Mask) || matchPatternB(Mask) || matchPatternC(Mask);
4281 X =
Node->getOperand(0);
4284 if (matchLowBitMask(Mask)) {
4288 if (!matchLowBitMask(Mask))
4291 }
else if (matchLowBitMask(
SDValue(Node, 0))) {
4292 X = CurDAG->getAllOnesConstant(SDLoc(Node), NVT);
4293 }
else if (!matchPatternD(Node))
4298 if (NegateNBits && !Subtarget->hasBMI2())
4303 if (NBits.getSimpleValueType() != MVT::i8) {
4310 ConstantSDNode *
Imm =
nullptr;
4311 if (NBits->getOpcode() ==
ISD::AND)
4313 NBits = NBits->getOperand(0);
4318 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, MVT::i32), 0);
4321 SDValue SRIdxVal = CurDAG->getTargetConstant(X86::sub_8bit,
DL, MVT::i32);
4323 NBits =
SDValue(CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG,
DL,
4324 MVT::i32, ImplDef, NBits, SRIdxVal),
4330 CurDAG->getNode(
ISD::AND,
DL, MVT::i32, NBits,
4331 CurDAG->getConstant(
Imm->getZExtValue(),
DL, MVT::i32));
4341 NBits = CurDAG->getNode(
ISD::SUB,
DL, MVT::i32, BitWidthC, NBits);
4345 if (Subtarget->hasBMI2()) {
4347 if (NVT != MVT::i32) {
4353 SDValue Extract = CurDAG->getNode(X86ISD::BZHI,
DL, NVT,
X, NBits);
4354 ReplaceNode(Node, Extract.
getNode());
4355 SelectCode(Extract.
getNode());
4364 SDValue RealX = peekThroughOneUseTruncation(
X);
4370 MVT XVT =
X.getSimpleValueType();
4380 SDValue C8 = CurDAG->getConstant(8,
DL, MVT::i8);
4388 SDValue ShiftAmt =
X.getOperand(1);
4389 X =
X.getOperand(0);
4392 "Expected shift amount to be i8");
4396 SDValue OrigShiftAmt = ShiftAmt;
4401 Control = CurDAG->getNode(
ISD::OR,
DL, MVT::i32, Control, ShiftAmt);
4406 if (XVT != MVT::i32) {
4412 SDValue Extract = CurDAG->getNode(X86ISD::BEXTR,
DL, XVT,
X, Control);
4420 ReplaceNode(Node, Extract.
getNode());
4421 SelectCode(Extract.
getNode());
4427MachineSDNode *X86DAGToDAGISel::matchBEXTRFromAndImm(SDNode *Node) {
4428 MVT NVT =
Node->getSimpleValueType(0);
4441 Subtarget->hasTBM() || (Subtarget->hasBMI() && Subtarget->hasFastBEXTR());
4442 if (!PreferBEXTR && !Subtarget->hasBMI2())
4454 if (NVT != MVT::i32 && NVT != MVT::i64)
4460 if (!MaskCst || !ShiftCst)
4468 uint64_t Shift = ShiftCst->getZExtValue();
4473 if (Shift == 8 && MaskSize == 8)
4484 if (!PreferBEXTR && MaskSize <= 32)
4488 unsigned ROpc, MOpc;
4490#define GET_EGPR_IF_ENABLED(OPC) (Subtarget->hasEGPR() ? OPC##_EVEX : OPC)
4492 assert(Subtarget->hasBMI2() &&
"We must have BMI2's BZHI then.");
4496 Control = CurDAG->getTargetConstant(Shift + MaskSize, dl, NVT);
4501 unsigned NewOpc = NVT == MVT::i64 ? X86::MOV32ri64 : X86::MOV32ri;
4502 Control =
SDValue(CurDAG->getMachineNode(NewOpc, dl, NVT, Control), 0);
4508 Control = CurDAG->getTargetConstant(Shift | (MaskSize << 8), dl, NVT);
4509 if (Subtarget->hasTBM()) {
4510 ROpc = NVT == MVT::i64 ? X86::BEXTRI64ri : X86::BEXTRI32ri;
4511 MOpc = NVT == MVT::i64 ? X86::BEXTRI64mi : X86::BEXTRI32mi;
4513 assert(Subtarget->hasBMI() &&
"We must have BMI1's BEXTR then.");
4519 unsigned NewOpc = NVT == MVT::i64 ? X86::MOV32ri64 : X86::MOV32ri;
4520 Control =
SDValue(CurDAG->getMachineNode(NewOpc, dl, NVT, Control), 0);
4524 MachineSDNode *NewNode;
4526 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4527 if (tryFoldLoad(Node, N0.
getNode(), Input, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4529 Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Control, Input.
getOperand(0)};
4530 SDVTList VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
4531 NewNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4535 CurDAG->setNodeMemRefs(NewNode, {
cast<LoadSDNode>(Input)->getMemOperand()});
4537 NewNode = CurDAG->getMachineNode(ROpc, dl, NVT, MVT::i32, Input, Control);
4542 SDValue ShAmt = CurDAG->getTargetConstant(Shift, dl, NVT);
4546 CurDAG->getMachineNode(NewOpc, dl, NVT,
SDValue(NewNode, 0), ShAmt);
4553MachineSDNode *X86DAGToDAGISel::emitPCMPISTR(
unsigned ROpc,
unsigned MOpc,
4554 bool MayFoldLoad,
const SDLoc &dl,
4555 MVT VT, SDNode *Node) {
4560 Imm = CurDAG->getTargetConstant(*Val, SDLoc(Node),
Imm.getValueType());
4563 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4564 if (MayFoldLoad && tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4567 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Other);
4568 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4577 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32);
4578 MachineSDNode *CNode = CurDAG->getMachineNode(ROpc, dl, VTs,
Ops);
4585MachineSDNode *X86DAGToDAGISel::emitPCMPESTR(
unsigned ROpc,
unsigned MOpc,
4586 bool MayFoldLoad,
const SDLoc &dl,
4587 MVT VT, SDNode *Node,
4593 Imm = CurDAG->getTargetConstant(*Val, SDLoc(Node),
Imm.getValueType());
4596 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4597 if (MayFoldLoad && tryFoldLoad(Node, N2, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4600 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Other, MVT::Glue);
4601 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4611 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Glue);
4612 MachineSDNode *CNode = CurDAG->getMachineNode(ROpc, dl, VTs,
Ops);
4617bool X86DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
4618 EVT VT =
N->getValueType(0);
4625 unsigned Size = VT == MVT::i64 ? 64 : 32;
4628 SDValue ShiftAmt = OrigShiftAmt;
4647 if (Add1C && Add1C->getAPIntValue().urem(
Size) == 0) {
4651 ((Add0C && Add0C->getAPIntValue().urem(
Size) ==
Size - 1) ||
4652 (Add1C && Add1C->getAPIntValue().urem(
Size) ==
Size - 1))) {
4656 assert(Add0C ==
nullptr || Add1C ==
nullptr);
4665 NewShiftAmt = CurDAG->getNode(
ISD::XOR,
DL, OpVT,
4666 Add0C ==
nullptr ? Add0 : Add1,
AllOnes);
4672 Add0C->getZExtValue() != 0) {
4675 if (Add0C->getZExtValue() %
Size == 0)
4678 Add0C->getZExtValue() % 32 == 0) {
4686 Add0 = CurDAG->getZExtOrTrunc(Add0,
DL, SubVT);
4690 X = CurDAG->getNode(
ISD::ADD,
DL, SubVT, Add1, Add0);
4712 NewShiftAmt = CurDAG->getNode(
ISD::TRUNCATE,
DL, MVT::i8, NewShiftAmt);
4719 NewShiftAmt = CurDAG->getNode(
ISD::AND,
DL, MVT::i8, NewShiftAmt,
4720 CurDAG->getConstant(
Size - 1,
DL, MVT::i8));
4724 SDNode *UpdatedNode = CurDAG->UpdateNodeOperands(
N,
N->getOperand(0),
4726 if (UpdatedNode !=
N) {
4729 ReplaceNode(
N, UpdatedNode);
4736 CurDAG->RemoveDeadNode(OrigShiftAmt.
getNode());
4744bool X86DAGToDAGISel::tryShrinkShlLogicImm(SDNode *
N) {
4745 MVT NVT =
N->getSimpleValueType(0);
4746 unsigned Opcode =
N->getOpcode();
4758 int64_t Val = Cst->getSExtValue();
4763 bool FoundAnyExtend =
false;
4767 FoundAnyExtend =
true;
4775 if (NVT != MVT::i32 && NVT != MVT::i64)
4782 uint64_t ShAmt = ShlCst->getZExtValue();
4786 uint64_t RemovedBitsMask = (1ULL << ShAmt) - 1;
4787 if (Opcode !=
ISD::AND && (Val & RemovedBitsMask) != 0)
4792 auto CanShrinkImmediate = [&](int64_t &ShiftedVal) {
4796 ShiftedVal = (
uint64_t)Val >> ShAmt;
4800 if (ShiftedVal == UINT8_MAX || ShiftedVal == UINT16_MAX)
4803 ShiftedVal = Val >> ShAmt;
4809 ShiftedVal = (
uint64_t)Val >> ShAmt;
4817 if (!CanShrinkImmediate(ShiftedVal))
4827 unsigned ZExtWidth = Cst->getAPIntValue().getActiveBits();
4833 NeededMask &= ~Cst->getAPIntValue();
4835 if (CurDAG->MaskedValueIsZero(
N->getOperand(0), NeededMask))
4840 if (FoundAnyExtend) {
4846 SDValue NewCst = CurDAG->getSignedConstant(ShiftedVal, dl, NVT);
4848 SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT,
X, NewCst);
4857bool X86DAGToDAGISel::matchVPTERNLOG(SDNode *Root, SDNode *ParentA,
4858 SDNode *ParentB, SDNode *ParentC,
4861 assert(
A.isOperandOf(ParentA) &&
B.isOperandOf(ParentB) &&
4862 C.isOperandOf(ParentC) &&
"Incorrect parent node");
4864 auto tryFoldLoadOrBCast =
4867 if (tryFoldLoad(Root,
P, L,
Base, Scale, Index, Disp, Segment))
4873 L =
L.getOperand(0);
4876 if (
L.getOpcode() != X86ISD::VBROADCAST_LOAD)
4881 unsigned Size = MemIntr->getMemoryVT().getSizeInBits();
4885 return tryFoldBroadcast(Root,
P, L,
Base, Scale, Index, Disp, Segment);
4888 bool FoldedLoad =
false;
4889 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4890 if (tryFoldLoadOrBCast(Root, ParentC,
C, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4892 }
else if (tryFoldLoadOrBCast(Root, ParentA,
A, Tmp0, Tmp1, Tmp2, Tmp3,
4897 uint8_t OldImm =
Imm;
4898 Imm = OldImm & 0xa5;
4899 if (OldImm & 0x02)
Imm |= 0x10;
4900 if (OldImm & 0x10)
Imm |= 0x02;
4901 if (OldImm & 0x08)
Imm |= 0x40;
4902 if (OldImm & 0x40)
Imm |= 0x08;
4903 }
else if (tryFoldLoadOrBCast(Root, ParentB,
B, Tmp0, Tmp1, Tmp2, Tmp3,
4908 uint8_t OldImm =
Imm;
4909 Imm = OldImm & 0x99;
4910 if (OldImm & 0x02)
Imm |= 0x04;
4911 if (OldImm & 0x04)
Imm |= 0x02;
4912 if (OldImm & 0x20)
Imm |= 0x40;
4913 if (OldImm & 0x40)
Imm |= 0x20;
4918 SDValue TImm = CurDAG->getTargetConstant(
Imm,
DL, MVT::i8);
4922 MachineSDNode *MNode;
4924 SDVTList VTs = CurDAG->getVTList(NVT, MVT::Other);
4927 if (
C.getOpcode() == X86ISD::VBROADCAST_LOAD) {
4929 unsigned EltSize = MemIntr->getMemoryVT().getSizeInBits();
4930 assert((EltSize == 32 || EltSize == 64) &&
"Unexpected broadcast size!");
4932 bool UseD = EltSize == 32;
4934 Opc = UseD ? X86::VPTERNLOGDZ128rmbi : X86::VPTERNLOGQZ128rmbi;
4936 Opc = UseD ? X86::VPTERNLOGDZ256rmbi : X86::VPTERNLOGQZ256rmbi;
4938 Opc = UseD ? X86::VPTERNLOGDZrmbi : X86::VPTERNLOGQZrmbi;
4944 Opc = UseD ? X86::VPTERNLOGDZ128rmi : X86::VPTERNLOGQZ128rmi;
4946 Opc = UseD ? X86::VPTERNLOGDZ256rmi : X86::VPTERNLOGQZ256rmi;
4948 Opc = UseD ? X86::VPTERNLOGDZrmi : X86::VPTERNLOGQZrmi;
4954 MNode = CurDAG->getMachineNode(
Opc,
DL, VTs,
Ops);
4957 ReplaceUses(
C.getValue(1),
SDValue(MNode, 1));
4964 Opc = UseD ? X86::VPTERNLOGDZ128rri : X86::VPTERNLOGQZ128rri;
4966 Opc = UseD ? X86::VPTERNLOGDZ256rri : X86::VPTERNLOGQZ256rri;
4968 Opc = UseD ? X86::VPTERNLOGDZrri : X86::VPTERNLOGQZrri;
4972 MNode = CurDAG->getMachineNode(
Opc,
DL, NVT, {
A,
B,
C, TImm});
4976 CurDAG->RemoveDeadNode(Root);
4982bool X86DAGToDAGISel::tryVPTERNLOG(SDNode *
N) {
4983 MVT NVT =
N->getSimpleValueType(0);
4986 if (!NVT.
isVector() || !Subtarget->hasAVX512() ||
4994 auto getFoldableLogicOp = [](
SDValue Op) {
4997 Op =
Op.getOperand(0);
4999 if (!
Op.hasOneUse())
5002 unsigned Opc =
Op.getOpcode();
5004 Opc == X86ISD::ANDNP)
5013 auto tryPeelOuterNotWrappingLogic = [&](SDNode *
Op) {
5016 SDValue InnerOp = getFoldableLogicOp(
Op->getOperand(0));
5023 if ((FoldableOp = getFoldableLogicOp(N1))) {
5027 if ((FoldableOp = getFoldableLogicOp(N0))) {
5035 bool PeeledOuterNot =
false;
5037 if (
SDValue InnerOp = tryPeelOuterNotWrappingLogic(
N)) {
5038 PeeledOuterNot =
true;
5044 if ((FoldableOp = getFoldableLogicOp(N1)))
5046 else if ((FoldableOp = getFoldableLogicOp(N0)))
5054 SDNode *ParentA =
N;
5055 SDNode *ParentB = FoldableOp.
getNode();
5056 SDNode *ParentC = FoldableOp.
getNode();
5060 uint8_t TernlogMagicA = 0xf0;
5061 uint8_t TernlogMagicB = 0xcc;
5062 uint8_t TernlogMagicC = 0xaa;
5067 auto PeekThroughNot = [](
SDValue &
Op, SDNode *&Parent, uint8_t &
Magic) {
5071 Parent =
Op.getNode();
5072 Op =
Op.getOperand(0);
5076 PeekThroughNot(
A, ParentA, TernlogMagicA);
5077 PeekThroughNot(
B, ParentB, TernlogMagicB);
5078 PeekThroughNot(
C, ParentC, TernlogMagicC);
5083 case ISD::AND:
Imm = TernlogMagicB & TernlogMagicC;
break;
5084 case ISD::OR:
Imm = TernlogMagicB | TernlogMagicC;
break;
5085 case ISD::XOR:
Imm = TernlogMagicB ^ TernlogMagicC;
break;
5086 case X86ISD::ANDNP:
Imm = ~(TernlogMagicB) & TernlogMagicC;
break;
5089 switch (
N->getOpcode()) {
5093 Imm &= ~TernlogMagicA;
5095 Imm = ~(
Imm) & TernlogMagicA;
5105 return matchVPTERNLOG(OriN, ParentA, ParentB, ParentC,
A,
B,
C,
Imm);
5115bool X86DAGToDAGISel::shrinkAndImmediate(SDNode *
And) {
5118 MVT VT =
And->getSimpleValueType(0);
5119 if (VT != MVT::i32 && VT != MVT::i64)
5131 APInt MaskVal = And1C->getAPIntValue();
5133 if (!MaskLZ || (VT == MVT::i64 && MaskLZ == 32))
5137 if (VT == MVT::i64 && MaskLZ >= 32) {
5139 MaskVal = MaskVal.
trunc(32);
5144 APInt NegMaskVal = MaskVal | HighZeros;
5153 if (VT == MVT::i64 && MaskVal.
getBitWidth() < 64) {
5154 NegMaskVal = NegMaskVal.
zext(64);
5155 HighZeros = HighZeros.
zext(64);
5161 KnownBits Known0 = CurDAG->computeKnownBits(And0);
5173 SDValue NewMask = CurDAG->getConstant(NegMaskVal, SDLoc(
And), VT);
5182 bool FoldedBCast,
bool Masked) {
5183#define VPTESTM_CASE(VT, SUFFIX) \
5186 return IsTestN ? X86::VPTESTNM##SUFFIX##k: X86::VPTESTM##SUFFIX##k; \
5187 return IsTestN ? X86::VPTESTNM##SUFFIX : X86::VPTESTM##SUFFIX;
5190#define VPTESTM_BROADCAST_CASES(SUFFIX) \
5191default: llvm_unreachable("Unexpected VT!"); \
5192VPTESTM_CASE(v4i32, DZ128##SUFFIX) \
5193VPTESTM_CASE(v2i64, QZ128##SUFFIX) \
5194VPTESTM_CASE(v8i32, DZ256##SUFFIX) \
5195VPTESTM_CASE(v4i64, QZ256##SUFFIX) \
5196VPTESTM_CASE(v16i32, DZ##SUFFIX) \
5197VPTESTM_CASE(v8i64, QZ##SUFFIX)
5199#define VPTESTM_FULL_CASES(SUFFIX) \
5200VPTESTM_BROADCAST_CASES(SUFFIX) \
5201VPTESTM_CASE(v16i8, BZ128##SUFFIX) \
5202VPTESTM_CASE(v8i16, WZ128##SUFFIX) \
5203VPTESTM_CASE(v32i8, BZ256##SUFFIX) \
5204VPTESTM_CASE(v16i16, WZ256##SUFFIX) \
5205VPTESTM_CASE(v64i8, BZ##SUFFIX) \
5206VPTESTM_CASE(v32i16, WZ##SUFFIX)
5224#undef VPTESTM_FULL_CASES
5225#undef VPTESTM_BROADCAST_CASES
5235 if (
Reg.isVirtual())
5240 if (GetPhysReg(N1) == LoReg && GetPhysReg(N0) != LoReg)
5246bool X86DAGToDAGISel::tryVPTESTM(SDNode *Root,
SDValue Setcc,
5248 assert(Subtarget->hasAVX512() &&
"Expected AVX512!");
5293 auto tryFoldLoadOrBCast = [&](SDNode *Root, SDNode *
P,
SDValue &
L,
5298 if (tryFoldLoad(Root,
P, L,
Base, Scale, Index, Disp, Segment))
5303 if (CmpSVT != MVT::i32 && CmpSVT != MVT::i64)
5309 L =
L.getOperand(0);
5312 if (
L.getOpcode() != X86ISD::VBROADCAST_LOAD)
5316 if (MemIntr->getMemoryVT().getSizeInBits() != CmpSVT.
getSizeInBits())
5319 return tryFoldBroadcast(Root,
P, L,
Base, Scale, Index, Disp, Segment);
5323 bool CanFoldLoads = Src0 != Src1;
5325 bool FoldedLoad =
false;
5326 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5328 FoldedLoad = tryFoldLoadOrBCast(Root, N0.
getNode(), Src1, Tmp0, Tmp1, Tmp2,
5332 FoldedLoad = tryFoldLoadOrBCast(Root, N0.
getNode(), Src0, Tmp0, Tmp1,
5339 bool FoldedBCast = FoldedLoad && Src1.
getOpcode() == X86ISD::VBROADCAST_LOAD;
5341 bool IsMasked = InMask.
getNode() !=
nullptr;
5350 unsigned SubReg = CmpVT.
is128BitVector() ? X86::sub_xmm : X86::sub_ymm;
5354 SDValue ImplDef =
SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF, dl,
5356 Src0 = CurDAG->getTargetInsertSubreg(SubReg, dl, CmpVT, ImplDef, Src0);
5359 Src1 = CurDAG->getTargetInsertSubreg(SubReg, dl, CmpVT, ImplDef, Src1);
5364 SDValue RC = CurDAG->getTargetConstant(RegClass, dl, MVT::i32);
5365 InMask =
SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
5366 dl, MaskVT, InMask, RC), 0);
5374 MachineSDNode *CNode;
5376 SDVTList VTs = CurDAG->getVTList(MaskVT, MVT::Other);
5379 SDValue Ops[] = { InMask, Src0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
5381 CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5383 SDValue Ops[] = { Src0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
5385 CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5391 CurDAG->setNodeMemRefs(CNode, {
cast<MemSDNode>(Src1)->getMemOperand()});
5394 CNode = CurDAG->getMachineNode(
Opc, dl, MaskVT, InMask, Src0, Src1);
5396 CNode = CurDAG->getMachineNode(
Opc, dl, MaskVT, Src0, Src1);
5402 SDValue RC = CurDAG->getTargetConstant(RegClass, dl, MVT::i32);
5403 CNode = CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
5404 dl, ResVT,
SDValue(CNode, 0), RC);
5408 CurDAG->RemoveDeadNode(Root);
5414bool X86DAGToDAGISel::tryMatchBitSelect(SDNode *
N) {
5417 MVT NVT =
N->getSimpleValueType(0);
5420 if (!NVT.
isVector() || !Subtarget->hasAVX512())
5454 SDValue Imm = CurDAG->getTargetConstant(0xCA, dl, MVT::i8);
5455 SDValue Ternlog = CurDAG->getNode(X86ISD::VPTERNLOG, dl, NVT,
A,
B,
C,
Imm);
5462void X86DAGToDAGISel::Select(SDNode *Node) {
5463 MVT NVT =
Node->getSimpleValueType(0);
5464 unsigned Opcode =
Node->getOpcode();
5467 if (
Node->isMachineOpcode()) {
5469 Node->setNodeId(-1);
5476 unsigned IntNo =
Node->getConstantOperandVal(1);
5479 case Intrinsic::x86_encodekey128:
5480 case Intrinsic::x86_encodekey256: {
5481 if (!Subtarget->hasKL())
5487 case Intrinsic::x86_encodekey128:
5488 Opcode = X86::ENCODEKEY128;
5490 case Intrinsic::x86_encodekey256:
5491 Opcode = X86::ENCODEKEY256;
5496 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM0,
Node->getOperand(3),
5498 if (Opcode == X86::ENCODEKEY256)
5499 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM1,
Node->getOperand(4),
5502 MachineSDNode *Res = CurDAG->getMachineNode(
5503 Opcode, dl,
Node->getVTList(),
5504 {Node->getOperand(2), Chain, Chain.getValue(1)});
5505 ReplaceNode(Node, Res);
5508 case Intrinsic::x86_tileloaddrs64_internal:
5509 case Intrinsic::x86_tileloaddrst164_internal:
5510 if (!Subtarget->hasAMXMOVRS())
5513 case Intrinsic::x86_tileloadd64_internal:
5514 case Intrinsic::x86_tileloaddt164_internal: {
5515 if (!Subtarget->hasAMXTILE())
5518 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5519 MFI->setAMXProgModel(AMXProgModelEnum::ManagedRA);
5524 case Intrinsic::x86_tileloaddrs64_internal:
5525 Opc = X86::PTILELOADDRSV;
5527 case Intrinsic::x86_tileloaddrst164_internal:
5528 Opc = X86::PTILELOADDRST1V;
5530 case Intrinsic::x86_tileloadd64_internal:
5531 Opc = X86::PTILELOADDV;
5533 case Intrinsic::x86_tileloaddt164_internal:
5534 Opc = X86::PTILELOADDT1V;
5539 SDValue Scale = getI8Imm(1, dl);
5541 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5542 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5544 MachineSDNode *CNode;
5546 Node->getOperand(3),
5553 CNode = CurDAG->getMachineNode(
Opc, dl, {MVT::x86amx, MVT::Other},
Ops);
5554 ReplaceNode(Node, CNode);
5561 unsigned IntNo =
Node->getConstantOperandVal(1);
5564 case Intrinsic::x86_sse3_monitor:
5565 case Intrinsic::x86_monitorx:
5566 case Intrinsic::x86_clzero: {
5567 bool Use64BitPtr =
Node->getOperand(2).getValueType() == MVT::i64;
5572 case Intrinsic::x86_sse3_monitor:
5573 if (!Subtarget->hasSSE3())
5575 Opc = Use64BitPtr ? X86::MONITOR64rrr : X86::MONITOR32rrr;
5577 case Intrinsic::x86_monitorx:
5578 if (!Subtarget->hasMWAITX())
5580 Opc = Use64BitPtr ? X86::MONITORX64rrr : X86::MONITORX32rrr;
5582 case Intrinsic::x86_clzero:
5583 if (!Subtarget->hasCLZERO())
5585 Opc = Use64BitPtr ? X86::CLZERO64r : X86::CLZERO32r;
5590 unsigned PtrReg = Use64BitPtr ? X86::RAX : X86::EAX;
5591 SDValue Chain = CurDAG->getCopyToReg(
Node->getOperand(0), dl, PtrReg,
5595 if (IntNo == Intrinsic::x86_sse3_monitor ||
5596 IntNo == Intrinsic::x86_monitorx) {
5598 Chain = CurDAG->getCopyToReg(Chain, dl, X86::ECX,
Node->getOperand(3),
5601 Chain = CurDAG->getCopyToReg(Chain, dl, X86::EDX,
Node->getOperand(4),
5606 MachineSDNode *CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
5608 ReplaceNode(Node, CNode);
5614 case Intrinsic::x86_tilestored64_internal: {
5616 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5617 MFI->setAMXProgModel(AMXProgModelEnum::ManagedRA);
5618 unsigned Opc = X86::PTILESTOREDV;
5621 SDValue Scale = getI8Imm(1, dl);
5623 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5624 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5626 MachineSDNode *CNode;
5628 Node->getOperand(3),
5634 Node->getOperand(6),
5636 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5637 ReplaceNode(Node, CNode);
5640 case Intrinsic::x86_tileloaddrs64:
5641 case Intrinsic::x86_tileloaddrst164:
5642 if (!Subtarget->hasAMXMOVRS())
5645 case Intrinsic::x86_tileloadd64:
5646 case Intrinsic::x86_tileloaddt164:
5647 case Intrinsic::x86_tilestored64: {
5648 if (!Subtarget->hasAMXTILE())
5651 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5652 MFI->setAMXProgModel(AMXProgModelEnum::DirectReg);
5656 case Intrinsic::x86_tileloadd64:
Opc = X86::PTILELOADD;
break;
5657 case Intrinsic::x86_tileloaddrs64:
5658 Opc = X86::PTILELOADDRS;
5660 case Intrinsic::x86_tileloaddt164:
Opc = X86::PTILELOADDT1;
break;
5661 case Intrinsic::x86_tileloaddrst164:
5662 Opc = X86::PTILELOADDRST1;
5664 case Intrinsic::x86_tilestored64:
Opc = X86::PTILESTORED;
break;
5667 unsigned TIndex =
Node->getConstantOperandVal(2);
5670 SDValue Scale = getI8Imm(1, dl);
5672 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5673 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5675 MachineSDNode *CNode;
5676 if (
Opc == X86::PTILESTORED) {
5678 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5681 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5683 ReplaceNode(Node, CNode);
5690 case X86ISD::NT_BRIND: {
5691 if (Subtarget->isTarget64BitILP32()) {
5696 assert(
Target.getValueType() == MVT::i32 &&
"Unexpected VT!");
5697 SDValue ZextTarget = CurDAG->getZExtOrTrunc(Target, dl, MVT::i64);
5698 SDValue Brind = CurDAG->getNode(Opcode, dl, MVT::Other,
5699 Node->getOperand(0), ZextTarget);
5700 ReplaceNode(Node, Brind.
getNode());
5701 SelectCode(ZextTarget.
getNode());
5708 ReplaceNode(Node, getGlobalBaseReg());
5715 ReplaceUses(
SDValue(Node, 0),
Node->getOperand(0));
5716 CurDAG->RemoveDeadNode(Node);
5722 if (matchBitExtract(Node))
5727 if (tryShiftAmountMod(Node))
5731 case X86ISD::VPTERNLOG: {
5732 uint8_t
Imm =
Node->getConstantOperandVal(3);
5733 if (matchVPTERNLOG(Node, Node, Node, Node,
Node->getOperand(0),
5740 if (tryVPTERNLOG(Node))
5750 tryVPTESTM(Node, N0, N1))
5753 tryVPTESTM(Node, N1, N0))
5757 if (MachineSDNode *NewNode = matchBEXTRFromAndImm(Node)) {
5759 CurDAG->RemoveDeadNode(Node);
5762 if (matchBitExtract(Node))
5770 if (tryShrinkShlLogicImm(Node))
5772 if (Opcode ==
ISD::OR && tryMatchBitSelect(Node))
5774 if (tryVPTERNLOG(Node))
5779 if (Opcode ==
ISD::ADD && matchBitExtract(Node))
5789 if (!CurDAG->shouldOptForSize())
5793 if (NVT != MVT::i8 && NVT != MVT::i16 && NVT != MVT::i32 && NVT != MVT::i64)
5803 int64_t Val = Cst->getSExtValue();
5811 if (Opcode ==
ISD::ADD && (Val == 1 || Val == -1))
5815 if (!shouldAvoidImmediateInstFormsForSize(N1.
getNode()))
5819 unsigned ROpc, MOpc;
5928 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5929 if (tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
5931 SDVTList VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
5932 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
5938 CurDAG->RemoveDeadNode(Node);
5943 CurDAG->SelectNodeTo(Node, ROpc, NVT, MVT::i32, N0, N1);
5952 case X86ISD::UMUL: {
5956 unsigned LoReg, ROpc, MOpc;
5961 ROpc = Opcode == X86ISD::SMUL ? X86::IMUL8r : X86::MUL8r;
5962 MOpc = Opcode == X86ISD::SMUL ? X86::IMUL8m : X86::MUL8m;
5981 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5982 bool FoldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
5985 FoldedLoad = tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
5993 orderRegForMul(N0, N1, LoReg, CurDAG->getMachineFunction().getRegInfo());
5995 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg,
5998 MachineSDNode *CNode;
6004 VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
6006 VTs = CurDAG->getVTList(NVT, NVT, MVT::i32, MVT::Other);
6010 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6021 VTs = CurDAG->getVTList(NVT, MVT::i32);
6023 VTs = CurDAG->getVTList(NVT, NVT, MVT::i32);
6025 CNode = CurDAG->getMachineNode(ROpc, dl, VTs, {N1, InGlue});
6029 ReplaceUses(
SDValue(Node, 1),
SDValue(CNode, NVT == MVT::i8 ? 1 : 2));
6030 CurDAG->RemoveDeadNode(Node);
6040 unsigned LoReg, HiReg;
6042 bool UseMULX = !IsSigned && Subtarget->hasBMI2();
6043 bool UseMULXHi = UseMULX &&
SDValue(Node, 0).use_empty();
6047 Opc = UseMULXHi ? X86::MULX32Hrr
6049 : IsSigned ?
X86::IMUL32r
6051 MOpc = UseMULXHi ? X86::MULX32Hrm
6053 : IsSigned ?
X86::IMUL32m
6055 LoReg = UseMULX ? X86::EDX : X86::EAX;
6059 Opc = UseMULXHi ? X86::MULX64Hrr
6061 : IsSigned ?
X86::IMUL64r
6063 MOpc = UseMULXHi ? X86::MULX64Hrm
6065 : IsSigned ?
X86::IMUL64m
6067 LoReg = UseMULX ? X86::RDX : X86::RAX;
6072 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6073 bool foldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6076 foldedLoad = tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6084 orderRegForMul(N0, N1, LoReg, CurDAG->getMachineFunction().getRegInfo());
6086 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg,
6091 MachineSDNode *CNode =
nullptr;
6095 SDVTList VTs = CurDAG->getVTList(NVT, MVT::Other);
6096 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6099 }
else if (UseMULX) {
6100 SDVTList VTs = CurDAG->getVTList(NVT, NVT, MVT::Other);
6101 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6106 SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue);
6107 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6113 ReplaceUses(N1.
getValue(1), Chain);
6119 SDVTList VTs = CurDAG->getVTList(NVT);
6120 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6122 }
else if (UseMULX) {
6123 SDVTList VTs = CurDAG->getVTList(NVT, NVT);
6124 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6128 SDVTList VTs = CurDAG->getVTList(MVT::Glue);
6129 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6135 if (!
SDValue(Node, 0).use_empty()) {
6137 assert(LoReg &&
"Register for low half is not defined!");
6138 ResLo = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, LoReg,
6142 ReplaceUses(
SDValue(Node, 0), ResLo);
6147 if (!
SDValue(Node, 1).use_empty()) {
6149 assert(HiReg &&
"Register for high half is not defined!");
6150 ResHi = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, HiReg,
6154 ReplaceUses(
SDValue(Node, 1), ResHi);
6159 CurDAG->RemoveDeadNode(Node);
6168 unsigned ROpc, MOpc;
6173 case MVT::i8: ROpc = X86::DIV8r; MOpc = X86::DIV8m;
break;
6174 case MVT::i16: ROpc = X86::DIV16r; MOpc = X86::DIV16m;
break;
6175 case MVT::i32: ROpc = X86::DIV32r; MOpc = X86::DIV32m;
break;
6176 case MVT::i64: ROpc = X86::DIV64r; MOpc = X86::DIV64m;
break;
6181 case MVT::i8: ROpc = X86::IDIV8r; MOpc = X86::IDIV8m;
break;
6182 case MVT::i16: ROpc = X86::IDIV16r; MOpc = X86::IDIV16m;
break;
6183 case MVT::i32: ROpc = X86::IDIV32r; MOpc = X86::IDIV32m;
break;
6184 case MVT::i64: ROpc = X86::IDIV64r; MOpc = X86::IDIV64m;
break;
6188 unsigned LoReg, HiReg, ClrReg;
6189 unsigned SExtOpcode;
6193 LoReg = X86::AL; ClrReg = HiReg = X86::AH;
6197 LoReg = X86::AX; HiReg = X86::DX;
6199 SExtOpcode = X86::CWD;
6202 LoReg = X86::EAX; ClrReg = HiReg = X86::EDX;
6203 SExtOpcode = X86::CDQ;
6206 LoReg = X86::RAX; ClrReg = HiReg = X86::RDX;
6207 SExtOpcode = X86::CQO;
6211 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6212 bool foldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6213 bool signBitIsZero = CurDAG->SignBitIsZero(N0);
6216 if (NVT == MVT::i8) {
6219 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Chain;
6220 MachineSDNode *Move;
6221 if (tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
6223 unsigned Opc = (
isSigned && !signBitIsZero) ? X86::MOVSX16rm8
6225 Move = CurDAG->getMachineNode(
Opc, dl, MVT::i16, MVT::Other,
Ops);
6227 ReplaceUses(N0.
getValue(1), Chain);
6231 unsigned Opc = (
isSigned && !signBitIsZero) ? X86::MOVSX16rr8
6233 Move = CurDAG->getMachineNode(
Opc, dl, MVT::i16, N0);
6234 Chain = CurDAG->getEntryNode();
6236 Chain = CurDAG->getCopyToReg(Chain, dl, X86::AX,
SDValue(Move, 0),
6241 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl,
6242 LoReg, N0,
SDValue()).getValue(1);
6246 SDValue(CurDAG->getMachineNode(SExtOpcode, dl, MVT::Glue, InGlue),0);
6249 SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::i32);
6251 SDValue(CurDAG->getMachineNode(X86::MOV32r0, dl, VTs, {}), 0);
6255 SDValue(CurDAG->getMachineNode(
6256 TargetOpcode::EXTRACT_SUBREG, dl, MVT::i16, ClrNode,
6257 CurDAG->getTargetConstant(X86::sub_16bit, dl,
6265 CurDAG->getMachineNode(
6266 TargetOpcode::SUBREG_TO_REG, dl, MVT::i64, ClrNode,
6267 CurDAG->getTargetConstant(X86::sub_32bit, dl, MVT::i32)),
6274 InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, ClrReg,
6275 ClrNode, InGlue).getValue(1);
6282 MachineSDNode *CNode =
6283 CurDAG->getMachineNode(MOpc, dl, MVT::Other, MVT::Glue,
Ops);
6291 SDValue(CurDAG->getMachineNode(ROpc, dl, MVT::Glue, N1, InGlue), 0);
6301 if (HiReg == X86::AH && !
SDValue(Node, 1).use_empty()) {
6302 SDValue AHCopy = CurDAG->getRegister(X86::AH, MVT::i8);
6303 unsigned AHExtOpcode =
6304 isSigned ? X86::MOVSX32rr8_NOREX : X86::MOVZX32rr8_NOREX;
6306 SDNode *RNode = CurDAG->getMachineNode(AHExtOpcode, dl, MVT::i32,
6307 MVT::Glue, AHCopy, InGlue);
6312 CurDAG->getTargetExtractSubreg(X86::sub_8bit, dl, MVT::i8, Result);
6314 ReplaceUses(
SDValue(Node, 1), Result);
6319 if (!
SDValue(Node, 0).use_empty()) {
6320 SDValue Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
6321 LoReg, NVT, InGlue);
6322 InGlue =
Result.getValue(2);
6323 ReplaceUses(
SDValue(Node, 0), Result);
6328 if (!
SDValue(Node, 1).use_empty()) {
6329 SDValue Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
6330 HiReg, NVT, InGlue);
6331 InGlue =
Result.getValue(2);
6332 ReplaceUses(
SDValue(Node, 1), Result);
6336 CurDAG->RemoveDeadNode(Node);
6341 case X86ISD::STRICT_FCMP:
6342 case X86ISD::STRICT_FCMPS: {
6343 bool IsStrictCmp =
Node->getOpcode() == X86ISD::STRICT_FCMP ||
6344 Node->getOpcode() == X86ISD::STRICT_FCMPS;
6345 SDValue N0 =
Node->getOperand(IsStrictCmp ? 1 : 0);
6346 SDValue N1 =
Node->getOperand(IsStrictCmp ? 2 : 1);
6352 if (Subtarget->canUseCMOV())
6355 bool IsSignaling =
Node->getOpcode() == X86ISD::STRICT_FCMPS;
6361 Opc = IsSignaling ? X86::COM_Fpr32 : X86::UCOM_Fpr32;
6364 Opc = IsSignaling ? X86::COM_Fpr64 : X86::UCOM_Fpr64;
6367 Opc = IsSignaling ? X86::COM_Fpr80 : X86::UCOM_Fpr80;
6372 IsStrictCmp ?
Node->getOperand(0) : CurDAG->getEntryNode();
6375 SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue);
6376 Chain =
SDValue(CurDAG->getMachineNode(
Opc, dl, VTs, {N0, N1, Chain}), 0);
6379 Glue =
SDValue(CurDAG->getMachineNode(
Opc, dl, MVT::Glue, N0, N1), 0);
6384 SDValue(CurDAG->getMachineNode(X86::FNSTSW16r, dl, MVT::i16, Glue), 0);
6388 CurDAG->getTargetExtractSubreg(X86::sub_8bit_hi, dl, MVT::i8, FNSTSW);
6392 assert(Subtarget->canUseLAHFSAHF() &&
6393 "Target doesn't support SAHF or FCOMI?");
6394 SDValue AH = CurDAG->getCopyToReg(Chain, dl, X86::AH, Extract,
SDValue());
6397 CurDAG->getMachineNode(X86::SAHF, dl, MVT::i32, AH.
getValue(1)), 0);
6400 ReplaceUses(
SDValue(Node, 1), Chain);
6402 ReplaceUses(
SDValue(Node, 0), SAHF);
6403 CurDAG->RemoveDeadNode(Node);
6423 if (MachineSDNode *NewNode = matchBEXTRFromAndImm(N0.
getNode())) {
6424 unsigned TestOpc = CmpVT == MVT::i64 ? X86::TEST64rr
6427 NewNode = CurDAG->getMachineNode(TestOpc, dl, MVT::i32, BEXTR, BEXTR);
6429 CurDAG->RemoveDeadNode(Node);
6456 onlyUsesZeroFlag(
SDValue(Node, 0))) {
6461 unsigned TestOpcode;
6469 if (LeadingZeros == 0 && SavesBytes) {
6474 ShiftAmt = TrailingZeros;
6476 TestOpcode = X86::TEST64rr;
6477 }
else if (TrailingZeros == 0 && SavesBytes) {
6483 if (LeadingZeros == 1) {
6487 MachineSDNode *
Add = CurDAG->getMachineNode(
6490 MachineSDNode *
Test = CurDAG->getMachineNode(
6492 ReplaceNode(Node,
Test);
6496 ShiftAmt = LeadingZeros;
6498 TestOpcode = X86::TEST64rr;
6499 }
else if (MaskC->hasOneUse() && !
isInt<32>(Mask)) {
6502 unsigned PopCount = 64 - LeadingZeros - TrailingZeros;
6503 if (PopCount == 8) {
6505 ShiftAmt = TrailingZeros;
6506 SubRegIdx = X86::sub_8bit;
6508 TestOpcode = X86::TEST8rr;
6509 }
else if (PopCount == 16) {
6511 ShiftAmt = TrailingZeros;
6512 SubRegIdx = X86::sub_16bit;
6513 SubRegVT = MVT::i16;
6514 TestOpcode = X86::TEST16rr;
6515 }
else if (PopCount == 32) {
6517 ShiftAmt = TrailingZeros;
6518 SubRegIdx = X86::sub_32bit;
6519 SubRegVT = MVT::i32;
6520 TestOpcode = X86::TEST32rr;
6524 SDValue ShiftC = CurDAG->getTargetConstant(ShiftAmt, dl, MVT::i64);
6526 CurDAG->getMachineNode(ShiftOpcode, dl, MVT::i64, MVT::i32,
6529 if (SubRegIdx != 0) {
6531 CurDAG->getTargetExtractSubreg(SubRegIdx, dl, SubRegVT, Shift);
6533 MachineSDNode *
Test =
6534 CurDAG->getMachineNode(TestOpcode, dl, MVT::i32, Shift, Shift);
6535 ReplaceNode(Node,
Test);
6542 unsigned ROpc, MOpc;
6550 (!(Mask & 0x80) || CmpVT == MVT::i8 ||
6551 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6554 SubRegOp = X86::sub_8bit;
6555 ROpc = X86::TEST8ri;
6556 MOpc = X86::TEST8mi;
6557 }
else if (OptForMinSize &&
isUInt<16>(Mask) &&
6558 (!(Mask & 0x8000) || CmpVT == MVT::i16 ||
6559 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6565 SubRegOp = X86::sub_16bit;
6566 ROpc = X86::TEST16ri;
6567 MOpc = X86::TEST16mi;
6569 ((!(Mask & 0x80000000) &&
6572 (CmpVT != MVT::i16 || !(Mask & 0x8000))) ||
6573 CmpVT == MVT::i32 ||
6574 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6581 SubRegOp = X86::sub_32bit;
6582 ROpc = X86::TEST32ri;
6583 MOpc = X86::TEST32mi;
6589 SDValue Imm = CurDAG->getTargetConstant(Mask, dl, VT);
6593 MachineSDNode *NewNode;
6594 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6595 if (tryFoldLoad(Node, N0.
getNode(),
Reg, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
6597 if (!LoadN->isSimple()) {
6598 unsigned NumVolBits = LoadN->getValueType(0).getSizeInBits();
6599 if ((MOpc == X86::TEST8mi && NumVolBits != 8) ||
6600 (MOpc == X86::TEST16mi && NumVolBits != 16) ||
6601 (MOpc == X86::TEST32mi && NumVolBits != 32))
6606 Reg.getOperand(0) };
6607 NewNode = CurDAG->getMachineNode(MOpc, dl, MVT::i32, MVT::Other,
Ops);
6609 ReplaceUses(
Reg.getValue(1),
SDValue(NewNode, 1));
6611 CurDAG->setNodeMemRefs(NewNode,
6616 Reg = CurDAG->getTargetExtractSubreg(SubRegOp, dl, VT,
Reg);
6618 NewNode = CurDAG->getMachineNode(ROpc, dl, MVT::i32,
Reg,
Imm);
6621 ReplaceNode(Node, NewNode);
6627 if (!Subtarget->hasSSE42())
6630 bool NeedIndex = !
SDValue(Node, 0).use_empty();
6631 bool NeedMask = !
SDValue(Node, 1).use_empty();
6633 bool MayFoldLoad = !NeedIndex || !NeedMask;
6635 MachineSDNode *CNode;
6638 Subtarget->hasAVX() ? X86::VPCMPISTRMrri : X86::PCMPISTRMrri;
6640 Subtarget->hasAVX() ? X86::VPCMPISTRMrmi : X86::PCMPISTRMrmi;
6641 CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node);
6644 if (NeedIndex || !NeedMask) {
6646 Subtarget->hasAVX() ? X86::VPCMPISTRIrri : X86::PCMPISTRIrri;
6648 Subtarget->hasAVX() ? X86::VPCMPISTRIrmi : X86::PCMPISTRIrmi;
6649 CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node);
6655 CurDAG->RemoveDeadNode(Node);
6659 if (!Subtarget->hasSSE42())
6663 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EAX,
6664 Node->getOperand(1),
6666 InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EDX,
6667 Node->getOperand(3), InGlue).getValue(1);
6669 bool NeedIndex = !
SDValue(Node, 0).use_empty();
6670 bool NeedMask = !
SDValue(Node, 1).use_empty();
6672 bool MayFoldLoad = !NeedIndex || !NeedMask;
6674 MachineSDNode *CNode;
6677 Subtarget->hasAVX() ? X86::VPCMPESTRMrri : X86::PCMPESTRMrri;
6679 Subtarget->hasAVX() ? X86::VPCMPESTRMrmi : X86::PCMPESTRMrmi;
6681 emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node, InGlue);
6684 if (NeedIndex || !NeedMask) {
6686 Subtarget->hasAVX() ? X86::VPCMPESTRIrri : X86::PCMPESTRIrri;
6688 Subtarget->hasAVX() ? X86::VPCMPESTRIrmi : X86::PCMPESTRIrmi;
6689 CNode = emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node, InGlue);
6694 CurDAG->RemoveDeadNode(Node);
6706 if (foldLoadStoreIntoMemOperand(Node))
6710 case X86ISD::SETCC_CARRY: {
6711 MVT VT =
Node->getSimpleValueType(0);
6713 if (Subtarget->hasSBBDepBreaking()) {
6718 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EFLAGS,
6723 unsigned Opc = VT == MVT::i64 ? X86::SETB_C64r : X86::SETB_C32r;
6724 MVT SetVT = VT == MVT::i64 ? MVT::i64 : MVT::i32;
6726 CurDAG->getMachineNode(
Opc, dl, SetVT, EFLAGS, EFLAGS.
getValue(1)),
6731 Result = getSBBZero(Node);
6735 if (VT == MVT::i8 || VT == MVT::i16) {
6736 int SubIndex = VT == MVT::i16 ? X86::sub_16bit : X86::sub_8bit;
6737 Result = CurDAG->getTargetExtractSubreg(SubIndex, dl, VT, Result);
6740 ReplaceUses(
SDValue(Node, 0), Result);
6741 CurDAG->RemoveDeadNode(Node);
6753 if (!
SDValue(Node, 0).use_empty()) {
6755 MVT VT =
Node->getSimpleValueType(0);
6756 if (VT == MVT::i8 || VT == MVT::i16) {
6757 int SubIndex = VT == MVT::i16 ? X86::sub_16bit : X86::sub_8bit;
6758 Result = CurDAG->getTargetExtractSubreg(SubIndex, dl, VT, Result);
6760 ReplaceUses(
SDValue(Node, 0), Result);
6763 CurDAG->RemoveDeadNode(Node);
6770 SDValue IndexOp = Mgt->getIndex();
6773 MVT ValueVT =
Node->getSimpleValueType(0);
6774 MVT MaskVT =
Mask.getSimpleValueType();
6791 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6792 Opc = IsFP ? X86::VGATHERDPSZ128rm : X86::VPGATHERDDZ128rm;
6793 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6794 Opc = IsFP ? X86::VGATHERDPSZ256rm : X86::VPGATHERDDZ256rm;
6795 else if (IndexVT == MVT::v16i32 && NumElts == 16 && EltSize == 32)
6796 Opc = IsFP ? X86::VGATHERDPSZrm : X86::VPGATHERDDZrm;
6797 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6798 Opc = IsFP ? X86::VGATHERDPDZ128rm : X86::VPGATHERDQZ128rm;
6799 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6800 Opc = IsFP ? X86::VGATHERDPDZ256rm : X86::VPGATHERDQZ256rm;
6801 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 64)
6802 Opc = IsFP ? X86::VGATHERDPDZrm : X86::VPGATHERDQZrm;
6803 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6804 Opc = IsFP ? X86::VGATHERQPSZ128rm : X86::VPGATHERQDZ128rm;
6805 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6806 Opc = IsFP ? X86::VGATHERQPSZ256rm : X86::VPGATHERQDZ256rm;
6807 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 32)
6808 Opc = IsFP ? X86::VGATHERQPSZrm : X86::VPGATHERQDZrm;
6809 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6810 Opc = IsFP ? X86::VGATHERQPDZ128rm : X86::VPGATHERQQZ128rm;
6811 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6812 Opc = IsFP ? X86::VGATHERQPDZ256rm : X86::VPGATHERQQZ256rm;
6813 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 64)
6814 Opc = IsFP ? X86::VGATHERQPDZrm : X86::VPGATHERQQZrm;
6816 assert(EVT(MaskVT) == EVT(ValueVT).changeVectorElementTypeToInteger() &&
6817 "Unexpected mask VT!");
6818 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6819 Opc = IsFP ? X86::VGATHERDPSrm : X86::VPGATHERDDrm;
6820 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6821 Opc = IsFP ? X86::VGATHERDPSYrm : X86::VPGATHERDDYrm;
6822 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6823 Opc = IsFP ? X86::VGATHERDPDrm : X86::VPGATHERDQrm;
6824 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6825 Opc = IsFP ? X86::VGATHERDPDYrm : X86::VPGATHERDQYrm;
6826 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6827 Opc = IsFP ? X86::VGATHERQPSrm : X86::VPGATHERQDrm;
6828 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6829 Opc = IsFP ? X86::VGATHERQPSYrm : X86::VPGATHERQDYrm;
6830 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6831 Opc = IsFP ? X86::VGATHERQPDrm : X86::VPGATHERQQrm;
6832 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6833 Opc = IsFP ? X86::VGATHERQPDYrm : X86::VPGATHERQQYrm;
6840 if (!selectVectorAddr(Mgt, Mgt->getBasePtr(), IndexOp, Mgt->getScale(),
6841 Base, Scale, Index, Disp, Segment))
6844 SDValue PassThru = Mgt->getPassThru();
6845 SDValue Chain = Mgt->getChain();
6847 SDVTList VTs = CurDAG->getVTList(ValueVT, MaskVT, MVT::Other);
6849 MachineSDNode *NewNode;
6852 Index, Disp, Segment, Chain};
6853 NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6856 Disp, Segment,
Mask, Chain};
6857 NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6859 CurDAG->setNodeMemRefs(NewNode, {Mgt->getMemOperand()});
6862 CurDAG->RemoveDeadNode(Node);
6868 SDValue IndexOp = Sc->getIndex();
6870 MVT ValueVT =
Value.getSimpleValueType();
6885 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6886 Opc = IsFP ? X86::VSCATTERDPSZ128mr : X86::VPSCATTERDDZ128mr;
6887 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6888 Opc = IsFP ? X86::VSCATTERDPSZ256mr : X86::VPSCATTERDDZ256mr;
6889 else if (IndexVT == MVT::v16i32 && NumElts == 16 && EltSize == 32)
6890 Opc = IsFP ? X86::VSCATTERDPSZmr : X86::VPSCATTERDDZmr;
6891 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6892 Opc = IsFP ? X86::VSCATTERDPDZ128mr : X86::VPSCATTERDQZ128mr;
6893 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6894 Opc = IsFP ? X86::VSCATTERDPDZ256mr : X86::VPSCATTERDQZ256mr;
6895 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 64)
6896 Opc = IsFP ? X86::VSCATTERDPDZmr : X86::VPSCATTERDQZmr;
6897 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6898 Opc = IsFP ? X86::VSCATTERQPSZ128mr : X86::VPSCATTERQDZ128mr;
6899 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6900 Opc = IsFP ? X86::VSCATTERQPSZ256mr : X86::VPSCATTERQDZ256mr;
6901 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 32)
6902 Opc = IsFP ? X86::VSCATTERQPSZmr : X86::VPSCATTERQDZmr;
6903 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6904 Opc = IsFP ? X86::VSCATTERQPDZ128mr : X86::VPSCATTERQQZ128mr;
6905 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6906 Opc = IsFP ? X86::VSCATTERQPDZ256mr : X86::VPSCATTERQQZ256mr;
6907 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 64)
6908 Opc = IsFP ? X86::VSCATTERQPDZmr : X86::VPSCATTERQQZmr;
6913 if (!selectVectorAddr(Sc, Sc->getBasePtr(), IndexOp, Sc->getScale(),
6914 Base, Scale, Index, Disp, Segment))
6918 SDValue Chain = Sc->getChain();
6920 SDVTList VTs = CurDAG->getVTList(
Mask.getValueType(), MVT::Other);
6923 MachineSDNode *NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6924 CurDAG->setNodeMemRefs(NewNode, {Sc->getMemOperand()});
6926 CurDAG->RemoveDeadNode(Node);
6930 auto *MFI = CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
6931 auto CallId = MFI->getPreallocatedIdForCallSite(
6934 SDValue CallIdValue = CurDAG->getTargetConstant(CallId, dl, MVT::i32);
6935 MachineSDNode *
New = CurDAG->getMachineNode(
6936 TargetOpcode::PREALLOCATED_SETUP, dl, MVT::Other, CallIdValue, Chain);
6938 CurDAG->RemoveDeadNode(Node);
6942 auto *MFI = CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
6946 SDValue CallIdValue = CurDAG->getTargetConstant(CallId, dl, MVT::i32);
6949 Ops[0] = CallIdValue;
6952 MachineSDNode *
New = CurDAG->getMachineNode(
6953 TargetOpcode::PREALLOCATED_ARG, dl,
6954 CurDAG->getVTList(TLI->
getPointerTy(CurDAG->getDataLayout()),
6959 CurDAG->RemoveDeadNode(Node);
6966 if (!Subtarget->hasWIDEKL())
6970 switch (
Node->getOpcode()) {
6974 Opcode = X86::AESENCWIDE128KL;
6977 Opcode = X86::AESDECWIDE128KL;
6980 Opcode = X86::AESENCWIDE256KL;
6983 Opcode = X86::AESDECWIDE256KL;
6991 if (!selectAddr(Node, Addr,
Base, Scale, Index, Disp, Segment))
6994 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM0,
Node->getOperand(2),
6996 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM1,
Node->getOperand(3),
6998 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM2,
Node->getOperand(4),
7000 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM3,
Node->getOperand(5),
7002 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM4,
Node->getOperand(6),
7004 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM5,
Node->getOperand(7),
7006 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM6,
Node->getOperand(8),
7008 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM7,
Node->getOperand(9),
7011 MachineSDNode *Res = CurDAG->getMachineNode(
7012 Opcode, dl,
Node->getVTList(),
7013 {Base, Scale, Index, Disp, Segment, Chain, Chain.getValue(1)});
7015 ReplaceNode(Node, Res);
7022 if (
Node->getNumValues() == 3)
7023 Glue =
Node->getOperand(2);
7025 CurDAG->getCopyFromReg(Chain, dl,
Reg,
Node->getValueType(0), Glue);
7026 ReplaceNode(Node,
Copy.getNode());
7034bool X86DAGToDAGISel::SelectInlineAsmMemoryOperand(
7036 std::vector<SDValue> &OutOps) {
7037 SDValue Op0, Op1, Op2, Op3, Op4;
7038 switch (ConstraintID) {
7041 case InlineAsm::ConstraintCode::o:
7042 case InlineAsm::ConstraintCode::v:
7043 case InlineAsm::ConstraintCode::m:
7044 case InlineAsm::ConstraintCode::X:
7045 case InlineAsm::ConstraintCode::p:
7046 if (!selectAddr(
nullptr,
Op, Op0, Op1, Op2, Op3, Op4))
7051 OutOps.push_back(Op0);
7052 OutOps.push_back(Op1);
7053 OutOps.push_back(Op2);
7054 OutOps.push_back(Op3);
7055 OutOps.push_back(Op4);
7061 std::make_unique<X86DAGToDAGISel>(TM, TM.getOptLevel())) {}
7067 return new X86DAGToDAGISelLegacy(TM, OptLevel);
static SDValue Widen(SelectionDAG *CurDAG, SDValue N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis false
#define CASE(ATTRNAME, AANAME,...)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
const MCPhysReg ArgGPRs[]
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool isFusableLoadOpStorePattern(StoreSDNode *StoreNode, SDValue StoredVal, SelectionDAG *CurDAG, LoadSDNode *&LoadNode, SDValue &InputChain)
static void insertDAGNode(SelectionDAG *DAG, SDNode *Pos, SDValue N)
static bool isRIPRelative(const MCInst &MI, const MCInstrInfo &MCII)
Check if the instruction uses RIP relative addressing.
#define FROM_TO(FROM, TO)
#define GET_EGPR_IF_ENABLED(OPC)
static bool isLegalMaskCompare(SDNode *N, const X86Subtarget *Subtarget)
static bool foldMaskAndShiftToScale(SelectionDAG &DAG, SDValue N, uint64_t Mask, SDValue Shift, SDValue X, X86ISelAddressMode &AM)
static bool foldMaskAndShiftToExtract(SelectionDAG &DAG, SDValue N, uint64_t Mask, SDValue Shift, SDValue X, X86ISelAddressMode &AM)
static bool needBWI(MVT VT)
static unsigned getVPTESTMOpc(MVT TestVT, bool IsTestN, bool FoldedLoad, bool FoldedBCast, bool Masked)
#define GET_NDM_IF_ENABLED(OPC)
static bool foldMaskedShiftToBEXTR(SelectionDAG &DAG, SDValue N, uint64_t Mask, SDValue Shift, SDValue X, X86ISelAddressMode &AM, const X86Subtarget &Subtarget)
static bool mayUseCarryFlag(X86::CondCode CC)
static cl::opt< bool > EnablePromoteAnyextLoad("x86-promote-anyext-load", cl::init(true), cl::desc("Enable promoting aligned anyext load to wider load"), cl::Hidden)
static 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.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MCRegister getLiveInPhysReg(Register VReg) const
getLiveInPhysReg - If VReg is a live-in virtual register, return the corresponding live-in physical r...
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
bool isNonTemporal() const
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
ArrayRef< SDUse > ops() const
int getNodeId() const
Return the unique node id.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
SDNodeFlags getFlags() const
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
const SDValue & getOperand(unsigned Num) const
bool hasNUsesOfValue(unsigned NUses, unsigned Value) const
Return true if there are exactly NUSES uses of the indicated value.
iterator_range< user_iterator > users()
op_iterator op_end() const
op_iterator op_begin() const
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
bool isMachineOpcode() const
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getMachineOpcode() const
unsigned getOpcode() const
unsigned getNumOperands() const
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
static int getUninvalidatedNodeId(SDNode *N)
virtual bool runOnMachineFunction(MachineFunction &mf)
static void InvalidateNodeId(SDNode *N)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
static constexpr unsigned MaxRecursionDepth
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
void RepositionNode(allnodes_iterator Position, SDNode *N)
Move node N in the AllNodes list to be immediately before the given iterator Position.
ilist< SDNode >::iterator allnodes_iterator
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool hasOneUse() const
Return true if there is exactly one use of this value.
X86ISelDAGToDAGPass(X86TargetMachine &TM)
size_t getPreallocatedIdForCallSite(const Value *CS)
bool isScalarFPTypeInSSEReg(EVT VT) const
Return true if the specified scalar FP type is computed in an SSE register, not on the X87 floating p...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ PREALLOCATED_SETUP
PREALLOCATED_SETUP - This has 2 operands: an input chain and a SRCVALUE with the preallocated call Va...
@ PREALLOCATED_ARG
PREALLOCATED_ARG - This has 3 operands: an input chain, a SRCVALUE with the preallocated call Value,...
@ BRIND
BRIND - Indirect branch.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ SHL
Shift and rotation operations.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ LOCAL_RECOVER
LOCAL_RECOVER - Represents the llvm.localrecover intrinsic.
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ CALLSEQ_START
CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end of a call sequence,...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
LLVM_ABI bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
@ GlobalBaseReg
The result of the mflr at function entry, used for PIC code.
@ X86
Windows x64, Windows Itanium (IA-64)
@ MO_NO_FLAG
MO_NO_FLAG - No flag for the operand.
@ EVEX
EVEX - Specifies that this instruction use EVEX form which provides syntax support up to 32 512-bit r...
@ VEX
VEX - encoding using 0xC4/0xC5.
@ XOP
XOP - Opcode prefix used by XOP instructions.
int getMemoryOperandNo(uint64_t TSFlags)
@ GlobalBaseReg
On Darwin, this node represents the result of the popl at function entry, used for PIC code.
@ POP_FROM_X87_REG
The same as ISD::CopyFromReg except that this node makes it explicit that it may lower to an x87 FPU ...
int getCondSrcNoFromDesc(const MCInstrDesc &MCID)
Return the source operand # for condition code by MCID.
bool mayFoldLoad(SDValue Op, const X86Subtarget &Subtarget, bool AssumeSingleUse=false, bool IgnoreAlignment=false)
Check if Op is a load operation that could be folded into some other x86 instruction as a memory oper...
bool isOffsetSuitableForCodeModel(int64_t Offset, CodeModel::Model M, bool hasSymbolicDisplacement)
Returns true of the given offset can be fit into displacement field of the instruction.
bool isConstantSplat(SDValue Op, APInt &SplatVal, bool AllowPartialUndefs)
If Op is a constant whose elements are all the same constant or undefined, return true and return the...
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool isa_and_nonnull(const Y &Val)
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
unsigned M1(unsigned Val)
auto dyn_cast_or_null(const Y &Val)
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
FunctionPass * createX86ISelDag(X86TargetMachine &TM, CodeGenOptLevel OptLevel)
This pass converts a legalized DAG into a X86-specific DAG, ready for instruction scheduling.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
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