22#include "llvm/Config/llvm-config.h"
27#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;
84 X86ISelAddressMode() =
default;
86 bool hasSymbolicDisplacement()
const {
87 return GV !=
nullptr || CP !=
nullptr || ES !=
nullptr ||
88 MCSym !=
nullptr || JT != -1 || BlockAddr !=
nullptr;
91 bool hasBaseOrIndexReg()
const {
92 return BaseType == FrameIndexBase ||
93 IndexReg.getNode() !=
nullptr || Base_Reg.getNode() !=
nullptr;
98 if (BaseType != RegBase)
return false;
99 if (RegisterSDNode *RegNode =
101 return RegNode->getReg() == X86::RIP;
110#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
111 void dump(SelectionDAG *DAG =
nullptr) {
112 dbgs() <<
"X86ISelAddressMode " <<
this <<
'\n';
113 dbgs() <<
"Base_Reg ";
114 if (Base_Reg.getNode())
115 Base_Reg.getNode()->dump(DAG);
118 if (BaseType == FrameIndexBase)
119 dbgs() <<
" Base.FrameIndex " << Base_FrameIndex <<
'\n';
120 dbgs() <<
" Scale " << Scale <<
'\n'
124 if (IndexReg.getNode())
125 IndexReg.getNode()->dump(DAG);
128 dbgs() <<
" Disp " << Disp <<
'\n'
150 dbgs() <<
" JT" << JT <<
" Align" << Alignment.value() <<
'\n';
164 const X86Subtarget *Subtarget;
170 bool IndirectTlsSegRefs;
173 X86DAGToDAGISel() =
delete;
175 explicit X86DAGToDAGISel(X86TargetMachine &tm,
CodeGenOptLevel OptLevel)
176 : SelectionDAGISel(tm, OptLevel), Subtarget(nullptr),
177 OptForMinSize(
false), IndirectTlsSegRefs(
false) {}
179 bool runOnMachineFunction(MachineFunction &MF)
override {
183 "indirect-tls-seg-refs");
190 void emitFunctionEntryCode()
override;
192 bool IsProfitableToFold(
SDValue N, SDNode *U, SDNode *Root)
const override;
194 void PreprocessISelDAG()
override;
195 void PostprocessISelDAG()
override;
198#include "X86GenDAGISel.inc"
201 void Select(SDNode *
N)
override;
203 bool foldOffsetIntoAddress(uint64_t
Offset, X86ISelAddressMode &AM);
204 bool matchLoadInAddress(LoadSDNode *
N, X86ISelAddressMode &AM,
205 bool AllowSegmentRegForX32 =
false);
206 bool matchWrapper(
SDValue N, X86ISelAddressMode &AM);
207 bool matchAddress(
SDValue N, X86ISelAddressMode &AM);
208 bool matchVectorAddress(
SDValue N, X86ISelAddressMode &AM);
209 bool matchAdd(
SDValue &
N, X86ISelAddressMode &AM,
unsigned Depth);
212 bool matchAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
214 bool matchVectorAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
216 bool matchAddressBase(
SDValue N, X86ISelAddressMode &AM);
220 bool selectVectorAddr(MemSDNode *Parent,
SDValue BasePtr,
SDValue IndexOp,
234 bool tryFoldLoad(SDNode *Root, SDNode *
P,
SDValue N,
244 return tryFoldLoad(
P,
P,
N,
Base, Scale, Index, Disp, Segment);
247 bool tryFoldBroadcast(SDNode *Root, SDNode *
P,
SDValue N,
252 bool isProfitableToFormMaskedOp(SDNode *
N)
const;
255 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
257 std::vector<SDValue> &OutOps)
override;
259 void emitSpecialCodeForMain();
261 inline void getAddressOperands(X86ISelAddressMode &AM,
const SDLoc &
DL,
265 if (AM.BaseType == X86ISelAddressMode::FrameIndexBase)
266 Base = CurDAG->getTargetFrameIndex(
267 AM.Base_FrameIndex, TLI->getPointerTy(CurDAG->getDataLayout()));
268 else if (AM.Base_Reg.
getNode())
271 Base = CurDAG->getRegister(0, VT);
273 Scale = getI8Imm(AM.Scale,
DL);
275#define GET_ND_IF_ENABLED(OPC) (Subtarget->hasNDD() ? OPC##_ND : OPC)
277 if (AM.NegateIndex) {
303 Index = CurDAG->getRegister(0, VT);
308 Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(),
312 Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, AM.Alignment,
313 AM.Disp, AM.SymbolFlags);
315 assert(!AM.Disp &&
"Non-zero displacement is ignored with ES.");
316 Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags);
317 }
else if (AM.MCSym) {
318 assert(!AM.Disp &&
"Non-zero displacement is ignored with MCSym.");
319 assert(AM.SymbolFlags == 0 &&
"oo");
320 Disp = CurDAG->getMCSymbol(AM.MCSym, MVT::i32);
321 }
else if (AM.JT != -1) {
322 assert(!AM.Disp &&
"Non-zero displacement is ignored with JT.");
323 Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags);
324 }
else if (AM.BlockAddr)
325 Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, AM.Disp,
328 Disp = CurDAG->getSignedTargetConstant(AM.Disp,
DL, MVT::i32);
331 Segment = AM.Segment;
333 Segment = CurDAG->getRegister(0, MVT::i16);
338 bool isAMXSDNode(SDNode *
N)
const {
342 for (
unsigned Idx = 0,
E =
N->getNumValues(); Idx !=
E; ++Idx) {
343 if (
N->getValueType(Idx) == MVT::x86amx)
346 for (
unsigned Idx = 0,
E =
N->getNumOperands(); Idx !=
E; ++Idx) {
348 if (
Op.getValueType() == MVT::x86amx)
360 bool shouldAvoidImmediateInstFormsForSize(SDNode *
N)
const {
361 uint32_t UseCount = 0;
366 if (!CurDAG->shouldOptForSize())
370 for (
const SDNode *User :
N->users()) {
376 if (
User->isMachineOpcode()) {
383 User->getOperand(1).getNode() ==
N) {
394 if (
User->getNumOperands() != 2)
407 if (
User->getOpcode() == X86ISD::ADD ||
409 User->getOpcode() == X86ISD::SUB ||
415 OtherOp =
User->getOperand(1);
418 RegisterSDNode *RegNode;
422 if ((RegNode->
getReg() == X86::ESP) ||
423 (RegNode->
getReg() == X86::RSP))
432 return (UseCount > 1);
436 inline SDValue getI8Imm(
unsigned Imm,
const SDLoc &
DL) {
437 return CurDAG->getTargetConstant(Imm,
DL, MVT::i8);
441 inline SDValue getI32Imm(
unsigned Imm,
const SDLoc &
DL) {
442 return CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
446 inline SDValue getI64Imm(uint64_t Imm,
const SDLoc &
DL) {
447 return CurDAG->getTargetConstant(Imm,
DL, MVT::i64);
450 SDValue getExtractVEXTRACTImmediate(SDNode *
N,
unsigned VecWidth,
452 assert((VecWidth == 128 || VecWidth == 256) &&
"Unexpected vector width");
453 uint64_t
Index =
N->getConstantOperandVal(1);
454 MVT VecVT =
N->getOperand(0).getSimpleValueType();
458 SDValue getInsertVINSERTImmediate(SDNode *
N,
unsigned VecWidth,
460 assert((VecWidth == 128 || VecWidth == 256) &&
"Unexpected vector width");
461 uint64_t
Index =
N->getConstantOperandVal(2);
462 MVT VecVT =
N->getSimpleValueType(0);
466 SDValue getPermuteVINSERTCommutedImmediate(SDNode *
N,
unsigned VecWidth,
468 assert(VecWidth == 128 &&
"Unexpected vector width");
469 uint64_t
Index =
N->getConstantOperandVal(2);
470 MVT VecVT =
N->getSimpleValueType(0);
472 assert((InsertIdx == 0 || InsertIdx == 1) &&
"Bad insertf128 index");
475 return getI8Imm(InsertIdx ? 0x02 : 0x30,
DL);
480 MVT VT =
N->getSimpleValueType(0);
483 SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::i32);
485 SDValue(CurDAG->getMachineNode(X86::MOV32r0, dl, VTs, {}), 0);
486 if (VT == MVT::i64) {
488 CurDAG->getMachineNode(
489 TargetOpcode::SUBREG_TO_REG, dl, MVT::i64, Zero,
490 CurDAG->getTargetConstant(X86::sub_32bit, dl, MVT::i32)),
495 unsigned Opcode =
N->getOpcode();
496 assert((Opcode == X86ISD::SBB || Opcode == X86ISD::SETCC_CARRY) &&
497 "Unexpected opcode for SBB materialization");
498 unsigned FlagOpIndex = Opcode == X86ISD::SBB ? 2 : 1;
500 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EFLAGS,
501 N->getOperand(FlagOpIndex),
SDValue());
505 unsigned Opc = VT == MVT::i64 ? X86::SBB64rr : X86::SBB32rr;
506 MVT SBBVT = VT == MVT::i64 ? MVT::i64 : MVT::i32;
507 VTs = CurDAG->getVTList(SBBVT, MVT::i32);
509 CurDAG->getMachineNode(
Opc, dl, VTs,
510 {Zero, Zero, EFLAGS, EFLAGS.getValue(1)}),
516 bool isUnneededShiftMask(SDNode *
N,
unsigned Width)
const {
518 const APInt &Val =
N->getConstantOperandAPInt(1);
523 APInt
Mask = Val | CurDAG->computeKnownBits(
N->getOperand(0)).Zero;
524 return Mask.countr_one() >= Width;
530 SDNode *getGlobalBaseReg();
534 const X86TargetMachine &getTargetMachine()
const {
535 return static_cast<const X86TargetMachine &
>(TM);
540 const X86InstrInfo *getInstrInfo()
const {
541 return Subtarget->getInstrInfo();
550 bool ComplexPatternFuncMutatesDAG()
const override {
554 bool isSExtAbsoluteSymbolRef(
unsigned Width, SDNode *
N)
const;
557 bool useNonTemporalLoad(LoadSDNode *
N)
const {
558 if (!
N->isNonTemporal())
561 unsigned StoreSize =
N->getMemoryVT().getStoreSize();
563 if (
N->getAlign().value() < StoreSize)
572 return Subtarget->hasSSE41();
574 return Subtarget->hasAVX2();
576 return Subtarget->hasAVX512();
580 bool foldLoadStoreIntoMemOperand(SDNode *Node);
581 MachineSDNode *matchBEXTRFromAndImm(SDNode *Node);
582 bool matchBitExtract(SDNode *Node);
583 bool shrinkAndImmediate(SDNode *
N);
584 bool isMaskZeroExtended(SDNode *
N)
const;
585 bool tryShiftAmountMod(SDNode *
N);
586 bool tryShrinkShlLogicImm(SDNode *
N);
587 bool tryVPTERNLOG(SDNode *
N);
588 bool matchVPTERNLOG(SDNode *Root, SDNode *ParentA, SDNode *ParentB,
592 bool tryMatchBitSelect(SDNode *
N);
594 MachineSDNode *emitPCMPISTR(
unsigned ROpc,
unsigned MOpc,
bool MayFoldLoad,
595 const SDLoc &dl, MVT VT, SDNode *Node);
596 MachineSDNode *emitPCMPESTR(
unsigned ROpc,
unsigned MOpc,
bool MayFoldLoad,
597 const SDLoc &dl, MVT VT, SDNode *Node,
600 bool tryOptimizeRem8Extend(SDNode *
N);
602 bool onlyUsesZeroFlag(
SDValue Flags)
const;
603 bool hasNoSignFlagUses(
SDValue Flags)
const;
604 bool hasNoCarryFlagUses(
SDValue Flags)
const;
605 bool checkTCRetEnoughRegs(SDNode *
N)
const;
611 explicit X86DAGToDAGISelLegacy(X86TargetMachine &tm,
613 : SelectionDAGISelLegacy(
614 ID, std::make_unique<X86DAGToDAGISel>(tm, OptLevel)) {}
618char X86DAGToDAGISelLegacy::ID = 0;
625 unsigned Opcode =
N->getOpcode();
626 if (Opcode == X86ISD::CMPM || Opcode == X86ISD::CMPMM ||
627 Opcode == X86ISD::STRICT_CMPM || Opcode ==
ISD::SETCC ||
628 Opcode == X86ISD::CMPMM_SAE || Opcode == X86ISD::VFPCLASS) {
632 EVT OpVT =
N->getOperand(0).getValueType();
635 if (Opcode == X86ISD::STRICT_CMPM)
636 OpVT =
N->getOperand(1).getValueType();
638 return Subtarget->hasVLX();
643 if (Opcode == X86ISD::VFPCLASSS || Opcode == X86ISD::FSETCCM ||
644 Opcode == X86ISD::FSETCCM_SAE)
652bool X86DAGToDAGISel::isMaskZeroExtended(
SDNode *
N)
const {
664X86DAGToDAGISel::IsProfitableToFold(
SDValue N, SDNode *U, SDNode *Root)
const {
665 if (OptLevel == CodeGenOptLevel::None)
680 switch (
U->getOpcode()) {
707 if (
Imm->getAPIntValue().isSignedIntN(8))
716 Imm->getAPIntValue().getBitWidth() == 64 &&
717 Imm->getAPIntValue().isIntN(32))
724 (
Imm->getAPIntValue() == UINT8_MAX ||
725 Imm->getAPIntValue() == UINT16_MAX ||
726 Imm->getAPIntValue() == UINT32_MAX))
732 (-
Imm->getAPIntValue()).isSignedIntN(8))
735 if ((
U->getOpcode() == X86ISD::ADD ||
U->getOpcode() == X86ISD::SUB) &&
736 (-
Imm->getAPIntValue()).isSignedIntN(8) &&
737 hasNoCarryFlagUses(
SDValue(U, 1)))
751 if (Op1.
getOpcode() == X86ISD::Wrapper) {
762 if (
U->getOperand(0).getOpcode() ==
ISD::SHL &&
766 if (
U->getOperand(1).getOpcode() ==
ISD::SHL &&
775 if (
C &&
C->getSExtValue() == -2)
781 if (
C &&
C->getSExtValue() == -2)
816bool X86DAGToDAGISel::isProfitableToFormMaskedOp(SDNode *
N)
const {
818 (
N->getOpcode() ==
ISD::VSELECT ||
N->getOpcode() == X86ISD::SELECTS) &&
819 "Unexpected opcode!");
824 return N->getOperand(1).hasOneUse();
833 if (Chain.
getNode() == Load.getNode())
834 Ops.push_back(Load.getOperand(0));
837 "Unexpected chain operand");
840 Ops.push_back(Load.getOperand(0));
846 Ops.push_back(NewChain);
851 Load.getOperand(1), Load.getOperand(2));
869 if (Callee.getNode() == Chain.
getNode() || !Callee.hasOneUse())
881 if (!Callee.getValue(1).hasOneUse())
912 Callee.getValue(1).hasOneUse())
929 if ((Imm & 0x00FFFFFF) != 0x0F1EFA)
932 uint8_t OptionalPrefixBytes [] = {0x26, 0x2e, 0x36, 0x3e, 0x64,
933 0x65, 0x66, 0x67, 0xf0, 0xf2};
936 uint8_t Byte = (Imm >> i) & 0xFF;
948 return (VT == MVT::v32i16 || VT == MVT::v32f16 || VT == MVT::v64i8);
951void X86DAGToDAGISel::PreprocessISelDAG() {
952 bool MadeChange =
false;
954 E = CurDAG->allnodes_end();
I !=
E; ) {
973 MVT VT =
N->getSimpleValueType(0);
975 int32_t EndbrImm = Subtarget->is64Bit() ? 0xF30F1EFA : 0xF30F1EFB;
980 "cf-protection-branch");
983 SDValue Complement = CurDAG->getConstant(~Imm, dl, VT,
false,
true);
984 Complement = CurDAG->getNOT(dl, Complement, VT);
986 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Complement);
996 if (
N->getOpcode() == X86ISD::AND && !
N->hasAnyUseOfValue(1)) {
998 N->getOperand(0),
N->getOperand(1));
1000 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1024 auto mayPreventLoadFold = [&]() {
1026 N->getOpcode() ==
ISD::ADD && Subtarget->hasAVX() &&
1027 !
N->getOperand(1).hasOneUse();
1030 N->getSimpleValueType(0).isVector() && !mayPreventLoadFold()) {
1038 MVT VT =
N->getSimpleValueType(0);
1046 CurDAG->getNode(NewOpcode,
DL, VT,
N->getOperand(0),
AllOnes);
1048 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1055 switch (
N->getOpcode()) {
1056 case X86ISD::VBROADCAST: {
1057 MVT VT =
N->getSimpleValueType(0);
1059 if (!Subtarget->hasBWI() &&
needBWI(VT)) {
1063 CurDAG->getNode(X86ISD::VBROADCAST, dl, NarrowVT,
N->getOperand(0));
1066 NarrowBCast, CurDAG->getIntPtrConstant(0, dl));
1069 CurDAG->getIntPtrConstant(Index, dl));
1072 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1080 case X86ISD::VBROADCAST_LOAD: {
1081 MVT VT =
N->getSimpleValueType(0);
1083 if (!Subtarget->hasBWI() &&
needBWI(VT)) {
1087 SDVTList VTs = CurDAG->getVTList(NarrowVT, MVT::Other);
1088 SDValue Ops[] = {MemNode->getChain(), MemNode->getBasePtr()};
1089 SDValue NarrowBCast = CurDAG->getMemIntrinsicNode(
1090 X86ISD::VBROADCAST_LOAD, dl, VTs,
Ops, MemNode->getMemoryVT(),
1091 MemNode->getMemOperand());
1094 NarrowBCast, CurDAG->getIntPtrConstant(0, dl));
1097 CurDAG->getIntPtrConstant(Index, dl));
1101 CurDAG->ReplaceAllUsesWith(
N, To);
1113 MVT VT =
N->getSimpleValueType(0);
1119 SDNode *MaxLd =
nullptr;
1120 SDValue Ptr = Ld->getBasePtr();
1121 SDValue Chain = Ld->getChain();
1122 for (SDNode *User : Ptr->
users()) {
1124 MVT UserVT =
User->getSimpleValueType(0);
1126 UserLd->getBasePtr() == Ptr && UserLd->getChain() == Chain &&
1127 !
User->hasAnyUseOfValue(1) &&
1141 CurDAG->getIntPtrConstant(0, dl));
1142 SDValue Res = CurDAG->getBitcast(VT, Extract);
1146 CurDAG->ReplaceAllUsesWith(
N, To);
1155 EVT EleVT =
N->getOperand(0).getValueType().getVectorElementType();
1156 if (EleVT == MVT::i1)
1159 assert(Subtarget->hasSSE41() &&
"Expected SSE4.1 support!");
1160 assert(
N->getValueType(0).getVectorElementType() != MVT::i16 &&
1161 "We can't replace VSELECT with BLENDV in vXi16!");
1163 if (Subtarget->hasVLX() && CurDAG->ComputeNumSignBits(
N->getOperand(0)) ==
1165 R = CurDAG->getNode(X86ISD::VPTERNLOG, SDLoc(
N),
N->getValueType(0),
1166 N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
1167 CurDAG->getTargetConstant(0xCA, SDLoc(
N), MVT::i8));
1169 R = CurDAG->getNode(X86ISD::BLENDV, SDLoc(
N),
N->getValueType(0),
1170 N->getOperand(0),
N->getOperand(1),
1174 CurDAG->ReplaceAllUsesWith(
N,
R.getNode());
1187 if (!
N->getSimpleValueType(0).isVector())
1191 switch (
N->getOpcode()) {
1201 if (
N->isStrictFPOpcode())
1203 CurDAG->getNode(NewOpc, SDLoc(
N), {
N->getValueType(0), MVT::Other},
1204 {
N->getOperand(0),
N->getOperand(1)});
1207 CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1210 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1220 if (!
N->getValueType(0).isVector())
1224 switch (
N->getOpcode()) {
1226 case ISD::SHL: NewOpc = X86ISD::VSHLV;
break;
1227 case ISD::SRA: NewOpc = X86ISD::VSRAV;
break;
1228 case ISD::SRL: NewOpc = X86ISD::VSRLV;
break;
1230 SDValue Res = CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1231 N->getOperand(0),
N->getOperand(1));
1233 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1242 if (!
N->getValueType(0).isVector())
1246 if (
N->getOperand(0).getScalarValueSizeInBits() == 1) {
1248 "Unexpected opcode for mask vector!");
1256 SDValue Res = CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1259 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1279 switch (
N->getOpcode()) {
1295 bool IsStrict =
N->isStrictFPOpcode();
1298 Res = CurDAG->getNode(X86ISD::STRICT_VRNDSCALE, dl,
1299 {
N->getValueType(0), MVT::Other},
1300 {
N->getOperand(0),
N->getOperand(1),
1301 CurDAG->getTargetConstant(Imm, dl, MVT::i32)});
1303 Res = CurDAG->getNode(X86ISD::VRNDSCALE, dl,
N->getValueType(0),
1305 CurDAG->getTargetConstant(Imm, dl, MVT::i32));
1307 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1315 case X86ISD::FXOR: {
1318 MVT VT =
N->getSimpleValueType(0);
1319 if (VT.
isVector() || VT == MVT::f128)
1322 MVT VecVT = VT == MVT::f64 ? MVT::v2f64
1323 : VT == MVT::f32 ? MVT::v4f32
1333 if (Subtarget->hasSSE2()) {
1334 EVT IntVT = EVT(VecVT).changeVectorElementTypeToInteger();
1338 switch (
N->getOpcode()) {
1340 case X86ISD::FANDN:
Opc = X86ISD::ANDNP;
break;
1345 Res = CurDAG->getNode(
Opc, dl, IntVT, Op0, Op1);
1348 Res = CurDAG->getNode(
N->getOpcode(), dl, VecVT, Op0, Op1);
1351 CurDAG->getIntPtrConstant(0, dl));
1353 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1360 if (OptLevel != CodeGenOptLevel::None &&
1363 !Subtarget->useIndirectThunkCalls() &&
1364 ((
N->getOpcode() == X86ISD::CALL && !Subtarget->slowTwoMemOps()) ||
1365 (
N->getOpcode() == X86ISD::TC_RETURN &&
1366 (Subtarget->is64Bit() ||
1367 !getTargetMachine().isPositionIndependent())))) {
1387 bool HasCallSeq =
N->getOpcode() == X86ISD::CALL;
1392 if (
N->getOpcode() == X86ISD::TC_RETURN && !checkTCRetEnoughRegs(
N))
1408 switch (
N->getOpcode()) {
1413 MVT SrcVT =
N->getOperand(0).getSimpleValueType();
1414 MVT DstVT =
N->getSimpleValueType(0);
1422 const X86TargetLowering *X86Lowering =
1423 static_cast<const X86TargetLowering *
>(TLI);
1426 if (SrcIsSSE && DstIsSSE)
1429 if (!SrcIsSSE && !DstIsSSE) {
1434 if (
N->getConstantOperandVal(1))
1442 SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
1444 MachinePointerInfo MPI =
1451 CurDAG->getEntryNode(), dl,
N->getOperand(0), MemTmp, MPI, MemVT);
1453 MemTmp, MPI, MemVT);
1460 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Result);
1469 MVT SrcVT =
N->getOperand(1).getSimpleValueType();
1470 MVT DstVT =
N->getSimpleValueType(0);
1478 const X86TargetLowering *X86Lowering =
1479 static_cast<const X86TargetLowering *
>(TLI);
1482 if (SrcIsSSE && DstIsSSE)
1485 if (!SrcIsSSE && !DstIsSSE) {
1490 if (
N->getConstantOperandVal(2))
1498 SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
1500 MachinePointerInfo MPI =
1509 SDVTList VTs = CurDAG->getVTList(MVT::Other);
1510 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), MemTmp};
1511 Store = CurDAG->getMemIntrinsicNode(X86ISD::FST, dl, VTs,
Ops, MemVT,
1514 if (
N->getFlags().hasNoFPExcept()) {
1516 Flags.setNoFPExcept(
true);
1517 Store->setFlags(Flags);
1520 assert(SrcVT == MemVT &&
"Unexpected VT!");
1521 Store = CurDAG->getStore(
N->getOperand(0), dl,
N->getOperand(1), MemTmp,
1526 SDVTList VTs = CurDAG->getVTList(DstVT, MVT::Other);
1528 Result = CurDAG->getMemIntrinsicNode(
1529 X86ISD::FLD, dl, VTs,
Ops, MemVT, MPI,
1531 if (
N->getFlags().hasNoFPExcept()) {
1533 Flags.setNoFPExcept(
true);
1537 assert(DstVT == MemVT &&
"Unexpected VT!");
1538 Result = CurDAG->getLoad(DstVT, dl, Store, MemTmp, MPI);
1546 CurDAG->ReplaceAllUsesWith(
N,
Result.getNode());
1560 CurDAG->RemoveDeadNodes();
1564bool X86DAGToDAGISel::tryOptimizeRem8Extend(SDNode *
N) {
1565 unsigned Opc =
N->getMachineOpcode();
1566 if (
Opc != X86::MOVZX32rr8 &&
Opc != X86::MOVSX32rr8 &&
1567 Opc != X86::MOVSX64rr8)
1579 unsigned ExpectedOpc =
Opc == X86::MOVZX32rr8 ? X86::MOVZX32rr8_NOREX
1580 : X86::MOVSX32rr8_NOREX;
1585 if (
Opc == X86::MOVSX64rr8) {
1588 MachineSDNode *Extend = CurDAG->getMachineNode(X86::MOVSX64rr32, SDLoc(
N),
1590 ReplaceUses(
N, Extend);
1599void X86DAGToDAGISel::PostprocessISelDAG() {
1601 if (TM.getOptLevel() == CodeGenOptLevel::None)
1606 bool MadeChange =
false;
1607 while (Position != CurDAG->allnodes_begin()) {
1608 SDNode *
N = &*--Position;
1610 if (
N->use_empty() || !
N->isMachineOpcode())
1613 if (tryOptimizeRem8Extend(
N)) {
1618 unsigned Opc =
N->getMachineOpcode();
1629 case X86::CTEST16rr:
1630 case X86::CTEST32rr:
1631 case X86::CTEST64rr: {
1637#define CASE_ND(OP) \
1640 switch (
And.getMachineOpcode()) {
1647 if (
And->hasAnyUseOfValue(1))
1650 Ops[0] =
And.getOperand(0);
1651 Ops[1] =
And.getOperand(1);
1652 MachineSDNode *
Test =
1653 CurDAG->getMachineNode(
Opc, SDLoc(
N), MVT::i32,
Ops);
1654 ReplaceUses(
N,
Test);
1662 if (
And->hasAnyUseOfValue(1))
1665 bool IsCTESTCC = X86::isCTESTCC(
Opc);
1666#define FROM_TO(A, B) \
1667 CASE_ND(A) NewOpc = IsCTESTCC ? X86::C##B : X86::B; \
1669 switch (
And.getMachineOpcode()) {
1679 And.getOperand(3),
And.getOperand(4),
1680 And.getOperand(5),
And.getOperand(0)};
1683 Ops.push_back(
N->getOperand(2));
1684 Ops.push_back(
N->getOperand(3));
1687 Ops.push_back(
And.getOperand(6));
1690 Ops.push_back(
N->getOperand(4));
1692 MachineSDNode *
Test = CurDAG->getMachineNode(
1693 NewOpc, SDLoc(
N), MVT::i32, MVT::Other,
Ops);
1694 CurDAG->setNodeMemRefs(
1707 case X86::KORTESTBkk:
1708 case X86::KORTESTWkk:
1709 case X86::KORTESTDkk:
1710 case X86::KORTESTQkk: {
1712 if (Op0 !=
N->getOperand(1) || !
N->isOnlyUserOf(Op0.
getNode()) ||
1727#define FROM_TO(A, B) \
1739 if (NewOpc == X86::KTESTWkk && !Subtarget->hasDQI())
1742 MachineSDNode *KTest = CurDAG->getMachineNode(
1744 ReplaceUses(
N, KTest);
1749 case TargetOpcode::SUBREG_TO_REG: {
1750 unsigned SubRegIdx =
N->getConstantOperandVal(1);
1751 if (SubRegIdx != X86::sub_xmm && SubRegIdx != X86::sub_ymm)
1768 CASE(VMOVAPDZ128rr)
CASE(VMOVUPDZ128rr)
1769 CASE(VMOVAPSZ128rr)
CASE(VMOVUPSZ128rr)
1770 CASE(VMOVDQA32Z128rr)
CASE(VMOVDQU32Z128rr)
1771 CASE(VMOVDQA64Z128rr)
CASE(VMOVDQU64Z128rr)
1772 CASE(VMOVAPDZ256rr)
CASE(VMOVUPDZ256rr)
1773 CASE(VMOVAPSZ256rr)
CASE(VMOVUPSZ256rr)
1774 CASE(VMOVDQA32Z256rr)
CASE(VMOVDQU32Z256rr)
1775 CASE(VMOVDQA64Z256rr)
CASE(VMOVDQU64Z256rr)
1780 if (!
In.isMachineOpcode() ||
1781 In.getMachineOpcode() <= TargetOpcode::GENERIC_OP_END)
1786 uint64_t TSFlags = getInstrInfo()->get(
In.getMachineOpcode()).TSFlags;
1794 CurDAG->UpdateNodeOperands(
N, In,
N->getOperand(1));
1801 CurDAG->RemoveDeadNodes();
1806void X86DAGToDAGISel::emitSpecialCodeForMain() {
1807 if (Subtarget->isTargetCygMing()) {
1808 TargetLowering::ArgListTy
Args;
1809 auto &
DL = CurDAG->getDataLayout();
1811 TargetLowering::CallLoweringInfo CLI(*CurDAG);
1812 CLI.setChain(CurDAG->getRoot())
1813 .setCallee(CallingConv::C, Type::getVoidTy(*CurDAG->getContext()),
1814 CurDAG->getExternalSymbol(
"__main", TLI->getPointerTy(
DL)),
1816 const TargetLowering &TLI = CurDAG->getTargetLoweringInfo();
1818 CurDAG->setRoot(
Result.second);
1822void X86DAGToDAGISel::emitFunctionEntryCode() {
1825 if (
F.hasExternalLinkage() &&
F.getName() ==
"main")
1826 emitSpecialCodeForMain();
1839bool X86DAGToDAGISel::foldOffsetIntoAddress(uint64_t
Offset,
1840 X86ISelAddressMode &AM) {
1845 int64_t Val = AM.Disp +
Offset;
1848 if (Val != 0 && (AM.ES || AM.MCSym))
1852 if (Subtarget->is64Bit()) {
1855 AM.hasSymbolicDisplacement()))
1859 if (AM.BaseType == X86ISelAddressMode::FrameIndexBase &&
1878 if (Subtarget->isTarget64BitILP32() &&
1880 !AM.hasBaseOrIndexReg())
1882 }
else if (Subtarget->is16Bit()) {
1885 if (Val < -(int64_t)UINT16_MAX || Val > (int64_t)UINT16_MAX)
1895bool X86DAGToDAGISel::matchLoadInAddress(LoadSDNode *
N, X86ISelAddressMode &AM,
1896 bool AllowSegmentRegForX32) {
1909 !IndirectTlsSegRefs &&
1910 (Subtarget->isTargetGlibc() || Subtarget->isTargetMusl() ||
1911 Subtarget->isTargetAndroid() || Subtarget->isTargetFuchsia())) {
1912 if (Subtarget->isTarget64BitILP32() && !AllowSegmentRegForX32)
1914 switch (
N->getPointerInfo().getAddrSpace()) {
1916 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
1919 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
1932bool X86DAGToDAGISel::matchWrapper(
SDValue N, X86ISelAddressMode &AM) {
1935 if (AM.hasSymbolicDisplacement())
1938 bool IsRIPRelTLS =
false;
1939 bool IsRIPRel =
N.getOpcode() == X86ISD::WrapperRIP;
1956 if (IsRIPRel && AM.hasBaseOrIndexReg())
1960 X86ISelAddressMode Backup = AM;
1965 AM.GV =
G->getGlobal();
1966 AM.SymbolFlags =
G->getTargetFlags();
1969 AM.CP = CP->getConstVal();
1970 AM.Alignment = CP->getAlign();
1971 AM.SymbolFlags = CP->getTargetFlags();
1972 Offset = CP->getOffset();
1974 AM.ES = S->getSymbol();
1975 AM.SymbolFlags = S->getTargetFlags();
1977 AM.MCSym = S->getMCSymbol();
1979 AM.JT = J->getIndex();
1980 AM.SymbolFlags = J->getTargetFlags();
1982 AM.BlockAddr = BA->getBlockAddress();
1983 AM.SymbolFlags = BA->getTargetFlags();
1984 Offset = BA->getOffset();
1989 if (Subtarget->is64Bit() && !IsRIPRel && AM.GV &&
1990 TM.isLargeGlobalValue(AM.GV)) {
1995 if (foldOffsetIntoAddress(
Offset, AM)) {
2001 AM.setBaseReg(CurDAG->getRegister(X86::RIP, MVT::i64));
2009bool X86DAGToDAGISel::matchAddress(
SDValue N, X86ISelAddressMode &AM) {
2010 if (matchAddressRecursively(
N, AM, 0))
2017 if (Subtarget->isTarget64BitILP32() &&
2018 AM.BaseType == X86ISelAddressMode::RegBase &&
2019 AM.Base_Reg.
getNode() !=
nullptr && AM.IndexReg.
getNode() ==
nullptr) {
2020 SDValue Save_Base_Reg = AM.Base_Reg;
2023 if (matchLoadInAddress(LoadN, AM,
true))
2024 AM.Base_Reg = Save_Base_Reg;
2030 if (AM.Scale == 2 &&
2031 AM.BaseType == X86ISelAddressMode::RegBase &&
2032 AM.Base_Reg.
getNode() ==
nullptr) {
2033 AM.Base_Reg = AM.IndexReg;
2040 (!AM.GV || !TM.isLargeGlobalValue(AM.GV)) && Subtarget->is64Bit() &&
2041 AM.Scale == 1 && AM.BaseType == X86ISelAddressMode::RegBase &&
2042 AM.Base_Reg.
getNode() ==
nullptr && AM.IndexReg.
getNode() ==
nullptr &&
2054 AM.Base_Reg = CurDAG->getRegister(X86::RIP, MVT::i64);
2060bool X86DAGToDAGISel::matchAdd(
SDValue &
N, X86ISelAddressMode &AM,
2064 HandleSDNode Handle(
N);
2066 X86ISelAddressMode Backup = AM;
2067 if (!matchAddressRecursively(
N.getOperand(0), AM,
Depth+1) &&
2068 !matchAddressRecursively(Handle.getValue().getOperand(1), AM,
Depth+1))
2073 if (!matchAddressRecursively(Handle.getValue().getOperand(1), AM,
2075 !matchAddressRecursively(Handle.getValue().getOperand(0), AM,
Depth + 1))
2082 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2085 N = Handle.getValue();
2091 N = Handle.getValue();
2101 if (
N->getNodeId() == -1 ||
2121 X86ISelAddressMode &AM) {
2128 if (ScaleLog <= 0 || ScaleLog >= 4 ||
2129 Mask != (0xffu << ScaleLog))
2132 MVT XVT =
X.getSimpleValueType();
2133 MVT VT =
N.getSimpleValueType();
2158 AM.Scale = (1 << ScaleLog);
2166 X86ISelAddressMode &AM) {
2177 bool FoundAnyExtend =
false;
2181 FoundAnyExtend =
true;
2199 if (ShiftAmt != 1 && ShiftAmt != 2 && ShiftAmt != 3)
2202 MVT VT =
N.getSimpleValueType();
2204 if (FoundAnyExtend) {
2225 AM.Scale = 1 << ShiftAmt;
2226 AM.IndexReg = NewAnd;
2260 X86ISelAddressMode &AM) {
2266 unsigned MaskIdx, MaskLen;
2269 unsigned MaskLZ = 64 - (MaskIdx + MaskLen);
2275 unsigned AMShiftAmt = MaskIdx;
2279 if (AMShiftAmt == 0 || AMShiftAmt > 3)
return true;
2283 unsigned ScaleDown = (64 -
X.getSimpleValueType().getSizeInBits()) + ShiftAmt;
2284 if (MaskLZ < ScaleDown)
2286 MaskLZ -= ScaleDown;
2294 bool ReplacingAnyExtend =
false;
2296 unsigned ExtendBits =
X.getSimpleValueType().getSizeInBits() -
2297 X.getOperand(0).getSimpleValueType().getSizeInBits();
2300 X =
X.getOperand(0);
2301 MaskLZ = ExtendBits > MaskLZ ? 0 : MaskLZ - ExtendBits;
2302 ReplacingAnyExtend =
true;
2304 APInt MaskedHighBits =
2311 MVT VT =
N.getSimpleValueType();
2312 if (ReplacingAnyExtend) {
2313 assert(
X.getValueType() != VT);
2320 MVT XVT =
X.getSimpleValueType();
2341 AM.Scale = 1 << AMShiftAmt;
2342 AM.IndexReg = NewExt;
2352 X86ISelAddressMode &AM,
2360 if (!Subtarget.hasTBM() &&
2361 !(Subtarget.hasBMI() && Subtarget.hasFastBEXTR()))
2365 unsigned MaskIdx, MaskLen;
2373 unsigned AMShiftAmt = MaskIdx;
2377 if (AMShiftAmt == 0 || AMShiftAmt > 3)
return true;
2379 MVT XVT =
X.getSimpleValueType();
2380 MVT VT =
N.getSimpleValueType();
2405 AM.Scale = 1 << AMShiftAmt;
2406 AM.IndexReg = NewExt;
2413 X86ISelAddressMode &AM,
2415 assert(AM.IndexReg.
getNode() ==
nullptr &&
"IndexReg already matched");
2416 assert((AM.Scale == 1 || AM.Scale == 2 || AM.Scale == 4 || AM.Scale == 8) &&
2417 "Illegal index scale");
2423 EVT VT =
N.getValueType();
2424 unsigned Opc =
N.getOpcode();
2427 if (CurDAG->isBaseWithConstantOffset(
N)) {
2429 uint64_t
Offset = (uint64_t)AddVal->getSExtValue() * AM.Scale;
2430 if (!foldOffsetIntoAddress(
Offset, AM))
2431 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2435 if (
Opc ==
ISD::ADD &&
N.getOperand(0) ==
N.getOperand(1)) {
2436 if (AM.Scale <= 4) {
2438 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2443 if (
Opc == X86ISD::VSHLI) {
2444 uint64_t ShiftAmt =
N.getConstantOperandVal(1);
2445 uint64_t ScaleAmt = 1ULL << ShiftAmt;
2446 if ((AM.Scale * ScaleAmt) <= 8) {
2447 AM.Scale *= ScaleAmt;
2448 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2456 if (Src.getOpcode() ==
ISD::ADD && Src->getFlags().hasNoSignedWrap() &&
2458 if (CurDAG->isBaseWithConstantOffset(Src)) {
2459 SDValue AddSrc = Src.getOperand(0);
2461 int64_t
Offset = AddVal->getSExtValue();
2462 if (!foldOffsetIntoAddress((uint64_t)
Offset * AM.Scale, AM)) {
2470 CurDAG->ReplaceAllUsesWith(
N, ExtAdd);
2471 CurDAG->RemoveDeadNode(
N.getNode());
2483 unsigned SrcOpc = Src.getOpcode();
2484 if (((SrcOpc ==
ISD::ADD && Src->getFlags().hasNoUnsignedWrap()) ||
2485 CurDAG->isADDLike(Src,
true)) &&
2487 if (CurDAG->isBaseWithConstantOffset(Src)) {
2488 SDValue AddSrc = Src.getOperand(0);
2489 uint64_t
Offset = Src.getConstantOperandVal(1);
2490 if (!foldOffsetIntoAddress(
Offset * AM.Scale, AM)) {
2500 uint64_t ScaleAmt = 1ULL << ShAmt;
2501 if ((AM.Scale * ScaleAmt) <= 8 &&
2503 CurDAG->MaskedValueIsZero(ShVal, HiBits))) {
2504 AM.Scale *= ScaleAmt;
2505 SDValue ExtShVal = CurDAG->getNode(
Opc,
DL, VT, ShVal);
2516 SDValue ExtAdd = CurDAG->getNode(SrcOpc,
DL, VT, ExtSrc, ExtVal);
2520 CurDAG->ReplaceAllUsesWith(
N, ExtAdd);
2521 CurDAG->RemoveDeadNode(
N.getNode());
2522 return Res ? Res : ExtSrc;
2532bool X86DAGToDAGISel::matchAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
2535 dbgs() <<
"MatchAddress: ";
2540 return matchAddressBase(
N, AM);
2545 if (AM.isRIPRelative()) {
2549 if (!(AM.ES || AM.MCSym) && AM.JT != -1)
2553 if (!foldOffsetIntoAddress(Cst->getSExtValue(), AM))
2558 switch (
N.getOpcode()) {
2561 if (!AM.hasSymbolicDisplacement() && AM.Disp == 0)
2564 AM.MCSym = ESNode->getMCSymbol();
2571 if (!foldOffsetIntoAddress(Val, AM))
2576 case X86ISD::Wrapper:
2577 case X86ISD::WrapperRIP:
2578 if (!matchWrapper(
N, AM))
2588 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2589 AM.Base_Reg.
getNode() ==
nullptr &&
2591 AM.BaseType = X86ISelAddressMode::FrameIndexBase;
2598 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
2602 unsigned Val = CN->getZExtValue();
2607 if (Val == 1 || Val == 2 || Val == 3) {
2609 AM.Scale = 1 << Val;
2610 AM.IndexReg = matchIndexRecursively(ShVal, AM,
Depth + 1);
2618 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
break;
2622 assert(
N.getSimpleValueType().getSizeInBits() <= 64 &&
2623 "Unexpected value size!");
2635 uint64_t
Mask =
And.getConstantOperandVal(1) >>
N.getConstantOperandVal(1);
2647 if (
N.getResNo() != 0)
break;
2650 case X86ISD::MUL_IMM:
2652 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2653 AM.Base_Reg.
getNode() ==
nullptr &&
2654 AM.IndexReg.
getNode() ==
nullptr) {
2656 if (CN->getZExtValue() == 3 || CN->getZExtValue() == 5 ||
2657 CN->getZExtValue() == 9) {
2658 AM.Scale = unsigned(CN->getZExtValue())-1;
2670 uint64_t Disp = AddVal->getSExtValue() * CN->getZExtValue();
2671 if (foldOffsetIntoAddress(Disp, AM))
2672 Reg =
N.getOperand(0);
2674 Reg =
N.getOperand(0);
2677 AM.IndexReg = AM.Base_Reg =
Reg;
2693 HandleSDNode Handle(
N);
2696 X86ISelAddressMode Backup = AM;
2697 if (matchAddressRecursively(
N.getOperand(0), AM,
Depth+1)) {
2698 N = Handle.getValue();
2702 N = Handle.getValue();
2704 if (AM.IndexReg.
getNode() || AM.isRIPRelative()) {
2719 RHS.getOperand(0).getValueType() == MVT::i32))
2723 if ((AM.BaseType == X86ISelAddressMode::RegBase && AM.Base_Reg.
getNode() &&
2725 AM.BaseType == X86ISelAddressMode::FrameIndexBase)
2729 if ((AM.hasSymbolicDisplacement() && !Backup.hasSymbolicDisplacement()) +
2730 ((AM.Disp != 0) && (Backup.Disp == 0)) +
2743 AM.NegateIndex =
true;
2751 if (!CurDAG->isADDLike(
N))
2755 if (!matchAdd(
N, AM,
Depth))
2764 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
break;
2768 assert(
N.getSimpleValueType().getSizeInBits() <= 64 &&
2769 "Unexpected value size!");
2774 if (
N.getOperand(0).getOpcode() ==
ISD::SRL) {
2778 uint64_t
Mask =
N.getConstantOperandVal(1);
2803 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
2811 if (
SDValue Index = matchIndexRecursively(
N, AM,
Depth + 1))
2813 AM.IndexReg =
Index;
2819 if (Src.getOpcode() ==
ISD::AND && Src.hasOneUse())
2821 Mask = MaskC->getAPIntValue();
2822 Src = Src.getOperand(0);
2825 if (Src.getOpcode() ==
ISD::SHL && Src.hasOneUse() &&
N->hasOneUse()) {
2827 SDValue ShlSrc = Src.getOperand(0);
2828 SDValue ShlAmt = Src.getOperand(1);
2832 unsigned ShAmtV = ShAmtC->getZExtValue();
2840 if (!Src->getFlags().hasNoUnsignedWrap() &&
2841 !CurDAG->MaskedValueIsZero(ShlSrc, HighZeros & Mask))
2849 MVT VT =
N.getSimpleValueType();
2853 if (!
Mask.isAllOnes()) {
2854 Res = CurDAG->getConstant(
Mask.lshr(ShAmtV),
DL, SrcVT);
2856 Res = CurDAG->getNode(
ISD::AND,
DL, SrcVT, ShlSrc, Res);
2863 CurDAG->ReplaceAllUsesWith(
N, NewShl);
2864 CurDAG->RemoveDeadNode(
N.getNode());
2867 AM.Scale = 1 << ShAmtV;
2871 AM.IndexReg = matchIndexRecursively(Zext, AM,
Depth + 1);
2875 if (Src.getOpcode() ==
ISD::SRL && !
Mask.isAllOnes()) {
2878 Src.getOperand(0), AM))
2883 Src.getOperand(0), AM))
2888 Src.getOperand(0), AM, *Subtarget))
2896 return matchAddressBase(
N, AM);
2901bool X86DAGToDAGISel::matchAddressBase(
SDValue N, X86ISelAddressMode &AM) {
2903 if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base_Reg.
getNode()) {
2916 AM.BaseType = X86ISelAddressMode::RegBase;
2921bool X86DAGToDAGISel::matchVectorAddressRecursively(
SDValue N,
2922 X86ISelAddressMode &AM,
2925 dbgs() <<
"MatchVectorAddress: ";
2930 return matchAddressBase(
N, AM);
2933 switch (
N.getOpcode()) {
2936 if (!foldOffsetIntoAddress(Val, AM))
2940 case X86ISD::Wrapper:
2941 if (!matchWrapper(
N, AM))
2947 HandleSDNode Handle(
N);
2949 X86ISelAddressMode Backup = AM;
2950 if (!matchVectorAddressRecursively(
N.getOperand(0), AM,
Depth + 1) &&
2951 !matchVectorAddressRecursively(Handle.getValue().getOperand(1), AM,
2957 if (!matchVectorAddressRecursively(Handle.getValue().getOperand(1), AM,
2959 !matchVectorAddressRecursively(Handle.getValue().getOperand(0), AM,
2964 N = Handle.getValue();
2969 return matchAddressBase(
N, AM);
2975bool X86DAGToDAGISel::matchVectorAddress(
SDValue N, X86ISelAddressMode &AM) {
2976 return matchVectorAddressRecursively(
N, AM, 0);
2979bool X86DAGToDAGISel::selectVectorAddr(MemSDNode *Parent,
SDValue BasePtr,
2984 X86ISelAddressMode AM;
2990 AM.IndexReg = matchIndexRecursively(IndexOp, AM, 0);
2992 AM.IndexReg = IndexOp;
2996 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
2998 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
3000 AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16);
3003 MVT VT =
BasePtr.getSimpleValueType();
3006 if (matchVectorAddress(BasePtr, AM))
3009 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3023 X86ISelAddressMode AM;
3030 Parent->
getOpcode() != X86ISD::TLSCALL &&
3031 Parent->
getOpcode() != X86ISD::ENQCMD &&
3032 Parent->
getOpcode() != X86ISD::ENQCMDS &&
3033 Parent->
getOpcode() != X86ISD::EH_SJLJ_SETJMP &&
3034 Parent->
getOpcode() != X86ISD::EH_SJLJ_LONGJMP) {
3035 unsigned AddrSpace =
3038 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
3040 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
3042 AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16);
3047 MVT VT =
N.getSimpleValueType();
3049 if (matchAddress(
N, AM))
3052 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3065 if (
N->getOpcode() != X86ISD::Wrapper)
3068 N =
N.getOperand(0);
3085 return CR->getUnsignedMax().ult(1ull << 32);
3087 return !TM.isLargeGlobalValue(GV);
3096 if (!selectLEAAddr(
N,
Base, Scale, Index, Disp, Segment))
3102 SubReg = X86::sub_8bit;
3104 SubReg = X86::sub_16bit;
3106 SubReg = X86::sub_32bit;
3109 if (RN &&
RN->getReg() == 0)
3110 Base = CurDAG->getRegister(0, MVT::i64);
3117 Base = CurDAG->getTargetInsertSubreg(SubReg,
DL, MVT::i64, ImplDef,
Base);
3120 [[maybe_unused]] EVT IndexType =
Index.getValueType();
3122 if (RN &&
RN->getReg() == 0)
3123 Index = CurDAG->getRegister(0, MVT::i64);
3126 "Expect to be extending 8/16/32-bit registers for use in LEA");
3129 Index = CurDAG->getTargetInsertSubreg(SubReg,
DL, MVT::i64, ImplDef, Index);
3137bool X86DAGToDAGISel::selectLEAAddr(
SDValue N,
3141 X86ISelAddressMode AM;
3145 MVT VT =
N.getSimpleValueType();
3150 SDValue T = CurDAG->getRegister(0, MVT::i32);
3152 if (matchAddress(
N, AM))
3157 unsigned Complexity = 0;
3158 if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base_Reg.
getNode())
3160 else if (AM.BaseType == X86ISelAddressMode::FrameIndexBase)
3176 if (AM.hasSymbolicDisplacement()) {
3178 if (Subtarget->is64Bit())
3188 auto isMathWithFlags = [](
SDValue V) {
3189 switch (
V.getOpcode()) {
3203 return !
SDValue(
V.getNode(), 1).use_empty();
3210 if (isMathWithFlags(
N.getOperand(0)) || isMathWithFlags(
N.getOperand(1)))
3218 if (Complexity <= 2)
3221 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3232 X86ISelAddressMode AM;
3234 AM.GV = GA->getGlobal();
3235 AM.Disp += GA->getOffset();
3236 AM.SymbolFlags = GA->getTargetFlags();
3239 AM.ES = SA->getSymbol();
3240 AM.SymbolFlags = SA->getTargetFlags();
3243 if (Subtarget->is32Bit()) {
3245 AM.IndexReg = CurDAG->getRegister(X86::EBX, MVT::i32);
3248 MVT VT =
N.getSimpleValueType();
3249 getAddressOperands(AM, SDLoc(
N), VT,
Base, Scale, Index, Disp, Segment);
3257 EVT VT =
N.getValueType();
3258 bool WasTruncated =
false;
3260 WasTruncated =
true;
3261 N =
N.getOperand(0);
3264 if (
N.getOpcode() != X86ISD::Wrapper)
3270 unsigned Opc =
N.getOperand(0)->getOpcode();
3272 Op =
N.getOperand(0);
3275 return !WasTruncated;
3280 std::optional<ConstantRange> CR = GA->getGlobal()->getAbsoluteSymbolRange();
3281 if (!CR || CR->getUnsignedMax().uge(1ull << VT.
getSizeInBits()))
3285 Op = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(
N), VT,
3286 GA->getOffset(), GA->getTargetFlags());
3290bool X86DAGToDAGISel::tryFoldLoad(SDNode *Root, SDNode *
P,
SDValue N,
3294 assert(Root &&
P &&
"Unknown root/parent nodes");
3296 !IsProfitableToFold(
N,
P, Root) ||
3297 !IsLegalToFold(
N,
P, Root, OptLevel))
3300 return selectAddr(
N.getNode(),
3301 N.getOperand(1),
Base, Scale, Index, Disp, Segment);
3304bool X86DAGToDAGISel::tryFoldBroadcast(SDNode *Root, SDNode *
P,
SDValue N,
3308 assert(Root &&
P &&
"Unknown root/parent nodes");
3309 if (
N->getOpcode() != X86ISD::VBROADCAST_LOAD ||
3310 !IsProfitableToFold(
N,
P, Root) ||
3311 !IsLegalToFold(
N,
P, Root, OptLevel))
3314 return selectAddr(
N.getNode(),
3315 N.getOperand(1),
Base, Scale, Index, Disp, Segment);
3321SDNode *X86DAGToDAGISel::getGlobalBaseReg() {
3324 return CurDAG->getRegister(GlobalBaseReg, TLI->
getPointerTy(
DL)).getNode();
3327bool X86DAGToDAGISel::isSExtAbsoluteSymbolRef(
unsigned Width, SDNode *
N)
const {
3329 N =
N->getOperand(0).getNode();
3330 if (
N->getOpcode() != X86ISD::Wrapper)
3337 auto *GV = GA->getGlobal();
3340 return CR->getSignedMin().sge(-1ull << Width) &&
3341 CR->getSignedMax().slt(1ull << Width);
3347 !TM.isLargeGlobalValue(GV);
3351 assert(
N->isMachineOpcode() &&
"Unexpected node");
3352 unsigned Opc =
N->getMachineOpcode();
3353 const MCInstrDesc &MCID = getInstrInfo()->get(
Opc);
3358 return static_cast<X86::CondCode>(
N->getConstantOperandVal(CondNo));
3363bool X86DAGToDAGISel::onlyUsesZeroFlag(
SDValue Flags)
const {
3365 for (SDUse &Use :
Flags->uses()) {
3367 if (
Use.getResNo() !=
Flags.getResNo())
3375 for (SDUse &FlagUse :
User->uses()) {
3377 if (FlagUse.getResNo() != 1)
3380 if (!FlagUse.getUser()->isMachineOpcode())
3400bool X86DAGToDAGISel::hasNoSignFlagUses(
SDValue Flags)
const {
3402 for (SDUse &Use :
Flags->uses()) {
3404 if (
Use.getResNo() !=
Flags.getResNo())
3412 for (SDUse &FlagUse :
User->uses()) {
3414 if (FlagUse.getResNo() != 1)
3417 if (!FlagUse.getUser()->isMachineOpcode())
3457 bool X86DAGToDAGISel::hasNoCarryFlagUses(
SDValue Flags)
const {
3459 for (SDUse &Use :
Flags->uses()) {
3461 if (
Use.getResNo() !=
Flags.getResNo())
3465 unsigned UserOpc =
User->getOpcode();
3472 for (SDUse &FlagUse :
User->uses()) {
3474 if (FlagUse.getResNo() != 1)
3477 if (!FlagUse.getUser()->isMachineOpcode())
3497 case X86ISD::SETCC: CCOpNo = 0;
break;
3498 case X86ISD::SETCC_CARRY: CCOpNo = 0;
break;
3499 case X86ISD::CMOV: CCOpNo = 2;
break;
3500 case X86ISD::BRCOND: CCOpNo = 2;
break;
3510bool X86DAGToDAGISel::checkTCRetEnoughRegs(SDNode *
N)
const {
3513 const X86RegisterInfo *RI = Subtarget->getRegisterInfo();
3517 if (Subtarget->is64Bit()) {
3518 const TargetRegisterClass *TCGPRs =
3520 ? &X86::GR64_TCW64RegClass
3521 : &X86::GR64_TCRegClass;
3527 const TargetRegisterClass *TCGPRs =
3529 ? &X86::GR32RegClass
3530 : &X86::GR32_TCRegClass;
3537 unsigned LoadGPRs = 2;
3539 assert(
N->getOpcode() == X86ISD::TC_RETURN);
3542 if (Subtarget->is32Bit()) {
3548 }
else if (
BasePtr.getOpcode() == X86ISD::Wrapper &&
3550 assert(!getTargetMachine().isPositionIndependent());
3557 for (
unsigned I = 3,
E =
N->getNumOperands();
I !=
E; ++
I) {
3559 if (!RI->isGeneralPurposeRegister(*MF,
RN->getReg()))
3561 if (++
ArgGPRs + LoadGPRs > AvailGPRs)
3577 if (StoredVal.
getResNo() != 0)
return false;
3594 if (!Load.hasOneUse())
3602 bool FoundLoad =
false;
3606 const unsigned int Max = 1024;
3648 if (Chain == Load.getValue(1)) {
3654 if (
Op == Load.getValue(1)) {
3670 if (
Op.getNode() != LoadNode)
3702bool X86DAGToDAGISel::foldLoadStoreIntoMemOperand(SDNode *Node) {
3704 SDValue StoredVal = StoreNode->getOperand(1);
3710 EVT MemVT = StoreNode->getMemoryVT();
3711 if (MemVT != MVT::i64 && MemVT != MVT::i32 && MemVT != MVT::i16 &&
3715 bool IsCommutable =
false;
3716 bool IsNegate =
false;
3730 IsCommutable =
true;
3734 unsigned LoadOpNo = IsNegate ? 1 : 0;
3735 LoadSDNode *LoadNode =
nullptr;
3738 LoadNode, InputChain)) {
3745 LoadNode, InputChain))
3750 if (!selectAddr(LoadNode, LoadNode->
getBasePtr(),
Base, Scale, Index, Disp,
3754 auto SelectOpcode = [&](
unsigned Opc64,
unsigned Opc32,
unsigned Opc16,
3775 unsigned NewOpc = SelectOpcode(X86::NEG64m, X86::NEG32m, X86::NEG16m,
3778 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32,
3785 if (!Subtarget->slowIncDec() || CurDAG->shouldOptForSize()) {
3789 if ((IsOne || IsNegOne) && hasNoCarryFlagUses(StoredVal.
getValue(1))) {
3791 ((
Opc == X86ISD::ADD) == IsOne)
3792 ? SelectOpcode(X86::INC64m, X86::INC32m, X86::INC16m, X86::INC8m)
3793 : SelectOpcode(X86::DEC64m, X86::DEC32m, X86::DEC16m, X86::DEC8m);
3795 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32,
3806 auto SelectRegOpcode = [SelectOpcode](
unsigned Opc) {
3809 return SelectOpcode(X86::ADD64mr, X86::ADD32mr, X86::ADD16mr,
3812 return SelectOpcode(X86::ADC64mr, X86::ADC32mr, X86::ADC16mr,
3815 return SelectOpcode(X86::SUB64mr, X86::SUB32mr, X86::SUB16mr,
3818 return SelectOpcode(X86::SBB64mr, X86::SBB32mr, X86::SBB16mr,
3821 return SelectOpcode(X86::AND64mr, X86::AND32mr, X86::AND16mr,
3824 return SelectOpcode(X86::OR64mr, X86::OR32mr, X86::OR16mr, X86::OR8mr);
3826 return SelectOpcode(X86::XOR64mr, X86::XOR32mr, X86::XOR16mr,
3832 auto SelectImmOpcode = [SelectOpcode](
unsigned Opc) {
3835 return SelectOpcode(X86::ADD64mi32, X86::ADD32mi, X86::ADD16mi,
3838 return SelectOpcode(X86::ADC64mi32, X86::ADC32mi, X86::ADC16mi,
3841 return SelectOpcode(X86::SUB64mi32, X86::SUB32mi, X86::SUB16mi,
3844 return SelectOpcode(X86::SBB64mi32, X86::SBB32mi, X86::SBB16mi,
3847 return SelectOpcode(X86::AND64mi32, X86::AND32mi, X86::AND16mi,
3850 return SelectOpcode(X86::OR64mi32, X86::OR32mi, X86::OR16mi,
3853 return SelectOpcode(X86::XOR64mi32, X86::XOR32mi, X86::XOR16mi,
3860 unsigned NewOpc = SelectRegOpcode(
Opc);
3866 int64_t OperandV = OperandC->getSExtValue();
3871 if ((
Opc == X86ISD::ADD ||
Opc == X86ISD::SUB) &&
3873 (MemVT == MVT::i64 && !
isInt<32>(OperandV) &&
3875 hasNoCarryFlagUses(StoredVal.
getValue(1))) {
3876 OperandV = -OperandV;
3877 Opc =
Opc == X86ISD::ADD ? X86ISD::SUB : X86ISD::ADD;
3880 if (MemVT != MVT::i64 ||
isInt<32>(OperandV)) {
3881 Operand = CurDAG->getSignedTargetConstant(OperandV, SDLoc(Node), MemVT);
3882 NewOpc = SelectImmOpcode(
Opc);
3886 if (
Opc == X86ISD::ADC ||
Opc == X86ISD::SBB) {
3888 CurDAG->getCopyToReg(InputChain, SDLoc(Node), X86::EFLAGS,
3892 Segment, Operand, CopyTo, CopyTo.
getValue(1)};
3893 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other,
3897 Segment, Operand, InputChain};
3898 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other,
3907 MachineMemOperand *MemOps[] = {StoreNode->getMemOperand(),
3909 CurDAG->setNodeMemRefs(Result, MemOps);
3915 CurDAG->RemoveDeadNode(Node);
3926bool X86DAGToDAGISel::matchBitExtract(SDNode *Node) {
3930 "Should be either an and-mask, or right-shift after clearing high bits.");
3933 if (!Subtarget->hasBMI() && !Subtarget->hasBMI2())
3936 MVT NVT =
Node->getSimpleValueType(0);
3939 if (NVT != MVT::i32 && NVT != MVT::i64)
3947 const bool AllowExtraUsesByDefault = Subtarget->hasBMI2();
3948 auto checkUses = [AllowExtraUsesByDefault](
3950 std::optional<bool> AllowExtraUses) {
3951 return AllowExtraUses.value_or(AllowExtraUsesByDefault) ||
3952 Op.getNode()->hasNUsesOfValue(NUses,
Op.getResNo());
3954 auto checkOneUse = [checkUses](
SDValue Op,
3955 std::optional<bool> AllowExtraUses =
3957 return checkUses(
Op, 1, AllowExtraUses);
3959 auto checkTwoUse = [checkUses](
SDValue Op,
3960 std::optional<bool> AllowExtraUses =
3962 return checkUses(
Op, 2, AllowExtraUses);
3965 auto peekThroughOneUseTruncation = [checkOneUse](
SDValue V) {
3967 assert(
V.getSimpleValueType() == MVT::i32 &&
3968 V.getOperand(0).getSimpleValueType() == MVT::i64 &&
3969 "Expected i64 -> i32 truncation");
3970 V =
V.getOperand(0);
3976 auto matchPatternA = [checkOneUse, peekThroughOneUseTruncation, &NBits,
3979 if (
Mask->getOpcode() !=
ISD::ADD || !checkOneUse(Mask))
3985 SDValue M0 = peekThroughOneUseTruncation(
Mask->getOperand(0));
3990 NBits =
M0->getOperand(1);
3991 NegateNBits =
false;
3995 auto isAllOnes = [
this, peekThroughOneUseTruncation, NVT](
SDValue V) {
3996 V = peekThroughOneUseTruncation(V);
3997 return CurDAG->MaskedValueIsAllOnes(
4003 auto matchPatternB = [checkOneUse, isAllOnes, peekThroughOneUseTruncation,
4006 if (
Mask.getOpcode() !=
ISD::XOR || !checkOneUse(Mask))
4009 if (!isAllOnes(
Mask->getOperand(1)))
4012 SDValue M0 = peekThroughOneUseTruncation(
Mask->getOperand(0));
4016 if (!isAllOnes(
M0->getOperand(0)))
4018 NBits =
M0->getOperand(1);
4019 NegateNBits =
false;
4025 auto canonicalizeShiftAmt = [&NBits, &NegateNBits](
SDValue ShiftAmt,
4026 unsigned Bitwidth) {
4031 NBits = NBits.getOperand(0);
4037 if (!V0 || V0->getZExtValue() != Bitwidth)
4039 NBits = NBits.getOperand(1);
4040 NegateNBits =
false;
4046 auto matchPatternC = [checkOneUse, peekThroughOneUseTruncation, &NegateNBits,
4049 Mask = peekThroughOneUseTruncation(Mask);
4050 unsigned Bitwidth =
Mask.getSimpleValueType().getSizeInBits();
4052 if (
Mask.getOpcode() !=
ISD::SRL || !checkOneUse(Mask))
4059 if (!checkOneUse(
M1))
4061 canonicalizeShiftAmt(
M1, Bitwidth);
4066 return !NegateNBits;
4074 auto matchPatternD = [checkOneUse, checkTwoUse, canonicalizeShiftAmt,
4075 AllowExtraUsesByDefault, &NegateNBits,
4076 &
X](SDNode *
Node) ->
bool {
4088 canonicalizeShiftAmt(N1, Bitwidth);
4092 const bool AllowExtraUses = AllowExtraUsesByDefault && !NegateNBits;
4093 if (!checkOneUse(N0, AllowExtraUses) || !checkTwoUse(N1, AllowExtraUses))
4099 auto matchLowBitMask = [matchPatternA, matchPatternB,
4101 return matchPatternA(Mask) || matchPatternB(Mask) || matchPatternC(Mask);
4105 X =
Node->getOperand(0);
4108 if (matchLowBitMask(Mask)) {
4112 if (!matchLowBitMask(Mask))
4115 }
else if (matchLowBitMask(
SDValue(Node, 0))) {
4116 X = CurDAG->getAllOnesConstant(SDLoc(Node), NVT);
4117 }
else if (!matchPatternD(Node))
4122 if (NegateNBits && !Subtarget->hasBMI2())
4127 if (NBits.getSimpleValueType() != MVT::i8) {
4134 ConstantSDNode *
Imm =
nullptr;
4135 if (NBits->getOpcode() ==
ISD::AND)
4137 NBits = NBits->getOperand(0);
4142 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, MVT::i32), 0);
4145 SDValue SRIdxVal = CurDAG->getTargetConstant(X86::sub_8bit,
DL, MVT::i32);
4147 NBits =
SDValue(CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG,
DL,
4148 MVT::i32, ImplDef, NBits, SRIdxVal),
4154 CurDAG->getNode(
ISD::AND,
DL, MVT::i32, NBits,
4155 CurDAG->getConstant(
Imm->getZExtValue(),
DL, MVT::i32));
4165 NBits = CurDAG->getNode(
ISD::SUB,
DL, MVT::i32, BitWidthC, NBits);
4169 if (Subtarget->hasBMI2()) {
4171 if (NVT != MVT::i32) {
4177 SDValue Extract = CurDAG->getNode(X86ISD::BZHI,
DL, NVT,
X, NBits);
4178 ReplaceNode(Node, Extract.
getNode());
4179 SelectCode(Extract.
getNode());
4188 SDValue RealX = peekThroughOneUseTruncation(
X);
4194 MVT XVT =
X.getSimpleValueType();
4204 SDValue C8 = CurDAG->getConstant(8,
DL, MVT::i8);
4212 SDValue ShiftAmt =
X.getOperand(1);
4213 X =
X.getOperand(0);
4216 "Expected shift amount to be i8");
4220 SDValue OrigShiftAmt = ShiftAmt;
4225 Control = CurDAG->getNode(
ISD::OR,
DL, MVT::i32, Control, ShiftAmt);
4230 if (XVT != MVT::i32) {
4236 SDValue Extract = CurDAG->getNode(X86ISD::BEXTR,
DL, XVT,
X, Control);
4244 ReplaceNode(Node, Extract.
getNode());
4245 SelectCode(Extract.
getNode());
4251MachineSDNode *X86DAGToDAGISel::matchBEXTRFromAndImm(SDNode *Node) {
4252 MVT NVT =
Node->getSimpleValueType(0);
4265 Subtarget->hasTBM() || (Subtarget->hasBMI() && Subtarget->hasFastBEXTR());
4266 if (!PreferBEXTR && !Subtarget->hasBMI2())
4278 if (NVT != MVT::i32 && NVT != MVT::i64)
4284 if (!MaskCst || !ShiftCst)
4288 uint64_t
Mask = MaskCst->getZExtValue();
4292 uint64_t Shift = ShiftCst->getZExtValue();
4297 if (Shift == 8 && MaskSize == 8)
4308 if (!PreferBEXTR && MaskSize <= 32)
4312 unsigned ROpc, MOpc;
4314#define GET_EGPR_IF_ENABLED(OPC) (Subtarget->hasEGPR() ? OPC##_EVEX : OPC)
4316 assert(Subtarget->hasBMI2() &&
"We must have BMI2's BZHI then.");
4320 Control = CurDAG->getTargetConstant(Shift + MaskSize, dl, NVT);
4325 unsigned NewOpc = NVT == MVT::i64 ? X86::MOV32ri64 : X86::MOV32ri;
4326 Control =
SDValue(CurDAG->getMachineNode(NewOpc, dl, NVT, Control), 0);
4332 Control = CurDAG->getTargetConstant(Shift | (MaskSize << 8), dl, NVT);
4333 if (Subtarget->hasTBM()) {
4334 ROpc = NVT == MVT::i64 ? X86::BEXTRI64ri : X86::BEXTRI32ri;
4335 MOpc = NVT == MVT::i64 ? X86::BEXTRI64mi : X86::BEXTRI32mi;
4337 assert(Subtarget->hasBMI() &&
"We must have BMI1's BEXTR then.");
4343 unsigned NewOpc = NVT == MVT::i64 ? X86::MOV32ri64 : X86::MOV32ri;
4344 Control =
SDValue(CurDAG->getMachineNode(NewOpc, dl, NVT, Control), 0);
4348 MachineSDNode *NewNode;
4350 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4351 if (tryFoldLoad(Node, N0.
getNode(), Input, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4353 Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Control, Input.
getOperand(0)};
4354 SDVTList VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
4355 NewNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4359 CurDAG->setNodeMemRefs(NewNode, {
cast<LoadSDNode>(Input)->getMemOperand()});
4361 NewNode = CurDAG->getMachineNode(ROpc, dl, NVT, MVT::i32, Input, Control);
4366 SDValue ShAmt = CurDAG->getTargetConstant(Shift, dl, NVT);
4370 CurDAG->getMachineNode(NewOpc, dl, NVT,
SDValue(NewNode, 0), ShAmt);
4377MachineSDNode *X86DAGToDAGISel::emitPCMPISTR(
unsigned ROpc,
unsigned MOpc,
4378 bool MayFoldLoad,
const SDLoc &dl,
4379 MVT VT, SDNode *Node) {
4384 Imm = CurDAG->getTargetConstant(*Val, SDLoc(Node),
Imm.getValueType());
4387 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4388 if (MayFoldLoad && tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4391 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Other);
4392 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4401 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32);
4402 MachineSDNode *CNode = CurDAG->getMachineNode(ROpc, dl, VTs,
Ops);
4409MachineSDNode *X86DAGToDAGISel::emitPCMPESTR(
unsigned ROpc,
unsigned MOpc,
4410 bool MayFoldLoad,
const SDLoc &dl,
4411 MVT VT, SDNode *Node,
4417 Imm = CurDAG->getTargetConstant(*Val, SDLoc(Node),
Imm.getValueType());
4420 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4421 if (MayFoldLoad && tryFoldLoad(Node, N2, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4424 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Other, MVT::Glue);
4425 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4435 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Glue);
4436 MachineSDNode *CNode = CurDAG->getMachineNode(ROpc, dl, VTs,
Ops);
4441bool X86DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
4442 EVT VT =
N->getValueType(0);
4449 unsigned Size = VT == MVT::i64 ? 64 : 32;
4452 SDValue ShiftAmt = OrigShiftAmt;
4471 if (Add1C && Add1C->getAPIntValue().urem(
Size) == 0) {
4475 ((Add0C && Add0C->getAPIntValue().urem(
Size) ==
Size - 1) ||
4476 (Add1C && Add1C->getAPIntValue().urem(
Size) ==
Size - 1))) {
4480 assert(Add0C ==
nullptr || Add1C ==
nullptr);
4489 NewShiftAmt = CurDAG->getNode(
ISD::XOR,
DL, OpVT,
4490 Add0C ==
nullptr ? Add0 : Add1,
AllOnes);
4496 Add0C->getZExtValue() != 0) {
4499 if (Add0C->getZExtValue() %
Size == 0)
4502 Add0C->getZExtValue() % 32 == 0) {
4510 Add0 = CurDAG->getZExtOrTrunc(Add0,
DL, SubVT);
4514 X = CurDAG->getNode(
ISD::ADD,
DL, SubVT, Add1, Add0);
4536 NewShiftAmt = CurDAG->getNode(
ISD::TRUNCATE,
DL, MVT::i8, NewShiftAmt);
4543 NewShiftAmt = CurDAG->getNode(
ISD::AND,
DL, MVT::i8, NewShiftAmt,
4544 CurDAG->getConstant(
Size - 1,
DL, MVT::i8));
4548 SDNode *UpdatedNode = CurDAG->UpdateNodeOperands(
N,
N->getOperand(0),
4550 if (UpdatedNode !=
N) {
4553 ReplaceNode(
N, UpdatedNode);
4560 CurDAG->RemoveDeadNode(OrigShiftAmt.
getNode());
4568bool X86DAGToDAGISel::tryShrinkShlLogicImm(SDNode *
N) {
4569 MVT NVT =
N->getSimpleValueType(0);
4570 unsigned Opcode =
N->getOpcode();
4582 int64_t Val = Cst->getSExtValue();
4587 bool FoundAnyExtend =
false;
4591 FoundAnyExtend =
true;
4599 if (NVT != MVT::i32 && NVT != MVT::i64)
4606 uint64_t ShAmt = ShlCst->getZExtValue();
4610 uint64_t RemovedBitsMask = (1ULL << ShAmt) - 1;
4611 if (Opcode !=
ISD::AND && (Val & RemovedBitsMask) != 0)
4616 auto CanShrinkImmediate = [&](int64_t &ShiftedVal) {
4620 ShiftedVal = (uint64_t)Val >> ShAmt;
4624 if (ShiftedVal == UINT8_MAX || ShiftedVal == UINT16_MAX)
4627 ShiftedVal = Val >> ShAmt;
4633 ShiftedVal = (uint64_t)Val >> ShAmt;
4641 if (!CanShrinkImmediate(ShiftedVal))
4651 unsigned ZExtWidth = Cst->getAPIntValue().getActiveBits();
4657 NeededMask &= ~Cst->getAPIntValue();
4659 if (CurDAG->MaskedValueIsZero(
N->getOperand(0), NeededMask))
4664 if (FoundAnyExtend) {
4670 SDValue NewCst = CurDAG->getSignedConstant(ShiftedVal, dl, NVT);
4672 SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT,
X, NewCst);
4681bool X86DAGToDAGISel::matchVPTERNLOG(SDNode *Root, SDNode *ParentA,
4682 SDNode *ParentB, SDNode *ParentC,
4685 assert(
A.isOperandOf(ParentA) &&
B.isOperandOf(ParentB) &&
4686 C.isOperandOf(ParentC) &&
"Incorrect parent node");
4688 auto tryFoldLoadOrBCast =
4691 if (tryFoldLoad(Root,
P, L,
Base, Scale, Index, Disp, Segment))
4697 L =
L.getOperand(0);
4700 if (
L.getOpcode() != X86ISD::VBROADCAST_LOAD)
4705 unsigned Size = MemIntr->getMemoryVT().getSizeInBits();
4709 return tryFoldBroadcast(Root,
P, L,
Base, Scale, Index, Disp, Segment);
4712 bool FoldedLoad =
false;
4713 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4714 if (tryFoldLoadOrBCast(Root, ParentC,
C, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4716 }
else if (tryFoldLoadOrBCast(Root, ParentA,
A, Tmp0, Tmp1, Tmp2, Tmp3,
4721 uint8_t OldImm =
Imm;
4722 Imm = OldImm & 0xa5;
4723 if (OldImm & 0x02)
Imm |= 0x10;
4724 if (OldImm & 0x10)
Imm |= 0x02;
4725 if (OldImm & 0x08)
Imm |= 0x40;
4726 if (OldImm & 0x40)
Imm |= 0x08;
4727 }
else if (tryFoldLoadOrBCast(Root, ParentB,
B, Tmp0, Tmp1, Tmp2, Tmp3,
4732 uint8_t OldImm =
Imm;
4733 Imm = OldImm & 0x99;
4734 if (OldImm & 0x02)
Imm |= 0x04;
4735 if (OldImm & 0x04)
Imm |= 0x02;
4736 if (OldImm & 0x20)
Imm |= 0x40;
4737 if (OldImm & 0x40)
Imm |= 0x20;
4742 SDValue TImm = CurDAG->getTargetConstant(Imm,
DL, MVT::i8);
4746 MachineSDNode *MNode;
4748 SDVTList VTs = CurDAG->getVTList(NVT, MVT::Other);
4751 if (
C.getOpcode() == X86ISD::VBROADCAST_LOAD) {
4753 unsigned EltSize = MemIntr->getMemoryVT().getSizeInBits();
4754 assert((EltSize == 32 || EltSize == 64) &&
"Unexpected broadcast size!");
4756 bool UseD = EltSize == 32;
4758 Opc = UseD ? X86::VPTERNLOGDZ128rmbi : X86::VPTERNLOGQZ128rmbi;
4760 Opc = UseD ? X86::VPTERNLOGDZ256rmbi : X86::VPTERNLOGQZ256rmbi;
4762 Opc = UseD ? X86::VPTERNLOGDZrmbi : X86::VPTERNLOGQZrmbi;
4768 Opc = UseD ? X86::VPTERNLOGDZ128rmi : X86::VPTERNLOGQZ128rmi;
4770 Opc = UseD ? X86::VPTERNLOGDZ256rmi : X86::VPTERNLOGQZ256rmi;
4772 Opc = UseD ? X86::VPTERNLOGDZrmi : X86::VPTERNLOGQZrmi;
4778 MNode = CurDAG->getMachineNode(
Opc,
DL, VTs,
Ops);
4781 ReplaceUses(
C.getValue(1),
SDValue(MNode, 1));
4788 Opc = UseD ? X86::VPTERNLOGDZ128rri : X86::VPTERNLOGQZ128rri;
4790 Opc = UseD ? X86::VPTERNLOGDZ256rri : X86::VPTERNLOGQZ256rri;
4792 Opc = UseD ? X86::VPTERNLOGDZrri : X86::VPTERNLOGQZrri;
4796 MNode = CurDAG->getMachineNode(
Opc,
DL, NVT, {
A,
B,
C, TImm});
4800 CurDAG->RemoveDeadNode(Root);
4806bool X86DAGToDAGISel::tryVPTERNLOG(SDNode *
N) {
4807 MVT NVT =
N->getSimpleValueType(0);
4810 if (!NVT.
isVector() || !Subtarget->hasAVX512() ||
4818 auto getFoldableLogicOp = [](
SDValue Op) {
4821 Op =
Op.getOperand(0);
4823 if (!
Op.hasOneUse())
4826 unsigned Opc =
Op.getOpcode();
4828 Opc == X86ISD::ANDNP)
4837 auto tryPeelOuterNotWrappingLogic = [&](SDNode *
Op) {
4840 SDValue InnerOp = getFoldableLogicOp(
Op->getOperand(0));
4847 if ((FoldableOp = getFoldableLogicOp(N1))) {
4851 if ((FoldableOp = getFoldableLogicOp(N0))) {
4859 bool PeeledOuterNot =
false;
4861 if (
SDValue InnerOp = tryPeelOuterNotWrappingLogic(
N)) {
4862 PeeledOuterNot =
true;
4868 if ((FoldableOp = getFoldableLogicOp(N1)))
4870 else if ((FoldableOp = getFoldableLogicOp(N0)))
4878 SDNode *ParentA =
N;
4879 SDNode *ParentB = FoldableOp.
getNode();
4880 SDNode *ParentC = FoldableOp.
getNode();
4884 uint8_t TernlogMagicA = 0xf0;
4885 uint8_t TernlogMagicB = 0xcc;
4886 uint8_t TernlogMagicC = 0xaa;
4891 auto PeekThroughNot = [](
SDValue &
Op, SDNode *&Parent, uint8_t &
Magic) {
4895 Parent =
Op.getNode();
4896 Op =
Op.getOperand(0);
4900 PeekThroughNot(
A, ParentA, TernlogMagicA);
4901 PeekThroughNot(
B, ParentB, TernlogMagicB);
4902 PeekThroughNot(
C, ParentC, TernlogMagicC);
4907 case ISD::AND:
Imm = TernlogMagicB & TernlogMagicC;
break;
4908 case ISD::OR:
Imm = TernlogMagicB | TernlogMagicC;
break;
4909 case ISD::XOR:
Imm = TernlogMagicB ^ TernlogMagicC;
break;
4910 case X86ISD::ANDNP:
Imm = ~(TernlogMagicB) & TernlogMagicC;
break;
4913 switch (
N->getOpcode()) {
4917 Imm &= ~TernlogMagicA;
4919 Imm = ~(
Imm) & TernlogMagicA;
4929 return matchVPTERNLOG(OriN, ParentA, ParentB, ParentC,
A,
B,
C, Imm);
4939bool X86DAGToDAGISel::shrinkAndImmediate(SDNode *
And) {
4942 MVT VT =
And->getSimpleValueType(0);
4943 if (VT != MVT::i32 && VT != MVT::i64)
4955 APInt MaskVal = And1C->getAPIntValue();
4957 if (!MaskLZ || (VT == MVT::i64 && MaskLZ == 32))
4961 if (VT == MVT::i64 && MaskLZ >= 32) {
4963 MaskVal = MaskVal.
trunc(32);
4968 APInt NegMaskVal = MaskVal | HighZeros;
4977 if (VT == MVT::i64 && MaskVal.
getBitWidth() < 64) {
4978 NegMaskVal = NegMaskVal.
zext(64);
4979 HighZeros = HighZeros.
zext(64);
4985 KnownBits Known0 = CurDAG->computeKnownBits(And0);
4997 SDValue NewMask = CurDAG->getConstant(NegMaskVal, SDLoc(
And), VT);
5006 bool FoldedBCast,
bool Masked) {
5007#define VPTESTM_CASE(VT, SUFFIX) \
5010 return IsTestN ? X86::VPTESTNM##SUFFIX##k: X86::VPTESTM##SUFFIX##k; \
5011 return IsTestN ? X86::VPTESTNM##SUFFIX : X86::VPTESTM##SUFFIX;
5014#define VPTESTM_BROADCAST_CASES(SUFFIX) \
5015default: llvm_unreachable("Unexpected VT!"); \
5016VPTESTM_CASE(v4i32, DZ128##SUFFIX) \
5017VPTESTM_CASE(v2i64, QZ128##SUFFIX) \
5018VPTESTM_CASE(v8i32, DZ256##SUFFIX) \
5019VPTESTM_CASE(v4i64, QZ256##SUFFIX) \
5020VPTESTM_CASE(v16i32, DZ##SUFFIX) \
5021VPTESTM_CASE(v8i64, QZ##SUFFIX)
5023#define VPTESTM_FULL_CASES(SUFFIX) \
5024VPTESTM_BROADCAST_CASES(SUFFIX) \
5025VPTESTM_CASE(v16i8, BZ128##SUFFIX) \
5026VPTESTM_CASE(v8i16, WZ128##SUFFIX) \
5027VPTESTM_CASE(v32i8, BZ256##SUFFIX) \
5028VPTESTM_CASE(v16i16, WZ256##SUFFIX) \
5029VPTESTM_CASE(v64i8, BZ##SUFFIX) \
5030VPTESTM_CASE(v32i16, WZ##SUFFIX)
5048#undef VPTESTM_FULL_CASES
5049#undef VPTESTM_BROADCAST_CASES
5055bool X86DAGToDAGISel::tryVPTESTM(SDNode *Root,
SDValue Setcc,
5057 assert(Subtarget->hasAVX512() &&
"Expected AVX512!");
5102 auto tryFoldLoadOrBCast = [&](SDNode *Root, SDNode *
P,
SDValue &
L,
5107 if (tryFoldLoad(Root,
P, L,
Base, Scale, Index, Disp, Segment))
5112 if (CmpSVT != MVT::i32 && CmpSVT != MVT::i64)
5118 L =
L.getOperand(0);
5121 if (
L.getOpcode() != X86ISD::VBROADCAST_LOAD)
5125 if (MemIntr->getMemoryVT().getSizeInBits() != CmpSVT.
getSizeInBits())
5128 return tryFoldBroadcast(Root,
P, L,
Base, Scale, Index, Disp, Segment);
5132 bool CanFoldLoads = Src0 != Src1;
5134 bool FoldedLoad =
false;
5135 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5137 FoldedLoad = tryFoldLoadOrBCast(Root, N0.
getNode(), Src1, Tmp0, Tmp1, Tmp2,
5141 FoldedLoad = tryFoldLoadOrBCast(Root, N0.
getNode(), Src0, Tmp0, Tmp1,
5148 bool FoldedBCast = FoldedLoad && Src1.
getOpcode() == X86ISD::VBROADCAST_LOAD;
5150 bool IsMasked = InMask.
getNode() !=
nullptr;
5159 unsigned SubReg = CmpVT.
is128BitVector() ? X86::sub_xmm : X86::sub_ymm;
5163 SDValue ImplDef =
SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF, dl,
5165 Src0 = CurDAG->getTargetInsertSubreg(SubReg, dl, CmpVT, ImplDef, Src0);
5168 Src1 = CurDAG->getTargetInsertSubreg(SubReg, dl, CmpVT, ImplDef, Src1);
5173 SDValue RC = CurDAG->getTargetConstant(RegClass, dl, MVT::i32);
5174 InMask =
SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
5175 dl, MaskVT, InMask, RC), 0);
5183 MachineSDNode *CNode;
5185 SDVTList VTs = CurDAG->getVTList(MaskVT, MVT::Other);
5188 SDValue Ops[] = { InMask, Src0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
5190 CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5192 SDValue Ops[] = { Src0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
5194 CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5200 CurDAG->setNodeMemRefs(CNode, {
cast<MemSDNode>(Src1)->getMemOperand()});
5203 CNode = CurDAG->getMachineNode(
Opc, dl, MaskVT, InMask, Src0, Src1);
5205 CNode = CurDAG->getMachineNode(
Opc, dl, MaskVT, Src0, Src1);
5211 SDValue RC = CurDAG->getTargetConstant(RegClass, dl, MVT::i32);
5212 CNode = CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
5213 dl, ResVT,
SDValue(CNode, 0), RC);
5217 CurDAG->RemoveDeadNode(Root);
5223bool X86DAGToDAGISel::tryMatchBitSelect(SDNode *
N) {
5226 MVT NVT =
N->getSimpleValueType(0);
5229 if (!NVT.
isVector() || !Subtarget->hasAVX512())
5263 SDValue Imm = CurDAG->getTargetConstant(0xCA, dl, MVT::i8);
5264 SDValue Ternlog = CurDAG->getNode(X86ISD::VPTERNLOG, dl, NVT,
A,
B,
C, Imm);
5271void X86DAGToDAGISel::Select(SDNode *Node) {
5272 MVT NVT =
Node->getSimpleValueType(0);
5273 unsigned Opcode =
Node->getOpcode();
5276 if (
Node->isMachineOpcode()) {
5278 Node->setNodeId(-1);
5285 unsigned IntNo =
Node->getConstantOperandVal(1);
5288 case Intrinsic::x86_encodekey128:
5289 case Intrinsic::x86_encodekey256: {
5290 if (!Subtarget->hasKL())
5296 case Intrinsic::x86_encodekey128:
5297 Opcode = X86::ENCODEKEY128;
5299 case Intrinsic::x86_encodekey256:
5300 Opcode = X86::ENCODEKEY256;
5305 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM0,
Node->getOperand(3),
5307 if (Opcode == X86::ENCODEKEY256)
5308 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM1,
Node->getOperand(4),
5311 MachineSDNode *Res = CurDAG->getMachineNode(
5312 Opcode, dl,
Node->getVTList(),
5313 {Node->getOperand(2), Chain, Chain.getValue(1)});
5314 ReplaceNode(Node, Res);
5317 case Intrinsic::x86_tileloaddrs64_internal:
5318 case Intrinsic::x86_tileloaddrst164_internal:
5319 if (!Subtarget->hasAMXMOVRS())
5322 case Intrinsic::x86_tileloadd64_internal:
5323 case Intrinsic::x86_tileloaddt164_internal: {
5324 if (!Subtarget->hasAMXTILE())
5327 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5328 MFI->setAMXProgModel(AMXProgModelEnum::ManagedRA);
5333 case Intrinsic::x86_tileloaddrs64_internal:
5334 Opc = X86::PTILELOADDRSV;
5336 case Intrinsic::x86_tileloaddrst164_internal:
5337 Opc = X86::PTILELOADDRST1V;
5339 case Intrinsic::x86_tileloadd64_internal:
5340 Opc = X86::PTILELOADDV;
5342 case Intrinsic::x86_tileloaddt164_internal:
5343 Opc = X86::PTILELOADDT1V;
5348 SDValue Scale = getI8Imm(1, dl);
5350 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5351 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5353 MachineSDNode *CNode;
5355 Node->getOperand(3),
5362 CNode = CurDAG->getMachineNode(
Opc, dl, {MVT::x86amx, MVT::Other},
Ops);
5363 ReplaceNode(Node, CNode);
5370 unsigned IntNo =
Node->getConstantOperandVal(1);
5373 case Intrinsic::x86_sse3_monitor:
5374 case Intrinsic::x86_monitorx:
5375 case Intrinsic::x86_clzero: {
5376 bool Use64BitPtr =
Node->getOperand(2).getValueType() == MVT::i64;
5381 case Intrinsic::x86_sse3_monitor:
5382 if (!Subtarget->hasSSE3())
5384 Opc = Use64BitPtr ? X86::MONITOR64rrr : X86::MONITOR32rrr;
5386 case Intrinsic::x86_monitorx:
5387 if (!Subtarget->hasMWAITX())
5389 Opc = Use64BitPtr ? X86::MONITORX64rrr : X86::MONITORX32rrr;
5391 case Intrinsic::x86_clzero:
5392 if (!Subtarget->hasCLZERO())
5394 Opc = Use64BitPtr ? X86::CLZERO64r : X86::CLZERO32r;
5399 unsigned PtrReg = Use64BitPtr ? X86::RAX : X86::EAX;
5400 SDValue Chain = CurDAG->getCopyToReg(
Node->getOperand(0), dl, PtrReg,
5404 if (IntNo == Intrinsic::x86_sse3_monitor ||
5405 IntNo == Intrinsic::x86_monitorx) {
5407 Chain = CurDAG->getCopyToReg(Chain, dl, X86::ECX,
Node->getOperand(3),
5410 Chain = CurDAG->getCopyToReg(Chain, dl, X86::EDX,
Node->getOperand(4),
5415 MachineSDNode *CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
5417 ReplaceNode(Node, CNode);
5423 case Intrinsic::x86_tilestored64_internal: {
5425 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5426 MFI->setAMXProgModel(AMXProgModelEnum::ManagedRA);
5427 unsigned Opc = X86::PTILESTOREDV;
5430 SDValue Scale = getI8Imm(1, dl);
5432 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5433 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5435 MachineSDNode *CNode;
5437 Node->getOperand(3),
5443 Node->getOperand(6),
5445 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5446 ReplaceNode(Node, CNode);
5449 case Intrinsic::x86_tileloaddrs64:
5450 case Intrinsic::x86_tileloaddrst164:
5451 if (!Subtarget->hasAMXMOVRS())
5454 case Intrinsic::x86_tileloadd64:
5455 case Intrinsic::x86_tileloaddt164:
5456 case Intrinsic::x86_tilestored64: {
5457 if (!Subtarget->hasAMXTILE())
5460 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5461 MFI->setAMXProgModel(AMXProgModelEnum::DirectReg);
5465 case Intrinsic::x86_tileloadd64:
Opc = X86::PTILELOADD;
break;
5466 case Intrinsic::x86_tileloaddrs64:
5467 Opc = X86::PTILELOADDRS;
5469 case Intrinsic::x86_tileloaddt164:
Opc = X86::PTILELOADDT1;
break;
5470 case Intrinsic::x86_tileloaddrst164:
5471 Opc = X86::PTILELOADDRST1;
5473 case Intrinsic::x86_tilestored64:
Opc = X86::PTILESTORED;
break;
5476 unsigned TIndex =
Node->getConstantOperandVal(2);
5479 SDValue Scale = getI8Imm(1, dl);
5481 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5482 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5484 MachineSDNode *CNode;
5485 if (
Opc == X86::PTILESTORED) {
5487 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5490 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5492 ReplaceNode(Node, CNode);
5499 case X86ISD::NT_BRIND: {
5500 if (Subtarget->isTarget64BitILP32()) {
5505 assert(
Target.getValueType() == MVT::i32 &&
"Unexpected VT!");
5506 SDValue ZextTarget = CurDAG->getZExtOrTrunc(Target, dl, MVT::i64);
5507 SDValue Brind = CurDAG->getNode(Opcode, dl, MVT::Other,
5508 Node->getOperand(0), ZextTarget);
5509 ReplaceNode(Node, Brind.
getNode());
5510 SelectCode(ZextTarget.
getNode());
5517 ReplaceNode(Node, getGlobalBaseReg());
5524 ReplaceUses(
SDValue(Node, 0),
Node->getOperand(0));
5525 CurDAG->RemoveDeadNode(Node);
5531 if (matchBitExtract(Node))
5536 if (tryShiftAmountMod(Node))
5540 case X86ISD::VPTERNLOG: {
5541 uint8_t
Imm =
Node->getConstantOperandVal(3);
5542 if (matchVPTERNLOG(Node, Node, Node, Node,
Node->getOperand(0),
5543 Node->getOperand(1),
Node->getOperand(2), Imm))
5549 if (tryVPTERNLOG(Node))
5559 tryVPTESTM(Node, N0, N1))
5562 tryVPTESTM(Node, N1, N0))
5566 if (MachineSDNode *NewNode = matchBEXTRFromAndImm(Node)) {
5568 CurDAG->RemoveDeadNode(Node);
5571 if (matchBitExtract(Node))
5579 if (tryShrinkShlLogicImm(Node))
5581 if (Opcode ==
ISD::OR && tryMatchBitSelect(Node))
5583 if (tryVPTERNLOG(Node))
5588 if (Opcode ==
ISD::ADD && matchBitExtract(Node))
5598 if (!CurDAG->shouldOptForSize())
5602 if (NVT != MVT::i8 && NVT != MVT::i16 && NVT != MVT::i32 && NVT != MVT::i64)
5612 int64_t Val = Cst->getSExtValue();
5620 if (Opcode ==
ISD::ADD && (Val == 1 || Val == -1))
5624 if (!shouldAvoidImmediateInstFormsForSize(N1.
getNode()))
5628 unsigned ROpc, MOpc;
5737 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5738 if (tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
5740 SDVTList VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
5741 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
5747 CurDAG->RemoveDeadNode(Node);
5752 CurDAG->SelectNodeTo(Node, ROpc, NVT, MVT::i32, N0, N1);
5761 case X86ISD::UMUL: {
5765 unsigned LoReg, ROpc, MOpc;
5770 ROpc = Opcode == X86ISD::SMUL ? X86::IMUL8r : X86::MUL8r;
5771 MOpc = Opcode == X86ISD::SMUL ? X86::IMUL8m : X86::MUL8m;
5790 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5791 bool FoldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
5794 FoldedLoad = tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
5799 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg,
5802 MachineSDNode *CNode;
5808 VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
5810 VTs = CurDAG->getVTList(NVT, NVT, MVT::i32, MVT::Other);
5814 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
5825 VTs = CurDAG->getVTList(NVT, MVT::i32);
5827 VTs = CurDAG->getVTList(NVT, NVT, MVT::i32);
5829 CNode = CurDAG->getMachineNode(ROpc, dl, VTs, {N1, InGlue});
5833 ReplaceUses(
SDValue(Node, 1),
SDValue(CNode, NVT == MVT::i8 ? 1 : 2));
5834 CurDAG->RemoveDeadNode(Node);
5844 unsigned LoReg, HiReg;
5846 bool UseMULX = !IsSigned && Subtarget->hasBMI2();
5847 bool UseMULXHi = UseMULX &&
SDValue(Node, 0).use_empty();
5851 Opc = UseMULXHi ? X86::MULX32Hrr
5853 : IsSigned ?
X86::IMUL32r
5855 MOpc = UseMULXHi ? X86::MULX32Hrm
5857 : IsSigned ?
X86::IMUL32m
5859 LoReg = UseMULX ? X86::EDX : X86::EAX;
5863 Opc = UseMULXHi ? X86::MULX64Hrr
5865 : IsSigned ?
X86::IMUL64r
5867 MOpc = UseMULXHi ? X86::MULX64Hrm
5869 : IsSigned ?
X86::IMUL64m
5871 LoReg = UseMULX ? X86::RDX : X86::RAX;
5876 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5877 bool foldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
5880 foldedLoad = tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
5889 if (UseMULX && !foldedLoad) {
5890 MachineRegisterInfo &MRI = CurDAG->getMachineFunction().getRegInfo();
5899 if (GetPhysReg(N1) == LoReg && GetPhysReg(N0) != LoReg)
5903 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg,
5908 MachineSDNode *CNode =
nullptr;
5912 SDVTList VTs = CurDAG->getVTList(NVT, MVT::Other);
5913 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
5916 }
else if (UseMULX) {
5917 SDVTList VTs = CurDAG->getVTList(NVT, NVT, MVT::Other);
5918 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
5923 SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue);
5924 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
5930 ReplaceUses(N1.
getValue(1), Chain);
5936 SDVTList VTs = CurDAG->getVTList(NVT);
5937 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5939 }
else if (UseMULX) {
5940 SDVTList VTs = CurDAG->getVTList(NVT, NVT);
5941 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5945 SDVTList VTs = CurDAG->getVTList(MVT::Glue);
5946 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5952 if (!
SDValue(Node, 0).use_empty()) {
5954 assert(LoReg &&
"Register for low half is not defined!");
5955 ResLo = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, LoReg,
5959 ReplaceUses(
SDValue(Node, 0), ResLo);
5964 if (!
SDValue(Node, 1).use_empty()) {
5966 assert(HiReg &&
"Register for high half is not defined!");
5967 ResHi = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, HiReg,
5971 ReplaceUses(
SDValue(Node, 1), ResHi);
5976 CurDAG->RemoveDeadNode(Node);
5985 unsigned ROpc, MOpc;
5990 case MVT::i8: ROpc = X86::DIV8r; MOpc = X86::DIV8m;
break;
5991 case MVT::i16: ROpc = X86::DIV16r; MOpc = X86::DIV16m;
break;
5992 case MVT::i32: ROpc = X86::DIV32r; MOpc = X86::DIV32m;
break;
5993 case MVT::i64: ROpc = X86::DIV64r; MOpc = X86::DIV64m;
break;
5998 case MVT::i8: ROpc = X86::IDIV8r; MOpc = X86::IDIV8m;
break;
5999 case MVT::i16: ROpc = X86::IDIV16r; MOpc = X86::IDIV16m;
break;
6000 case MVT::i32: ROpc = X86::IDIV32r; MOpc = X86::IDIV32m;
break;
6001 case MVT::i64: ROpc = X86::IDIV64r; MOpc = X86::IDIV64m;
break;
6005 unsigned LoReg, HiReg, ClrReg;
6006 unsigned SExtOpcode;
6010 LoReg = X86::AL; ClrReg = HiReg = X86::AH;
6014 LoReg = X86::AX; HiReg = X86::DX;
6016 SExtOpcode = X86::CWD;
6019 LoReg = X86::EAX; ClrReg = HiReg = X86::EDX;
6020 SExtOpcode = X86::CDQ;
6023 LoReg = X86::RAX; ClrReg = HiReg = X86::RDX;
6024 SExtOpcode = X86::CQO;
6028 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6029 bool foldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6030 bool signBitIsZero = CurDAG->SignBitIsZero(N0);
6033 if (NVT == MVT::i8) {
6036 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Chain;
6037 MachineSDNode *Move;
6038 if (tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
6040 unsigned Opc = (isSigned && !signBitIsZero) ? X86::MOVSX16rm8
6042 Move = CurDAG->getMachineNode(
Opc, dl, MVT::i16, MVT::Other,
Ops);
6044 ReplaceUses(N0.
getValue(1), Chain);
6048 unsigned Opc = (isSigned && !signBitIsZero) ? X86::MOVSX16rr8
6050 Move = CurDAG->getMachineNode(
Opc, dl, MVT::i16, N0);
6051 Chain = CurDAG->getEntryNode();
6053 Chain = CurDAG->getCopyToReg(Chain, dl, X86::AX,
SDValue(Move, 0),
6058 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl,
6059 LoReg, N0,
SDValue()).getValue(1);
6060 if (isSigned && !signBitIsZero) {
6063 SDValue(CurDAG->getMachineNode(SExtOpcode, dl, MVT::Glue, InGlue),0);
6066 SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::i32);
6068 SDValue(CurDAG->getMachineNode(X86::MOV32r0, dl, VTs, {}), 0);
6072 SDValue(CurDAG->getMachineNode(
6073 TargetOpcode::EXTRACT_SUBREG, dl, MVT::i16, ClrNode,
6074 CurDAG->getTargetConstant(X86::sub_16bit, dl,
6082 CurDAG->getMachineNode(
6083 TargetOpcode::SUBREG_TO_REG, dl, MVT::i64, ClrNode,
6084 CurDAG->getTargetConstant(X86::sub_32bit, dl, MVT::i32)),
6091 InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, ClrReg,
6092 ClrNode, InGlue).getValue(1);
6099 MachineSDNode *CNode =
6100 CurDAG->getMachineNode(MOpc, dl, MVT::Other, MVT::Glue,
Ops);
6108 SDValue(CurDAG->getMachineNode(ROpc, dl, MVT::Glue, N1, InGlue), 0);
6118 if (HiReg == X86::AH && !
SDValue(Node, 1).use_empty()) {
6119 SDValue AHCopy = CurDAG->getRegister(X86::AH, MVT::i8);
6120 unsigned AHExtOpcode =
6121 isSigned ? X86::MOVSX32rr8_NOREX : X86::MOVZX32rr8_NOREX;
6123 SDNode *RNode = CurDAG->getMachineNode(AHExtOpcode, dl, MVT::i32,
6124 MVT::Glue, AHCopy, InGlue);
6129 CurDAG->getTargetExtractSubreg(X86::sub_8bit, dl, MVT::i8, Result);
6131 ReplaceUses(
SDValue(Node, 1), Result);
6136 if (!
SDValue(Node, 0).use_empty()) {
6137 SDValue Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
6138 LoReg, NVT, InGlue);
6139 InGlue =
Result.getValue(2);
6140 ReplaceUses(
SDValue(Node, 0), Result);
6145 if (!
SDValue(Node, 1).use_empty()) {
6146 SDValue Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
6147 HiReg, NVT, InGlue);
6148 InGlue =
Result.getValue(2);
6149 ReplaceUses(
SDValue(Node, 1), Result);
6153 CurDAG->RemoveDeadNode(Node);
6158 case X86ISD::STRICT_FCMP:
6159 case X86ISD::STRICT_FCMPS: {
6160 bool IsStrictCmp =
Node->getOpcode() == X86ISD::STRICT_FCMP ||
6161 Node->getOpcode() == X86ISD::STRICT_FCMPS;
6162 SDValue N0 =
Node->getOperand(IsStrictCmp ? 1 : 0);
6163 SDValue N1 =
Node->getOperand(IsStrictCmp ? 2 : 1);
6169 if (Subtarget->canUseCMOV())
6172 bool IsSignaling =
Node->getOpcode() == X86ISD::STRICT_FCMPS;
6178 Opc = IsSignaling ? X86::COM_Fpr32 : X86::UCOM_Fpr32;
6181 Opc = IsSignaling ? X86::COM_Fpr64 : X86::UCOM_Fpr64;
6184 Opc = IsSignaling ? X86::COM_Fpr80 : X86::UCOM_Fpr80;
6189 IsStrictCmp ?
Node->getOperand(0) : CurDAG->getEntryNode();
6192 SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue);
6193 Chain =
SDValue(CurDAG->getMachineNode(
Opc, dl, VTs, {N0, N1, Chain}), 0);
6196 Glue =
SDValue(CurDAG->getMachineNode(
Opc, dl, MVT::Glue, N0, N1), 0);
6201 SDValue(CurDAG->getMachineNode(X86::FNSTSW16r, dl, MVT::i16, Glue), 0);
6205 CurDAG->getTargetExtractSubreg(X86::sub_8bit_hi, dl, MVT::i8, FNSTSW);
6209 assert(Subtarget->canUseLAHFSAHF() &&
6210 "Target doesn't support SAHF or FCOMI?");
6211 SDValue AH = CurDAG->getCopyToReg(Chain, dl, X86::AH, Extract,
SDValue());
6214 CurDAG->getMachineNode(X86::SAHF, dl, MVT::i32, AH.
getValue(1)), 0);
6217 ReplaceUses(
SDValue(Node, 1), Chain);
6219 ReplaceUses(
SDValue(Node, 0), SAHF);
6220 CurDAG->RemoveDeadNode(Node);
6240 if (MachineSDNode *NewNode = matchBEXTRFromAndImm(N0.
getNode())) {
6241 unsigned TestOpc = CmpVT == MVT::i64 ? X86::TEST64rr
6244 NewNode = CurDAG->getMachineNode(TestOpc, dl, MVT::i32, BEXTR, BEXTR);
6246 CurDAG->RemoveDeadNode(Node);
6266 uint64_t
Mask = MaskC->getZExtValue();
6273 onlyUsesZeroFlag(
SDValue(Node, 0))) {
6278 unsigned TestOpcode;
6286 if (LeadingZeros == 0 && SavesBytes) {
6291 ShiftAmt = TrailingZeros;
6293 TestOpcode = X86::TEST64rr;
6294 }
else if (TrailingZeros == 0 && SavesBytes) {
6299 ShiftAmt = LeadingZeros;
6301 TestOpcode = X86::TEST64rr;
6302 }
else if (MaskC->hasOneUse() && !
isInt<32>(Mask)) {
6305 unsigned PopCount = 64 - LeadingZeros - TrailingZeros;
6306 if (PopCount == 8) {
6308 ShiftAmt = TrailingZeros;
6309 SubRegIdx = X86::sub_8bit;
6311 TestOpcode = X86::TEST8rr;
6312 }
else if (PopCount == 16) {
6314 ShiftAmt = TrailingZeros;
6315 SubRegIdx = X86::sub_16bit;
6316 SubRegVT = MVT::i16;
6317 TestOpcode = X86::TEST16rr;
6318 }
else if (PopCount == 32) {
6320 ShiftAmt = TrailingZeros;
6321 SubRegIdx = X86::sub_32bit;
6322 SubRegVT = MVT::i32;
6323 TestOpcode = X86::TEST32rr;
6327 SDValue ShiftC = CurDAG->getTargetConstant(ShiftAmt, dl, MVT::i64);
6329 CurDAG->getMachineNode(ShiftOpcode, dl, MVT::i64, MVT::i32,
6332 if (SubRegIdx != 0) {
6334 CurDAG->getTargetExtractSubreg(SubRegIdx, dl, SubRegVT, Shift);
6336 MachineSDNode *
Test =
6337 CurDAG->getMachineNode(TestOpcode, dl, MVT::i32, Shift, Shift);
6338 ReplaceNode(Node,
Test);
6345 unsigned ROpc, MOpc;
6353 (!(Mask & 0x80) || CmpVT == MVT::i8 ||
6354 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6357 SubRegOp = X86::sub_8bit;
6358 ROpc = X86::TEST8ri;
6359 MOpc = X86::TEST8mi;
6360 }
else if (OptForMinSize &&
isUInt<16>(Mask) &&
6361 (!(Mask & 0x8000) || CmpVT == MVT::i16 ||
6362 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6368 SubRegOp = X86::sub_16bit;
6369 ROpc = X86::TEST16ri;
6370 MOpc = X86::TEST16mi;
6372 ((!(Mask & 0x80000000) &&
6375 (CmpVT != MVT::i16 || !(Mask & 0x8000))) ||
6376 CmpVT == MVT::i32 ||
6377 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6384 SubRegOp = X86::sub_32bit;
6385 ROpc = X86::TEST32ri;
6386 MOpc = X86::TEST32mi;
6392 SDValue Imm = CurDAG->getTargetConstant(Mask, dl, VT);
6396 MachineSDNode *NewNode;
6397 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6398 if (tryFoldLoad(Node, N0.
getNode(),
Reg, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
6400 if (!LoadN->isSimple()) {
6401 unsigned NumVolBits = LoadN->getValueType(0).getSizeInBits();
6402 if ((MOpc == X86::TEST8mi && NumVolBits != 8) ||
6403 (MOpc == X86::TEST16mi && NumVolBits != 16) ||
6404 (MOpc == X86::TEST32mi && NumVolBits != 32))
6409 Reg.getOperand(0) };
6410 NewNode = CurDAG->getMachineNode(MOpc, dl, MVT::i32, MVT::Other,
Ops);
6412 ReplaceUses(
Reg.getValue(1),
SDValue(NewNode, 1));
6414 CurDAG->setNodeMemRefs(NewNode,
6419 Reg = CurDAG->getTargetExtractSubreg(SubRegOp, dl, VT,
Reg);
6421 NewNode = CurDAG->getMachineNode(ROpc, dl, MVT::i32,
Reg, Imm);
6424 ReplaceNode(Node, NewNode);
6430 if (!Subtarget->hasSSE42())
6433 bool NeedIndex = !
SDValue(Node, 0).use_empty();
6434 bool NeedMask = !
SDValue(Node, 1).use_empty();
6436 bool MayFoldLoad = !NeedIndex || !NeedMask;
6438 MachineSDNode *CNode;
6441 Subtarget->hasAVX() ? X86::VPCMPISTRMrri : X86::PCMPISTRMrri;
6443 Subtarget->hasAVX() ? X86::VPCMPISTRMrmi : X86::PCMPISTRMrmi;
6444 CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node);
6447 if (NeedIndex || !NeedMask) {
6449 Subtarget->hasAVX() ? X86::VPCMPISTRIrri : X86::PCMPISTRIrri;
6451 Subtarget->hasAVX() ? X86::VPCMPISTRIrmi : X86::PCMPISTRIrmi;
6452 CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node);
6458 CurDAG->RemoveDeadNode(Node);
6462 if (!Subtarget->hasSSE42())
6466 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EAX,
6467 Node->getOperand(1),
6469 InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EDX,
6470 Node->getOperand(3), InGlue).getValue(1);
6472 bool NeedIndex = !
SDValue(Node, 0).use_empty();
6473 bool NeedMask = !
SDValue(Node, 1).use_empty();
6475 bool MayFoldLoad = !NeedIndex || !NeedMask;
6477 MachineSDNode *CNode;
6480 Subtarget->hasAVX() ? X86::VPCMPESTRMrri : X86::PCMPESTRMrri;
6482 Subtarget->hasAVX() ? X86::VPCMPESTRMrmi : X86::PCMPESTRMrmi;
6484 emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node, InGlue);
6487 if (NeedIndex || !NeedMask) {
6489 Subtarget->hasAVX() ? X86::VPCMPESTRIrri : X86::PCMPESTRIrri;
6491 Subtarget->hasAVX() ? X86::VPCMPESTRIrmi : X86::PCMPESTRIrmi;
6492 CNode = emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node, InGlue);
6497 CurDAG->RemoveDeadNode(Node);
6509 if (foldLoadStoreIntoMemOperand(Node))
6513 case X86ISD::SETCC_CARRY: {
6514 MVT VT =
Node->getSimpleValueType(0);
6516 if (Subtarget->hasSBBDepBreaking()) {
6521 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EFLAGS,
6526 unsigned Opc = VT == MVT::i64 ? X86::SETB_C64r : X86::SETB_C32r;
6527 MVT SetVT = VT == MVT::i64 ? MVT::i64 : MVT::i32;
6529 CurDAG->getMachineNode(
Opc, dl, SetVT, EFLAGS, EFLAGS.
getValue(1)),
6534 Result = getSBBZero(Node);
6538 if (VT == MVT::i8 || VT == MVT::i16) {
6539 int SubIndex = VT == MVT::i16 ? X86::sub_16bit : X86::sub_8bit;
6540 Result = CurDAG->getTargetExtractSubreg(SubIndex, dl, VT, Result);
6543 ReplaceUses(
SDValue(Node, 0), Result);
6544 CurDAG->RemoveDeadNode(Node);
6556 if (!
SDValue(Node, 0).use_empty()) {
6558 MVT VT =
Node->getSimpleValueType(0);
6559 if (VT == MVT::i8 || VT == MVT::i16) {
6560 int SubIndex = VT == MVT::i16 ? X86::sub_16bit : X86::sub_8bit;
6561 Result = CurDAG->getTargetExtractSubreg(SubIndex, dl, VT, Result);
6563 ReplaceUses(
SDValue(Node, 0), Result);
6566 CurDAG->RemoveDeadNode(Node);
6573 SDValue IndexOp = Mgt->getIndex();
6576 MVT ValueVT =
Node->getSimpleValueType(0);
6577 MVT MaskVT =
Mask.getSimpleValueType();
6594 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6595 Opc = IsFP ? X86::VGATHERDPSZ128rm : X86::VPGATHERDDZ128rm;
6596 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6597 Opc = IsFP ? X86::VGATHERDPSZ256rm : X86::VPGATHERDDZ256rm;
6598 else if (IndexVT == MVT::v16i32 && NumElts == 16 && EltSize == 32)
6599 Opc = IsFP ? X86::VGATHERDPSZrm : X86::VPGATHERDDZrm;
6600 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6601 Opc = IsFP ? X86::VGATHERDPDZ128rm : X86::VPGATHERDQZ128rm;
6602 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6603 Opc = IsFP ? X86::VGATHERDPDZ256rm : X86::VPGATHERDQZ256rm;
6604 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 64)
6605 Opc = IsFP ? X86::VGATHERDPDZrm : X86::VPGATHERDQZrm;
6606 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6607 Opc = IsFP ? X86::VGATHERQPSZ128rm : X86::VPGATHERQDZ128rm;
6608 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6609 Opc = IsFP ? X86::VGATHERQPSZ256rm : X86::VPGATHERQDZ256rm;
6610 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 32)
6611 Opc = IsFP ? X86::VGATHERQPSZrm : X86::VPGATHERQDZrm;
6612 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6613 Opc = IsFP ? X86::VGATHERQPDZ128rm : X86::VPGATHERQQZ128rm;
6614 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6615 Opc = IsFP ? X86::VGATHERQPDZ256rm : X86::VPGATHERQQZ256rm;
6616 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 64)
6617 Opc = IsFP ? X86::VGATHERQPDZrm : X86::VPGATHERQQZrm;
6619 assert(EVT(MaskVT) == EVT(ValueVT).changeVectorElementTypeToInteger() &&
6620 "Unexpected mask VT!");
6621 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6622 Opc = IsFP ? X86::VGATHERDPSrm : X86::VPGATHERDDrm;
6623 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6624 Opc = IsFP ? X86::VGATHERDPSYrm : X86::VPGATHERDDYrm;
6625 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6626 Opc = IsFP ? X86::VGATHERDPDrm : X86::VPGATHERDQrm;
6627 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6628 Opc = IsFP ? X86::VGATHERDPDYrm : X86::VPGATHERDQYrm;
6629 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6630 Opc = IsFP ? X86::VGATHERQPSrm : X86::VPGATHERQDrm;
6631 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6632 Opc = IsFP ? X86::VGATHERQPSYrm : X86::VPGATHERQDYrm;
6633 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6634 Opc = IsFP ? X86::VGATHERQPDrm : X86::VPGATHERQQrm;
6635 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6636 Opc = IsFP ? X86::VGATHERQPDYrm : X86::VPGATHERQQYrm;
6643 if (!selectVectorAddr(Mgt, Mgt->getBasePtr(), IndexOp, Mgt->getScale(),
6644 Base, Scale, Index, Disp, Segment))
6647 SDValue PassThru = Mgt->getPassThru();
6648 SDValue Chain = Mgt->getChain();
6650 SDVTList VTs = CurDAG->getVTList(ValueVT, MaskVT, MVT::Other);
6652 MachineSDNode *NewNode;
6655 Index, Disp, Segment, Chain};
6656 NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6659 Disp, Segment,
Mask, Chain};
6660 NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6662 CurDAG->setNodeMemRefs(NewNode, {Mgt->getMemOperand()});
6665 CurDAG->RemoveDeadNode(Node);
6671 SDValue IndexOp = Sc->getIndex();
6673 MVT ValueVT =
Value.getSimpleValueType();
6688 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6689 Opc = IsFP ? X86::VSCATTERDPSZ128mr : X86::VPSCATTERDDZ128mr;
6690 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6691 Opc = IsFP ? X86::VSCATTERDPSZ256mr : X86::VPSCATTERDDZ256mr;
6692 else if (IndexVT == MVT::v16i32 && NumElts == 16 && EltSize == 32)
6693 Opc = IsFP ? X86::VSCATTERDPSZmr : X86::VPSCATTERDDZmr;
6694 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6695 Opc = IsFP ? X86::VSCATTERDPDZ128mr : X86::VPSCATTERDQZ128mr;
6696 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6697 Opc = IsFP ? X86::VSCATTERDPDZ256mr : X86::VPSCATTERDQZ256mr;
6698 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 64)
6699 Opc = IsFP ? X86::VSCATTERDPDZmr : X86::VPSCATTERDQZmr;
6700 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6701 Opc = IsFP ? X86::VSCATTERQPSZ128mr : X86::VPSCATTERQDZ128mr;
6702 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6703 Opc = IsFP ? X86::VSCATTERQPSZ256mr : X86::VPSCATTERQDZ256mr;
6704 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 32)
6705 Opc = IsFP ? X86::VSCATTERQPSZmr : X86::VPSCATTERQDZmr;
6706 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6707 Opc = IsFP ? X86::VSCATTERQPDZ128mr : X86::VPSCATTERQQZ128mr;
6708 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6709 Opc = IsFP ? X86::VSCATTERQPDZ256mr : X86::VPSCATTERQQZ256mr;
6710 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 64)
6711 Opc = IsFP ? X86::VSCATTERQPDZmr : X86::VPSCATTERQQZmr;
6716 if (!selectVectorAddr(Sc, Sc->getBasePtr(), IndexOp, Sc->getScale(),
6717 Base, Scale, Index, Disp, Segment))
6721 SDValue Chain = Sc->getChain();
6723 SDVTList VTs = CurDAG->getVTList(
Mask.getValueType(), MVT::Other);
6726 MachineSDNode *NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6727 CurDAG->setNodeMemRefs(NewNode, {Sc->getMemOperand()});
6729 CurDAG->RemoveDeadNode(Node);
6733 auto *MFI = CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
6734 auto CallId = MFI->getPreallocatedIdForCallSite(
6737 SDValue CallIdValue = CurDAG->getTargetConstant(CallId, dl, MVT::i32);
6738 MachineSDNode *
New = CurDAG->getMachineNode(
6739 TargetOpcode::PREALLOCATED_SETUP, dl, MVT::Other, CallIdValue, Chain);
6741 CurDAG->RemoveDeadNode(Node);
6745 auto *MFI = CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
6749 SDValue CallIdValue = CurDAG->getTargetConstant(CallId, dl, MVT::i32);
6752 Ops[0] = CallIdValue;
6755 MachineSDNode *
New = CurDAG->getMachineNode(
6756 TargetOpcode::PREALLOCATED_ARG, dl,
6757 CurDAG->getVTList(TLI->
getPointerTy(CurDAG->getDataLayout()),
6762 CurDAG->RemoveDeadNode(Node);
6769 if (!Subtarget->hasWIDEKL())
6773 switch (
Node->getOpcode()) {
6777 Opcode = X86::AESENCWIDE128KL;
6780 Opcode = X86::AESDECWIDE128KL;
6783 Opcode = X86::AESENCWIDE256KL;
6786 Opcode = X86::AESDECWIDE256KL;
6794 if (!selectAddr(Node, Addr,
Base, Scale, Index, Disp, Segment))
6797 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM0,
Node->getOperand(2),
6799 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM1,
Node->getOperand(3),
6801 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM2,
Node->getOperand(4),
6803 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM3,
Node->getOperand(5),
6805 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM4,
Node->getOperand(6),
6807 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM5,
Node->getOperand(7),
6809 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM6,
Node->getOperand(8),
6811 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM7,
Node->getOperand(9),
6814 MachineSDNode *Res = CurDAG->getMachineNode(
6815 Opcode, dl,
Node->getVTList(),
6816 {Base, Scale, Index, Disp, Segment, Chain, Chain.getValue(1)});
6818 ReplaceNode(Node, Res);
6825 if (
Node->getNumValues() == 3)
6826 Glue =
Node->getOperand(2);
6828 CurDAG->getCopyFromReg(Chain, dl,
Reg,
Node->getValueType(0), Glue);
6829 ReplaceNode(Node,
Copy.getNode());
6837bool X86DAGToDAGISel::SelectInlineAsmMemoryOperand(
6839 std::vector<SDValue> &OutOps) {
6840 SDValue Op0, Op1, Op2, Op3, Op4;
6841 switch (ConstraintID) {
6844 case InlineAsm::ConstraintCode::o:
6845 case InlineAsm::ConstraintCode::v:
6846 case InlineAsm::ConstraintCode::m:
6847 case InlineAsm::ConstraintCode::X:
6848 case InlineAsm::ConstraintCode::p:
6849 if (!selectAddr(
nullptr,
Op, Op0, Op1, Op2, Op3, Op4))
6854 OutOps.push_back(Op0);
6855 OutOps.push_back(Op1);
6856 OutOps.push_back(Op2);
6857 OutOps.push_back(Op3);
6858 OutOps.push_back(Op4);
6864 std::make_unique<X86DAGToDAGISel>(TM, TM.getOptLevel())) {}
6870 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< 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")
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 TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
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)
static bool foldMaskedShiftToBEXTR(SelectionDAG &DAG, SDValue N, uint64_t Mask, SDValue Shift, SDValue X, X86ISelAddressMode &AM, const X86Subtarget &Subtarget)
static bool mayUseCarryFlag(X86::CondCode CC)
static cl::opt< bool > EnablePromoteAnyextLoad("x86-promote-anyext-load", cl::init(true), cl::desc("Enable promoting aligned anyext load to wider load"), cl::Hidden)
static void moveBelowOrigChain(SelectionDAG *CurDAG, SDValue Load, SDValue Call, SDValue OrigChain)
Replace the original chain operand of the call with load's chain operand and move load below the call...
#define GET_ND_IF_ENABLED(OPC)
#define VPTESTM_BROADCAST_CASES(SUFFIX)
static cl::opt< bool > AndImmShrink("x86-and-imm-shrink", cl::init(true), cl::desc("Enable setting constant bits to reduce size of mask immediates"), cl::Hidden)
static bool foldMaskedShiftToScaledMask(SelectionDAG &DAG, SDValue N, X86ISelAddressMode &AM)
#define VPTESTM_FULL_CASES(SUFFIX)
static bool isCalleeLoad(SDValue Callee, SDValue &Chain, bool HasCallSeq)
Return true if call address is a load and it can be moved below CALLSEQ_START and the chains leading ...
static bool isDispSafeForFrameIndexOrRegBase(int64_t Val)
static bool isEndbrImm64(uint64_t Imm)
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
bool is128BitVector() const
Return true if this is a 128-bit vector type.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool is512BitVector() const
Return true if this is a 512-bit vector type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
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.
constexpr bool isVirtual() const
Return true if the specified register number is in the virtual register namespace.
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.
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.
unsigned getNumRegs() const
Return the number of registers in this class.
unsigned getID() const
Return the register class ID number.
bool contains(Register Reg) const
Return true if the specified register is included in this register class.
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.
@ C
The default llvm calling convention, compatible with C.
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.
@ 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)
FunctionAddr VTableAddr Value
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.
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.
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
unsigned M1(unsigned Val)
auto dyn_cast_or_null(const Y &Val)
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
FunctionPass * createX86ISelDag(X86TargetMachine &TM, CodeGenOptLevel OptLevel)
This pass converts a legalized DAG into a X86-specific DAG, ready for instruction scheduling.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
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