21#include "llvm/Config/llvm-config.h"
26#include "llvm/IR/IntrinsicsX86.h"
37#define DEBUG_TYPE "x86-isel"
38#define PASS_NAME "X86 DAG->DAG Instruction Selection"
40STATISTIC(NumLoadMoved,
"Number of loads moved below TokenFactor");
43 cl::desc(
"Enable setting constant bits to reduce size of mask immediates"),
47 "x86-promote-anyext-load",
cl::init(
true),
59 struct X86ISelAddressMode {
67 int Base_FrameIndex = 0;
73 const GlobalValue *GV =
nullptr;
76 const char *ES =
nullptr;
81 bool NegateIndex =
false;
86 bool IsForLEA =
false;
88 X86ISelAddressMode() =
default;
90 bool hasSymbolicDisplacement()
const {
91 return GV !=
nullptr || CP !=
nullptr || ES !=
nullptr ||
92 MCSym !=
nullptr || JT != -1 || BlockAddr !=
nullptr;
95 bool hasBaseOrIndexReg()
const {
96 return BaseType == FrameIndexBase ||
97 IndexReg.getNode() !=
nullptr || Base_Reg.getNode() !=
nullptr;
102 if (BaseType != RegBase)
return false;
103 if (RegisterSDNode *RegNode =
105 return RegNode->getReg() == X86::RIP;
114#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
115 void dump(SelectionDAG *DAG =
nullptr) {
116 dbgs() <<
"X86ISelAddressMode " <<
this <<
'\n';
117 dbgs() <<
"Base_Reg ";
118 if (Base_Reg.getNode())
119 Base_Reg.getNode()->dump(DAG);
122 if (BaseType == FrameIndexBase)
123 dbgs() <<
" Base.FrameIndex " << Base_FrameIndex <<
'\n';
124 dbgs() <<
" Scale " << Scale <<
'\n'
128 if (IndexReg.getNode())
129 IndexReg.getNode()->dump(DAG);
132 dbgs() <<
" Disp " << Disp <<
'\n'
154 dbgs() <<
" JT" << JT <<
" Align" << Alignment.value() <<
'\n';
168 const X86Subtarget *Subtarget;
174 bool IndirectTlsSegRefs;
177 X86DAGToDAGISel() =
delete;
179 explicit X86DAGToDAGISel(X86TargetMachine &tm,
CodeGenOptLevel OptLevel)
180 : SelectionDAGISel(tm, OptLevel), Subtarget(nullptr),
181 OptForMinSize(
false), IndirectTlsSegRefs(
false) {}
183 bool runOnMachineFunction(MachineFunction &MF)
override {
187 "indirect-tls-seg-refs");
194 void emitFunctionEntryCode()
override;
196 bool IsProfitableToFold(
SDValue N, SDNode *U, SDNode *Root)
const override;
198 void PreprocessISelDAG()
override;
199 void PostprocessISelDAG()
override;
202#include "X86GenDAGISel.inc"
205 void Select(SDNode *
N)
override;
207 bool foldOffsetIntoAddress(uint64_t
Offset, X86ISelAddressMode &AM);
208 bool matchLoadInAddress(LoadSDNode *
N, X86ISelAddressMode &AM,
209 bool AllowSegmentRegForX32 =
false);
210 bool matchWrapper(
SDValue N, X86ISelAddressMode &AM);
211 bool matchAddress(
SDValue N, X86ISelAddressMode &AM);
212 bool matchVectorAddress(
SDValue N, X86ISelAddressMode &AM);
213 bool matchAdd(
SDValue &
N, X86ISelAddressMode &AM,
unsigned Depth);
214 bool hasMaterializingUse(
SDValue V)
const;
217 bool matchAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
219 bool matchVectorAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
221 bool matchAddressBase(
SDValue N, X86ISelAddressMode &AM);
224 bool HasNDDM =
true);
227 bool selectVectorAddr(MemSDNode *Parent,
SDValue BasePtr,
SDValue IndexOp,
241 bool tryFoldLoad(SDNode *Root, SDNode *
P,
SDValue N,
251 return tryFoldLoad(
P,
P,
N,
Base, Scale, Index, Disp, Segment);
254 bool tryFoldBroadcast(SDNode *Root, SDNode *
P,
SDValue N,
259 bool isProfitableToFormMaskedOp(SDNode *
N)
const;
262 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
264 std::vector<SDValue> &OutOps)
override;
266 void emitSpecialCodeForMain();
268 inline void getAddressOperands(X86ISelAddressMode &AM,
const SDLoc &
DL,
272 if (AM.BaseType == X86ISelAddressMode::FrameIndexBase)
273 Base = CurDAG->getTargetFrameIndex(
274 AM.Base_FrameIndex, TLI->getPointerTy(CurDAG->getDataLayout()));
275 else if (AM.Base_Reg.
getNode())
278 Base = CurDAG->getRegister(0, VT);
280 Scale = getI8Imm(AM.Scale,
DL);
282#define GET_ND_IF_ENABLED(OPC) (Subtarget->hasNDD() ? OPC##_ND : OPC)
283#define GET_NDM_IF_ENABLED(OPC) \
284 (Subtarget->hasNDD() && Subtarget->hasNDDM() ? OPC##_ND : OPC)
286 if (AM.NegateIndex) {
312 Index = CurDAG->getRegister(0, VT);
317 Disp = CurDAG->getTargetGlobalAddress(AM.GV, SDLoc(),
321 Disp = CurDAG->getTargetConstantPool(AM.CP, MVT::i32, AM.Alignment,
322 AM.Disp, AM.SymbolFlags);
324 assert(!AM.Disp &&
"Non-zero displacement is ignored with ES.");
325 Disp = CurDAG->getTargetExternalSymbol(AM.ES, MVT::i32, AM.SymbolFlags);
326 }
else if (AM.MCSym) {
327 assert(!AM.Disp &&
"Non-zero displacement is ignored with MCSym.");
328 assert(AM.SymbolFlags == 0 &&
"oo");
329 Disp = CurDAG->getMCSymbol(AM.MCSym, MVT::i32);
330 }
else if (AM.JT != -1) {
331 assert(!AM.Disp &&
"Non-zero displacement is ignored with JT.");
332 Disp = CurDAG->getTargetJumpTable(AM.JT, MVT::i32, AM.SymbolFlags);
333 }
else if (AM.BlockAddr)
334 Disp = CurDAG->getTargetBlockAddress(AM.BlockAddr, MVT::i32, AM.Disp,
337 Disp = CurDAG->getSignedTargetConstant(AM.Disp,
DL, MVT::i32);
340 Segment = AM.Segment;
342 Segment = CurDAG->getRegister(0, MVT::i16);
347 bool isAMXSDNode(SDNode *
N)
const {
351 for (
unsigned Idx = 0,
E =
N->getNumValues(); Idx !=
E; ++Idx) {
352 if (
N->getValueType(Idx) == MVT::x86amx)
355 for (
unsigned Idx = 0,
E =
N->getNumOperands(); Idx !=
E; ++Idx) {
357 if (
Op.getValueType() == MVT::x86amx)
369 bool shouldAvoidImmediateInstFormsForSize(SDNode *
N)
const {
370 uint32_t UseCount = 0;
375 if (!CurDAG->shouldOptForSize())
379 for (
const SDNode *User :
N->users()) {
385 if (
User->isMachineOpcode()) {
392 User->getOperand(1).getNode() ==
N) {
403 if (
User->getNumOperands() != 2)
416 if (
User->getOpcode() == X86ISD::ADD ||
418 User->getOpcode() == X86ISD::SUB ||
424 OtherOp =
User->getOperand(1);
427 RegisterSDNode *RegNode;
431 if ((RegNode->
getReg() == X86::ESP) ||
432 (RegNode->
getReg() == X86::RSP))
441 return (UseCount > 1);
445 inline SDValue getI8Imm(
unsigned Imm,
const SDLoc &
DL) {
446 return CurDAG->getTargetConstant(Imm,
DL, MVT::i8);
450 inline SDValue getI32Imm(
unsigned Imm,
const SDLoc &
DL) {
451 return CurDAG->getTargetConstant(Imm,
DL, MVT::i32);
455 inline SDValue getI64Imm(uint64_t Imm,
const SDLoc &
DL) {
456 return CurDAG->getTargetConstant(Imm,
DL, MVT::i64);
459 SDValue getExtractVEXTRACTImmediate(SDNode *
N,
unsigned VecWidth,
461 assert((VecWidth == 128 || VecWidth == 256) &&
"Unexpected vector width");
462 uint64_t
Index =
N->getConstantOperandVal(1);
463 MVT VecVT =
N->getOperand(0).getSimpleValueType();
467 SDValue getInsertVINSERTImmediate(SDNode *
N,
unsigned VecWidth,
469 assert((VecWidth == 128 || VecWidth == 256) &&
"Unexpected vector width");
470 uint64_t
Index =
N->getConstantOperandVal(2);
471 MVT VecVT =
N->getSimpleValueType(0);
475 SDValue getPermuteVINSERTCommutedImmediate(SDNode *
N,
unsigned VecWidth,
477 assert(VecWidth == 128 &&
"Unexpected vector width");
478 uint64_t
Index =
N->getConstantOperandVal(2);
479 MVT VecVT =
N->getSimpleValueType(0);
481 assert((InsertIdx == 0 || InsertIdx == 1) &&
"Bad insertf128 index");
484 return getI8Imm(InsertIdx ? 0x02 : 0x30,
DL);
489 MVT VT =
N->getSimpleValueType(0);
492 SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::i32);
494 SDValue(CurDAG->getMachineNode(X86::MOV32r0, dl, VTs, {}), 0);
495 if (VT == MVT::i64) {
497 CurDAG->getMachineNode(
498 TargetOpcode::SUBREG_TO_REG, dl, MVT::i64, Zero,
499 CurDAG->getTargetConstant(X86::sub_32bit, dl, MVT::i32)),
504 unsigned Opcode =
N->getOpcode();
505 assert((Opcode == X86ISD::SBB || Opcode == X86ISD::SETCC_CARRY) &&
506 "Unexpected opcode for SBB materialization");
507 unsigned FlagOpIndex = Opcode == X86ISD::SBB ? 2 : 1;
509 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EFLAGS,
510 N->getOperand(FlagOpIndex),
SDValue());
514 unsigned Opc = VT == MVT::i64 ? X86::SBB64rr : X86::SBB32rr;
515 MVT SBBVT = VT == MVT::i64 ? MVT::i64 : MVT::i32;
516 VTs = CurDAG->getVTList(SBBVT, MVT::i32);
518 CurDAG->getMachineNode(
Opc, dl, VTs,
519 {Zero, Zero, EFLAGS, EFLAGS.getValue(1)}),
525 bool isUnneededShiftMask(SDNode *
N,
unsigned Width)
const {
527 const APInt &Val =
N->getConstantOperandAPInt(1);
532 APInt
Mask = Val | CurDAG->computeKnownBits(
N->getOperand(0)).Zero;
533 return Mask.countr_one() >= Width;
539 SDNode *getGlobalBaseReg();
543 const X86TargetMachine &getTargetMachine()
const {
544 return static_cast<const X86TargetMachine &
>(TM);
549 const X86InstrInfo *getInstrInfo()
const {
550 return Subtarget->getInstrInfo();
559 bool ComplexPatternFuncMutatesDAG()
const override {
563 bool isSExtAbsoluteSymbolRef(
unsigned Width, SDNode *
N)
const;
566 bool useNonTemporalLoad(LoadSDNode *
N)
const {
567 if (!
N->isNonTemporal())
570 unsigned StoreSize =
N->getMemoryVT().getStoreSize();
572 if (
N->getAlign().value() < StoreSize)
581 return Subtarget->hasSSE41();
583 return Subtarget->hasAVX2();
585 return Subtarget->hasAVX512();
589 bool foldLoadStoreIntoMemOperand(SDNode *Node);
590 MachineSDNode *matchBEXTRFromAndImm(SDNode *Node);
591 bool matchBitExtract(SDNode *Node);
592 bool shrinkAndImmediate(SDNode *
N);
593 bool isMaskZeroExtended(SDNode *
N)
const;
594 bool tryShiftAmountMod(SDNode *
N);
595 bool tryShrinkShlLogicImm(SDNode *
N);
596 bool tryVPTERNLOG(SDNode *
N);
597 bool matchVPTERNLOG(SDNode *Root, SDNode *ParentA, SDNode *ParentB,
601 bool tryMatchBitSelect(SDNode *
N);
603 MachineSDNode *emitPCMPISTR(
unsigned ROpc,
unsigned MOpc,
bool MayFoldLoad,
604 const SDLoc &dl, MVT VT, SDNode *Node);
605 MachineSDNode *emitPCMPESTR(
unsigned ROpc,
unsigned MOpc,
bool MayFoldLoad,
606 const SDLoc &dl, MVT VT, SDNode *Node,
609 bool tryOptimizeRem8Extend(SDNode *
N);
611 bool onlyUsesZeroFlag(
SDValue Flags)
const;
612 bool hasNoSignFlagUses(
SDValue Flags)
const;
613 bool hasNoCarryFlagUses(
SDValue Flags)
const;
614 bool checkTCRetEnoughRegs(SDNode *
N)
const;
620 explicit X86DAGToDAGISelLegacy(X86TargetMachine &tm,
622 : SelectionDAGISelLegacy(
623 ID, std::make_unique<X86DAGToDAGISel>(tm, OptLevel)) {}
627char X86DAGToDAGISelLegacy::ID = 0;
634 unsigned Opcode =
N->getOpcode();
635 if (Opcode == X86ISD::CMPM || Opcode == X86ISD::CMPMM ||
636 Opcode == X86ISD::STRICT_CMPM || Opcode ==
ISD::SETCC ||
637 Opcode == X86ISD::CMPMM_SAE || Opcode == X86ISD::VFPCLASS) {
641 EVT OpVT =
N->getOperand(0).getValueType();
644 if (Opcode == X86ISD::STRICT_CMPM)
645 OpVT =
N->getOperand(1).getValueType();
647 return Subtarget->hasVLX();
652 if (Opcode == X86ISD::VFPCLASSS || Opcode == X86ISD::FSETCCM ||
653 Opcode == X86ISD::FSETCCM_SAE)
661bool X86DAGToDAGISel::isMaskZeroExtended(
SDNode *
N)
const {
673X86DAGToDAGISel::IsProfitableToFold(
SDValue N, SDNode *U, SDNode *Root)
const {
674 if (OptLevel == CodeGenOptLevel::None)
689 switch (
U->getOpcode()) {
716 if (
Imm->getAPIntValue().isSignedIntN(8))
725 Imm->getAPIntValue().getBitWidth() == 64 &&
726 Imm->getAPIntValue().isIntN(32))
733 (
Imm->getAPIntValue() == UINT8_MAX ||
734 Imm->getAPIntValue() == UINT16_MAX ||
735 Imm->getAPIntValue() == UINT32_MAX))
741 (-
Imm->getAPIntValue()).isSignedIntN(8))
744 if ((
U->getOpcode() == X86ISD::ADD ||
U->getOpcode() == X86ISD::SUB) &&
745 (-
Imm->getAPIntValue()).isSignedIntN(8) &&
746 hasNoCarryFlagUses(
SDValue(U, 1)))
760 if (Op1.
getOpcode() == X86ISD::Wrapper) {
771 if (
U->getOperand(0).getOpcode() ==
ISD::SHL &&
775 if (
U->getOperand(1).getOpcode() ==
ISD::SHL &&
784 if (
C &&
C->getSExtValue() == -2)
790 if (
C &&
C->getSExtValue() == -2)
825bool X86DAGToDAGISel::isProfitableToFormMaskedOp(SDNode *
N)
const {
827 (
N->getOpcode() ==
ISD::VSELECT ||
N->getOpcode() == X86ISD::SELECTS) &&
828 "Unexpected opcode!");
833 return N->getOperand(1).hasOneUse();
843 Ops.push_back(
Load.getOperand(0));
846 "Unexpected chain operand");
849 Ops.push_back(
Load.getOperand(0));
855 Ops.push_back(NewChain);
860 Load.getOperand(1),
Load.getOperand(2));
878 if (Callee.getNode() == Chain.
getNode() || !Callee.hasOneUse())
890 if (!Callee.getValue(1).hasOneUse())
921 Callee.getValue(1).hasOneUse())
938 if ((Imm & 0x00FFFFFF) != 0x0F1EFA)
941 uint8_t OptionalPrefixBytes [] = {0x26, 0x2e, 0x36, 0x3e, 0x64,
942 0x65, 0x66, 0x67, 0xf0, 0xf2};
945 uint8_t Byte = (Imm >> i) & 0xFF;
957 return (VT == MVT::v32i16 || VT == MVT::v32f16 || VT == MVT::v64i8);
960void X86DAGToDAGISel::PreprocessISelDAG() {
961 bool MadeChange =
false;
963 E = CurDAG->allnodes_end();
I !=
E; ) {
982 MVT VT =
N->getSimpleValueType(0);
984 int32_t EndbrImm = Subtarget->is64Bit() ? 0xF30F1EFA : 0xF30F1EFB;
989 "cf-protection-branch");
992 SDValue Complement = CurDAG->getConstant(~Imm, dl, VT,
false,
true);
993 Complement = CurDAG->getNOT(dl, Complement, VT);
995 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Complement);
1005 if (
N->getOpcode() == X86ISD::AND && !
N->hasAnyUseOfValue(1)) {
1007 N->getOperand(0),
N->getOperand(1));
1009 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1033 auto mayPreventLoadFold = [&]() {
1035 N->getOpcode() ==
ISD::ADD && Subtarget->hasAVX() &&
1036 !
N->getOperand(1).hasOneUse();
1039 N->getSimpleValueType(0).isVector() && !mayPreventLoadFold()) {
1047 MVT VT =
N->getSimpleValueType(0);
1055 CurDAG->getNode(NewOpcode,
DL, VT,
N->getOperand(0),
AllOnes);
1057 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1064 switch (
N->getOpcode()) {
1065 case X86ISD::VBROADCAST: {
1066 MVT VT =
N->getSimpleValueType(0);
1068 if (!Subtarget->hasBWI() &&
needBWI(VT)) {
1072 CurDAG->getNode(X86ISD::VBROADCAST, dl, NarrowVT,
N->getOperand(0));
1075 NarrowBCast, CurDAG->getIntPtrConstant(0, dl));
1078 CurDAG->getIntPtrConstant(Index, dl));
1081 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1089 case X86ISD::VBROADCAST_LOAD: {
1090 MVT VT =
N->getSimpleValueType(0);
1092 if (!Subtarget->hasBWI() &&
needBWI(VT)) {
1096 SDVTList VTs = CurDAG->getVTList(NarrowVT, MVT::Other);
1097 SDValue Ops[] = {MemNode->getChain(), MemNode->getBasePtr()};
1098 SDValue NarrowBCast = CurDAG->getMemIntrinsicNode(
1099 X86ISD::VBROADCAST_LOAD, dl, VTs,
Ops, MemNode->getMemoryVT(),
1100 MemNode->getMemOperand());
1103 NarrowBCast, CurDAG->getIntPtrConstant(0, dl));
1106 CurDAG->getIntPtrConstant(Index, dl));
1110 CurDAG->ReplaceAllUsesWith(
N, To);
1122 MVT VT =
N->getSimpleValueType(0);
1128 SDNode *MaxLd =
nullptr;
1129 SDValue Ptr = Ld->getBasePtr();
1130 SDValue Chain = Ld->getChain();
1131 for (SDNode *User : Ptr->
users()) {
1133 MVT UserVT =
User->getSimpleValueType(0);
1135 UserLd->getBasePtr() == Ptr && UserLd->getChain() == Chain &&
1136 !
User->hasAnyUseOfValue(1) &&
1150 CurDAG->getIntPtrConstant(0, dl));
1151 SDValue Res = CurDAG->getBitcast(VT, Extract);
1155 CurDAG->ReplaceAllUsesWith(
N, To);
1164 EVT EleVT =
N->getOperand(0).getValueType().getVectorElementType();
1165 if (EleVT == MVT::i1)
1168 assert(Subtarget->hasSSE41() &&
"Expected SSE4.1 support!");
1169 assert(
N->getValueType(0).getVectorElementType() != MVT::i16 &&
1170 "We can't replace VSELECT with BLENDV in vXi16!");
1172 if (Subtarget->hasVLX() && CurDAG->ComputeNumSignBits(
N->getOperand(0)) ==
1174 R = CurDAG->getNode(X86ISD::VPTERNLOG, SDLoc(
N),
N->getValueType(0),
1175 N->getOperand(0),
N->getOperand(1),
N->getOperand(2),
1176 CurDAG->getTargetConstant(0xCA, SDLoc(
N), MVT::i8));
1178 R = CurDAG->getNode(X86ISD::BLENDV, SDLoc(
N),
N->getValueType(0),
1179 N->getOperand(0),
N->getOperand(1),
1183 CurDAG->ReplaceAllUsesWith(
N,
R.getNode());
1196 if (!
N->getSimpleValueType(0).isVector())
1200 switch (
N->getOpcode()) {
1210 if (
N->isStrictFPOpcode())
1212 CurDAG->getNode(NewOpc, SDLoc(
N), {
N->getValueType(0), MVT::Other},
1213 {
N->getOperand(0),
N->getOperand(1)});
1216 CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1219 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1229 if (!
N->getValueType(0).isVector())
1233 switch (
N->getOpcode()) {
1235 case ISD::SHL: NewOpc = X86ISD::VSHLV;
break;
1236 case ISD::SRA: NewOpc = X86ISD::VSRAV;
break;
1237 case ISD::SRL: NewOpc = X86ISD::VSRLV;
break;
1239 SDValue Res = CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1240 N->getOperand(0),
N->getOperand(1));
1242 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1251 if (!
N->getValueType(0).isVector())
1255 if (
N->getOperand(0).getScalarValueSizeInBits() == 1) {
1257 "Unexpected opcode for mask vector!");
1265 SDValue Res = CurDAG->getNode(NewOpc, SDLoc(
N),
N->getValueType(0),
1268 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1288 switch (
N->getOpcode()) {
1304 bool IsStrict =
N->isStrictFPOpcode();
1307 Res = CurDAG->getNode(X86ISD::STRICT_VRNDSCALE, dl,
1308 {
N->getValueType(0), MVT::Other},
1309 {
N->getOperand(0),
N->getOperand(1),
1310 CurDAG->getTargetConstant(Imm, dl, MVT::i32)});
1312 Res = CurDAG->getNode(X86ISD::VRNDSCALE, dl,
N->getValueType(0),
1314 CurDAG->getTargetConstant(Imm, dl, MVT::i32));
1316 CurDAG->ReplaceAllUsesWith(
N, Res.
getNode());
1324 case X86ISD::FXOR: {
1327 MVT VT =
N->getSimpleValueType(0);
1328 if (VT.
isVector() || VT == MVT::f128)
1331 MVT VecVT = VT == MVT::f64 ? MVT::v2f64
1332 : VT == MVT::f32 ? MVT::v4f32
1342 if (Subtarget->hasSSE2()) {
1343 EVT IntVT = EVT(VecVT).changeVectorElementTypeToInteger();
1347 switch (
N->getOpcode()) {
1349 case X86ISD::FANDN:
Opc = X86ISD::ANDNP;
break;
1354 Res = CurDAG->getNode(
Opc, dl, IntVT, Op0, Op1);
1357 Res = CurDAG->getNode(
N->getOpcode(), dl, VecVT, Op0, Op1);
1360 CurDAG->getIntPtrConstant(0, dl));
1362 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
1369 if (OptLevel != CodeGenOptLevel::None &&
1372 !Subtarget->useIndirectThunkCalls() &&
1373 ((
N->getOpcode() == X86ISD::CALL && !Subtarget->slowTwoMemOps() &&
1374 !Subtarget->slowIndirectCall()) ||
1375 (
N->getOpcode() == X86ISD::TC_RETURN &&
1376 (Subtarget->is64Bit() ||
1377 !getTargetMachine().isPositionIndependent())))) {
1397 bool HasCallSeq =
N->getOpcode() == X86ISD::CALL;
1402 if (
N->getOpcode() == X86ISD::TC_RETURN && !checkTCRetEnoughRegs(
N))
1418 switch (
N->getOpcode()) {
1423 MVT SrcVT =
N->getOperand(0).getSimpleValueType();
1424 MVT DstVT =
N->getSimpleValueType(0);
1432 const X86TargetLowering *X86Lowering =
1433 static_cast<const X86TargetLowering *
>(TLI);
1436 if (SrcIsSSE && DstIsSSE)
1439 if (!SrcIsSSE && !DstIsSSE) {
1444 if (
N->getConstantOperandVal(1))
1452 SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
1454 MachinePointerInfo MPI =
1461 CurDAG->getEntryNode(), dl,
N->getOperand(0), MemTmp, MPI, MemVT);
1463 MemTmp, MPI, MemVT);
1470 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Result);
1479 MVT SrcVT =
N->getOperand(1).getSimpleValueType();
1480 MVT DstVT =
N->getSimpleValueType(0);
1488 const X86TargetLowering *X86Lowering =
1489 static_cast<const X86TargetLowering *
>(TLI);
1492 if (SrcIsSSE && DstIsSSE)
1495 if (!SrcIsSSE && !DstIsSSE) {
1500 if (
N->getConstantOperandVal(2))
1508 SDValue MemTmp = CurDAG->CreateStackTemporary(MemVT);
1510 MachinePointerInfo MPI =
1519 SDVTList VTs = CurDAG->getVTList(MVT::Other);
1520 SDValue Ops[] = {
N->getOperand(0),
N->getOperand(1), MemTmp};
1521 Store = CurDAG->getMemIntrinsicNode(X86ISD::FST, dl, VTs,
Ops, MemVT,
1524 if (
N->getFlags().hasNoFPExcept()) {
1526 Flags.setNoFPExcept(
true);
1527 Store->setFlags(Flags);
1530 assert(SrcVT == MemVT &&
"Unexpected VT!");
1531 Store = CurDAG->getStore(
N->getOperand(0), dl,
N->getOperand(1), MemTmp,
1536 SDVTList VTs = CurDAG->getVTList(DstVT, MVT::Other);
1538 Result = CurDAG->getMemIntrinsicNode(
1539 X86ISD::FLD, dl, VTs,
Ops, MemVT, MPI,
1541 if (
N->getFlags().hasNoFPExcept()) {
1543 Flags.setNoFPExcept(
true);
1547 assert(DstVT == MemVT &&
"Unexpected VT!");
1548 Result = CurDAG->getLoad(DstVT, dl,
Store, MemTmp, MPI);
1556 CurDAG->ReplaceAllUsesWith(
N,
Result.getNode());
1570 CurDAG->RemoveDeadNodes();
1574bool X86DAGToDAGISel::tryOptimizeRem8Extend(SDNode *
N) {
1575 unsigned Opc =
N->getMachineOpcode();
1576 if (
Opc != X86::MOVZX32rr8 &&
Opc != X86::MOVSX32rr8 &&
1577 Opc != X86::MOVSX64rr8)
1589 unsigned ExpectedOpc =
Opc == X86::MOVZX32rr8 ? X86::MOVZX32rr8_NOREX
1590 : X86::MOVSX32rr8_NOREX;
1595 if (
Opc == X86::MOVSX64rr8) {
1598 MachineSDNode *Extend = CurDAG->getMachineNode(X86::MOVSX64rr32, SDLoc(
N),
1600 ReplaceUses(
N, Extend);
1609void X86DAGToDAGISel::PostprocessISelDAG() {
1611 if (TM.getOptLevel() == CodeGenOptLevel::None)
1616 bool MadeChange =
false;
1617 while (Position != CurDAG->allnodes_begin()) {
1618 SDNode *
N = &*--Position;
1620 if (
N->use_empty() || !
N->isMachineOpcode())
1623 if (tryOptimizeRem8Extend(
N)) {
1628 unsigned Opc =
N->getMachineOpcode();
1639 case X86::CTEST16rr:
1640 case X86::CTEST32rr:
1641 case X86::CTEST64rr: {
1647#define CASE_ND(OP) \
1650 switch (
And.getMachineOpcode()) {
1657 if (
And->hasAnyUseOfValue(1))
1660 Ops[0] =
And.getOperand(0);
1661 Ops[1] =
And.getOperand(1);
1662 MachineSDNode *
Test =
1663 CurDAG->getMachineNode(
Opc, SDLoc(
N), MVT::i32,
Ops);
1664 ReplaceUses(
N,
Test);
1672 if (
And->hasAnyUseOfValue(1))
1675 bool IsCTESTCC = X86::isCTESTCC(
Opc);
1676#define FROM_TO(A, B) \
1677 CASE_ND(A) NewOpc = IsCTESTCC ? X86::C##B : X86::B; \
1679 switch (
And.getMachineOpcode()) {
1689 And.getOperand(3),
And.getOperand(4),
1690 And.getOperand(5),
And.getOperand(0)};
1693 Ops.push_back(
N->getOperand(2));
1694 Ops.push_back(
N->getOperand(3));
1697 Ops.push_back(
And.getOperand(6));
1700 Ops.push_back(
N->getOperand(4));
1702 MachineSDNode *
Test = CurDAG->getMachineNode(
1703 NewOpc, SDLoc(
N), MVT::i32, MVT::Other,
Ops);
1704 CurDAG->setNodeMemRefs(
1717 case X86::KORTESTBkk:
1718 case X86::KORTESTWkk:
1719 case X86::KORTESTDkk:
1720 case X86::KORTESTQkk: {
1722 if (Op0 !=
N->getOperand(1) || !
N->isOnlyUserOf(Op0.
getNode()) ||
1737#define FROM_TO(A, B) \
1749 if (NewOpc == X86::KTESTWkk && !Subtarget->hasDQI())
1752 MachineSDNode *KTest = CurDAG->getMachineNode(
1754 ReplaceUses(
N, KTest);
1759 case TargetOpcode::SUBREG_TO_REG: {
1760 unsigned SubRegIdx =
N->getConstantOperandVal(1);
1761 if (SubRegIdx != X86::sub_xmm && SubRegIdx != X86::sub_ymm)
1778 CASE(VMOVAPDZ128rr)
CASE(VMOVUPDZ128rr)
1779 CASE(VMOVAPSZ128rr)
CASE(VMOVUPSZ128rr)
1780 CASE(VMOVDQA32Z128rr)
CASE(VMOVDQU32Z128rr)
1781 CASE(VMOVDQA64Z128rr)
CASE(VMOVDQU64Z128rr)
1782 CASE(VMOVAPDZ256rr)
CASE(VMOVUPDZ256rr)
1783 CASE(VMOVAPSZ256rr)
CASE(VMOVUPSZ256rr)
1784 CASE(VMOVDQA32Z256rr)
CASE(VMOVDQU32Z256rr)
1785 CASE(VMOVDQA64Z256rr)
CASE(VMOVDQU64Z256rr)
1790 if (!
In.isMachineOpcode() ||
1791 In.getMachineOpcode() <= TargetOpcode::GENERIC_OP_END)
1796 uint64_t TSFlags = getInstrInfo()->get(
In.getMachineOpcode()).TSFlags;
1804 CurDAG->UpdateNodeOperands(
N, In,
N->getOperand(1));
1811 CurDAG->RemoveDeadNodes();
1816void X86DAGToDAGISel::emitSpecialCodeForMain() {
1817 if (Subtarget->isTargetCygMing()) {
1818 TargetLowering::ArgListTy
Args;
1819 auto &
DL = CurDAG->getDataLayout();
1821 TargetLowering::CallLoweringInfo CLI(*CurDAG);
1822 CLI.setChain(CurDAG->getRoot())
1823 .setCallee(CallingConv::C, Type::getVoidTy(*CurDAG->getContext()),
1824 CurDAG->getExternalSymbol(
"__main", TLI->getPointerTy(
DL)),
1826 const TargetLowering &TLI = CurDAG->getTargetLoweringInfo();
1828 CurDAG->setRoot(
Result.second);
1832void X86DAGToDAGISel::emitFunctionEntryCode() {
1835 if (
F.hasExternalLinkage() &&
F.getName() ==
"main")
1836 emitSpecialCodeForMain();
1849bool X86DAGToDAGISel::foldOffsetIntoAddress(uint64_t
Offset,
1850 X86ISelAddressMode &AM) {
1855 int64_t Val = AM.Disp +
Offset;
1858 if (Val != 0 && (AM.ES || AM.MCSym))
1862 if (Subtarget->is64Bit()) {
1865 AM.hasSymbolicDisplacement()))
1869 if (AM.BaseType == X86ISelAddressMode::FrameIndexBase &&
1888 if (Subtarget->isTarget64BitILP32() &&
1890 !AM.hasBaseOrIndexReg())
1892 }
else if (Subtarget->is16Bit()) {
1895 if (Val < -(int64_t)UINT16_MAX || Val > (int64_t)UINT16_MAX)
1905bool X86DAGToDAGISel::matchLoadInAddress(LoadSDNode *
N, X86ISelAddressMode &AM,
1906 bool AllowSegmentRegForX32) {
1919 !IndirectTlsSegRefs &&
1920 (Subtarget->isTargetGlibc() || Subtarget->isTargetMusl() ||
1921 Subtarget->isTargetAndroid() || Subtarget->isTargetFuchsia())) {
1922 if (Subtarget->isTarget64BitILP32() && !AllowSegmentRegForX32)
1924 switch (
N->getPointerInfo().getAddrSpace()) {
1926 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
1929 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
1942bool X86DAGToDAGISel::matchWrapper(
SDValue N, X86ISelAddressMode &AM) {
1945 if (AM.hasSymbolicDisplacement())
1948 bool IsRIPRelTLS =
false;
1949 bool IsRIPRel =
N.getOpcode() == X86ISD::WrapperRIP;
1966 if (IsRIPRel && AM.hasBaseOrIndexReg())
1970 X86ISelAddressMode Backup = AM;
1975 AM.GV =
G->getGlobal();
1976 AM.SymbolFlags =
G->getTargetFlags();
1979 AM.CP = CP->getConstVal();
1980 AM.Alignment = CP->getAlign();
1981 AM.SymbolFlags = CP->getTargetFlags();
1982 Offset = CP->getOffset();
1984 AM.ES = S->getSymbol();
1985 AM.SymbolFlags = S->getTargetFlags();
1987 AM.MCSym = S->getMCSymbol();
1989 AM.JT = J->getIndex();
1990 AM.SymbolFlags = J->getTargetFlags();
1992 AM.BlockAddr = BA->getBlockAddress();
1993 AM.SymbolFlags = BA->getTargetFlags();
1994 Offset = BA->getOffset();
1999 if (Subtarget->is64Bit() && !IsRIPRel && AM.GV &&
2000 TM.isLargeGlobalValue(AM.GV)) {
2005 if (foldOffsetIntoAddress(
Offset, AM)) {
2011 AM.setBaseReg(CurDAG->getRegister(X86::RIP, MVT::i64));
2019bool X86DAGToDAGISel::matchAddress(
SDValue N, X86ISelAddressMode &AM) {
2020 if (matchAddressRecursively(
N, AM, 0))
2027 if (Subtarget->isTarget64BitILP32() &&
2028 AM.BaseType == X86ISelAddressMode::RegBase &&
2029 AM.Base_Reg.
getNode() !=
nullptr && AM.IndexReg.
getNode() ==
nullptr) {
2030 SDValue Save_Base_Reg = AM.Base_Reg;
2033 if (matchLoadInAddress(LoadN, AM,
true))
2034 AM.Base_Reg = Save_Base_Reg;
2040 if (AM.Scale == 2 &&
2041 AM.BaseType == X86ISelAddressMode::RegBase &&
2042 AM.Base_Reg.
getNode() ==
nullptr) {
2043 AM.Base_Reg = AM.IndexReg;
2050 (!AM.GV || !TM.isLargeGlobalValue(AM.GV)) && Subtarget->is64Bit() &&
2051 AM.Scale == 1 && AM.BaseType == X86ISelAddressMode::RegBase &&
2052 AM.Base_Reg.
getNode() ==
nullptr && AM.IndexReg.
getNode() ==
nullptr &&
2064 AM.Base_Reg = CurDAG->getRegister(X86::RIP, MVT::i64);
2077bool X86DAGToDAGISel::hasMaterializingUse(
SDValue V)
const {
2078 const TargetInstrInfo *
TII = Subtarget->getInstrInfo();
2079 for (SDUse &U :
V->uses()) {
2080 if (
U.getResNo() !=
V.getResNo())
2082 SDNode *
User =
U.getUser();
2088 if (St->getValue() == V)
2099 if (!
User->isMachineOpcode())
2101 const MCInstrDesc &
Desc =
TII->get(
User->getMachineOpcode());
2102 if (!
Desc.mayStore())
2105 if (MemRefBegin < 0)
2108 for (
unsigned I = 0,
E =
User->getNumOperands();
I !=
E; ++
I) {
2109 if (
I >=
static_cast<unsigned>(MemRefBegin) &&
I < MemRefEnd)
2121bool X86DAGToDAGISel::matchAdd(
SDValue &
N, X86ISelAddressMode &AM,
2125 HandleSDNode Handle(
N);
2127 auto IsAddOrAddLike = [&](
SDValue V) {
2128 return V.getOpcode() ==
ISD::ADD || CurDAG->isADDLike(V);
2137 auto SplitsMaterializedValue = [&](
SDValue Op) {
2138 if (!AM.IsForLEA || !hasMaterializingUse(
Op))
2142 if (IsAddOrAddLike(
Op))
2143 return IsAddOrAddLike(
Op.getOperand(0)) ||
2144 IsAddOrAddLike(
Op.getOperand(1));
2149 return C->getZExtValue() >= 1 &&
C->getZExtValue() <= 3 &&
2150 IsAddOrAddLike(
Op.getOperand(0));
2170 if (SplitsMaterializedValue(
Op) && !AM.isRIPRelative())
2171 return matchAddressBase(
Op, AM);
2172 return matchAddressRecursively(
Op, AM,
Depth + 1);
2175 X86ISelAddressMode Backup = AM;
2176 if (!MatchOperand(
N.getOperand(0)) &&
2177 !MatchOperand(Handle.getValue().getOperand(1)))
2182 if (!MatchOperand(Handle.getValue().getOperand(1)) &&
2183 !MatchOperand(Handle.getValue().getOperand(0)))
2190 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2193 N = Handle.getValue();
2199 N = Handle.getValue();
2209 if (
N->getNodeId() == -1 ||
2229 X86ISelAddressMode &AM) {
2236 if (ScaleLog <= 0 || ScaleLog >= 4 ||
2237 Mask != (0xffu << ScaleLog))
2240 MVT XVT =
X.getSimpleValueType();
2241 MVT VT =
N.getSimpleValueType();
2266 AM.Scale = (1 << ScaleLog);
2274 X86ISelAddressMode &AM) {
2285 bool FoundAnyExtend =
false;
2289 FoundAnyExtend =
true;
2307 if (ShiftAmt != 1 && ShiftAmt != 2 && ShiftAmt != 3)
2310 MVT VT =
N.getSimpleValueType();
2312 if (FoundAnyExtend) {
2333 AM.Scale = 1 << ShiftAmt;
2334 AM.IndexReg = NewAnd;
2368 X86ISelAddressMode &AM) {
2374 unsigned MaskIdx, MaskLen;
2377 unsigned MaskLZ = 64 - (MaskIdx + MaskLen);
2383 unsigned AMShiftAmt = MaskIdx;
2387 if (AMShiftAmt == 0 || AMShiftAmt > 3)
return true;
2391 unsigned ScaleDown = (64 -
X.getSimpleValueType().getSizeInBits()) + ShiftAmt;
2392 if (MaskLZ < ScaleDown)
2394 MaskLZ -= ScaleDown;
2402 bool ReplacingAnyExtend =
false;
2404 unsigned ExtendBits =
X.getSimpleValueType().getSizeInBits() -
2405 X.getOperand(0).getSimpleValueType().getSizeInBits();
2408 X =
X.getOperand(0);
2409 MaskLZ = ExtendBits > MaskLZ ? 0 : MaskLZ - ExtendBits;
2410 ReplacingAnyExtend =
true;
2412 APInt MaskedHighBits =
2419 MVT VT =
N.getSimpleValueType();
2420 if (ReplacingAnyExtend) {
2421 assert(
X.getValueType() != VT);
2428 MVT XVT =
X.getSimpleValueType();
2449 AM.Scale = 1 << AMShiftAmt;
2450 AM.IndexReg = NewExt;
2460 X86ISelAddressMode &AM,
2468 if (!Subtarget.hasTBM() &&
2469 !(Subtarget.hasBMI() && Subtarget.hasFastBEXTR()))
2473 unsigned MaskIdx, MaskLen;
2481 unsigned AMShiftAmt = MaskIdx;
2485 if (AMShiftAmt == 0 || AMShiftAmt > 3)
return true;
2487 MVT XVT =
X.getSimpleValueType();
2488 MVT VT =
N.getSimpleValueType();
2513 AM.Scale = 1 << AMShiftAmt;
2514 AM.IndexReg = NewExt;
2521 X86ISelAddressMode &AM,
2523 assert(AM.IndexReg.
getNode() ==
nullptr &&
"IndexReg already matched");
2524 assert((AM.Scale == 1 || AM.Scale == 2 || AM.Scale == 4 || AM.Scale == 8) &&
2525 "Illegal index scale");
2531 EVT VT =
N.getValueType();
2532 unsigned Opc =
N.getOpcode();
2535 if (CurDAG->isBaseWithConstantOffset(
N)) {
2537 uint64_t
Offset = (uint64_t)AddVal->getSExtValue() * AM.Scale;
2538 if (!foldOffsetIntoAddress(
Offset, AM))
2539 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2543 if (
Opc ==
ISD::ADD &&
N.getOperand(0) ==
N.getOperand(1)) {
2544 if (AM.Scale <= 4) {
2546 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2551 if (
Opc == X86ISD::VSHLI) {
2552 uint64_t ShiftAmt =
N.getConstantOperandVal(1);
2553 uint64_t ScaleAmt = 1ULL << ShiftAmt;
2554 if ((AM.Scale * ScaleAmt) <= 8) {
2555 AM.Scale *= ScaleAmt;
2556 return matchIndexRecursively(
N.getOperand(0), AM,
Depth + 1);
2564 if (Src.getOpcode() ==
ISD::ADD && Src->getFlags().hasNoSignedWrap() &&
2566 if (CurDAG->isBaseWithConstantOffset(Src)) {
2567 SDValue AddSrc = Src.getOperand(0);
2569 int64_t
Offset = AddVal->getSExtValue();
2570 if (!foldOffsetIntoAddress((uint64_t)
Offset * AM.Scale, AM)) {
2578 CurDAG->ReplaceAllUsesWith(
N, ExtAdd);
2579 CurDAG->RemoveDeadNode(
N.getNode());
2591 unsigned SrcOpc = Src.getOpcode();
2592 if (((SrcOpc ==
ISD::ADD && Src->getFlags().hasNoUnsignedWrap()) ||
2593 CurDAG->isADDLike(Src,
true)) &&
2595 if (CurDAG->isBaseWithConstantOffset(Src)) {
2596 SDValue AddSrc = Src.getOperand(0);
2597 uint64_t
Offset = Src.getConstantOperandVal(1);
2598 if (!foldOffsetIntoAddress(
Offset * AM.Scale, AM)) {
2608 uint64_t ScaleAmt = 1ULL << ShAmt;
2609 if ((AM.Scale * ScaleAmt) <= 8 &&
2611 CurDAG->MaskedValueIsZero(ShVal, HiBits))) {
2612 AM.Scale *= ScaleAmt;
2613 SDValue ExtShVal = CurDAG->getNode(
Opc,
DL, VT, ShVal);
2624 SDValue ExtAdd = CurDAG->getNode(SrcOpc,
DL, VT, ExtSrc, ExtVal);
2628 CurDAG->ReplaceAllUsesWith(
N, ExtAdd);
2629 CurDAG->RemoveDeadNode(
N.getNode());
2630 return Res ? Res : ExtSrc;
2640bool X86DAGToDAGISel::matchAddressRecursively(
SDValue N, X86ISelAddressMode &AM,
2643 dbgs() <<
"MatchAddress: ";
2648 return matchAddressBase(
N, AM);
2653 if (AM.isRIPRelative()) {
2657 if (!(AM.ES || AM.MCSym) && AM.JT != -1)
2661 if (!foldOffsetIntoAddress(Cst->getSExtValue(), AM))
2666 switch (
N.getOpcode()) {
2669 if (!AM.hasSymbolicDisplacement() && AM.Disp == 0)
2672 AM.MCSym = ESNode->getMCSymbol();
2679 if (!foldOffsetIntoAddress(Val, AM))
2684 case X86ISD::Wrapper:
2685 case X86ISD::WrapperRIP:
2686 if (!matchWrapper(
N, AM))
2696 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2697 AM.Base_Reg.
getNode() ==
nullptr &&
2699 AM.BaseType = X86ISelAddressMode::FrameIndexBase;
2706 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
2710 unsigned Val = CN->getZExtValue();
2715 if (Val == 1 || Val == 2 || Val == 3) {
2717 AM.Scale = 1 << Val;
2718 AM.IndexReg = matchIndexRecursively(ShVal, AM,
Depth + 1);
2726 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
break;
2730 assert(
N.getSimpleValueType().getSizeInBits() <= 64 &&
2731 "Unexpected value size!");
2743 uint64_t
Mask =
And.getConstantOperandVal(1) >>
N.getConstantOperandVal(1);
2755 if (
N.getResNo() != 0)
break;
2758 case X86ISD::MUL_IMM:
2760 if (AM.BaseType == X86ISelAddressMode::RegBase &&
2761 AM.Base_Reg.
getNode() ==
nullptr &&
2762 AM.IndexReg.
getNode() ==
nullptr) {
2764 if (CN->getZExtValue() == 3 || CN->getZExtValue() == 5 ||
2765 CN->getZExtValue() == 9) {
2766 AM.Scale = unsigned(CN->getZExtValue())-1;
2778 uint64_t Disp = AddVal->getSExtValue() * CN->getZExtValue();
2779 if (foldOffsetIntoAddress(Disp, AM))
2780 Reg =
N.getOperand(0);
2782 Reg =
N.getOperand(0);
2785 AM.IndexReg = AM.Base_Reg =
Reg;
2801 HandleSDNode Handle(
N);
2804 X86ISelAddressMode Backup = AM;
2805 if (matchAddressRecursively(
N.getOperand(0), AM,
Depth+1)) {
2806 N = Handle.getValue();
2810 N = Handle.getValue();
2812 if (AM.IndexReg.
getNode() || AM.isRIPRelative()) {
2827 RHS.getOperand(0).getValueType() == MVT::i32))
2831 if ((AM.BaseType == X86ISelAddressMode::RegBase && AM.Base_Reg.
getNode() &&
2833 AM.BaseType == X86ISelAddressMode::FrameIndexBase)
2837 if ((AM.hasSymbolicDisplacement() && !Backup.hasSymbolicDisplacement()) +
2838 ((AM.Disp != 0) && (Backup.Disp == 0)) +
2851 AM.NegateIndex =
true;
2859 if (!CurDAG->isADDLike(
N))
2863 if (!matchAdd(
N, AM,
Depth))
2872 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
break;
2876 assert(
N.getSimpleValueType().getSizeInBits() <= 64 &&
2877 "Unexpected value size!");
2882 if (
N.getOperand(0).getOpcode() ==
ISD::SRL) {
2886 uint64_t
Mask =
N.getConstantOperandVal(1);
2911 if (AM.IndexReg.
getNode() !=
nullptr || AM.Scale != 1)
2919 if (
SDValue Index = matchIndexRecursively(
N, AM,
Depth + 1))
2921 AM.IndexReg =
Index;
2927 if (Src.getOpcode() ==
ISD::AND && Src.hasOneUse())
2929 Mask = MaskC->getAPIntValue();
2930 Src = Src.getOperand(0);
2933 if (Src.getOpcode() ==
ISD::SHL && Src.hasOneUse() &&
N->hasOneUse()) {
2935 SDValue ShlSrc = Src.getOperand(0);
2936 SDValue ShlAmt = Src.getOperand(1);
2940 unsigned ShAmtV = ShAmtC->getZExtValue();
2948 if (!Src->getFlags().hasNoUnsignedWrap() &&
2949 !CurDAG->MaskedValueIsZero(ShlSrc, HighZeros & Mask))
2957 MVT VT =
N.getSimpleValueType();
2961 if (!
Mask.isAllOnes()) {
2962 Res = CurDAG->getConstant(
Mask.lshr(ShAmtV),
DL, SrcVT);
2964 Res = CurDAG->getNode(
ISD::AND,
DL, SrcVT, ShlSrc, Res);
2971 CurDAG->ReplaceAllUsesWith(
N, NewShl);
2972 CurDAG->RemoveDeadNode(
N.getNode());
2975 AM.Scale = 1 << ShAmtV;
2979 AM.IndexReg = matchIndexRecursively(Zext, AM,
Depth + 1);
2983 if (Src.getOpcode() ==
ISD::SRL && !
Mask.isAllOnes()) {
2986 Src.getOperand(0), AM))
2991 Src.getOperand(0), AM))
2996 Src.getOperand(0), AM, *Subtarget))
3004 return matchAddressBase(
N, AM);
3009bool X86DAGToDAGISel::matchAddressBase(
SDValue N, X86ISelAddressMode &AM) {
3011 if (AM.BaseType != X86ISelAddressMode::RegBase || AM.Base_Reg.
getNode()) {
3024 AM.BaseType = X86ISelAddressMode::RegBase;
3029bool X86DAGToDAGISel::matchVectorAddressRecursively(
SDValue N,
3030 X86ISelAddressMode &AM,
3033 dbgs() <<
"MatchVectorAddress: ";
3038 return matchAddressBase(
N, AM);
3041 switch (
N.getOpcode()) {
3044 if (!foldOffsetIntoAddress(Val, AM))
3048 case X86ISD::Wrapper:
3049 if (!matchWrapper(
N, AM))
3055 HandleSDNode Handle(
N);
3057 X86ISelAddressMode Backup = AM;
3058 if (!matchVectorAddressRecursively(
N.getOperand(0), AM,
Depth + 1) &&
3059 !matchVectorAddressRecursively(Handle.getValue().getOperand(1), AM,
3065 if (!matchVectorAddressRecursively(Handle.getValue().getOperand(1), AM,
3067 !matchVectorAddressRecursively(Handle.getValue().getOperand(0), AM,
3072 N = Handle.getValue();
3077 return matchAddressBase(
N, AM);
3083bool X86DAGToDAGISel::matchVectorAddress(
SDValue N, X86ISelAddressMode &AM) {
3084 return matchVectorAddressRecursively(
N, AM, 0);
3087bool X86DAGToDAGISel::selectVectorAddr(MemSDNode *Parent,
SDValue BasePtr,
3092 X86ISelAddressMode AM;
3098 AM.IndexReg = matchIndexRecursively(IndexOp, AM, 0);
3100 AM.IndexReg = IndexOp;
3104 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
3106 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
3108 AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16);
3111 MVT VT =
BasePtr.getSimpleValueType();
3114 if (matchVectorAddress(BasePtr, AM))
3117 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3130 SDValue &Segment,
bool HasNDDM) {
3131 X86ISelAddressMode AM;
3138 Parent->
getOpcode() != X86ISD::TLSCALL &&
3139 Parent->
getOpcode() != X86ISD::ENQCMD &&
3140 Parent->
getOpcode() != X86ISD::ENQCMDS &&
3141 Parent->
getOpcode() != X86ISD::EH_SJLJ_SETJMP &&
3142 Parent->
getOpcode() != X86ISD::EH_SJLJ_LONGJMP) {
3143 unsigned AddrSpace =
3146 AM.Segment = CurDAG->getRegister(X86::GS, MVT::i16);
3148 AM.Segment = CurDAG->getRegister(X86::FS, MVT::i16);
3150 AM.Segment = CurDAG->getRegister(X86::SS, MVT::i16);
3155 MVT VT =
N.getSimpleValueType();
3157 if (matchAddress(
N, AM))
3160 if (!HasNDDM && !AM.isRIPRelative())
3163 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3170 return selectAddr(Parent,
N,
Base, Scale, Index, Disp, Segment,
3171 Subtarget->hasNDDM());
3183 if (
N->getOpcode() != X86ISD::Wrapper)
3186 N =
N.getOperand(0);
3203 return CR->getUnsignedMax().ult(1ull << 32);
3205 return !TM.isLargeGlobalValue(GV);
3214 if (!selectLEAAddr(
N,
Base, Scale, Index, Disp, Segment))
3220 SubReg = X86::sub_8bit;
3222 SubReg = X86::sub_16bit;
3224 SubReg = X86::sub_32bit;
3227 if (RN &&
RN->getReg() == 0)
3228 Base = CurDAG->getRegister(0, MVT::i64);
3235 Base = CurDAG->getTargetInsertSubreg(SubReg,
DL, MVT::i64, ImplDef,
Base);
3238 [[maybe_unused]] EVT IndexType =
Index.getValueType();
3240 if (RN &&
RN->getReg() == 0)
3241 Index = CurDAG->getRegister(0, MVT::i64);
3244 "Expect to be extending 8/16/32-bit registers for use in LEA");
3247 Index = CurDAG->getTargetInsertSubreg(SubReg,
DL, MVT::i64, ImplDef, Index);
3255bool X86DAGToDAGISel::selectLEAAddr(
SDValue N,
3259 X86ISelAddressMode AM;
3264 MVT VT =
N.getSimpleValueType();
3269 SDValue T = CurDAG->getRegister(0, MVT::i32);
3271 if (matchAddress(
N, AM))
3276 unsigned Complexity = 0;
3277 if (AM.BaseType == X86ISelAddressMode::RegBase && AM.Base_Reg.
getNode())
3279 else if (AM.BaseType == X86ISelAddressMode::FrameIndexBase)
3295 if (AM.hasSymbolicDisplacement()) {
3297 if (Subtarget->is64Bit())
3307 auto isMathWithFlags = [](
SDValue V) {
3308 switch (
V.getOpcode()) {
3322 return !
SDValue(
V.getNode(), 1).use_empty();
3329 if (isMathWithFlags(
N.getOperand(0)) || isMathWithFlags(
N.getOperand(1)))
3337 if (Complexity <= 2)
3340 getAddressOperands(AM,
DL, VT,
Base, Scale, Index, Disp, Segment);
3351 X86ISelAddressMode AM;
3353 AM.GV = GA->getGlobal();
3354 AM.Disp += GA->getOffset();
3355 AM.SymbolFlags = GA->getTargetFlags();
3358 AM.ES = SA->getSymbol();
3359 AM.SymbolFlags = SA->getTargetFlags();
3362 if (Subtarget->is32Bit()) {
3364 AM.IndexReg = CurDAG->getRegister(X86::EBX, MVT::i32);
3367 MVT VT =
N.getSimpleValueType();
3368 getAddressOperands(AM, SDLoc(
N), VT,
Base, Scale, Index, Disp, Segment);
3376 EVT VT =
N.getValueType();
3377 bool WasTruncated =
false;
3379 WasTruncated =
true;
3380 N =
N.getOperand(0);
3383 if (
N.getOpcode() != X86ISD::Wrapper)
3389 unsigned Opc =
N.getOperand(0)->getOpcode();
3391 Op =
N.getOperand(0);
3394 return !WasTruncated;
3399 std::optional<ConstantRange> CR = GA->getGlobal()->getAbsoluteSymbolRange();
3400 if (!CR || CR->getUnsignedMax().uge(1ull << VT.
getSizeInBits()))
3404 Op = CurDAG->getTargetGlobalAddress(GA->getGlobal(), SDLoc(
N), VT,
3405 GA->getOffset(), GA->getTargetFlags());
3409bool X86DAGToDAGISel::tryFoldLoad(SDNode *Root, SDNode *
P,
SDValue N,
3413 assert(Root &&
P &&
"Unknown root/parent nodes");
3415 !IsProfitableToFold(
N,
P, Root) ||
3416 !IsLegalToFold(
N,
P, Root, OptLevel))
3419 return selectAddr(
N.getNode(),
3420 N.getOperand(1),
Base, Scale, Index, Disp, Segment);
3423bool X86DAGToDAGISel::tryFoldBroadcast(SDNode *Root, SDNode *
P,
SDValue N,
3427 assert(Root &&
P &&
"Unknown root/parent nodes");
3428 if (
N->getOpcode() != X86ISD::VBROADCAST_LOAD ||
3429 !IsProfitableToFold(
N,
P, Root) ||
3430 !IsLegalToFold(
N,
P, Root, OptLevel))
3433 return selectAddr(
N.getNode(),
3434 N.getOperand(1),
Base, Scale, Index, Disp, Segment);
3440SDNode *X86DAGToDAGISel::getGlobalBaseReg() {
3443 return CurDAG->getRegister(GlobalBaseReg, TLI->
getPointerTy(
DL)).getNode();
3446bool X86DAGToDAGISel::isSExtAbsoluteSymbolRef(
unsigned Width, SDNode *
N)
const {
3448 N =
N->getOperand(0).getNode();
3449 if (
N->getOpcode() != X86ISD::Wrapper)
3456 auto *GV = GA->getGlobal();
3459 return CR->getSignedMin().sge(-1ull << Width) &&
3460 CR->getSignedMax().slt(1ull << Width);
3466 !TM.isLargeGlobalValue(GV);
3470 assert(
N->isMachineOpcode() &&
"Unexpected node");
3471 unsigned Opc =
N->getMachineOpcode();
3472 const MCInstrDesc &MCID = getInstrInfo()->get(
Opc);
3477 return static_cast<X86::CondCode>(
N->getConstantOperandVal(CondNo));
3482bool X86DAGToDAGISel::onlyUsesZeroFlag(
SDValue Flags)
const {
3484 for (SDUse &Use :
Flags->uses()) {
3486 if (
Use.getResNo() !=
Flags.getResNo())
3494 for (SDUse &FlagUse :
User->uses()) {
3496 if (FlagUse.getResNo() != 1)
3499 if (!FlagUse.getUser()->isMachineOpcode())
3519bool X86DAGToDAGISel::hasNoSignFlagUses(
SDValue Flags)
const {
3521 for (SDUse &Use :
Flags->uses()) {
3523 if (
Use.getResNo() !=
Flags.getResNo())
3531 for (SDUse &FlagUse :
User->uses()) {
3533 if (FlagUse.getResNo() != 1)
3536 if (!FlagUse.getUser()->isMachineOpcode())
3576 bool X86DAGToDAGISel::hasNoCarryFlagUses(
SDValue Flags)
const {
3578 for (SDUse &Use :
Flags->uses()) {
3580 if (
Use.getResNo() !=
Flags.getResNo())
3584 unsigned UserOpc =
User->getOpcode();
3591 for (SDUse &FlagUse :
User->uses()) {
3593 if (FlagUse.getResNo() != 1)
3596 if (!FlagUse.getUser()->isMachineOpcode())
3616 case X86ISD::SETCC: CCOpNo = 0;
break;
3617 case X86ISD::SETCC_CARRY: CCOpNo = 0;
break;
3618 case X86ISD::CMOV: CCOpNo = 2;
break;
3619 case X86ISD::BRCOND: CCOpNo = 2;
break;
3629bool X86DAGToDAGISel::checkTCRetEnoughRegs(SDNode *
N)
const {
3632 const X86RegisterInfo *RI = Subtarget->getRegisterInfo();
3636 if (Subtarget->is64Bit()) {
3639 ? &X86::GR64_TCW64RegClass
3640 : &X86::GR64_TCRegClass;
3648 ? &X86::GR32RegClass
3649 : &X86::GR32_TCRegClass;
3656 unsigned LoadGPRs = 2;
3658 assert(
N->getOpcode() == X86ISD::TC_RETURN);
3661 if (Subtarget->is32Bit()) {
3667 }
else if (
BasePtr.getOpcode() == X86ISD::Wrapper &&
3669 if (getTargetMachine().isPositionIndependent())
3677 for (
unsigned I = 3,
E =
N->getNumOperands();
I !=
E; ++
I) {
3679 if (!RI->isGeneralPurposeRegister(*MF,
RN->getReg()))
3681 if (++
ArgGPRs + LoadGPRs > AvailGPRs)
3697 if (StoredVal.
getResNo() != 0)
return false;
3714 if (!
Load.hasOneUse())
3722 bool FoundLoad =
false;
3726 const unsigned int Max = 1024;
3768 if (Chain ==
Load.getValue(1)) {
3774 if (
Op ==
Load.getValue(1)) {
3790 if (
Op.getNode() != LoadNode)
3822bool X86DAGToDAGISel::foldLoadStoreIntoMemOperand(SDNode *Node) {
3824 SDValue StoredVal = StoreNode->getOperand(1);
3830 EVT MemVT = StoreNode->getMemoryVT();
3831 if (MemVT != MVT::i64 && MemVT != MVT::i32 && MemVT != MVT::i16 &&
3835 bool IsCommutable =
false;
3836 bool IsNegate =
false;
3850 IsCommutable =
true;
3854 unsigned LoadOpNo = IsNegate ? 1 : 0;
3855 LoadSDNode *LoadNode =
nullptr;
3858 LoadNode, InputChain)) {
3865 LoadNode, InputChain))
3870 if (!selectAddr(LoadNode, LoadNode->
getBasePtr(),
Base, Scale, Index, Disp,
3874 auto SelectOpcode = [&](
unsigned Opc64,
unsigned Opc32,
unsigned Opc16,
3895 unsigned NewOpc = SelectOpcode(X86::NEG64m, X86::NEG32m, X86::NEG16m,
3898 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32,
3905 if (!Subtarget->slowIncDec() || CurDAG->shouldOptForSize()) {
3909 if ((IsOne || IsNegOne) && hasNoCarryFlagUses(StoredVal.
getValue(1))) {
3911 ((
Opc == X86ISD::ADD) == IsOne)
3912 ? SelectOpcode(X86::INC64m, X86::INC32m, X86::INC16m, X86::INC8m)
3913 : SelectOpcode(X86::DEC64m, X86::DEC32m, X86::DEC16m, X86::DEC8m);
3915 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32,
3926 auto SelectRegOpcode = [SelectOpcode](
unsigned Opc) {
3929 return SelectOpcode(X86::ADD64mr, X86::ADD32mr, X86::ADD16mr,
3932 return SelectOpcode(X86::ADC64mr, X86::ADC32mr, X86::ADC16mr,
3935 return SelectOpcode(X86::SUB64mr, X86::SUB32mr, X86::SUB16mr,
3938 return SelectOpcode(X86::SBB64mr, X86::SBB32mr, X86::SBB16mr,
3941 return SelectOpcode(X86::AND64mr, X86::AND32mr, X86::AND16mr,
3944 return SelectOpcode(X86::OR64mr, X86::OR32mr, X86::OR16mr, X86::OR8mr);
3946 return SelectOpcode(X86::XOR64mr, X86::XOR32mr, X86::XOR16mr,
3952 auto SelectImmOpcode = [SelectOpcode](
unsigned Opc) {
3955 return SelectOpcode(X86::ADD64mi32, X86::ADD32mi, X86::ADD16mi,
3958 return SelectOpcode(X86::ADC64mi32, X86::ADC32mi, X86::ADC16mi,
3961 return SelectOpcode(X86::SUB64mi32, X86::SUB32mi, X86::SUB16mi,
3964 return SelectOpcode(X86::SBB64mi32, X86::SBB32mi, X86::SBB16mi,
3967 return SelectOpcode(X86::AND64mi32, X86::AND32mi, X86::AND16mi,
3970 return SelectOpcode(X86::OR64mi32, X86::OR32mi, X86::OR16mi,
3973 return SelectOpcode(X86::XOR64mi32, X86::XOR32mi, X86::XOR16mi,
3980 unsigned NewOpc = SelectRegOpcode(
Opc);
3986 int64_t OperandV = OperandC->getSExtValue();
3991 if ((
Opc == X86ISD::ADD ||
Opc == X86ISD::SUB) &&
3993 (MemVT == MVT::i64 && !
isInt<32>(OperandV) &&
3995 hasNoCarryFlagUses(StoredVal.
getValue(1))) {
3996 OperandV = -OperandV;
3997 Opc =
Opc == X86ISD::ADD ? X86ISD::SUB : X86ISD::ADD;
4000 if (MemVT != MVT::i64 ||
isInt<32>(OperandV)) {
4001 Operand = CurDAG->getSignedTargetConstant(OperandV, SDLoc(Node), MemVT);
4002 NewOpc = SelectImmOpcode(
Opc);
4006 if (
Opc == X86ISD::ADC ||
Opc == X86ISD::SBB) {
4008 CurDAG->getCopyToReg(InputChain, SDLoc(Node), X86::EFLAGS,
4012 Segment, Operand, CopyTo, CopyTo.
getValue(1)};
4013 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other,
4017 Segment, Operand, InputChain};
4018 Result = CurDAG->getMachineNode(NewOpc, SDLoc(Node), MVT::i32, MVT::Other,
4027 MachineMemOperand *MemOps[] = {StoreNode->getMemOperand(),
4029 CurDAG->setNodeMemRefs(Result, MemOps);
4035 CurDAG->RemoveDeadNode(Node);
4046bool X86DAGToDAGISel::matchBitExtract(SDNode *Node) {
4050 "Should be either an and-mask, or right-shift after clearing high bits.");
4053 if (!Subtarget->hasBMI() && !Subtarget->hasBMI2())
4056 MVT NVT =
Node->getSimpleValueType(0);
4059 if (NVT != MVT::i32 && NVT != MVT::i64)
4067 const bool AllowExtraUsesByDefault = Subtarget->hasBMI2();
4068 auto checkUses = [AllowExtraUsesByDefault](
4070 std::optional<bool> AllowExtraUses) {
4071 return AllowExtraUses.value_or(AllowExtraUsesByDefault) ||
4072 Op.getNode()->hasNUsesOfValue(NUses,
Op.getResNo());
4074 auto checkOneUse = [checkUses](
SDValue Op,
4075 std::optional<bool> AllowExtraUses =
4077 return checkUses(
Op, 1, AllowExtraUses);
4079 auto checkTwoUse = [checkUses](
SDValue Op,
4080 std::optional<bool> AllowExtraUses =
4082 return checkUses(
Op, 2, AllowExtraUses);
4085 auto peekThroughOneUseTruncation = [checkOneUse](
SDValue V) {
4087 assert(
V.getSimpleValueType() == MVT::i32 &&
4088 V.getOperand(0).getSimpleValueType() == MVT::i64 &&
4089 "Expected i64 -> i32 truncation");
4090 V =
V.getOperand(0);
4096 auto matchPatternA = [checkOneUse, peekThroughOneUseTruncation, &NBits,
4099 if (
Mask->getOpcode() !=
ISD::ADD || !checkOneUse(Mask))
4105 SDValue M0 = peekThroughOneUseTruncation(
Mask->getOperand(0));
4110 NBits =
M0->getOperand(1);
4111 NegateNBits =
false;
4115 auto isAllOnes = [
this, peekThroughOneUseTruncation, NVT](
SDValue V) {
4116 V = peekThroughOneUseTruncation(V);
4117 return CurDAG->MaskedValueIsAllOnes(
4123 auto matchPatternB = [checkOneUse, isAllOnes, peekThroughOneUseTruncation,
4126 if (
Mask.getOpcode() !=
ISD::XOR || !checkOneUse(Mask))
4129 if (!isAllOnes(
Mask->getOperand(1)))
4132 SDValue M0 = peekThroughOneUseTruncation(
Mask->getOperand(0));
4136 if (!isAllOnes(
M0->getOperand(0)))
4138 NBits =
M0->getOperand(1);
4139 NegateNBits =
false;
4145 auto canonicalizeShiftAmt = [&NBits, &NegateNBits](
SDValue ShiftAmt,
4146 unsigned Bitwidth) {
4151 NBits = NBits.getOperand(0);
4157 if (!V0 || V0->getZExtValue() != Bitwidth)
4159 NBits = NBits.getOperand(1);
4160 NegateNBits =
false;
4166 auto matchPatternC = [checkOneUse, peekThroughOneUseTruncation, &NegateNBits,
4169 Mask = peekThroughOneUseTruncation(Mask);
4170 unsigned Bitwidth =
Mask.getSimpleValueType().getSizeInBits();
4172 if (
Mask.getOpcode() !=
ISD::SRL || !checkOneUse(Mask))
4179 if (!checkOneUse(
M1))
4181 canonicalizeShiftAmt(
M1, Bitwidth);
4186 return !NegateNBits;
4194 auto matchPatternD = [checkOneUse, checkTwoUse, canonicalizeShiftAmt,
4195 AllowExtraUsesByDefault, &NegateNBits,
4196 &
X](SDNode *
Node) ->
bool {
4208 canonicalizeShiftAmt(N1, Bitwidth);
4212 const bool AllowExtraUses = AllowExtraUsesByDefault && !NegateNBits;
4213 if (!checkOneUse(N0, AllowExtraUses) || !checkTwoUse(N1, AllowExtraUses))
4219 auto matchLowBitMask = [matchPatternA, matchPatternB,
4221 return matchPatternA(Mask) || matchPatternB(Mask) || matchPatternC(Mask);
4225 X =
Node->getOperand(0);
4228 if (matchLowBitMask(Mask)) {
4232 if (!matchLowBitMask(Mask))
4235 }
else if (matchLowBitMask(
SDValue(Node, 0))) {
4236 X = CurDAG->getAllOnesConstant(SDLoc(Node), NVT);
4237 }
else if (!matchPatternD(Node))
4242 if (NegateNBits && !Subtarget->hasBMI2())
4247 if (NBits.getSimpleValueType() != MVT::i8) {
4254 ConstantSDNode *
Imm =
nullptr;
4255 if (NBits->getOpcode() ==
ISD::AND)
4257 NBits = NBits->getOperand(0);
4262 CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, MVT::i32), 0);
4265 SDValue SRIdxVal = CurDAG->getTargetConstant(X86::sub_8bit,
DL, MVT::i32);
4267 NBits =
SDValue(CurDAG->getMachineNode(TargetOpcode::INSERT_SUBREG,
DL,
4268 MVT::i32, ImplDef, NBits, SRIdxVal),
4274 CurDAG->getNode(
ISD::AND,
DL, MVT::i32, NBits,
4275 CurDAG->getConstant(
Imm->getZExtValue(),
DL, MVT::i32));
4285 NBits = CurDAG->getNode(
ISD::SUB,
DL, MVT::i32, BitWidthC, NBits);
4289 if (Subtarget->hasBMI2()) {
4291 if (NVT != MVT::i32) {
4297 SDValue Extract = CurDAG->getNode(X86ISD::BZHI,
DL, NVT,
X, NBits);
4298 ReplaceNode(Node, Extract.
getNode());
4299 SelectCode(Extract.
getNode());
4308 SDValue RealX = peekThroughOneUseTruncation(
X);
4314 MVT XVT =
X.getSimpleValueType();
4324 SDValue C8 = CurDAG->getConstant(8,
DL, MVT::i8);
4332 SDValue ShiftAmt =
X.getOperand(1);
4333 X =
X.getOperand(0);
4336 "Expected shift amount to be i8");
4340 SDValue OrigShiftAmt = ShiftAmt;
4345 Control = CurDAG->getNode(
ISD::OR,
DL, MVT::i32, Control, ShiftAmt);
4350 if (XVT != MVT::i32) {
4356 SDValue Extract = CurDAG->getNode(X86ISD::BEXTR,
DL, XVT,
X, Control);
4364 ReplaceNode(Node, Extract.
getNode());
4365 SelectCode(Extract.
getNode());
4371MachineSDNode *X86DAGToDAGISel::matchBEXTRFromAndImm(SDNode *Node) {
4372 MVT NVT =
Node->getSimpleValueType(0);
4385 Subtarget->hasTBM() || (Subtarget->hasBMI() && Subtarget->hasFastBEXTR());
4386 if (!PreferBEXTR && !Subtarget->hasBMI2())
4398 if (NVT != MVT::i32 && NVT != MVT::i64)
4404 if (!MaskCst || !ShiftCst)
4408 uint64_t
Mask = MaskCst->getZExtValue();
4412 uint64_t Shift = ShiftCst->getZExtValue();
4417 if (Shift == 8 && MaskSize == 8)
4428 if (!PreferBEXTR && MaskSize <= 32)
4432 unsigned ROpc, MOpc;
4434#define GET_EGPR_IF_ENABLED(OPC) (Subtarget->hasEGPR() ? OPC##_EVEX : OPC)
4436 assert(Subtarget->hasBMI2() &&
"We must have BMI2's BZHI then.");
4440 Control = CurDAG->getTargetConstant(Shift + MaskSize, dl, NVT);
4445 unsigned NewOpc = NVT == MVT::i64 ? X86::MOV32ri64 : X86::MOV32ri;
4446 Control =
SDValue(CurDAG->getMachineNode(NewOpc, dl, NVT, Control), 0);
4452 Control = CurDAG->getTargetConstant(Shift | (MaskSize << 8), dl, NVT);
4453 if (Subtarget->hasTBM()) {
4454 ROpc = NVT == MVT::i64 ? X86::BEXTRI64ri : X86::BEXTRI32ri;
4455 MOpc = NVT == MVT::i64 ? X86::BEXTRI64mi : X86::BEXTRI32mi;
4457 assert(Subtarget->hasBMI() &&
"We must have BMI1's BEXTR then.");
4463 unsigned NewOpc = NVT == MVT::i64 ? X86::MOV32ri64 : X86::MOV32ri;
4464 Control =
SDValue(CurDAG->getMachineNode(NewOpc, dl, NVT, Control), 0);
4468 MachineSDNode *NewNode;
4470 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4471 if (tryFoldLoad(Node, N0.
getNode(), Input, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4473 Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Control, Input.
getOperand(0)};
4474 SDVTList VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
4475 NewNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4479 CurDAG->setNodeMemRefs(NewNode, {
cast<LoadSDNode>(Input)->getMemOperand()});
4481 NewNode = CurDAG->getMachineNode(ROpc, dl, NVT, MVT::i32, Input, Control);
4486 SDValue ShAmt = CurDAG->getTargetConstant(Shift, dl, NVT);
4490 CurDAG->getMachineNode(NewOpc, dl, NVT,
SDValue(NewNode, 0), ShAmt);
4497MachineSDNode *X86DAGToDAGISel::emitPCMPISTR(
unsigned ROpc,
unsigned MOpc,
4498 bool MayFoldLoad,
const SDLoc &dl,
4499 MVT VT, SDNode *Node) {
4504 Imm = CurDAG->getTargetConstant(*Val, SDLoc(Node),
Imm.getValueType());
4507 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4508 if (MayFoldLoad && tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4511 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Other);
4512 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4521 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32);
4522 MachineSDNode *CNode = CurDAG->getMachineNode(ROpc, dl, VTs,
Ops);
4529MachineSDNode *X86DAGToDAGISel::emitPCMPESTR(
unsigned ROpc,
unsigned MOpc,
4530 bool MayFoldLoad,
const SDLoc &dl,
4531 MVT VT, SDNode *Node,
4537 Imm = CurDAG->getTargetConstant(*Val, SDLoc(Node),
Imm.getValueType());
4540 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4541 if (MayFoldLoad && tryFoldLoad(Node, N2, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4544 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Other, MVT::Glue);
4545 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
4555 SDVTList VTs = CurDAG->getVTList(VT, MVT::i32, MVT::Glue);
4556 MachineSDNode *CNode = CurDAG->getMachineNode(ROpc, dl, VTs,
Ops);
4561bool X86DAGToDAGISel::tryShiftAmountMod(SDNode *
N) {
4562 EVT VT =
N->getValueType(0);
4569 unsigned Size = VT == MVT::i64 ? 64 : 32;
4572 SDValue ShiftAmt = OrigShiftAmt;
4591 if (Add1C && Add1C->getAPIntValue().urem(
Size) == 0) {
4595 ((Add0C && Add0C->getAPIntValue().urem(
Size) ==
Size - 1) ||
4596 (Add1C && Add1C->getAPIntValue().urem(
Size) ==
Size - 1))) {
4600 assert(Add0C ==
nullptr || Add1C ==
nullptr);
4609 NewShiftAmt = CurDAG->getNode(
ISD::XOR,
DL, OpVT,
4610 Add0C ==
nullptr ? Add0 : Add1,
AllOnes);
4616 Add0C->getZExtValue() != 0) {
4619 if (Add0C->getZExtValue() %
Size == 0)
4622 Add0C->getZExtValue() % 32 == 0) {
4630 Add0 = CurDAG->getZExtOrTrunc(Add0,
DL, SubVT);
4634 X = CurDAG->getNode(
ISD::ADD,
DL, SubVT, Add1, Add0);
4656 NewShiftAmt = CurDAG->getNode(
ISD::TRUNCATE,
DL, MVT::i8, NewShiftAmt);
4663 NewShiftAmt = CurDAG->getNode(
ISD::AND,
DL, MVT::i8, NewShiftAmt,
4664 CurDAG->getConstant(
Size - 1,
DL, MVT::i8));
4668 SDNode *UpdatedNode = CurDAG->UpdateNodeOperands(
N,
N->getOperand(0),
4670 if (UpdatedNode !=
N) {
4673 ReplaceNode(
N, UpdatedNode);
4680 CurDAG->RemoveDeadNode(OrigShiftAmt.
getNode());
4688bool X86DAGToDAGISel::tryShrinkShlLogicImm(SDNode *
N) {
4689 MVT NVT =
N->getSimpleValueType(0);
4690 unsigned Opcode =
N->getOpcode();
4702 int64_t Val = Cst->getSExtValue();
4707 bool FoundAnyExtend =
false;
4711 FoundAnyExtend =
true;
4719 if (NVT != MVT::i32 && NVT != MVT::i64)
4726 uint64_t ShAmt = ShlCst->getZExtValue();
4730 uint64_t RemovedBitsMask = (1ULL << ShAmt) - 1;
4731 if (Opcode !=
ISD::AND && (Val & RemovedBitsMask) != 0)
4736 auto CanShrinkImmediate = [&](int64_t &ShiftedVal) {
4740 ShiftedVal = (uint64_t)Val >> ShAmt;
4744 if (ShiftedVal == UINT8_MAX || ShiftedVal == UINT16_MAX)
4747 ShiftedVal = Val >> ShAmt;
4753 ShiftedVal = (uint64_t)Val >> ShAmt;
4761 if (!CanShrinkImmediate(ShiftedVal))
4771 unsigned ZExtWidth = Cst->getAPIntValue().getActiveBits();
4777 NeededMask &= ~Cst->getAPIntValue();
4779 if (CurDAG->MaskedValueIsZero(
N->getOperand(0), NeededMask))
4784 if (FoundAnyExtend) {
4790 SDValue NewCst = CurDAG->getSignedConstant(ShiftedVal, dl, NVT);
4792 SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT,
X, NewCst);
4801bool X86DAGToDAGISel::matchVPTERNLOG(SDNode *Root, SDNode *ParentA,
4802 SDNode *ParentB, SDNode *ParentC,
4805 assert(
A.isOperandOf(ParentA) &&
B.isOperandOf(ParentB) &&
4806 C.isOperandOf(ParentC) &&
"Incorrect parent node");
4808 auto tryFoldLoadOrBCast =
4811 if (tryFoldLoad(Root,
P, L,
Base, Scale, Index, Disp, Segment))
4817 L =
L.getOperand(0);
4820 if (
L.getOpcode() != X86ISD::VBROADCAST_LOAD)
4825 unsigned Size = MemIntr->getMemoryVT().getSizeInBits();
4829 return tryFoldBroadcast(Root,
P, L,
Base, Scale, Index, Disp, Segment);
4832 bool FoldedLoad =
false;
4833 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
4834 if (tryFoldLoadOrBCast(Root, ParentC,
C, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
4836 }
else if (tryFoldLoadOrBCast(Root, ParentA,
A, Tmp0, Tmp1, Tmp2, Tmp3,
4841 uint8_t OldImm =
Imm;
4842 Imm = OldImm & 0xa5;
4843 if (OldImm & 0x02)
Imm |= 0x10;
4844 if (OldImm & 0x10)
Imm |= 0x02;
4845 if (OldImm & 0x08)
Imm |= 0x40;
4846 if (OldImm & 0x40)
Imm |= 0x08;
4847 }
else if (tryFoldLoadOrBCast(Root, ParentB,
B, Tmp0, Tmp1, Tmp2, Tmp3,
4852 uint8_t OldImm =
Imm;
4853 Imm = OldImm & 0x99;
4854 if (OldImm & 0x02)
Imm |= 0x04;
4855 if (OldImm & 0x04)
Imm |= 0x02;
4856 if (OldImm & 0x20)
Imm |= 0x40;
4857 if (OldImm & 0x40)
Imm |= 0x20;
4862 SDValue TImm = CurDAG->getTargetConstant(Imm,
DL, MVT::i8);
4866 MachineSDNode *MNode;
4868 SDVTList VTs = CurDAG->getVTList(NVT, MVT::Other);
4871 if (
C.getOpcode() == X86ISD::VBROADCAST_LOAD) {
4873 unsigned EltSize = MemIntr->getMemoryVT().getSizeInBits();
4874 assert((EltSize == 32 || EltSize == 64) &&
"Unexpected broadcast size!");
4876 bool UseD = EltSize == 32;
4878 Opc = UseD ? X86::VPTERNLOGDZ128rmbi : X86::VPTERNLOGQZ128rmbi;
4880 Opc = UseD ? X86::VPTERNLOGDZ256rmbi : X86::VPTERNLOGQZ256rmbi;
4882 Opc = UseD ? X86::VPTERNLOGDZrmbi : X86::VPTERNLOGQZrmbi;
4888 Opc = UseD ? X86::VPTERNLOGDZ128rmi : X86::VPTERNLOGQZ128rmi;
4890 Opc = UseD ? X86::VPTERNLOGDZ256rmi : X86::VPTERNLOGQZ256rmi;
4892 Opc = UseD ? X86::VPTERNLOGDZrmi : X86::VPTERNLOGQZrmi;
4898 MNode = CurDAG->getMachineNode(
Opc,
DL, VTs,
Ops);
4901 ReplaceUses(
C.getValue(1),
SDValue(MNode, 1));
4908 Opc = UseD ? X86::VPTERNLOGDZ128rri : X86::VPTERNLOGQZ128rri;
4910 Opc = UseD ? X86::VPTERNLOGDZ256rri : X86::VPTERNLOGQZ256rri;
4912 Opc = UseD ? X86::VPTERNLOGDZrri : X86::VPTERNLOGQZrri;
4916 MNode = CurDAG->getMachineNode(
Opc,
DL, NVT, {
A,
B,
C, TImm});
4920 CurDAG->RemoveDeadNode(Root);
4926bool X86DAGToDAGISel::tryVPTERNLOG(SDNode *
N) {
4927 MVT NVT =
N->getSimpleValueType(0);
4930 if (!NVT.
isVector() || !Subtarget->hasAVX512() ||
4938 auto getFoldableLogicOp = [](
SDValue Op) {
4941 Op =
Op.getOperand(0);
4943 if (!
Op.hasOneUse())
4946 unsigned Opc =
Op.getOpcode();
4948 Opc == X86ISD::ANDNP)
4957 auto tryPeelOuterNotWrappingLogic = [&](SDNode *
Op) {
4960 SDValue InnerOp = getFoldableLogicOp(
Op->getOperand(0));
4967 if ((FoldableOp = getFoldableLogicOp(N1))) {
4971 if ((FoldableOp = getFoldableLogicOp(N0))) {
4979 bool PeeledOuterNot =
false;
4981 if (
SDValue InnerOp = tryPeelOuterNotWrappingLogic(
N)) {
4982 PeeledOuterNot =
true;
4988 if ((FoldableOp = getFoldableLogicOp(N1)))
4990 else if ((FoldableOp = getFoldableLogicOp(N0)))
4998 SDNode *ParentA =
N;
4999 SDNode *ParentB = FoldableOp.
getNode();
5000 SDNode *ParentC = FoldableOp.
getNode();
5004 uint8_t TernlogMagicA = 0xf0;
5005 uint8_t TernlogMagicB = 0xcc;
5006 uint8_t TernlogMagicC = 0xaa;
5011 auto PeekThroughNot = [](
SDValue &
Op, SDNode *&Parent, uint8_t &
Magic) {
5015 Parent =
Op.getNode();
5016 Op =
Op.getOperand(0);
5020 PeekThroughNot(
A, ParentA, TernlogMagicA);
5021 PeekThroughNot(
B, ParentB, TernlogMagicB);
5022 PeekThroughNot(
C, ParentC, TernlogMagicC);
5027 case ISD::AND:
Imm = TernlogMagicB & TernlogMagicC;
break;
5028 case ISD::OR:
Imm = TernlogMagicB | TernlogMagicC;
break;
5029 case ISD::XOR:
Imm = TernlogMagicB ^ TernlogMagicC;
break;
5030 case X86ISD::ANDNP:
Imm = ~(TernlogMagicB) & TernlogMagicC;
break;
5033 switch (
N->getOpcode()) {
5037 Imm &= ~TernlogMagicA;
5039 Imm = ~(
Imm) & TernlogMagicA;
5049 return matchVPTERNLOG(OriN, ParentA, ParentB, ParentC,
A,
B,
C, Imm);
5059bool X86DAGToDAGISel::shrinkAndImmediate(SDNode *
And) {
5062 MVT VT =
And->getSimpleValueType(0);
5063 if (VT != MVT::i32 && VT != MVT::i64)
5075 APInt MaskVal = And1C->getAPIntValue();
5077 if (!MaskLZ || (VT == MVT::i64 && MaskLZ == 32))
5081 if (VT == MVT::i64 && MaskLZ >= 32) {
5083 MaskVal = MaskVal.
trunc(32);
5088 APInt NegMaskVal = MaskVal | HighZeros;
5097 if (VT == MVT::i64 && MaskVal.
getBitWidth() < 64) {
5098 NegMaskVal = NegMaskVal.
zext(64);
5099 HighZeros = HighZeros.
zext(64);
5105 KnownBits Known0 = CurDAG->computeKnownBits(And0);
5117 SDValue NewMask = CurDAG->getConstant(NegMaskVal, SDLoc(
And), VT);
5126 bool FoldedBCast,
bool Masked) {
5127#define VPTESTM_CASE(VT, SUFFIX) \
5130 return IsTestN ? X86::VPTESTNM##SUFFIX##k: X86::VPTESTM##SUFFIX##k; \
5131 return IsTestN ? X86::VPTESTNM##SUFFIX : X86::VPTESTM##SUFFIX;
5134#define VPTESTM_BROADCAST_CASES(SUFFIX) \
5135default: llvm_unreachable("Unexpected VT!"); \
5136VPTESTM_CASE(v4i32, DZ128##SUFFIX) \
5137VPTESTM_CASE(v2i64, QZ128##SUFFIX) \
5138VPTESTM_CASE(v8i32, DZ256##SUFFIX) \
5139VPTESTM_CASE(v4i64, QZ256##SUFFIX) \
5140VPTESTM_CASE(v16i32, DZ##SUFFIX) \
5141VPTESTM_CASE(v8i64, QZ##SUFFIX)
5143#define VPTESTM_FULL_CASES(SUFFIX) \
5144VPTESTM_BROADCAST_CASES(SUFFIX) \
5145VPTESTM_CASE(v16i8, BZ128##SUFFIX) \
5146VPTESTM_CASE(v8i16, WZ128##SUFFIX) \
5147VPTESTM_CASE(v32i8, BZ256##SUFFIX) \
5148VPTESTM_CASE(v16i16, WZ256##SUFFIX) \
5149VPTESTM_CASE(v64i8, BZ##SUFFIX) \
5150VPTESTM_CASE(v32i16, WZ##SUFFIX)
5168#undef VPTESTM_FULL_CASES
5169#undef VPTESTM_BROADCAST_CASES
5179 if (
Reg.isVirtual())
5184 if (GetPhysReg(N1) == LoReg && GetPhysReg(N0) != LoReg)
5190bool X86DAGToDAGISel::tryVPTESTM(SDNode *Root,
SDValue Setcc,
5192 assert(Subtarget->hasAVX512() &&
"Expected AVX512!");
5237 auto tryFoldLoadOrBCast = [&](SDNode *Root, SDNode *
P,
SDValue &
L,
5242 if (tryFoldLoad(Root,
P, L,
Base, Scale, Index, Disp, Segment))
5247 if (CmpSVT != MVT::i32 && CmpSVT != MVT::i64)
5253 L =
L.getOperand(0);
5256 if (
L.getOpcode() != X86ISD::VBROADCAST_LOAD)
5260 if (MemIntr->getMemoryVT().getSizeInBits() != CmpSVT.
getSizeInBits())
5263 return tryFoldBroadcast(Root,
P, L,
Base, Scale, Index, Disp, Segment);
5267 bool CanFoldLoads = Src0 != Src1;
5269 bool FoldedLoad =
false;
5270 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5272 FoldedLoad = tryFoldLoadOrBCast(Root, N0.
getNode(), Src1, Tmp0, Tmp1, Tmp2,
5276 FoldedLoad = tryFoldLoadOrBCast(Root, N0.
getNode(), Src0, Tmp0, Tmp1,
5283 bool FoldedBCast = FoldedLoad && Src1.
getOpcode() == X86ISD::VBROADCAST_LOAD;
5285 bool IsMasked = InMask.
getNode() !=
nullptr;
5294 unsigned SubReg = CmpVT.
is128BitVector() ? X86::sub_xmm : X86::sub_ymm;
5298 SDValue ImplDef =
SDValue(CurDAG->getMachineNode(X86::IMPLICIT_DEF, dl,
5300 Src0 = CurDAG->getTargetInsertSubreg(SubReg, dl, CmpVT, ImplDef, Src0);
5303 Src1 = CurDAG->getTargetInsertSubreg(SubReg, dl, CmpVT, ImplDef, Src1);
5308 SDValue RC = CurDAG->getTargetConstant(RegClass, dl, MVT::i32);
5309 InMask =
SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
5310 dl, MaskVT, InMask, RC), 0);
5318 MachineSDNode *CNode;
5320 SDVTList VTs = CurDAG->getVTList(MaskVT, MVT::Other);
5323 SDValue Ops[] = { InMask, Src0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
5325 CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5327 SDValue Ops[] = { Src0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4,
5329 CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
5335 CurDAG->setNodeMemRefs(CNode, {
cast<MemSDNode>(Src1)->getMemOperand()});
5338 CNode = CurDAG->getMachineNode(
Opc, dl, MaskVT, InMask, Src0, Src1);
5340 CNode = CurDAG->getMachineNode(
Opc, dl, MaskVT, Src0, Src1);
5346 SDValue RC = CurDAG->getTargetConstant(RegClass, dl, MVT::i32);
5347 CNode = CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
5348 dl, ResVT,
SDValue(CNode, 0), RC);
5352 CurDAG->RemoveDeadNode(Root);
5358bool X86DAGToDAGISel::tryMatchBitSelect(SDNode *
N) {
5361 MVT NVT =
N->getSimpleValueType(0);
5364 if (!NVT.
isVector() || !Subtarget->hasAVX512())
5398 SDValue Imm = CurDAG->getTargetConstant(0xCA, dl, MVT::i8);
5399 SDValue Ternlog = CurDAG->getNode(X86ISD::VPTERNLOG, dl, NVT,
A,
B,
C, Imm);
5406void X86DAGToDAGISel::Select(SDNode *Node) {
5407 MVT NVT =
Node->getSimpleValueType(0);
5408 unsigned Opcode =
Node->getOpcode();
5411 if (
Node->isMachineOpcode()) {
5413 Node->setNodeId(-1);
5420 unsigned IntNo =
Node->getConstantOperandVal(1);
5423 case Intrinsic::x86_encodekey128:
5424 case Intrinsic::x86_encodekey256: {
5425 if (!Subtarget->hasKL())
5431 case Intrinsic::x86_encodekey128:
5432 Opcode = X86::ENCODEKEY128;
5434 case Intrinsic::x86_encodekey256:
5435 Opcode = X86::ENCODEKEY256;
5440 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM0,
Node->getOperand(3),
5442 if (Opcode == X86::ENCODEKEY256)
5443 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM1,
Node->getOperand(4),
5446 MachineSDNode *Res = CurDAG->getMachineNode(
5447 Opcode, dl,
Node->getVTList(),
5448 {Node->getOperand(2), Chain, Chain.getValue(1)});
5449 ReplaceNode(Node, Res);
5452 case Intrinsic::x86_tileloaddrs64_internal:
5453 case Intrinsic::x86_tileloaddrst164_internal:
5454 if (!Subtarget->hasAMXMOVRS())
5457 case Intrinsic::x86_tileloadd64_internal:
5458 case Intrinsic::x86_tileloaddt164_internal: {
5459 if (!Subtarget->hasAMXTILE())
5462 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5463 MFI->setAMXProgModel(AMXProgModelEnum::ManagedRA);
5468 case Intrinsic::x86_tileloaddrs64_internal:
5469 Opc = X86::PTILELOADDRSV;
5471 case Intrinsic::x86_tileloaddrst164_internal:
5472 Opc = X86::PTILELOADDRST1V;
5474 case Intrinsic::x86_tileloadd64_internal:
5475 Opc = X86::PTILELOADDV;
5477 case Intrinsic::x86_tileloaddt164_internal:
5478 Opc = X86::PTILELOADDT1V;
5483 SDValue Scale = getI8Imm(1, dl);
5485 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5486 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5488 MachineSDNode *CNode;
5490 Node->getOperand(3),
5497 CNode = CurDAG->getMachineNode(
Opc, dl, {MVT::x86amx, MVT::Other},
Ops);
5498 ReplaceNode(Node, CNode);
5505 unsigned IntNo =
Node->getConstantOperandVal(1);
5508 case Intrinsic::x86_sse3_monitor:
5509 case Intrinsic::x86_monitorx:
5510 case Intrinsic::x86_clzero: {
5511 bool Use64BitPtr =
Node->getOperand(2).getValueType() == MVT::i64;
5516 case Intrinsic::x86_sse3_monitor:
5517 if (!Subtarget->hasSSE3())
5519 Opc = Use64BitPtr ? X86::MONITOR64rrr : X86::MONITOR32rrr;
5521 case Intrinsic::x86_monitorx:
5522 if (!Subtarget->hasMWAITX())
5524 Opc = Use64BitPtr ? X86::MONITORX64rrr : X86::MONITORX32rrr;
5526 case Intrinsic::x86_clzero:
5527 if (!Subtarget->hasCLZERO())
5529 Opc = Use64BitPtr ? X86::CLZERO64r : X86::CLZERO32r;
5534 unsigned PtrReg = Use64BitPtr ? X86::RAX : X86::EAX;
5535 SDValue Chain = CurDAG->getCopyToReg(
Node->getOperand(0), dl, PtrReg,
5539 if (IntNo == Intrinsic::x86_sse3_monitor ||
5540 IntNo == Intrinsic::x86_monitorx) {
5542 Chain = CurDAG->getCopyToReg(Chain, dl, X86::ECX,
Node->getOperand(3),
5545 Chain = CurDAG->getCopyToReg(Chain, dl, X86::EDX,
Node->getOperand(4),
5550 MachineSDNode *CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
5552 ReplaceNode(Node, CNode);
5558 case Intrinsic::x86_tilestored64_internal: {
5560 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5561 MFI->setAMXProgModel(AMXProgModelEnum::ManagedRA);
5562 unsigned Opc = X86::PTILESTOREDV;
5565 SDValue Scale = getI8Imm(1, dl);
5567 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5568 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5570 MachineSDNode *CNode;
5572 Node->getOperand(3),
5578 Node->getOperand(6),
5580 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5581 ReplaceNode(Node, CNode);
5584 case Intrinsic::x86_tileloaddrs64:
5585 case Intrinsic::x86_tileloaddrst164:
5586 if (!Subtarget->hasAMXMOVRS())
5589 case Intrinsic::x86_tileloadd64:
5590 case Intrinsic::x86_tileloaddt164:
5591 case Intrinsic::x86_tilestored64: {
5592 if (!Subtarget->hasAMXTILE())
5595 CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
5596 MFI->setAMXProgModel(AMXProgModelEnum::DirectReg);
5600 case Intrinsic::x86_tileloadd64:
Opc = X86::PTILELOADD;
break;
5601 case Intrinsic::x86_tileloaddrs64:
5602 Opc = X86::PTILELOADDRS;
5604 case Intrinsic::x86_tileloaddt164:
Opc = X86::PTILELOADDT1;
break;
5605 case Intrinsic::x86_tileloaddrst164:
5606 Opc = X86::PTILELOADDRST1;
5608 case Intrinsic::x86_tilestored64:
Opc = X86::PTILESTORED;
break;
5611 unsigned TIndex =
Node->getConstantOperandVal(2);
5614 SDValue Scale = getI8Imm(1, dl);
5616 SDValue Disp = CurDAG->getTargetConstant(0, dl, MVT::i32);
5617 SDValue Segment = CurDAG->getRegister(0, MVT::i16);
5619 MachineSDNode *CNode;
5620 if (
Opc == X86::PTILESTORED) {
5622 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5625 CNode = CurDAG->getMachineNode(
Opc, dl, MVT::Other,
Ops);
5627 ReplaceNode(Node, CNode);
5634 case X86ISD::NT_BRIND: {
5635 if (Subtarget->isTarget64BitILP32()) {
5640 assert(
Target.getValueType() == MVT::i32 &&
"Unexpected VT!");
5641 SDValue ZextTarget = CurDAG->getZExtOrTrunc(Target, dl, MVT::i64);
5642 SDValue Brind = CurDAG->getNode(Opcode, dl, MVT::Other,
5643 Node->getOperand(0), ZextTarget);
5644 ReplaceNode(Node, Brind.
getNode());
5645 SelectCode(ZextTarget.
getNode());
5652 ReplaceNode(Node, getGlobalBaseReg());
5659 ReplaceUses(
SDValue(Node, 0),
Node->getOperand(0));
5660 CurDAG->RemoveDeadNode(Node);
5666 if (matchBitExtract(Node))
5671 if (tryShiftAmountMod(Node))
5675 case X86ISD::VPTERNLOG: {
5676 uint8_t
Imm =
Node->getConstantOperandVal(3);
5677 if (matchVPTERNLOG(Node, Node, Node, Node,
Node->getOperand(0),
5678 Node->getOperand(1),
Node->getOperand(2), Imm))
5684 if (tryVPTERNLOG(Node))
5694 tryVPTESTM(Node, N0, N1))
5697 tryVPTESTM(Node, N1, N0))
5701 if (MachineSDNode *NewNode = matchBEXTRFromAndImm(Node)) {
5703 CurDAG->RemoveDeadNode(Node);
5706 if (matchBitExtract(Node))
5714 if (tryShrinkShlLogicImm(Node))
5716 if (Opcode ==
ISD::OR && tryMatchBitSelect(Node))
5718 if (tryVPTERNLOG(Node))
5723 if (Opcode ==
ISD::ADD && matchBitExtract(Node))
5733 if (!CurDAG->shouldOptForSize())
5737 if (NVT != MVT::i8 && NVT != MVT::i16 && NVT != MVT::i32 && NVT != MVT::i64)
5747 int64_t Val = Cst->getSExtValue();
5755 if (Opcode ==
ISD::ADD && (Val == 1 || Val == -1))
5759 if (!shouldAvoidImmediateInstFormsForSize(N1.
getNode()))
5763 unsigned ROpc, MOpc;
5872 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5873 if (tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
5875 SDVTList VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
5876 MachineSDNode *CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
5882 CurDAG->RemoveDeadNode(Node);
5887 CurDAG->SelectNodeTo(Node, ROpc, NVT, MVT::i32, N0, N1);
5896 case X86ISD::UMUL: {
5900 unsigned LoReg, ROpc, MOpc;
5905 ROpc = Opcode == X86ISD::SMUL ? X86::IMUL8r : X86::MUL8r;
5906 MOpc = Opcode == X86ISD::SMUL ? X86::IMUL8m : X86::MUL8m;
5925 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
5926 bool FoldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
5929 FoldedLoad = tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
5937 orderRegForMul(N0, N1, LoReg, CurDAG->getMachineFunction().getRegInfo());
5939 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg,
5942 MachineSDNode *CNode;
5948 VTs = CurDAG->getVTList(NVT, MVT::i32, MVT::Other);
5950 VTs = CurDAG->getVTList(NVT, NVT, MVT::i32, MVT::Other);
5954 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
5965 VTs = CurDAG->getVTList(NVT, MVT::i32);
5967 VTs = CurDAG->getVTList(NVT, NVT, MVT::i32);
5969 CNode = CurDAG->getMachineNode(ROpc, dl, VTs, {N1, InGlue});
5973 ReplaceUses(
SDValue(Node, 1),
SDValue(CNode, NVT == MVT::i8 ? 1 : 2));
5974 CurDAG->RemoveDeadNode(Node);
5984 unsigned LoReg, HiReg;
5986 bool UseMULX = !IsSigned && Subtarget->hasBMI2();
5987 bool UseMULXHi = UseMULX &&
SDValue(Node, 0).use_empty();
5991 Opc = UseMULXHi ? X86::MULX32Hrr
5993 : IsSigned ?
X86::IMUL32r
5995 MOpc = UseMULXHi ? X86::MULX32Hrm
5997 : IsSigned ?
X86::IMUL32m
5999 LoReg = UseMULX ? X86::EDX : X86::EAX;
6003 Opc = UseMULXHi ? X86::MULX64Hrr
6005 : IsSigned ?
X86::IMUL64r
6007 MOpc = UseMULXHi ? X86::MULX64Hrm
6009 : IsSigned ?
X86::IMUL64m
6011 LoReg = UseMULX ? X86::RDX : X86::RAX;
6016 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6017 bool foldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6020 foldedLoad = tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6028 orderRegForMul(N0, N1, LoReg, CurDAG->getMachineFunction().getRegInfo());
6030 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, LoReg,
6035 MachineSDNode *CNode =
nullptr;
6039 SDVTList VTs = CurDAG->getVTList(NVT, MVT::Other);
6040 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6043 }
else if (UseMULX) {
6044 SDVTList VTs = CurDAG->getVTList(NVT, NVT, MVT::Other);
6045 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6050 SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue);
6051 CNode = CurDAG->getMachineNode(MOpc, dl, VTs,
Ops);
6057 ReplaceUses(N1.
getValue(1), Chain);
6063 SDVTList VTs = CurDAG->getVTList(NVT);
6064 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6066 }
else if (UseMULX) {
6067 SDVTList VTs = CurDAG->getVTList(NVT, NVT);
6068 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6072 SDVTList VTs = CurDAG->getVTList(MVT::Glue);
6073 SDNode *CNode = CurDAG->getMachineNode(
Opc, dl, VTs,
Ops);
6079 if (!
SDValue(Node, 0).use_empty()) {
6081 assert(LoReg &&
"Register for low half is not defined!");
6082 ResLo = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, LoReg,
6086 ReplaceUses(
SDValue(Node, 0), ResLo);
6091 if (!
SDValue(Node, 1).use_empty()) {
6093 assert(HiReg &&
"Register for high half is not defined!");
6094 ResHi = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl, HiReg,
6098 ReplaceUses(
SDValue(Node, 1), ResHi);
6103 CurDAG->RemoveDeadNode(Node);
6112 unsigned ROpc, MOpc;
6117 case MVT::i8: ROpc = X86::DIV8r; MOpc = X86::DIV8m;
break;
6118 case MVT::i16: ROpc = X86::DIV16r; MOpc = X86::DIV16m;
break;
6119 case MVT::i32: ROpc = X86::DIV32r; MOpc = X86::DIV32m;
break;
6120 case MVT::i64: ROpc = X86::DIV64r; MOpc = X86::DIV64m;
break;
6125 case MVT::i8: ROpc = X86::IDIV8r; MOpc = X86::IDIV8m;
break;
6126 case MVT::i16: ROpc = X86::IDIV16r; MOpc = X86::IDIV16m;
break;
6127 case MVT::i32: ROpc = X86::IDIV32r; MOpc = X86::IDIV32m;
break;
6128 case MVT::i64: ROpc = X86::IDIV64r; MOpc = X86::IDIV64m;
break;
6132 unsigned LoReg, HiReg, ClrReg;
6133 unsigned SExtOpcode;
6137 LoReg = X86::AL; ClrReg = HiReg = X86::AH;
6141 LoReg = X86::AX; HiReg = X86::DX;
6143 SExtOpcode = X86::CWD;
6146 LoReg = X86::EAX; ClrReg = HiReg = X86::EDX;
6147 SExtOpcode = X86::CDQ;
6150 LoReg = X86::RAX; ClrReg = HiReg = X86::RDX;
6151 SExtOpcode = X86::CQO;
6155 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6156 bool foldedLoad = tryFoldLoad(Node, N1, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4);
6157 bool signBitIsZero = CurDAG->SignBitIsZero(N0);
6160 if (NVT == MVT::i8) {
6163 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4, Chain;
6164 MachineSDNode *Move;
6165 if (tryFoldLoad(Node, N0, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
6167 unsigned Opc = (
isSigned && !signBitIsZero) ? X86::MOVSX16rm8
6169 Move = CurDAG->getMachineNode(
Opc, dl, MVT::i16, MVT::Other,
Ops);
6171 ReplaceUses(N0.
getValue(1), Chain);
6175 unsigned Opc = (
isSigned && !signBitIsZero) ? X86::MOVSX16rr8
6177 Move = CurDAG->getMachineNode(
Opc, dl, MVT::i16, N0);
6178 Chain = CurDAG->getEntryNode();
6180 Chain = CurDAG->getCopyToReg(Chain, dl, X86::AX,
SDValue(Move, 0),
6185 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl,
6186 LoReg, N0,
SDValue()).getValue(1);
6190 SDValue(CurDAG->getMachineNode(SExtOpcode, dl, MVT::Glue, InGlue),0);
6193 SDVTList VTs = CurDAG->getVTList(MVT::i32, MVT::i32);
6195 SDValue(CurDAG->getMachineNode(X86::MOV32r0, dl, VTs, {}), 0);
6199 SDValue(CurDAG->getMachineNode(
6200 TargetOpcode::EXTRACT_SUBREG, dl, MVT::i16, ClrNode,
6201 CurDAG->getTargetConstant(X86::sub_16bit, dl,
6209 CurDAG->getMachineNode(
6210 TargetOpcode::SUBREG_TO_REG, dl, MVT::i64, ClrNode,
6211 CurDAG->getTargetConstant(X86::sub_32bit, dl, MVT::i32)),
6218 InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, ClrReg,
6219 ClrNode, InGlue).getValue(1);
6226 MachineSDNode *CNode =
6227 CurDAG->getMachineNode(MOpc, dl, MVT::Other, MVT::Glue,
Ops);
6235 SDValue(CurDAG->getMachineNode(ROpc, dl, MVT::Glue, N1, InGlue), 0);
6245 if (HiReg == X86::AH && !
SDValue(Node, 1).use_empty()) {
6246 SDValue AHCopy = CurDAG->getRegister(X86::AH, MVT::i8);
6247 unsigned AHExtOpcode =
6248 isSigned ? X86::MOVSX32rr8_NOREX : X86::MOVZX32rr8_NOREX;
6250 SDNode *RNode = CurDAG->getMachineNode(AHExtOpcode, dl, MVT::i32,
6251 MVT::Glue, AHCopy, InGlue);
6256 CurDAG->getTargetExtractSubreg(X86::sub_8bit, dl, MVT::i8, Result);
6258 ReplaceUses(
SDValue(Node, 1), Result);
6263 if (!
SDValue(Node, 0).use_empty()) {
6264 SDValue Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
6265 LoReg, NVT, InGlue);
6266 InGlue =
Result.getValue(2);
6267 ReplaceUses(
SDValue(Node, 0), Result);
6272 if (!
SDValue(Node, 1).use_empty()) {
6273 SDValue Result = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), dl,
6274 HiReg, NVT, InGlue);
6275 InGlue =
Result.getValue(2);
6276 ReplaceUses(
SDValue(Node, 1), Result);
6280 CurDAG->RemoveDeadNode(Node);
6285 case X86ISD::STRICT_FCMP:
6286 case X86ISD::STRICT_FCMPS: {
6287 bool IsStrictCmp =
Node->getOpcode() == X86ISD::STRICT_FCMP ||
6288 Node->getOpcode() == X86ISD::STRICT_FCMPS;
6289 SDValue N0 =
Node->getOperand(IsStrictCmp ? 1 : 0);
6290 SDValue N1 =
Node->getOperand(IsStrictCmp ? 2 : 1);
6296 if (Subtarget->canUseCMOV())
6299 bool IsSignaling =
Node->getOpcode() == X86ISD::STRICT_FCMPS;
6305 Opc = IsSignaling ? X86::COM_Fpr32 : X86::UCOM_Fpr32;
6308 Opc = IsSignaling ? X86::COM_Fpr64 : X86::UCOM_Fpr64;
6311 Opc = IsSignaling ? X86::COM_Fpr80 : X86::UCOM_Fpr80;
6316 IsStrictCmp ?
Node->getOperand(0) : CurDAG->getEntryNode();
6319 SDVTList VTs = CurDAG->getVTList(MVT::Other, MVT::Glue);
6320 Chain =
SDValue(CurDAG->getMachineNode(
Opc, dl, VTs, {N0, N1, Chain}), 0);
6323 Glue =
SDValue(CurDAG->getMachineNode(
Opc, dl, MVT::Glue, N0, N1), 0);
6328 SDValue(CurDAG->getMachineNode(X86::FNSTSW16r, dl, MVT::i16, Glue), 0);
6332 CurDAG->getTargetExtractSubreg(X86::sub_8bit_hi, dl, MVT::i8, FNSTSW);
6336 assert(Subtarget->canUseLAHFSAHF() &&
6337 "Target doesn't support SAHF or FCOMI?");
6338 SDValue AH = CurDAG->getCopyToReg(Chain, dl, X86::AH, Extract,
SDValue());
6341 CurDAG->getMachineNode(X86::SAHF, dl, MVT::i32, AH.
getValue(1)), 0);
6344 ReplaceUses(
SDValue(Node, 1), Chain);
6346 ReplaceUses(
SDValue(Node, 0), SAHF);
6347 CurDAG->RemoveDeadNode(Node);
6367 if (MachineSDNode *NewNode = matchBEXTRFromAndImm(N0.
getNode())) {
6368 unsigned TestOpc = CmpVT == MVT::i64 ? X86::TEST64rr
6371 NewNode = CurDAG->getMachineNode(TestOpc, dl, MVT::i32, BEXTR, BEXTR);
6373 CurDAG->RemoveDeadNode(Node);
6393 uint64_t
Mask = MaskC->getZExtValue();
6400 onlyUsesZeroFlag(
SDValue(Node, 0))) {
6405 unsigned TestOpcode;
6413 if (LeadingZeros == 0 && SavesBytes) {
6418 ShiftAmt = TrailingZeros;
6420 TestOpcode = X86::TEST64rr;
6421 }
else if (TrailingZeros == 0 && SavesBytes) {
6426 ShiftAmt = LeadingZeros;
6428 TestOpcode = X86::TEST64rr;
6429 }
else if (MaskC->hasOneUse() && !
isInt<32>(Mask)) {
6432 unsigned PopCount = 64 - LeadingZeros - TrailingZeros;
6433 if (PopCount == 8) {
6435 ShiftAmt = TrailingZeros;
6436 SubRegIdx = X86::sub_8bit;
6438 TestOpcode = X86::TEST8rr;
6439 }
else if (PopCount == 16) {
6441 ShiftAmt = TrailingZeros;
6442 SubRegIdx = X86::sub_16bit;
6443 SubRegVT = MVT::i16;
6444 TestOpcode = X86::TEST16rr;
6445 }
else if (PopCount == 32) {
6447 ShiftAmt = TrailingZeros;
6448 SubRegIdx = X86::sub_32bit;
6449 SubRegVT = MVT::i32;
6450 TestOpcode = X86::TEST32rr;
6454 SDValue ShiftC = CurDAG->getTargetConstant(ShiftAmt, dl, MVT::i64);
6456 CurDAG->getMachineNode(ShiftOpcode, dl, MVT::i64, MVT::i32,
6459 if (SubRegIdx != 0) {
6461 CurDAG->getTargetExtractSubreg(SubRegIdx, dl, SubRegVT, Shift);
6463 MachineSDNode *
Test =
6464 CurDAG->getMachineNode(TestOpcode, dl, MVT::i32, Shift, Shift);
6465 ReplaceNode(Node,
Test);
6472 unsigned ROpc, MOpc;
6480 (!(Mask & 0x80) || CmpVT == MVT::i8 ||
6481 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6484 SubRegOp = X86::sub_8bit;
6485 ROpc = X86::TEST8ri;
6486 MOpc = X86::TEST8mi;
6487 }
else if (OptForMinSize &&
isUInt<16>(Mask) &&
6488 (!(Mask & 0x8000) || CmpVT == MVT::i16 ||
6489 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6495 SubRegOp = X86::sub_16bit;
6496 ROpc = X86::TEST16ri;
6497 MOpc = X86::TEST16mi;
6499 ((!(Mask & 0x80000000) &&
6502 (CmpVT != MVT::i16 || !(Mask & 0x8000))) ||
6503 CmpVT == MVT::i32 ||
6504 hasNoSignFlagUses(
SDValue(Node, 0)))) {
6511 SubRegOp = X86::sub_32bit;
6512 ROpc = X86::TEST32ri;
6513 MOpc = X86::TEST32mi;
6519 SDValue Imm = CurDAG->getTargetConstant(Mask, dl, VT);
6523 MachineSDNode *NewNode;
6524 SDValue Tmp0, Tmp1, Tmp2, Tmp3, Tmp4;
6525 if (tryFoldLoad(Node, N0.
getNode(),
Reg, Tmp0, Tmp1, Tmp2, Tmp3, Tmp4)) {
6527 if (!LoadN->isSimple()) {
6528 unsigned NumVolBits = LoadN->getValueType(0).getSizeInBits();
6529 if ((MOpc == X86::TEST8mi && NumVolBits != 8) ||
6530 (MOpc == X86::TEST16mi && NumVolBits != 16) ||
6531 (MOpc == X86::TEST32mi && NumVolBits != 32))
6536 Reg.getOperand(0) };
6537 NewNode = CurDAG->getMachineNode(MOpc, dl, MVT::i32, MVT::Other,
Ops);
6539 ReplaceUses(
Reg.getValue(1),
SDValue(NewNode, 1));
6541 CurDAG->setNodeMemRefs(NewNode,
6546 Reg = CurDAG->getTargetExtractSubreg(SubRegOp, dl, VT,
Reg);
6548 NewNode = CurDAG->getMachineNode(ROpc, dl, MVT::i32,
Reg, Imm);
6551 ReplaceNode(Node, NewNode);
6557 if (!Subtarget->hasSSE42())
6560 bool NeedIndex = !
SDValue(Node, 0).use_empty();
6561 bool NeedMask = !
SDValue(Node, 1).use_empty();
6563 bool MayFoldLoad = !NeedIndex || !NeedMask;
6565 MachineSDNode *CNode;
6568 Subtarget->hasAVX() ? X86::VPCMPISTRMrri : X86::PCMPISTRMrri;
6570 Subtarget->hasAVX() ? X86::VPCMPISTRMrmi : X86::PCMPISTRMrmi;
6571 CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node);
6574 if (NeedIndex || !NeedMask) {
6576 Subtarget->hasAVX() ? X86::VPCMPISTRIrri : X86::PCMPISTRIrri;
6578 Subtarget->hasAVX() ? X86::VPCMPISTRIrmi : X86::PCMPISTRIrmi;
6579 CNode = emitPCMPISTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node);
6585 CurDAG->RemoveDeadNode(Node);
6589 if (!Subtarget->hasSSE42())
6593 SDValue InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EAX,
6594 Node->getOperand(1),
6596 InGlue = CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EDX,
6597 Node->getOperand(3), InGlue).getValue(1);
6599 bool NeedIndex = !
SDValue(Node, 0).use_empty();
6600 bool NeedMask = !
SDValue(Node, 1).use_empty();
6602 bool MayFoldLoad = !NeedIndex || !NeedMask;
6604 MachineSDNode *CNode;
6607 Subtarget->hasAVX() ? X86::VPCMPESTRMrri : X86::PCMPESTRMrri;
6609 Subtarget->hasAVX() ? X86::VPCMPESTRMrmi : X86::PCMPESTRMrmi;
6611 emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::v16i8, Node, InGlue);
6614 if (NeedIndex || !NeedMask) {
6616 Subtarget->hasAVX() ? X86::VPCMPESTRIrri : X86::PCMPESTRIrri;
6618 Subtarget->hasAVX() ? X86::VPCMPESTRIrmi : X86::PCMPESTRIrmi;
6619 CNode = emitPCMPESTR(ROpc, MOpc, MayFoldLoad, dl, MVT::i32, Node, InGlue);
6624 CurDAG->RemoveDeadNode(Node);
6636 if (foldLoadStoreIntoMemOperand(Node))
6640 case X86ISD::SETCC_CARRY: {
6641 MVT VT =
Node->getSimpleValueType(0);
6643 if (Subtarget->hasSBBDepBreaking()) {
6648 CurDAG->getCopyToReg(CurDAG->getEntryNode(), dl, X86::EFLAGS,
6653 unsigned Opc = VT == MVT::i64 ? X86::SETB_C64r : X86::SETB_C32r;
6654 MVT SetVT = VT == MVT::i64 ? MVT::i64 : MVT::i32;
6656 CurDAG->getMachineNode(
Opc, dl, SetVT, EFLAGS, EFLAGS.
getValue(1)),
6661 Result = getSBBZero(Node);
6665 if (VT == MVT::i8 || VT == MVT::i16) {
6666 int SubIndex = VT == MVT::i16 ? X86::sub_16bit : X86::sub_8bit;
6667 Result = CurDAG->getTargetExtractSubreg(SubIndex, dl, VT, Result);
6670 ReplaceUses(
SDValue(Node, 0), Result);
6671 CurDAG->RemoveDeadNode(Node);
6683 if (!
SDValue(Node, 0).use_empty()) {
6685 MVT VT =
Node->getSimpleValueType(0);
6686 if (VT == MVT::i8 || VT == MVT::i16) {
6687 int SubIndex = VT == MVT::i16 ? X86::sub_16bit : X86::sub_8bit;
6688 Result = CurDAG->getTargetExtractSubreg(SubIndex, dl, VT, Result);
6690 ReplaceUses(
SDValue(Node, 0), Result);
6693 CurDAG->RemoveDeadNode(Node);
6700 SDValue IndexOp = Mgt->getIndex();
6703 MVT ValueVT =
Node->getSimpleValueType(0);
6704 MVT MaskVT =
Mask.getSimpleValueType();
6721 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6722 Opc = IsFP ? X86::VGATHERDPSZ128rm : X86::VPGATHERDDZ128rm;
6723 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6724 Opc = IsFP ? X86::VGATHERDPSZ256rm : X86::VPGATHERDDZ256rm;
6725 else if (IndexVT == MVT::v16i32 && NumElts == 16 && EltSize == 32)
6726 Opc = IsFP ? X86::VGATHERDPSZrm : X86::VPGATHERDDZrm;
6727 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6728 Opc = IsFP ? X86::VGATHERDPDZ128rm : X86::VPGATHERDQZ128rm;
6729 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6730 Opc = IsFP ? X86::VGATHERDPDZ256rm : X86::VPGATHERDQZ256rm;
6731 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 64)
6732 Opc = IsFP ? X86::VGATHERDPDZrm : X86::VPGATHERDQZrm;
6733 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6734 Opc = IsFP ? X86::VGATHERQPSZ128rm : X86::VPGATHERQDZ128rm;
6735 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6736 Opc = IsFP ? X86::VGATHERQPSZ256rm : X86::VPGATHERQDZ256rm;
6737 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 32)
6738 Opc = IsFP ? X86::VGATHERQPSZrm : X86::VPGATHERQDZrm;
6739 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6740 Opc = IsFP ? X86::VGATHERQPDZ128rm : X86::VPGATHERQQZ128rm;
6741 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6742 Opc = IsFP ? X86::VGATHERQPDZ256rm : X86::VPGATHERQQZ256rm;
6743 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 64)
6744 Opc = IsFP ? X86::VGATHERQPDZrm : X86::VPGATHERQQZrm;
6746 assert(EVT(MaskVT) == EVT(ValueVT).changeVectorElementTypeToInteger() &&
6747 "Unexpected mask VT!");
6748 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6749 Opc = IsFP ? X86::VGATHERDPSrm : X86::VPGATHERDDrm;
6750 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6751 Opc = IsFP ? X86::VGATHERDPSYrm : X86::VPGATHERDDYrm;
6752 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6753 Opc = IsFP ? X86::VGATHERDPDrm : X86::VPGATHERDQrm;
6754 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6755 Opc = IsFP ? X86::VGATHERDPDYrm : X86::VPGATHERDQYrm;
6756 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6757 Opc = IsFP ? X86::VGATHERQPSrm : X86::VPGATHERQDrm;
6758 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6759 Opc = IsFP ? X86::VGATHERQPSYrm : X86::VPGATHERQDYrm;
6760 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6761 Opc = IsFP ? X86::VGATHERQPDrm : X86::VPGATHERQQrm;
6762 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6763 Opc = IsFP ? X86::VGATHERQPDYrm : X86::VPGATHERQQYrm;
6770 if (!selectVectorAddr(Mgt, Mgt->getBasePtr(), IndexOp, Mgt->getScale(),
6771 Base, Scale, Index, Disp, Segment))
6774 SDValue PassThru = Mgt->getPassThru();
6775 SDValue Chain = Mgt->getChain();
6777 SDVTList VTs = CurDAG->getVTList(ValueVT, MaskVT, MVT::Other);
6779 MachineSDNode *NewNode;
6782 Index, Disp, Segment, Chain};
6783 NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6786 Disp, Segment,
Mask, Chain};
6787 NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6789 CurDAG->setNodeMemRefs(NewNode, {Mgt->getMemOperand()});
6792 CurDAG->RemoveDeadNode(Node);
6798 SDValue IndexOp = Sc->getIndex();
6800 MVT ValueVT =
Value.getSimpleValueType();
6815 if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 32)
6816 Opc = IsFP ? X86::VSCATTERDPSZ128mr : X86::VPSCATTERDDZ128mr;
6817 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 32)
6818 Opc = IsFP ? X86::VSCATTERDPSZ256mr : X86::VPSCATTERDDZ256mr;
6819 else if (IndexVT == MVT::v16i32 && NumElts == 16 && EltSize == 32)
6820 Opc = IsFP ? X86::VSCATTERDPSZmr : X86::VPSCATTERDDZmr;
6821 else if (IndexVT == MVT::v4i32 && NumElts == 2 && EltSize == 64)
6822 Opc = IsFP ? X86::VSCATTERDPDZ128mr : X86::VPSCATTERDQZ128mr;
6823 else if (IndexVT == MVT::v4i32 && NumElts == 4 && EltSize == 64)
6824 Opc = IsFP ? X86::VSCATTERDPDZ256mr : X86::VPSCATTERDQZ256mr;
6825 else if (IndexVT == MVT::v8i32 && NumElts == 8 && EltSize == 64)
6826 Opc = IsFP ? X86::VSCATTERDPDZmr : X86::VPSCATTERDQZmr;
6827 else if (IndexVT == MVT::v2i64 && NumElts == 4 && EltSize == 32)
6828 Opc = IsFP ? X86::VSCATTERQPSZ128mr : X86::VPSCATTERQDZ128mr;
6829 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 32)
6830 Opc = IsFP ? X86::VSCATTERQPSZ256mr : X86::VPSCATTERQDZ256mr;
6831 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 32)
6832 Opc = IsFP ? X86::VSCATTERQPSZmr : X86::VPSCATTERQDZmr;
6833 else if (IndexVT == MVT::v2i64 && NumElts == 2 && EltSize == 64)
6834 Opc = IsFP ? X86::VSCATTERQPDZ128mr : X86::VPSCATTERQQZ128mr;
6835 else if (IndexVT == MVT::v4i64 && NumElts == 4 && EltSize == 64)
6836 Opc = IsFP ? X86::VSCATTERQPDZ256mr : X86::VPSCATTERQQZ256mr;
6837 else if (IndexVT == MVT::v8i64 && NumElts == 8 && EltSize == 64)
6838 Opc = IsFP ? X86::VSCATTERQPDZmr : X86::VPSCATTERQQZmr;
6843 if (!selectVectorAddr(Sc, Sc->getBasePtr(), IndexOp, Sc->getScale(),
6844 Base, Scale, Index, Disp, Segment))
6848 SDValue Chain = Sc->getChain();
6850 SDVTList VTs = CurDAG->getVTList(
Mask.getValueType(), MVT::Other);
6853 MachineSDNode *NewNode = CurDAG->getMachineNode(
Opc, SDLoc(dl), VTs,
Ops);
6854 CurDAG->setNodeMemRefs(NewNode, {Sc->getMemOperand()});
6856 CurDAG->RemoveDeadNode(Node);
6860 auto *MFI = CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
6861 auto CallId = MFI->getPreallocatedIdForCallSite(
6864 SDValue CallIdValue = CurDAG->getTargetConstant(CallId, dl, MVT::i32);
6865 MachineSDNode *
New = CurDAG->getMachineNode(
6866 TargetOpcode::PREALLOCATED_SETUP, dl, MVT::Other, CallIdValue, Chain);
6868 CurDAG->RemoveDeadNode(Node);
6872 auto *MFI = CurDAG->getMachineFunction().getInfo<X86MachineFunctionInfo>();
6876 SDValue CallIdValue = CurDAG->getTargetConstant(CallId, dl, MVT::i32);
6879 Ops[0] = CallIdValue;
6882 MachineSDNode *
New = CurDAG->getMachineNode(
6883 TargetOpcode::PREALLOCATED_ARG, dl,
6884 CurDAG->getVTList(TLI->
getPointerTy(CurDAG->getDataLayout()),
6889 CurDAG->RemoveDeadNode(Node);
6896 if (!Subtarget->hasWIDEKL())
6900 switch (
Node->getOpcode()) {
6904 Opcode = X86::AESENCWIDE128KL;
6907 Opcode = X86::AESDECWIDE128KL;
6910 Opcode = X86::AESENCWIDE256KL;
6913 Opcode = X86::AESDECWIDE256KL;
6921 if (!selectAddr(Node, Addr,
Base, Scale, Index, Disp, Segment))
6924 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM0,
Node->getOperand(2),
6926 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM1,
Node->getOperand(3),
6928 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM2,
Node->getOperand(4),
6930 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM3,
Node->getOperand(5),
6932 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM4,
Node->getOperand(6),
6934 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM5,
Node->getOperand(7),
6936 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM6,
Node->getOperand(8),
6938 Chain = CurDAG->getCopyToReg(Chain, dl, X86::XMM7,
Node->getOperand(9),
6941 MachineSDNode *Res = CurDAG->getMachineNode(
6942 Opcode, dl,
Node->getVTList(),
6943 {Base, Scale, Index, Disp, Segment, Chain, Chain.getValue(1)});
6945 ReplaceNode(Node, Res);
6952 if (
Node->getNumValues() == 3)
6953 Glue =
Node->getOperand(2);
6955 CurDAG->getCopyFromReg(Chain, dl,
Reg,
Node->getValueType(0), Glue);
6956 ReplaceNode(Node,
Copy.getNode());
6964bool X86DAGToDAGISel::SelectInlineAsmMemoryOperand(
6966 std::vector<SDValue> &OutOps) {
6967 SDValue Op0, Op1, Op2, Op3, Op4;
6968 switch (ConstraintID) {
6971 case InlineAsm::ConstraintCode::o:
6972 case InlineAsm::ConstraintCode::v:
6973 case InlineAsm::ConstraintCode::m:
6974 case InlineAsm::ConstraintCode::X:
6975 case InlineAsm::ConstraintCode::p:
6976 if (!selectAddr(
nullptr,
Op, Op0, Op1, Op2, Op3, Op4))
6981 OutOps.push_back(Op0);
6982 OutOps.push_back(Op1);
6983 OutOps.push_back(Op2);
6984 OutOps.push_back(Op3);
6985 OutOps.push_back(Op4);
6991 std::make_unique<X86DAGToDAGISel>(TM, TM.getOptLevel())) {}
6997 return new X86DAGToDAGISelLegacy(TM, OptLevel);
static SDValue Widen(SelectionDAG *CurDAG, SDValue N)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
Function Alias Analysis false
#define CASE(ATTRNAME, AANAME,...)
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static bool isSigned(unsigned Opcode)
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
const MCPhysReg ArgGPRs[]
Promote Memory to Register
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
BaseType
A given derived pointer can have multiple base pointers through phi/selects.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
static bool isFusableLoadOpStorePattern(StoreSDNode *StoreNode, SDValue StoredVal, SelectionDAG *CurDAG, LoadSDNode *&LoadNode, SDValue &InputChain)
static void insertDAGNode(SelectionDAG *DAG, SDNode *Pos, SDValue N)
static bool isRIPRelative(const MCInst &MI, const MCInstrInfo &MCII)
Check if the instruction uses RIP relative addressing.
#define FROM_TO(FROM, TO)
#define GET_EGPR_IF_ENABLED(OPC)
static bool isLegalMaskCompare(SDNode *N, const X86Subtarget *Subtarget)
static bool foldMaskAndShiftToScale(SelectionDAG &DAG, SDValue N, uint64_t Mask, SDValue Shift, SDValue X, X86ISelAddressMode &AM)
static bool foldMaskAndShiftToExtract(SelectionDAG &DAG, SDValue N, uint64_t Mask, SDValue Shift, SDValue X, X86ISelAddressMode &AM)
static bool needBWI(MVT VT)
static unsigned getVPTESTMOpc(MVT TestVT, bool IsTestN, bool FoldedLoad, bool FoldedBCast, bool Masked)
#define GET_NDM_IF_ENABLED(OPC)
static bool foldMaskedShiftToBEXTR(SelectionDAG &DAG, SDValue N, uint64_t Mask, SDValue Shift, SDValue X, X86ISelAddressMode &AM, const X86Subtarget &Subtarget)
static bool mayUseCarryFlag(X86::CondCode CC)
static cl::opt< bool > EnablePromoteAnyextLoad("x86-promote-anyext-load", cl::init(true), cl::desc("Enable promoting aligned anyext load to wider load"), cl::Hidden)
static void moveBelowOrigChain(SelectionDAG *CurDAG, SDValue Load, SDValue Call, SDValue OrigChain)
Replace the original chain operand of the call with load's chain operand and move load below the call...
#define GET_ND_IF_ENABLED(OPC)
#define VPTESTM_BROADCAST_CASES(SUFFIX)
static cl::opt< bool > AndImmShrink("x86-and-imm-shrink", cl::init(true), cl::desc("Enable setting constant bits to reduce size of mask immediates"), cl::Hidden)
static bool foldMaskedShiftToScaledMask(SelectionDAG &DAG, SDValue N, X86ISelAddressMode &AM)
#define VPTESTM_FULL_CASES(SUFFIX)
static bool isCalleeLoad(SDValue Callee, SDValue &Chain, bool HasCallSeq)
Return true if call address is a load and it can be moved below CALLSEQ_START and the chains leading ...
static bool isDispSafeForFrameIndexOrRegBase(int64_t Val)
static bool isEndbrImm64(uint64_t Imm)
static void orderRegForMul(SDValue &N0, SDValue &N1, const unsigned LoReg, const MachineRegisterInfo &MRI)
cl::opt< bool > IndirectBranchTracking("x86-indirect-branch-tracking", cl::init(false), cl::Hidden, cl::desc("Enable X86 indirect branch tracking pass."))
#define GET_ND_IF_ENABLED(OPC)
Class for arbitrary precision integers.
static APInt getAllOnes(unsigned numBits)
Return an APInt of a specified width with all bits set.
LLVM_ABI APInt zext(unsigned width) const
Zero extend to a new width.
LLVM_ABI APInt trunc(unsigned width) const
Truncate to new width.
bool isAllOnes() const
Determine if all bits are set. This is true for zero-width values.
unsigned getBitWidth() const
Return the number of bits in the APInt.
unsigned countl_zero() const
The APInt version of std::countl_zero.
unsigned getSignificantBits() const
Get the minimum bit size for this signed APInt.
bool isSubsetOf(const APInt &RHS) const
This operation checks that all bits set in this APInt are also set in RHS.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Constructs an APInt value that has the bottom loBitsSet bits set.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Constructs an APInt value that has the top hiBitsSet bits set.
bool isOne() const
Determine if this is a value of 1.
unsigned countr_one() const
Count the number of trailing one bits.
FunctionPass class - This class is used to implement most global optimizations.
bool hasMinSize() const
Optimize this function for minimum size (-Oz).
CallingConv::ID getCallingConv() const
getCallingConv()/setCallingConv(CC) - These method get and set the calling convention of this functio...
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI std::optional< ConstantRange > getAbsoluteSymbolRange() const
If this is an absolute symbol reference, returns the range of the symbol, otherwise returns std::null...
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
unsigned getID() const
getID() - Return the register class ID number.
unsigned getNumRegs() const
getNumRegs - Return the number of registers in this class.
bool contains(MCRegister Reg) const
contains - Return true if the specified register is included in this register class.
bool isVectorOf(MVT EltVT) const
Return true if this is a vector with matching element type.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
unsigned getVectorMinNumElements() const
Given a vector type, return the minimum number of elements it contains.
uint64_t getScalarSizeInBits() const
unsigned getVectorNumElements() const
bool isVector() const
Return true if this is a vector value type.
bool is512BitVector() const
Return true if this is a 512-bit vector type.
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
static MVT getVectorVT(MVT VT, unsigned NumElements)
MVT getVectorElementType() const
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
MVT getHalfNumVectorElementsVT() const
Return a VT for a vector type with the same element type but half the number of elements.
MVT getScalarType() const
If this is a vector, return the element type, otherwise return this.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
const DataLayout & getDataLayout() const
Return the DataLayout attached to the Module associated to this MF.
Function & getFunction()
Return the LLVM function that this machine code represents.
@ MOLoad
The memory access reads data.
@ MOStore
The memory access writes data.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
LLVM_ABI MCRegister getLiveInPhysReg(Register VReg) const
getLiveInPhysReg - If VReg is a live-in virtual register, return the corresponding live-in physical r...
MachineMemOperand * getMemOperand() const
Return the unique MachineMemOperand object describing the memory reference performed by operation.
const MachinePointerInfo & getPointerInfo() const
const SDValue & getChain() const
bool isNonTemporal() const
Metadata * getModuleFlag(StringRef Key) const
Return the corresponding value if Key appears in module flags, otherwise return null.
Wrapper class representing virtual and physical registers.
Wrapper class for IR location info (IR ordering and DebugLoc) to be passed into SDNode creation funct...
Represents one node in the SelectionDAG.
ArrayRef< SDUse > ops() const
int getNodeId() const
Return the unique node id.
unsigned getOpcode() const
Return the SelectionDAG opcode value for this node.
bool hasOneUse() const
Return true if there is exactly one use of this node.
SDNodeFlags getFlags() const
MVT getSimpleValueType(unsigned ResNo) const
Return the type of a specified result as a simple type.
static bool hasPredecessorHelper(const SDNode *N, SmallPtrSetImpl< const SDNode * > &Visited, SmallVectorImpl< const SDNode * > &Worklist, unsigned int MaxSteps=0, bool TopologicalPrune=false)
Returns true if N is a predecessor of any node in Worklist.
uint64_t getAsZExtVal() const
Helper method returns the zero-extended integer value of a ConstantSDNode.
bool use_empty() const
Return true if there are no uses of this node.
const SDValue & getOperand(unsigned Num) const
bool hasNUsesOfValue(unsigned NUses, unsigned Value) const
Return true if there are exactly NUSES uses of the indicated value.
iterator_range< user_iterator > users()
op_iterator op_end() const
op_iterator op_begin() const
Unlike LLVM values, Selection DAG nodes may return multiple values as the result of a computation.
SDNode * getNode() const
get the SDNode which holds the desired result
bool hasOneUse() const
Return true if there is exactly one node using value ResNo of Node, in exactly one operand.
SDValue getValue(unsigned R) const
EVT getValueType() const
Return the ValueType of the referenced return value.
bool isMachineOpcode() const
TypeSize getValueSizeInBits() const
Returns the size of the value in bits.
const SDValue & getOperand(unsigned i) const
uint64_t getScalarValueSizeInBits() const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
uint64_t getConstantOperandVal(unsigned i) const
MVT getSimpleValueType() const
Return the simple ValueType of the referenced return value.
unsigned getMachineOpcode() const
unsigned getOpcode() const
unsigned getNumOperands() const
SelectionDAGISelPass(std::unique_ptr< SelectionDAGISel > Selector)
SelectionDAGISel - This is the common base class used for SelectionDAG-based pattern-matching instruc...
static int getUninvalidatedNodeId(SDNode *N)
virtual bool runOnMachineFunction(MachineFunction &mf)
static void InvalidateNodeId(SDNode *N)
This is used to represent a portion of an LLVM function in a low-level Data Dependence DAG representa...
static constexpr unsigned MaxRecursionDepth
LLVM_ABI SDValue getConstant(uint64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
Create a ConstantSDNode wrapping a constant value.
LLVM_ABI void ReplaceAllUsesWith(SDValue From, SDValue To)
Modify anything using 'From' to use 'To' instead.
LLVM_ABI SDValue getSignedConstant(int64_t Val, const SDLoc &DL, EVT VT, bool isTarget=false, bool isOpaque=false)
LLVM_ABI void RemoveDeadNode(SDNode *N)
Remove the specified node from the system.
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
LLVM_ABI SDValue getZExtOrTrunc(SDValue Op, const SDLoc &DL, EVT VT)
Convert Op, which must be of integer type, to the integer type VT, by either zero-extending or trunca...
LLVM_ABI bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth=0) const
Return true if 'Op & Mask' is known to be zero.
LLVM_ABI SDNode * UpdateNodeOperands(SDNode *N, SDValue Op)
Mutate the specified node in-place to have the specified operands.
void RepositionNode(allnodes_iterator Position, SDNode *N)
Move node N in the AllNodes list to be immediately before the given iterator Position.
ilist< SDNode >::iterator allnodes_iterator
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This class is used to represent ISD::STORE nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
virtual const TargetRegisterClass * getRegClassFor(MVT VT, bool isDivergent=false) const
Return the register class that should be used for the specified value type.
virtual MVT getPointerTy(const DataLayout &DL, uint32_t AS=0) const
Return the pointer type for the given address space, defaults to the pointer type from the data layou...
std::pair< SDValue, SDValue > LowerCallTo(CallLoweringInfo &CLI) const
This function lowers an abstract call to a function into an actual call.
bool hasOneUse() const
Return true if there is exactly one use of this value.
X86ISelDAGToDAGPass(X86TargetMachine &TM)
size_t getPreallocatedIdForCallSite(const Value *CS)
bool isScalarFPTypeInSSEReg(EVT VT) const
Return true if the specified scalar FP type is computed in an SSE register, not on the X87 floating p...
self_iterator getIterator()
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char Align[]
Key for Kernel::Arg::Metadata::mAlign.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
bool isNON_EXTLoad(const SDNode *N)
Returns true if the specified node is a non-extending load.
@ SETCC
SetCC operator - This evaluates to a true value iff the condition is true.
@ DELETED_NODE
DELETED_NODE - This is an illegal value that is used to catch errors.
@ SMUL_LOHI
SMUL_LOHI/UMUL_LOHI - Multiply two integers of type iN, producing a signed/unsigned value of type i[2...
@ INSERT_SUBVECTOR
INSERT_SUBVECTOR(VECTOR1, VECTOR2, IDX) - Returns a vector with VECTOR2 inserted into VECTOR1.
@ ADD
Simple integer binary arithmetic operators.
@ LOAD
LOAD and STORE have token chains as their first operand, then the same operands as an LLVM load/store...
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ INTRINSIC_VOID
OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) This node represents a target intrin...
@ SDIVREM
SDIVREM/UDIVREM - Divide two integers and produce both a quotient and remainder result.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ SIGN_EXTEND
Conversion operators.
@ SCALAR_TO_VECTOR
SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a scalar value into element 0 of the...
@ PREALLOCATED_SETUP
PREALLOCATED_SETUP - This has 2 operands: an input chain and a SRCVALUE with the preallocated call Va...
@ PREALLOCATED_ARG
PREALLOCATED_ARG - This has 3 operands: an input chain, a SRCVALUE with the preallocated call Value,...
@ BRIND
BRIND - Indirect branch.
@ CopyFromReg
CopyFromReg - This node indicates that the input value is a virtual or physical register that is defi...
@ TargetGlobalAddress
TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or anything else with this node...
@ SHL
Shift and rotation operations.
@ EXTRACT_SUBVECTOR
EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR.
@ EXTRACT_VECTOR_ELT
EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR identified by the (potentially...
@ CopyToReg
CopyToReg - This node has three operands: a chain, a register number to set to this value,...
@ ZERO_EXTEND
ZERO_EXTEND - Used for integer types, zeroing the new bits.
@ LOCAL_RECOVER
LOCAL_RECOVER - Represents the llvm.localrecover intrinsic.
@ ANY_EXTEND_VECTOR_INREG
ANY_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register any-extension of the low la...
@ FP_EXTEND
X = FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ VSELECT
Select with a vector condition (op #0) and two vector operands (ops #1 and #2), returning a vector re...
@ UADDO_CARRY
Carry-using nodes for multiple precision addition and subtraction.
@ STRICT_FP_ROUND
X = STRICT_FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision ...
@ STRICT_FP_TO_SINT
STRICT_FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ FP_TO_SINT
FP_TO_[US]INT - Convert a floating point value to a signed or unsigned integer.
@ STRICT_FP_EXTEND
X = STRICT_FP_EXTEND(Y) - Extend a smaller FP type into a larger FP type.
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ FP_ROUND
X = FP_ROUND(Y, TRUNC) - Rounding 'Y' from a larger floating point type down to the precision of the ...
@ ZERO_EXTEND_VECTOR_INREG
ZERO_EXTEND_VECTOR_INREG(Vector) - This operator represents an in-register zero-extension of the low ...
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ CALLSEQ_START
CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end of a call sequence,...
@ INTRINSIC_W_CHAIN
RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) This node represents a target in...
LLVM_ABI bool isBuildVectorOfConstantSDNodes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR node of all ConstantSDNode or undef.
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
LLVM_ABI bool isBuildVectorAllZeros(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are 0 or undef.
CondCode
ISD::CondCode enum - These are ordered carefully to make the bitfields below work out,...
LLVM_ABI bool isBuildVectorAllOnes(const SDNode *N)
Return true if the specified node is a BUILD_VECTOR where all of the elements are ~0 or undef.
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
@ GlobalBaseReg
The result of the mflr at function entry, used for PIC code.
@ X86
Windows x64, Windows Itanium (IA-64)
@ MO_NO_FLAG
MO_NO_FLAG - No flag for the operand.
@ EVEX
EVEX - Specifies that this instruction use EVEX form which provides syntax support up to 32 512-bit r...
@ VEX
VEX - encoding using 0xC4/0xC5.
@ XOP
XOP - Opcode prefix used by XOP instructions.
int getMemoryOperandNo(uint64_t TSFlags)
@ GlobalBaseReg
On Darwin, this node represents the result of the popl at function entry, used for PIC code.
@ POP_FROM_X87_REG
The same as ISD::CopyFromReg except that this node makes it explicit that it may lower to an x87 FPU ...
int getCondSrcNoFromDesc(const MCInstrDesc &MCID)
Return the source operand # for condition code by MCID.
bool mayFoldLoad(SDValue Op, const X86Subtarget &Subtarget, bool AssumeSingleUse=false, bool IgnoreAlignment=false)
Check if Op is a load operation that could be folded into some other x86 instruction as a memory oper...
bool isOffsetSuitableForCodeModel(int64_t Offset, CodeModel::Model M, bool hasSymbolicDisplacement)
Returns true of the given offset can be fit into displacement field of the instruction.
bool isConstantSplat(SDValue Op, APInt &SplatVal, bool AllowPartialUndefs)
If Op is a constant whose elements are all the same constant or undefined, return true and return the...
initializer< Ty > init(const Ty &Val)
@ User
could "use" a pointer
NodeAddr< UseNode * > Use
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
LLVM_ABI bool isNullConstant(SDValue V)
Returns true if V is a constant integer zero.
LLVM_ABI SDValue peekThroughBitcasts(SDValue V)
Return the non-bitcasted source operand of V if it exists.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
@ Load
The value being inserted comes from a load (InsertElement only).
@ Store
The extracted value is stored (ExtractElement only).
bool isa_and_nonnull(const Y &Val)
T bit_ceil(T Value)
Returns the smallest integral power of two no smaller than Value if Value is nonzero.
constexpr int popcount(T Value) noexcept
Count the number of set bits in a value.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
int countr_zero(T Val)
Count number of 0's from the least significant bit to the most stopping at the first 1.
constexpr bool isShiftedMask_64(uint64_t Value)
Return true if the argument contains a non-empty sequence of ones with the remainder zero (64 bit ver...
unsigned M1(unsigned Val)
auto dyn_cast_or_null(const Y &Val)
int countl_zero(T Val)
Count number of 0's from the most significant bit to the least stopping at the first 1.
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
constexpr bool isMask_64(uint64_t Value)
Return true if the argument is a non-empty sequence of ones starting at the least significant bit wit...
FunctionPass * createX86ISelDag(X86TargetMachine &TM, CodeGenOptLevel OptLevel)
This pass converts a legalized DAG into a X86-specific DAG, ready for instruction scheduling.
constexpr bool isUInt(uint64_t x)
Checks if an unsigned integer fits into the given bit width.
CodeGenOptLevel
Code generation optimization level.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
@ And
Bitwise or logical AND of integers.
DWARFExpression::Operation Op
unsigned M0(unsigned Val)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI bool isOneConstant(SDValue V)
Returns true if V is a constant integer one.
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
constexpr T maskTrailingOnes(unsigned N)
Create a bitmask with the N right-most bits set to 1, and all other bits set to 0.
LLVM_ABI bool isAllOnesConstant(SDValue V)
Returns true if V is an integer constant with all bits set.
MCRegisterClass TargetRegisterClass
Implement std::hash so that hash_code can be used in STL containers.
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
bool is128BitVector() const
Return true if this is a 128-bit vector type.
bool isVector() const
Return true if this is a vector value type.
bool is256BitVector() const
Return true if this is a 256-bit vector type.
bool isConstant() const
Returns true if we know the value of all bits.
LLVM_ABI unsigned getAddrSpace() const
Return the LLVM IR address space number that this pointer points into.
static LLVM_ABI MachinePointerInfo getFixedStack(MachineFunction &MF, int FI, int64_t Offset=0)
Return a MachinePointerInfo record that refers to the specified FrameIndex.
bool hasNoUnsignedWrap() const