23#define DEBUG_TYPE "systemz-isel"
24#define PASS_NAME "SystemZ DAG->DAG Pattern Instruction Selection"
28struct SystemZAddressingMode {
63 bool IncludesDynAlloc;
65 SystemZAddressingMode(AddrForm form, DispRange dr)
66 : Form(form), DR(dr), Disp(0), IncludesDynAlloc(
false) {}
69 bool hasIndexField() {
return Form != FormBD; }
72 bool isDynAlloc() {
return Form == FormBDXDynAlloc; }
75 errs() <<
"SystemZAddressingMode " <<
this <<
'\n';
79 Base.getNode()->dump(DAG);
83 if (hasIndexField()) {
86 Index.getNode()->dump(DAG);
91 errs() <<
" Disp " << Disp;
93 errs() <<
" + ADJDYNALLOC";
119struct RxSBGOperands {
121 : Opcode(
Op), BitSize(
N.getValueSizeInBits()),
122 Mask(
allOnes(BitSize)),
Input(
N), Start(64 - BitSize), End(63),
139 return CurDAG->getTargetConstant(Imm,
SDLoc(
Node),
Node->getValueType(0));
152 bool expandAddress(SystemZAddressingMode &AM,
bool IsBase)
const;
155 bool selectAddress(
SDValue N, SystemZAddressingMode &AM)
const;
158 void getAddressOperands(
const SystemZAddressingMode &AM,
EVT VT,
160 void getAddressOperands(
const SystemZAddressingMode &AM,
EVT VT,
166 bool selectBDAddr(SystemZAddressingMode::DispRange DR,
SDValue Addr,
172 bool selectMVIAddr(SystemZAddressingMode::DispRange DR,
SDValue Addr,
178 bool selectBDXAddr(SystemZAddressingMode::AddrForm Form,
179 SystemZAddressingMode::DispRange DR,
SDValue Addr,
193 return selectBDAddr(SystemZAddressingMode::Disp12Only, Addr,
Base, Disp);
196 return selectBDAddr(SystemZAddressingMode::Disp12Pair, Addr,
Base, Disp);
199 return selectBDAddr(SystemZAddressingMode::Disp20Only, Addr,
Base, Disp);
202 return selectBDAddr(SystemZAddressingMode::Disp20Pair, Addr,
Base, Disp);
207 return selectMVIAddr(SystemZAddressingMode::Disp12Pair, Addr,
Base, Disp);
210 return selectMVIAddr(SystemZAddressingMode::Disp20Pair, Addr,
Base, Disp);
216 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
217 SystemZAddressingMode::Disp12Only,
218 Addr,
Base, Disp, Index);
222 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
223 SystemZAddressingMode::Disp12Pair,
224 Addr,
Base, Disp, Index);
228 return selectBDXAddr(SystemZAddressingMode::FormBDXDynAlloc,
229 SystemZAddressingMode::Disp12Only,
230 Addr,
Base, Disp, Index);
234 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
235 SystemZAddressingMode::Disp20Only,
236 Addr,
Base, Disp, Index);
240 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
241 SystemZAddressingMode::Disp20Only128,
242 Addr,
Base, Disp, Index);
246 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
247 SystemZAddressingMode::Disp20Pair,
248 Addr,
Base, Disp, Index);
252 return selectBDXAddr(SystemZAddressingMode::FormBDXLA,
253 SystemZAddressingMode::Disp12Pair,
254 Addr,
Base, Disp, Index);
258 return selectBDXAddr(SystemZAddressingMode::FormBDXLA,
259 SystemZAddressingMode::Disp20Pair,
260 Addr,
Base, Disp, Index);
277 bool refineRxSBGMask(RxSBGOperands &RxSBG,
uint64_t Mask)
const;
281 bool expandRxSBG(RxSBGOperands &RxSBG)
const;
295 bool tryRxSBG(
SDNode *
N,
unsigned Opcode);
313 bool tryGather(
SDNode *
N,
unsigned Opcode);
316 bool tryScatter(
StoreSDNode *Store,
unsigned Opcode);
321 bool tryFoldLoadStoreIntoMemOperand(
SDNode *
Node);
336 bool storeLoadCanUseMVC(
SDNode *
N)
const;
341 bool storeLoadCanUseBlockBinary(
SDNode *
N,
unsigned I)
const;
345 bool storeLoadIsAligned(
SDNode *
N)
const;
356 bool shouldSelectForReassoc(
SDNode *
N)
const;
359 SystemZDAGToDAGISel() =
delete;
366 if (
F.getFnAttribute(
"fentry-call").getValueAsString() !=
"true") {
367 if (
F.hasFnAttribute(
"mnop-mcount"))
369 if (
F.hasFnAttribute(
"mrecord-mcount"))
379 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
381 std::vector<SDValue> &OutOps)
override;
383 void PreprocessISelDAG()
override;
386 #include "SystemZGenDAGISel.inc"
395 ID, std::make_unique<SystemZDAGToDAGISel>(TM, OptLevel)) {}
399char SystemZDAGToDAGISelLegacy::ID = 0;
405 return new SystemZDAGToDAGISelLegacy(TM, OptLevel);
411static bool selectDisp(SystemZAddressingMode::DispRange DR, int64_t Val) {
413 case SystemZAddressingMode::Disp12Only:
416 case SystemZAddressingMode::Disp12Pair:
417 case SystemZAddressingMode::Disp20Only:
418 case SystemZAddressingMode::Disp20Pair:
421 case SystemZAddressingMode::Disp20Only128:
442 if (AM.isDynAlloc() && !AM.IncludesDynAlloc) {
444 AM.IncludesDynAlloc =
true;
454 if (AM.hasIndexField() && !AM.Index.
getNode()) {
464static bool expandDisp(SystemZAddressingMode &AM,
bool IsBase,
467 int64_t TestDisp = AM.Disp + Op1;
479bool SystemZDAGToDAGISel::expandAddress(SystemZAddressingMode &AM,
484 if (Opcode ==
ISD::TRUNCATE &&
N.getOperand(0).getValueSizeInBits() <= 64) {
486 Opcode =
N.getOpcode();
488 if (Opcode ==
ISD::ADD || CurDAG->isBaseWithConstantOffset(
N)) {
523static bool isValidDisp(SystemZAddressingMode::DispRange DR, int64_t Val) {
526 case SystemZAddressingMode::Disp12Only:
527 case SystemZAddressingMode::Disp20Only:
528 case SystemZAddressingMode::Disp20Only128:
531 case SystemZAddressingMode::Disp12Pair:
535 case SystemZAddressingMode::Disp20Pair:
575 if (Index->hasOneUse())
580 unsigned IndexOpcode = Index->getOpcode();
588 if (
Base->hasOneUse())
595bool SystemZDAGToDAGISel::selectAddress(
SDValue Addr,
596 SystemZAddressingMode &AM)
const {
612 while (expandAddress(AM,
true) ||
613 (AM.Index.
getNode() && expandAddress(AM,
false)))
617 if (AM.Form == SystemZAddressingMode::FormBDXLA &&
626 if (AM.isDynAlloc() && !AM.IncludesDynAlloc)
639 if (
N->getNodeId() == -1 ||
652void SystemZDAGToDAGISel::getAddressOperands(
const SystemZAddressingMode &AM,
658 Base = CurDAG->getRegister(0, VT);
662 Base = CurDAG->getTargetFrameIndex(FrameIndex, VT);
663 }
else if (
Base.getValueType() != VT) {
665 assert(VT == MVT::i32 &&
Base.getValueType() == MVT::i64 &&
666 "Unexpected truncation");
674 Disp = CurDAG->getSignedTargetConstant(AM.Disp, SDLoc(
Base), VT);
677void SystemZDAGToDAGISel::getAddressOperands(
const SystemZAddressingMode &AM,
681 getAddressOperands(AM, VT,
Base, Disp);
684 if (!
Index.getNode())
686 Index = CurDAG->getRegister(0, VT);
689bool SystemZDAGToDAGISel::selectBDAddr(SystemZAddressingMode::DispRange DR,
692 SystemZAddressingMode AM(SystemZAddressingMode::FormBD, DR);
693 if (!selectAddress(Addr, AM))
700bool SystemZDAGToDAGISel::selectMVIAddr(SystemZAddressingMode::DispRange DR,
703 SystemZAddressingMode AM(SystemZAddressingMode::FormBDXNormal, DR);
704 if (!selectAddress(Addr, AM) || AM.Index.
getNode())
711bool SystemZDAGToDAGISel::selectBDXAddr(SystemZAddressingMode::AddrForm Form,
712 SystemZAddressingMode::DispRange DR,
715 SystemZAddressingMode AM(Form, DR);
716 if (!selectAddress(Addr, AM))
723bool SystemZDAGToDAGISel::selectBDVAddr12Only(
SDValue Addr,
SDValue Elem,
728 if (selectBDXAddr12Only(Addr, Regs[0], Disp, Regs[1]) &&
730 for (
unsigned int I = 0;
I < 2; ++
I) {
738 Index.getOperand(1) == Elem) {
747bool SystemZDAGToDAGISel::detectOrAndInsertion(
SDValue &
Op,
748 uint64_t InsertMask)
const {
760 uint64_t AndMask = MaskNode->getZExtValue();
761 if (InsertMask & AndMask)
767 if (Used != (AndMask | InsertMask)) {
768 KnownBits Known = CurDAG->computeKnownBits(
Op.getOperand(0));
773 Op =
Op.getOperand(0);
777bool SystemZDAGToDAGISel::refineRxSBGMask(RxSBGOperands &RxSBG,
778 uint64_t Mask)
const {
779 const SystemZInstrInfo *
TII = getInstrInfo();
780 if (RxSBG.Rotate != 0)
781 Mask = (
Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate));
783 if (
TII->isRxSBGMask(Mask, RxSBG.BitSize, RxSBG.Start, RxSBG.End)) {
793 if (RxSBG.Rotate != 0)
794 Mask = ((Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate)));
795 return (Mask & RxSBG.Mask) != 0;
798bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG)
const {
800 unsigned Opcode =
N.getOpcode();
803 if (RxSBG.Opcode == SystemZ::RNSBG)
805 if (
N.getOperand(0).getValueSizeInBits() > 64)
807 uint64_t BitSize =
N.getValueSizeInBits();
809 if (!refineRxSBGMask(RxSBG, Mask))
815 if (RxSBG.Opcode == SystemZ::RNSBG)
823 uint64_t
Mask = MaskNode->getZExtValue();
824 if (!refineRxSBGMask(RxSBG, Mask)) {
828 KnownBits Known = CurDAG->computeKnownBits(Input);
830 if (!refineRxSBGMask(RxSBG, Mask))
838 if (RxSBG.Opcode != SystemZ::RNSBG)
846 uint64_t
Mask = ~MaskNode->getZExtValue();
847 if (!refineRxSBGMask(RxSBG, Mask)) {
851 KnownBits Known = CurDAG->computeKnownBits(Input);
852 Mask &= ~Known.One.getZExtValue();
853 if (!refineRxSBGMask(RxSBG, Mask))
862 if (RxSBG.BitSize != 64 ||
N.getValueType() != MVT::i64)
868 RxSBG.Rotate = (RxSBG.Rotate + CountNode->getZExtValue()) & 63;
879 if (RxSBG.Opcode != SystemZ::RNSBG) {
881 unsigned InnerBitSize =
N.getOperand(0).getValueSizeInBits();
882 if (!refineRxSBGMask(RxSBG,
allOnes(InnerBitSize)))
893 unsigned BitSize =
N.getValueSizeInBits();
894 unsigned InnerBitSize =
N.getOperand(0).getValueSizeInBits();
898 if (RxSBG.Mask == 1 && RxSBG.Rotate == 1)
899 RxSBG.Rotate += (BitSize - InnerBitSize);
913 uint64_t
Count = CountNode->getZExtValue();
914 unsigned BitSize =
N.getValueSizeInBits();
918 if (RxSBG.Opcode == SystemZ::RNSBG) {
929 RxSBG.Rotate = (RxSBG.Rotate +
Count) & 63;
940 uint64_t
Count = CountNode->getZExtValue();
941 unsigned BitSize =
N.getValueSizeInBits();
945 if (RxSBG.Opcode == SystemZ::RNSBG || Opcode ==
ISD::SRA) {
957 RxSBG.Rotate = (RxSBG.Rotate -
Count) & 63;
966SDValue SystemZDAGToDAGISel::getUNDEF(
const SDLoc &
DL, EVT VT)
const {
967 SDNode *
N = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
971SDValue SystemZDAGToDAGISel::convertTo(
const SDLoc &
DL, EVT VT,
973 if (
N.getValueType() == MVT::i32 && VT == MVT::i64)
974 return CurDAG->getTargetInsertSubreg(SystemZ::subreg_l32,
975 DL, VT, getUNDEF(
DL, MVT::i64),
N);
976 if (
N.getValueType() == MVT::i64 && VT == MVT::i32)
977 return CurDAG->getTargetExtractSubreg(SystemZ::subreg_l32,
DL, VT,
N);
978 assert(
N.getValueType() == VT &&
"Unexpected value types");
982bool SystemZDAGToDAGISel::tryRISBGZero(SDNode *
N) {
984 EVT VT =
N->getValueType(0);
987 RxSBGOperands RISBG(SystemZ::RISBG,
SDValue(
N, 0));
989 while (expandRxSBG(RISBG))
1006 if (Subtarget->hasMiscellaneousExtensions4() &&
1007 RISBG.Rotate >= 1 && RISBG.Rotate <= 4 &&
1008 RISBG.Mask == (((uint64_t)1 << 32) - 1) << RISBG.Rotate &&
1009 RISBG.Input.getOpcode() ==
ISD::ADD)
1017 if (RISBG.Rotate == 0) {
1018 bool PreferAnd =
false;
1024 else if (RISBG.Mask == 0xff ||
1025 RISBG.Mask == 0xffff ||
1026 RISBG.Mask == 0x7fffffff ||
1033 if (
Load->getMemoryVT() == MVT::i32 &&
1036 RISBG.Mask == 0xffffff00 &&
1037 Subtarget->hasLoadAndZeroRightmostByte())
1047 if (
N !=
New.getNode()) {
1050 ReplaceNode(
N,
New.getNode());
1054 if (!
N->isMachineOpcode())
1060 unsigned Opcode = SystemZ::RISBG;
1062 if (Subtarget->hasMiscellaneousExtensions())
1063 Opcode = SystemZ::RISBGN;
1064 EVT OpcodeVT = MVT::i64;
1065 if (VT == MVT::i32 && Subtarget->hasHighWord() &&
1070 RISBG.Start >= 32 && RISBG.End >= RISBG.Start &&
1071 ((RISBG.Start + RISBG.Rotate) & 63) >= 32 &&
1072 ((RISBG.End + RISBG.Rotate) & 63) >=
1073 ((RISBG.Start + RISBG.Rotate) & 63)) {
1074 Opcode = SystemZ::RISBMux;
1075 OpcodeVT = MVT::i32;
1080 getUNDEF(
DL, OpcodeVT),
1081 convertTo(
DL, OpcodeVT, RISBG.Input),
1082 CurDAG->getTargetConstant(RISBG.Start,
DL, MVT::i32),
1083 CurDAG->getTargetConstant(RISBG.End | 128,
DL, MVT::i32),
1084 CurDAG->getTargetConstant(RISBG.Rotate,
DL, MVT::i32)
1087 DL, VT,
SDValue(CurDAG->getMachineNode(Opcode,
DL, OpcodeVT,
Ops), 0));
1088 ReplaceNode(
N,
New.getNode());
1092bool SystemZDAGToDAGISel::tryRxSBG(SDNode *
N,
unsigned Opcode) {
1094 EVT VT =
N->getValueType(0);
1099 RxSBGOperands RxSBG[] = {
1100 RxSBGOperands(Opcode,
N->getOperand(0)),
1101 RxSBGOperands(Opcode,
N->getOperand(1))
1103 unsigned Count[] = { 0, 0 };
1104 for (
unsigned I = 0;
I < 2; ++
I)
1105 while (RxSBG[
I].Input->
hasOneUse() && expandRxSBG(RxSBG[
I]))
1125 if (Opcode == SystemZ::ROSBG && (RxSBG[
I].Mask & 0xff) == 0)
1127 if (
Load->getMemoryVT() == MVT::i8)
1132 if (Opcode == SystemZ::ROSBG && detectOrAndInsertion(Op0, RxSBG[
I].Mask)) {
1133 Opcode = SystemZ::RISBG;
1135 if (Subtarget->hasMiscellaneousExtensions())
1136 Opcode = SystemZ::RISBGN;
1140 convertTo(
DL, MVT::i64, Op0),
1141 convertTo(
DL, MVT::i64, RxSBG[
I].Input),
1142 CurDAG->getTargetConstant(RxSBG[
I].Start,
DL, MVT::i32),
1143 CurDAG->getTargetConstant(RxSBG[
I].End,
DL, MVT::i32),
1144 CurDAG->getTargetConstant(RxSBG[
I].Rotate,
DL, MVT::i32)
1147 DL, VT,
SDValue(CurDAG->getMachineNode(Opcode,
DL, MVT::i64,
Ops), 0));
1148 ReplaceNode(
N,
New.getNode());
1152void SystemZDAGToDAGISel::splitLargeImmediate(
unsigned Opcode, SDNode *Node,
1153 SDValue Op0, uint64_t UpperVal,
1154 uint64_t LowerVal) {
1155 EVT VT =
Node->getValueType(0);
1174 HandleSDNode Handle(
Upper);
1175 SelectCode(
Upper.getNode());
1176 Upper = Handle.getValue();
1182 ReplaceNode(Node,
Or.getNode());
1184 SelectCode(
Or.getNode());
1187void SystemZDAGToDAGISel::loadVectorConstant(
1188 const SystemZVectorConstantInfo &VCI, SDNode *Node) {
1194 EVT VT =
Node->getValueType(0);
1197 for (
unsigned OpVal : VCI.
OpVals)
1198 Ops.push_back(CurDAG->getTargetConstant(OpVal,
DL, MVT::i32));
1202 ReplaceNode(Node,
Op.getNode());
1204 SDValue BitCast = CurDAG->getNode(ISD::BITCAST,
DL, VT,
Op);
1205 ReplaceNode(Node, BitCast.
getNode());
1206 SelectCode(BitCast.
getNode());
1208 unsigned SubRegIdx = (VT.
getSizeInBits() == 16 ? SystemZ::subreg_h16
1210 : SystemZ::subreg_h64);
1212 Node, CurDAG->getTargetExtractSubreg(SubRegIdx,
DL, VT,
Op).getNode());
1214 SelectCode(
Op.getNode());
1217SDNode *SystemZDAGToDAGISel::loadPoolVectorConstant(APInt Val, EVT VT, SDLoc
DL) {
1221 SDValue CP = CurDAG->getTargetConstantPool(
1222 ConstantInt::get(Type::getInt128Ty(*CurDAG->getContext()), Val),
1223 TLI->getPointerTy(CurDAG->getDataLayout()));
1225 EVT PtrVT =
CP.getValueType();
1227 SDValue(CurDAG->getMachineNode(SystemZ::LARL,
DL, PtrVT, CP), 0),
1228 CurDAG->getTargetConstant(0,
DL, PtrVT),
1229 CurDAG->getRegister(0, PtrVT),
1230 CurDAG->getEntryNode()
1232 ResNode = CurDAG->getMachineNode(SystemZ::VL,
DL, VT, MVT::Other,
Ops);
1237 MachineFunction& MF = CurDAG->getMachineFunction();
1238 MachineMemOperand *MemOp =
1246bool SystemZDAGToDAGISel::tryGather(SDNode *
N,
unsigned Opcode) {
1252 unsigned Elem = ElemN->getZExtValue();
1253 EVT VT =
N->getValueType(0);
1258 if (!Load || !
Load->hasNUsesOfValue(1, 0))
1260 if (
Load->getMemoryVT().getSizeInBits() !=
1261 Load->getValueType(0).getSizeInBits())
1265 if (!selectBDVAddr12Only(
Load->getBasePtr(), ElemV,
Base, Disp, Index) ||
1272 CurDAG->getTargetConstant(Elem,
DL, MVT::i32),
Load->getChain()
1274 SDNode *Res = CurDAG->getMachineNode(Opcode,
DL, VT, MVT::Other,
Ops);
1276 ReplaceNode(
N, Res);
1280bool SystemZDAGToDAGISel::tryScatter(StoreSDNode *Store,
unsigned Opcode) {
1284 if (
Store->getMemoryVT().getSizeInBits() !=
Value.getValueSizeInBits())
1294 unsigned Elem = ElemN->getZExtValue();
1299 if (!selectBDVAddr12Only(
Store->getBasePtr(), ElemV,
Base, Disp, Index) ||
1305 Vec,
Base, Disp,
Index, CurDAG->getTargetConstant(Elem,
DL, MVT::i32),
1308 ReplaceNode(Store, CurDAG->getMachineNode(Opcode,
DL, MVT::Other,
Ops));
1339 if (!Load.hasOneUse())
1351 bool ChainCheck =
false;
1352 if (Chain == Load.getValue(1)) {
1359 const unsigned int Max = 1024;
1362 if (
Op == Load.getValue(1)) {
1375 if (
Op.getNode() != LoadNode)
1386 MVT::Other, ChainOps);
1403bool SystemZDAGToDAGISel::tryFoldLoadStoreIntoMemOperand(SDNode *Node) {
1407 SDLoc
DL(StoreNode);
1413 unsigned NewOpc = 0;
1414 bool NegateOperand =
false;
1419 NegateOperand =
true;
1422 if (MemVT == MVT::i32)
1423 NewOpc = SystemZ::ASI;
1424 else if (MemVT == MVT::i64)
1425 NewOpc = SystemZ::AGSI;
1430 NegateOperand =
true;
1433 if (MemVT == MVT::i32)
1434 NewOpc = SystemZ::ALSI;
1435 else if (MemVT == MVT::i64)
1436 NewOpc = SystemZ::ALGSI;
1442 LoadSDNode *LoadNode =
nullptr;
1452 auto OperandV = OperandC->getAPIntValue();
1454 OperandV = -OperandV;
1455 if (OperandV.getSignificantBits() > 8)
1457 Operand = CurDAG->getTargetConstant(OperandV,
DL, MemVT);
1465 CurDAG->getMachineNode(NewOpc,
DL, MVT::i32, MVT::Other,
Ops);
1466 CurDAG->setNodeMemRefs(
1471 CurDAG->RemoveDeadNode(Node);
1475bool SystemZDAGToDAGISel::canUseBlockOperation(StoreSDNode *Store,
1476 LoadSDNode *Load)
const {
1478 if (
Load->getMemoryVT() !=
Store->getMemoryVT())
1482 if (
Load->isVolatile() ||
Store->isVolatile())
1486 if (
Load->isInvariant() &&
Load->isDereferenceable())
1490 const Value *V1 =
Load->getMemOperand()->getValue();
1491 const Value *V2 =
Store->getMemOperand()->getValue();
1496 uint64_t
Size =
Load->getMemoryVT().getStoreSize();
1497 int64_t End1 =
Load->getSrcValueOffset() +
Size;
1498 int64_t End2 =
Store->getSrcValueOffset() +
Size;
1499 if (V1 == V2 && End1 == End2)
1502 return BatchAA->isNoAlias(MemoryLocation(V1, End1,
Load->getAAInfo()),
1503 MemoryLocation(V2, End2,
Store->getAAInfo()));
1506bool SystemZDAGToDAGISel::storeLoadCanUseMVC(SDNode *
N)
const {
1512 uint64_t
Size =
Load->getMemoryVT().getStoreSize();
1522 return canUseBlockOperation(Store, Load);
1525bool SystemZDAGToDAGISel::storeLoadCanUseBlockBinary(SDNode *
N,
1530 return !LoadA->isVolatile() && LoadA->getMemoryVT() == LoadB->getMemoryVT() &&
1531 canUseBlockOperation(StoreA, LoadB);
1534bool SystemZDAGToDAGISel::storeLoadIsAligned(SDNode *
N)
const {
1538 TypeSize StoreSize = MemAccess->getMemoryVT().getStoreSize();
1540 MachineMemOperand *MMO = MemAccess->getMemOperand();
1541 assert(MMO &&
"Expected a memory operand.");
1545 if (MemAccess->getAlign().value() < StoreSize ||
1546 (LdSt && !LdSt->getOffset().isUndef()))
1555 if ((PSV->isGOT() || PSV->isConstantPool()))
1560 if (GlobalAddressSDNode *GA =
1563 if (GA->getOffset() % StoreSize != 0)
1567 const GlobalValue *GV = GA->getGlobal();
1579 ETy =
L->getExtensionType();
1581 ETy =
AL->getExtensionType();
1587void SystemZDAGToDAGISel::Select(SDNode *Node) {
1589 if (
Node->isMachineOpcode()) {
1591 Node->setNodeId(-1);
1595 unsigned Opcode =
Node->getOpcode();
1599 if (tryRxSBG(Node, SystemZ::ROSBG))
1605 if (tryRxSBG(Node, SystemZ::RXSBG))
1612 if (
Node->getValueType(0) == MVT::i64 &&
1615 uint64_t Val = Op1->getZExtValue();
1618 if (Subtarget->hasMiscellaneousExtensions3()) {
1619 unsigned ChildOpcode =
Node->getOperand(0).getOpcode();
1621 if (Val == (uint64_t)-1 && Opcode ==
ISD::XOR)
1628 auto Op0 =
Node->getOperand(0);
1630 if (Op0Op1->getZExtValue() == (uint64_t)-1)
1635 if (Opcode ==
ISD::XOR && Op1->isAllOnes())
1638 splitLargeImmediate(Opcode, Node,
Node->getOperand(0),
1639 Val - uint32_t(Val), uint32_t(Val));
1647 if (tryRxSBG(Node, SystemZ::RNSBG))
1654 if (tryRISBGZero(Node))
1659 if (
Node->getValueType(0) == MVT::i128) {
1662 Src = CurDAG->getNode(ISD::BITCAST,
DL, MVT::v16i8, Src);
1664 uint64_t Bytes[2] = { 0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL };
1665 SDNode *
Mask = loadPoolVectorConstant(APInt(128, Bytes), MVT::v16i8,
DL);
1668 MVT::v16i8,
Ops), 0);
1670 Res = CurDAG->getNode(ISD::BITCAST,
DL, MVT::i128, Res);
1671 SDNode *ResNode = Res.
getNode();
1672 ReplaceNode(Node, ResNode);
1673 SelectCode(Src.getNode());
1674 SelectCode(ResNode);
1682 if (
Node->getValueType(0) == MVT::i64) {
1683 uint64_t Val =
Node->getAsZExtVal();
1685 splitLargeImmediate(
ISD::OR, Node,
SDValue(), Val - uint32_t(Val),
1690 if (
Node->getValueType(0) == MVT::i128) {
1691 const APInt &Val =
Node->getAsAPIntVal();
1692 SystemZVectorConstantInfo VCI(Val);
1694 loadVectorConstant(VCI, Node);
1698 SDNode *ResNode = loadPoolVectorConstant(Val, MVT::i128, SDLoc(Node));
1699 ReplaceNode(Node, ResNode);
1710 (Subtarget->hasLoadStoreOnCond2() &&
1711 Node->getValueType(0).isInteger() &&
1712 Node->getValueType(0).getSizeInBits() <= 64 &&
1722 CCMask = CurDAG->getTargetConstant(ConstCCValid ^ ConstCCMask,
1725 SDNode *UpdatedNode =
1726 CurDAG->UpdateNodeOperands(Node, Op1, Op0, CCValid, CCMask, Op4);
1727 if (UpdatedNode != Node) {
1729 ReplaceNode(Node, UpdatedNode);
1737 EVT VT =
Node->getValueType(0);
1739 if (ElemBitSize == 32) {
1740 if (tryGather(Node, SystemZ::VGEF))
1742 }
else if (ElemBitSize == 64) {
1743 if (tryGather(Node, SystemZ::VGEG))
1751 SystemZVectorConstantInfo VCI(BVN);
1753 loadVectorConstant(VCI, Node);
1761 if (
Imm.isZero() ||
Imm.isNegZero())
1763 SystemZVectorConstantInfo VCI(Imm);
1766 loadVectorConstant(VCI, Node);
1771 if (tryFoldLoadStoreIntoMemOperand(Node))
1774 unsigned ElemBitSize =
Store->getValue().getValueSizeInBits();
1775 if (ElemBitSize == 32) {
1776 if (tryScatter(Store, SystemZ::VSCEF))
1778 }
else if (ElemBitSize == 64) {
1779 if (tryScatter(Store, SystemZ::VSCEG))
1785 case ISD::ATOMIC_STORE: {
1791 AtomOp->getChain(), SDLoc(AtomOp), AtomOp->getVal(),
1792 AtomOp->getBasePtr(), AtomOp->getMemoryVT(), AtomOp->getMemOperand()));
1797 if (AtomOp->getSuccessOrdering() == AtomicOrdering::SequentiallyConsistent)
1798 Chain = CurDAG->getMachineNode(SystemZ::Serialize, SDLoc(AtomOp),
1799 MVT::Other,
SDValue(Chain, 0));
1800 ReplaceNode(Node, Chain);
1809bool SystemZDAGToDAGISel::SelectInlineAsmMemoryOperand(
1811 std::vector<SDValue> &OutOps) {
1812 SystemZAddressingMode::AddrForm
Form;
1813 SystemZAddressingMode::DispRange DispRange;
1816 switch(ConstraintID) {
1819 case InlineAsm::ConstraintCode::i:
1820 case InlineAsm::ConstraintCode::Q:
1821 case InlineAsm::ConstraintCode::ZQ:
1823 Form = SystemZAddressingMode::FormBD;
1824 DispRange = SystemZAddressingMode::Disp12Only;
1826 case InlineAsm::ConstraintCode::R:
1827 case InlineAsm::ConstraintCode::ZR:
1829 Form = SystemZAddressingMode::FormBDXNormal;
1830 DispRange = SystemZAddressingMode::Disp12Only;
1832 case InlineAsm::ConstraintCode::S:
1833 case InlineAsm::ConstraintCode::ZS:
1835 Form = SystemZAddressingMode::FormBD;
1836 DispRange = SystemZAddressingMode::Disp20Only;
1838 case InlineAsm::ConstraintCode::T:
1839 case InlineAsm::ConstraintCode::m:
1840 case InlineAsm::ConstraintCode::o:
1841 case InlineAsm::ConstraintCode::p:
1842 case InlineAsm::ConstraintCode::ZT:
1847 Form = SystemZAddressingMode::FormBDXNormal;
1848 DispRange = SystemZAddressingMode::Disp20Only;
1852 if (selectBDXAddr(Form, DispRange,
Op,
Base, Disp, Index)) {
1853 const TargetRegisterClass *TRC =
1856 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(),
DL, MVT::i32);
1863 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
1871 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
1876 OutOps.push_back(
Base);
1877 OutOps.push_back(Disp);
1878 OutOps.push_back(Index);
1888SystemZDAGToDAGISel::IsProfitableToFold(
SDValue N, SDNode *U,
1889 SDNode *Root)
const {
1893 if (!
N.hasOneUse() || !
U->hasOneUse())
1900 SDNode *CCUser = *
U->user_begin();
1901 SDNode *CCRegUser =
nullptr;
1904 for (
auto *U : CCUser->
users()) {
1905 if (CCRegUser ==
nullptr)
1907 else if (CCRegUser != U)
1911 if (CCRegUser ==
nullptr)
1924 if (!IsLegalToFold(
N, U, CCRegUser, OptLevel,
false))
1934struct IPMConversion {
1935 IPMConversion(
unsigned xorValue, int64_t addValue,
unsigned bit)
1936 : XORValue(xorValue), AddValue(addValue), Bit(bit) {}
2011SDValue SystemZDAGToDAGISel::expandSelectBoolean(SDNode *Node) {
2014 if (!TrueOp || !FalseOp)
2016 if (FalseOp->getZExtValue() != 0)
2018 if (TrueOp->getSExtValue() != 1 && TrueOp->getSExtValue() != -1)
2023 if (!CCValidOp || !CCMaskOp)
2025 int CCValid = CCValidOp->getZExtValue();
2026 int CCMask = CCMaskOp->getZExtValue();
2035 CurDAG->getConstant(
IPM.XORValue,
DL, MVT::i32));
2039 CurDAG->getNode(
ISD::ADD,
DL, MVT::i32, Result,
2040 CurDAG->getSignedConstant(
IPM.AddValue,
DL, MVT::i32));
2042 EVT VT =
Node->getValueType(0);
2043 if (VT == MVT::i32 &&
IPM.Bit == 31) {
2045 Result = CurDAG->getNode(ShiftOp,
DL, MVT::i32, Result,
2046 CurDAG->getConstant(
IPM.Bit,
DL, MVT::i32));
2051 if (TrueOp->getSExtValue() == 1) {
2054 CurDAG->getConstant(
IPM.Bit,
DL, MVT::i32));
2056 CurDAG->getConstant(1,
DL, VT));
2062 CurDAG->getConstant(ShlAmt,
DL, MVT::i32));
2064 CurDAG->getConstant(SraAmt,
DL, MVT::i32));
2071bool SystemZDAGToDAGISel::shouldSelectForReassoc(SDNode *
N)
const {
2072 EVT VT =
N->getValueType(0);
2074 return N->getFlags().hasAllowReassociation() &&
2075 N->getFlags().hasNoSignedZeros() && Subtarget->hasVector() &&
2076 (VT != MVT::f32 || Subtarget->hasVectorEnhancements1()) &&
2077 !
N->isStrictFPOpcode();
2080void SystemZDAGToDAGISel::PreprocessISelDAG() {
2083 if (Subtarget->hasLoadStoreOnCond2())
2086 bool MadeChange =
false;
2089 E = CurDAG->allnodes_end();
2096 switch (
N->getOpcode()) {
2099 Res = expandSelectBoolean(
N);
2104 LLVM_DEBUG(
dbgs() <<
"SystemZ DAG preprocessing replacing:\nOld: ");
2110 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
2116 CurDAG->RemoveDeadNodes();
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
const HexagonInstrInfo * TII
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
static void changeComponent(SystemZAddressingMode &AM, bool IsBase, SDValue Value)
static IPMConversion getIPMConversion(unsigned CCValid, unsigned CCMask)
static bool selectDisp(SystemZAddressingMode::DispRange DR, int64_t Val)
static bool expandAdjDynAlloc(SystemZAddressingMode &AM, bool IsBase, SDValue Value)
static bool isFusableLoadOpStorePattern(StoreSDNode *StoreNode, SDValue StoredVal, SelectionDAG *CurDAG, LoadSDNode *&LoadNode, SDValue &InputChain)
static bool isValidDisp(SystemZAddressingMode::DispRange DR, int64_t Val)
static bool expandIndex(SystemZAddressingMode &AM, SDValue Base, SDValue Index)
static bool maskMatters(RxSBGOperands &RxSBG, uint64_t Mask)
static bool expandDisp(SystemZAddressingMode &AM, bool IsBase, SDValue Op0, uint64_t Op1)
static bool shouldUseLA(SDNode *Base, int64_t Disp, SDNode *Index)
static void insertDAGNode(SelectionDAG *DAG, SDNode *Pos, SDValue N)
static uint64_t allOnes(unsigned int Count)
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
FunctionPass class - This class is used to implement most global optimizations.
LLVM_ABI const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
This class is used to represent ISD::LOAD nodes.
const SDValue & getBasePtr() const
const SDValue & getOffset() const
TypeSize getSizeInBits() const
Returns the size of the specified MVT in bits.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags f, LLT MemTy, Align base_alignment, const AAMDNodes &AAInfo=AAMDNodes(), const MDNode *Ranges=nullptr, SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
Function & getFunction()
Return the LLVM function that this machine code represents.
const PseudoSourceValue * getPseudoValue() const
bool isAtomic() const
Returns true if this operation has an atomic ordering requirement of unordered or higher,...
@ MOLoad
The memory access reads data.
int64_t getOffset() const
For normal values, this is a byte offset added to the base address.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
bool isNonTemporal() const
EVT getMemoryVT() const
Return the type of the in-memory value.
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
bool isMachineOpcode() const
Test if this node has a post-isel opcode, directly corresponding to a MachineInstr opcode.
int getNodeId() const
Return the unique node id.
LLVM_ABI void dump() const
Dump this node, for debugging.
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.
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.
unsigned getMachineOpcode() const
This may only be called if isMachineOpcode returns true.
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()
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
EVT getValueType() const
Return the ValueType of the referenced return value.
const SDValue & getOperand(unsigned i) const
unsigned getResNo() const
get the index which selects a specific result in the SDNode
unsigned getOpcode() const
unsigned getNumOperands() const
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...
LLVM_ABI SDValue getNode(unsigned Opcode, const SDLoc &DL, EVT VT, ArrayRef< SDUse > Ops)
Gets or creates the specified node.
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
const SystemZInstrInfo * getInstrInfo() const override
const SystemZRegisterInfo * getRegisterInfo() const override
unsigned getID() const
Return the register class ID number.
Target - Wrapper for Target specific information.
LLVM Value Representation.
LLVM_ABI Align getPointerAlignment(const DataLayout &DL) const
Returns an alignment of the pointer value.
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 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.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ C
The default llvm calling convention, compatible with C.
@ BSWAP
Byte Swap and Counting operators.
@ ADD
Simple integer binary arithmetic operators.
@ ANY_EXTEND
ANY_EXTEND - Used for integer types. The high bits are undefined.
@ SIGN_EXTEND
Conversion operators.
@ SHL
Shift and rotation operations.
@ 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.
@ SIGN_EXTEND_INREG
SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to sign extend a small value in ...
@ AND
Bitwise operators - logical and, logical or, logical xor.
@ INSERT_VECTOR_ELT
INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element at IDX replaced with VAL.
@ TokenFactor
TokenFactor - This node takes multiple tokens as input and produces a single token result.
@ TRUNCATE
TRUNCATE - Completely drop the high bits.
@ BUILD_VECTOR
BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a fixed-width vector with the specified,...
bool isNormalStore(const SDNode *N)
Returns true if the specified node is a non-truncating and unindexed store.
LoadExtType
LoadExtType enum - This enum defines the three variants of LOADEXT (load with extension).
bool isNormalLoad(const SDNode *N)
Returns true if the specified node is a non-extending and unindexed load.
bool isPCREL(unsigned Opcode)
static bool isImmHF(uint64_t Val)
static bool isImmLF(uint64_t Val)
NodeAddr< NodeBase * > Node
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
FunctionAddr VTableAddr Value
FunctionPass * createSystemZISelDag(SystemZTargetMachine &TM, CodeGenOptLevel OptLevel)
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionAddr VTableAddr Count
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...
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Or
Bitwise or logical OR of integers.
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
uint64_t value() const
This is a hole in the type system and should not be abused.
EVT changeVectorElementTypeToInteger() const
Return a vector with the same number of elements as this vector, but with the element type converted ...
bool isFloatingPoint() const
Return true if this is a FP or a vector FP type.
TypeSize getSizeInBits() const
Return the size of the specified value type in bits.
uint64_t getScalarSizeInBits() const
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
unsigned getVectorNumElements() const
Given a vector type, return the number of elements it contains.
bool isInteger() const
Return true if this is an integer or a vector integer type.
static LLVM_ABI MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
const TargetRegisterClass * getPointerRegClass(unsigned Kind=0) const override
getPointerRegClass - Return the register class to use to hold pointers.
SmallVector< unsigned, 2 > OpVals
bool isVectorConstantLegal(const SystemZSubtarget &Subtarget)