26#define DEBUG_TYPE "systemz-isel"
27#define PASS_NAME "SystemZ DAG->DAG Pattern Instruction Selection"
31struct SystemZAddressingMode {
66 bool IncludesDynAlloc;
68 SystemZAddressingMode(AddrForm form, DispRange dr)
69 : Form(form), DR(dr), Disp(0), IncludesDynAlloc(
false) {}
72 bool hasIndexField() {
return Form != FormBD; }
75 bool isDynAlloc() {
return Form == FormBDXDynAlloc; }
78 errs() <<
"SystemZAddressingMode " <<
this <<
'\n';
82 Base.getNode()->dump(DAG);
86 if (hasIndexField()) {
89 Index.getNode()->dump(DAG);
94 errs() <<
" Disp " << Disp;
96 errs() <<
" + ADJDYNALLOC";
122struct RxSBGOperands {
124 : Opcode(
Op), BitSize(
N.getValueSizeInBits()),
155 bool expandAddress(SystemZAddressingMode &AM,
bool IsBase)
const;
158 bool selectAddress(
SDValue N, SystemZAddressingMode &AM)
const;
161 void getAddressOperands(
const SystemZAddressingMode &AM,
EVT VT,
163 void getAddressOperands(
const SystemZAddressingMode &AM,
EVT VT,
169 bool selectBDAddr(SystemZAddressingMode::DispRange DR,
SDValue Addr,
175 bool selectMVIAddr(SystemZAddressingMode::DispRange DR,
SDValue Addr,
181 bool selectBDXAddr(SystemZAddressingMode::AddrForm Form,
182 SystemZAddressingMode::DispRange DR,
SDValue Addr,
196 return selectBDAddr(SystemZAddressingMode::Disp12Only, Addr,
Base, Disp);
199 return selectBDAddr(SystemZAddressingMode::Disp12Pair, Addr,
Base, Disp);
202 return selectBDAddr(SystemZAddressingMode::Disp20Only, Addr,
Base, Disp);
205 return selectBDAddr(SystemZAddressingMode::Disp20Pair, Addr,
Base, Disp);
210 return selectMVIAddr(SystemZAddressingMode::Disp12Pair, Addr,
Base, Disp);
213 return selectMVIAddr(SystemZAddressingMode::Disp20Pair, Addr,
Base, Disp);
219 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
220 SystemZAddressingMode::Disp12Only,
221 Addr,
Base, Disp, Index);
225 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
226 SystemZAddressingMode::Disp12Pair,
227 Addr,
Base, Disp, Index);
231 return selectBDXAddr(SystemZAddressingMode::FormBDXDynAlloc,
232 SystemZAddressingMode::Disp12Only,
233 Addr,
Base, Disp, Index);
237 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
238 SystemZAddressingMode::Disp20Only,
239 Addr,
Base, Disp, Index);
243 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
244 SystemZAddressingMode::Disp20Only128,
245 Addr,
Base, Disp, Index);
249 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
250 SystemZAddressingMode::Disp20Pair,
251 Addr,
Base, Disp, Index);
255 return selectBDXAddr(SystemZAddressingMode::FormBDXLA,
256 SystemZAddressingMode::Disp12Pair,
257 Addr,
Base, Disp, Index);
261 return selectBDXAddr(SystemZAddressingMode::FormBDXLA,
262 SystemZAddressingMode::Disp20Pair,
263 Addr,
Base, Disp, Index);
289 bool refineRxSBGMask(RxSBGOperands &RxSBG,
uint64_t Mask)
const;
293 bool expandRxSBG(RxSBGOperands &RxSBG)
const;
307 bool tryRxSBG(
SDNode *
N,
unsigned Opcode);
325 bool tryGather(
SDNode *
N,
unsigned Opcode);
333 bool tryFoldLoadStoreIntoMemOperand(
SDNode *
Node);
348 bool storeLoadCanUseMVC(
SDNode *
N)
const;
353 bool storeLoadCanUseBlockBinary(
SDNode *
N,
unsigned I)
const;
357 bool storeLoadIsAligned(
SDNode *
N)
const;
368 bool shouldSelectForReassoc(
SDNode *
N)
const;
371 SystemZDAGToDAGISel() =
delete;
378 if (
F.getParent()->getStackProtectorGuard() !=
"global") {
379 if (
F.getParent()->hasStackProtectorGuardRecord())
381 "mstack-protector-guard=global");
389 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
391 std::vector<SDValue> &OutOps)
override;
393 void PreprocessISelDAG()
override;
396 #include "SystemZGenDAGISel.inc"
405 ID, std::make_unique<SystemZDAGToDAGISel>(TM, OptLevel)) {}
409char SystemZDAGToDAGISelLegacy::ID = 0;
416 std::make_unique<SystemZDAGToDAGISel>(TM, OptLevel)) {}
420 return new SystemZDAGToDAGISelLegacy(TM, OptLevel);
426static bool selectDisp(SystemZAddressingMode::DispRange DR, int64_t Val) {
428 case SystemZAddressingMode::Disp12Only:
431 case SystemZAddressingMode::Disp12Pair:
432 case SystemZAddressingMode::Disp20Only:
433 case SystemZAddressingMode::Disp20Pair:
436 case SystemZAddressingMode::Disp20Only128:
457 if (AM.isDynAlloc() && !AM.IncludesDynAlloc) {
459 AM.IncludesDynAlloc =
true;
469 if (AM.hasIndexField() && !AM.Index.
getNode()) {
479static bool expandDisp(SystemZAddressingMode &AM,
bool IsBase,
482 int64_t TestDisp = AM.Disp + Op1;
494bool SystemZDAGToDAGISel::expandAddress(SystemZAddressingMode &AM,
497 unsigned Opcode =
N.getOpcode();
499 if (Opcode ==
ISD::TRUNCATE &&
N.getOperand(0).getValueSizeInBits() <= 64) {
501 Opcode =
N.getOpcode();
503 if (Opcode ==
ISD::ADD || CurDAG->isBaseWithConstantOffset(
N)) {
510 if (Op0Code == SystemZISD::ADJDYNALLOC)
512 if (Op1Code == SystemZISD::ADJDYNALLOC)
525 if (Opcode == SystemZISD::PCREL_OFFSET) {
538static bool isValidDisp(SystemZAddressingMode::DispRange DR, int64_t Val) {
541 case SystemZAddressingMode::Disp12Only:
542 case SystemZAddressingMode::Disp20Only:
543 case SystemZAddressingMode::Disp20Only128:
546 case SystemZAddressingMode::Disp12Pair:
550 case SystemZAddressingMode::Disp20Pair:
590 if (Index->hasOneUse())
595 unsigned IndexOpcode = Index->getOpcode();
603 if (
Base->hasOneUse())
610bool SystemZDAGToDAGISel::selectAddress(
SDValue Addr,
611 SystemZAddressingMode &AM)
const {
622 else if (Addr.
getOpcode() == SystemZISD::ADJDYNALLOC &&
627 while (expandAddress(AM,
true) ||
628 (AM.Index.
getNode() && expandAddress(AM,
false)))
632 if (AM.Form == SystemZAddressingMode::FormBDXLA &&
641 if (AM.isDynAlloc() && !AM.IncludesDynAlloc)
654 if (
N->getNodeId() == -1 ||
667void SystemZDAGToDAGISel::getAddressOperands(
const SystemZAddressingMode &AM,
673 Base = CurDAG->getRegister(0, VT);
677 Base = CurDAG->getTargetFrameIndex(FrameIndex, VT);
678 }
else if (
Base.getValueType() != VT) {
680 assert(VT == MVT::i32 &&
Base.getValueType() == MVT::i64 &&
681 "Unexpected truncation");
689 Disp = CurDAG->getSignedTargetConstant(AM.Disp, SDLoc(
Base), VT);
692void SystemZDAGToDAGISel::getAddressOperands(
const SystemZAddressingMode &AM,
696 getAddressOperands(AM, VT,
Base, Disp);
699 if (!
Index.getNode())
701 Index = CurDAG->getRegister(0, VT);
704bool SystemZDAGToDAGISel::selectBDAddr(SystemZAddressingMode::DispRange DR,
707 SystemZAddressingMode AM(SystemZAddressingMode::FormBD, DR);
709 if (!selectAddress(Addr, AM))
716bool SystemZDAGToDAGISel::selectMVIAddr(SystemZAddressingMode::DispRange DR,
719 SystemZAddressingMode AM(SystemZAddressingMode::FormBDXNormal, DR);
720 if (!selectAddress(Addr, AM) || AM.Index.
getNode())
727bool SystemZDAGToDAGISel::selectBDXAddr(SystemZAddressingMode::AddrForm Form,
728 SystemZAddressingMode::DispRange DR,
731 SystemZAddressingMode AM(Form, DR);
732 if (!selectAddress(Addr, AM))
739bool SystemZDAGToDAGISel::selectBDVAddr12Only(
SDValue Addr,
SDValue Elem,
744 if (selectBDXAddr12Only(Addr, Regs[0], Disp, Regs[1]) &&
746 for (
unsigned int I = 0;
I < 2; ++
I) {
754 Index.getOperand(1) == Elem) {
765 return selectBDAddr(SystemZAddressingMode::Disp12Pair,
A,
B,
D, 1);
769 return selectBDAddr(SystemZAddressingMode::Disp12Pair,
A,
B,
D, 3);
773 return selectBDAddr(SystemZAddressingMode::Disp12Pair,
A,
B,
D, 7);
778 return selectBDAddr(SystemZAddressingMode::Disp20Pair,
A,
B,
D, 1);
782 return selectBDAddr(SystemZAddressingMode::Disp20Pair,
A,
B,
D, 3);
786 return selectBDAddr(SystemZAddressingMode::Disp20Pair,
A,
B,
D, 7);
789bool SystemZDAGToDAGISel::detectOrAndInsertion(
SDValue &
Op,
802 uint64_t AndMask = MaskNode->getZExtValue();
803 if (InsertMask & AndMask)
809 if (Used != (AndMask | InsertMask)) {
810 KnownBits
Known = CurDAG->computeKnownBits(
Op.getOperand(0));
811 if (Used != (AndMask | InsertMask |
Known.Zero.getZExtValue()))
815 Op =
Op.getOperand(0);
819bool SystemZDAGToDAGISel::refineRxSBGMask(RxSBGOperands &RxSBG,
821 const SystemZInstrInfo *
TII = getInstrInfo();
822 if (RxSBG.Rotate != 0)
823 Mask = (
Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate));
825 if (
TII->isRxSBGMask(Mask, RxSBG.BitSize, RxSBG.Start, RxSBG.End)) {
835 if (RxSBG.Rotate != 0)
836 Mask = ((Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate)));
837 return (Mask & RxSBG.Mask) != 0;
840bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG)
const {
842 unsigned Opcode =
N.getOpcode();
845 if (RxSBG.Opcode == SystemZ::RNSBG)
847 if (
N.getOperand(0).getValueSizeInBits() > 64)
849 uint64_t BitSize =
N.getValueSizeInBits();
851 if (!refineRxSBGMask(RxSBG, Mask))
857 if (RxSBG.Opcode == SystemZ::RNSBG)
866 if (!refineRxSBGMask(RxSBG, Mask)) {
870 KnownBits
Known = CurDAG->computeKnownBits(Input);
872 if (!refineRxSBGMask(RxSBG, Mask))
880 if (RxSBG.Opcode != SystemZ::RNSBG)
889 if (!refineRxSBGMask(RxSBG, Mask)) {
893 KnownBits
Known = CurDAG->computeKnownBits(Input);
894 Mask &= ~Known.One.getZExtValue();
895 if (!refineRxSBGMask(RxSBG, Mask))
904 if (RxSBG.BitSize != 64 ||
N.getValueType() != MVT::i64)
910 RxSBG.Rotate = (RxSBG.Rotate + CountNode->getZExtValue()) & 63;
921 if (RxSBG.Opcode != SystemZ::RNSBG) {
923 unsigned InnerBitSize =
N.getOperand(0).getValueSizeInBits();
924 if (!refineRxSBGMask(RxSBG,
allOnes(InnerBitSize)))
935 unsigned BitSize =
N.getValueSizeInBits();
936 unsigned InnerBitSize =
N.getOperand(0).getValueSizeInBits();
940 if (RxSBG.Mask == 1 && RxSBG.Rotate == 1)
941 RxSBG.Rotate += (BitSize - InnerBitSize);
956 unsigned BitSize =
N.getValueSizeInBits();
960 if (RxSBG.Opcode == SystemZ::RNSBG) {
971 RxSBG.Rotate = (RxSBG.Rotate +
Count) & 63;
983 unsigned BitSize =
N.getValueSizeInBits();
987 if (RxSBG.Opcode == SystemZ::RNSBG || Opcode ==
ISD::SRA) {
999 RxSBG.Rotate = (RxSBG.Rotate -
Count) & 63;
1008SDValue SystemZDAGToDAGISel::getUNDEF(
const SDLoc &
DL, EVT VT)
const {
1009 SDNode *
N = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
1013SDValue SystemZDAGToDAGISel::convertTo(
const SDLoc &
DL, EVT VT,
1015 if (
N.getValueType() == MVT::i32 && VT == MVT::i64)
1016 return CurDAG->getTargetInsertSubreg(SystemZ::subreg_l32,
1017 DL, VT, getUNDEF(
DL, MVT::i64),
N);
1018 if (
N.getValueType() == MVT::i64 && VT == MVT::i32)
1019 return CurDAG->getTargetExtractSubreg(SystemZ::subreg_l32,
DL, VT,
N);
1020 assert(
N.getValueType() == VT &&
"Unexpected value types");
1024bool SystemZDAGToDAGISel::tryRISBGZero(SDNode *
N) {
1026 EVT VT =
N->getValueType(0);
1029 RxSBGOperands RISBG(SystemZ::RISBG,
SDValue(
N, 0));
1031 while (expandRxSBG(RISBG))
1048 if (
Subtarget->hasMiscellaneousExtensions4() &&
1049 RISBG.Rotate >= 1 && RISBG.Rotate <= 4 &&
1050 RISBG.Mask == (((
uint64_t)1 << 32) - 1) << RISBG.Rotate &&
1051 RISBG.Input.getOpcode() ==
ISD::ADD)
1059 if (RISBG.Rotate == 0) {
1060 bool PreferAnd =
false;
1066 else if (RISBG.Mask == 0xff ||
1067 RISBG.Mask == 0xffff ||
1068 RISBG.Mask == 0x7fffffff ||
1075 if (
Load->getMemoryVT() == MVT::i32 &&
1078 RISBG.Mask == 0xffffff00 &&
1079 Subtarget->hasLoadAndZeroRightmostByte())
1089 if (
N !=
New.getNode()) {
1092 ReplaceNode(
N,
New.getNode());
1096 if (!
N->isMachineOpcode())
1102 unsigned Opcode = SystemZ::RISBG;
1104 if (
Subtarget->hasMiscellaneousExtensions())
1105 Opcode = SystemZ::RISBGN;
1106 EVT OpcodeVT = MVT::i64;
1107 if (VT == MVT::i32 &&
Subtarget->hasHighWord() &&
1112 RISBG.Start >= 32 && RISBG.End >= RISBG.Start &&
1113 ((RISBG.Start + RISBG.Rotate) & 63) >= 32 &&
1114 ((RISBG.End + RISBG.Rotate) & 63) >=
1115 ((RISBG.Start + RISBG.Rotate) & 63)) {
1116 Opcode = SystemZ::RISBMux;
1117 OpcodeVT = MVT::i32;
1122 getUNDEF(
DL, OpcodeVT),
1124 CurDAG->getTargetConstant(RISBG.Start,
DL, MVT::i32),
1125 CurDAG->getTargetConstant(RISBG.End | 128,
DL, MVT::i32),
1126 CurDAG->getTargetConstant(RISBG.Rotate,
DL, MVT::i32)
1129 DL, VT,
SDValue(CurDAG->getMachineNode(Opcode,
DL, OpcodeVT,
Ops), 0));
1130 ReplaceNode(
N,
New.getNode());
1134bool SystemZDAGToDAGISel::tryRxSBG(SDNode *
N,
unsigned Opcode) {
1136 EVT VT =
N->getValueType(0);
1141 RxSBGOperands RxSBG[] = {
1142 RxSBGOperands(Opcode,
N->getOperand(0)),
1143 RxSBGOperands(Opcode,
N->getOperand(1))
1145 unsigned Count[] = { 0, 0 };
1146 for (
unsigned I = 0;
I < 2; ++
I)
1147 while (RxSBG[
I].
Input->hasOneUse() && expandRxSBG(RxSBG[
I]))
1167 if (Opcode == SystemZ::ROSBG && (RxSBG[
I].Mask & 0xff) == 0)
1169 if (
Load->getMemoryVT() == MVT::i8)
1174 if (Opcode == SystemZ::ROSBG && detectOrAndInsertion(Op0, RxSBG[
I].Mask)) {
1175 Opcode = SystemZ::RISBG;
1177 if (
Subtarget->hasMiscellaneousExtensions())
1178 Opcode = SystemZ::RISBGN;
1184 CurDAG->getTargetConstant(RxSBG[
I].Start,
DL, MVT::i32),
1185 CurDAG->getTargetConstant(RxSBG[
I].
End,
DL, MVT::i32),
1186 CurDAG->getTargetConstant(RxSBG[
I].Rotate,
DL, MVT::i32)
1189 DL, VT,
SDValue(CurDAG->getMachineNode(Opcode,
DL, MVT::i64,
Ops), 0));
1190 ReplaceNode(
N,
New.getNode());
1194void SystemZDAGToDAGISel::splitLargeImmediate(
unsigned Opcode, SDNode *Node,
1197 EVT VT =
Node->getValueType(0);
1216 HandleSDNode Handle(
Upper);
1217 SelectCode(
Upper.getNode());
1218 Upper = Handle.getValue();
1224 ReplaceNode(Node,
Or.getNode());
1226 SelectCode(
Or.getNode());
1229void SystemZDAGToDAGISel::loadVectorConstant(
1230 const SystemZVectorConstantInfo &VCI, SDNode *Node) {
1232 VCI.
Opcode == SystemZISD::REPLICATE ||
1233 VCI.
Opcode == SystemZISD::ROTATE_MASK) &&
1236 EVT VT =
Node->getValueType(0);
1239 for (
unsigned OpVal : VCI.
OpVals)
1240 Ops.push_back(CurDAG->getTargetConstant(OpVal,
DL, MVT::i32));
1244 ReplaceNode(Node,
Op.getNode());
1247 ReplaceNode(Node, BitCast.
getNode());
1248 SelectCode(BitCast.
getNode());
1250 unsigned SubRegIdx = (VT.
getSizeInBits() == 16 ? SystemZ::subreg_h16
1252 : SystemZ::subreg_h64);
1254 Node, CurDAG->getTargetExtractSubreg(SubRegIdx,
DL, VT,
Op).getNode());
1256 SelectCode(
Op.getNode());
1259SDNode *SystemZDAGToDAGISel::loadPoolVectorConstant(APInt Val, EVT VT, SDLoc
DL) {
1263 SDValue CP = CurDAG->getTargetConstantPool(
1264 ConstantInt::get(Type::getInt128Ty(*CurDAG->getContext()), Val),
1269 SDValue(CurDAG->getMachineNode(SystemZ::LARL,
DL, PtrVT, CP), 0),
1270 CurDAG->getTargetConstant(0,
DL, PtrVT),
1271 CurDAG->getRegister(0, PtrVT),
1272 CurDAG->getEntryNode()
1274 ResNode = CurDAG->getMachineNode(SystemZ::VL,
DL, VT, MVT::Other,
Ops);
1280 MachineMemOperand *MemOp =
1288bool SystemZDAGToDAGISel::tryGather(SDNode *
N,
unsigned Opcode) {
1294 unsigned Elem = ElemN->getZExtValue();
1295 EVT VT =
N->getValueType(0);
1300 if (!
Load || !
Load->hasNUsesOfValue(1, 0))
1302 if (
Load->getMemoryVT().getSizeInBits() !=
1303 Load->getValueType(0).getSizeInBits())
1307 if (!selectBDVAddr12Only(
Load->getBasePtr(), ElemV,
Base, Disp, Index) ||
1314 CurDAG->getTargetConstant(Elem,
DL, MVT::i32),
Load->getChain()
1316 SDNode *Res = CurDAG->getMachineNode(Opcode,
DL, VT, MVT::Other,
Ops);
1318 ReplaceNode(
N, Res);
1322bool SystemZDAGToDAGISel::tryScatter(StoreSDNode *
Store,
unsigned Opcode) {
1326 if (
Store->getMemoryVT().getSizeInBits() !=
Value.getValueSizeInBits())
1336 unsigned Elem = ElemN->getZExtValue();
1341 if (!selectBDVAddr12Only(
Store->getBasePtr(), ElemV,
Base, Disp, Index) ||
1347 Vec,
Base, Disp,
Index, CurDAG->getTargetConstant(Elem,
DL, MVT::i32),
1350 ReplaceNode(
Store, CurDAG->getMachineNode(Opcode,
DL, MVT::Other,
Ops));
1381 if (!
Load.hasOneUse())
1393 bool ChainCheck =
false;
1394 if (Chain ==
Load.getValue(1)) {
1401 const unsigned int Max = 1024;
1404 if (
Op ==
Load.getValue(1)) {
1417 if (
Op.getNode() != LoadNode)
1428 MVT::Other, ChainOps);
1445bool SystemZDAGToDAGISel::tryFoldLoadStoreIntoMemOperand(SDNode *Node) {
1449 SDLoc
DL(StoreNode);
1455 unsigned NewOpc = 0;
1456 bool NegateOperand =
false;
1460 case SystemZISD::SSUBO:
1461 NegateOperand =
true;
1463 case SystemZISD::SADDO:
1464 if (MemVT == MVT::i32)
1465 NewOpc = SystemZ::ASI;
1466 else if (MemVT == MVT::i64)
1467 NewOpc = SystemZ::AGSI;
1471 case SystemZISD::USUBO:
1472 NegateOperand =
true;
1474 case SystemZISD::UADDO:
1475 if (MemVT == MVT::i32)
1476 NewOpc = SystemZ::ALSI;
1477 else if (MemVT == MVT::i64)
1478 NewOpc = SystemZ::ALGSI;
1484 LoadSDNode *LoadNode =
nullptr;
1494 auto OperandV = OperandC->getAPIntValue();
1496 OperandV = -OperandV;
1497 if (OperandV.getSignificantBits() > 8)
1499 Operand = CurDAG->getTargetConstant(OperandV,
DL, MemVT);
1507 CurDAG->getMachineNode(NewOpc,
DL, MVT::i32, MVT::Other,
Ops);
1508 CurDAG->setNodeMemRefs(
1513 CurDAG->RemoveDeadNode(Node);
1517bool SystemZDAGToDAGISel::canUseBlockOperation(StoreSDNode *
Store,
1518 LoadSDNode *
Load)
const {
1520 if (
Load->getMemoryVT() !=
Store->getMemoryVT())
1524 if (
Load->isVolatile() ||
Store->isVolatile())
1528 if (
Load->isInvariant() &&
Load->isDereferenceable())
1532 const Value *
V1 =
Load->getMemOperand()->getValue();
1533 const Value *V2 =
Store->getMemOperand()->getValue();
1539 int64_t End1 =
Load->getSrcValueOffset() +
Size;
1540 int64_t End2 =
Store->getSrcValueOffset() +
Size;
1541 if (
V1 == V2 && End1 == End2)
1544 return BatchAA->isNoAlias(MemoryLocation(
V1, End1,
Load->getAAInfo()),
1545 MemoryLocation(V2, End2,
Store->getAAInfo()));
1548bool SystemZDAGToDAGISel::storeLoadCanUseMVC(SDNode *
N)
const {
1564 return canUseBlockOperation(
Store,
Load);
1567bool SystemZDAGToDAGISel::storeLoadCanUseBlockBinary(SDNode *
N,
1572 return !LoadA->isVolatile() && LoadA->getMemoryVT() == LoadB->getMemoryVT() &&
1573 canUseBlockOperation(StoreA, LoadB);
1576bool SystemZDAGToDAGISel::storeLoadIsAligned(SDNode *
N)
const {
1580 TypeSize StoreSize = MemAccess->getMemoryVT().getStoreSize();
1582 MachineMemOperand *MMO = MemAccess->getMemOperand();
1583 assert(MMO &&
"Expected a memory operand.");
1587 if (MemAccess->getAlign().value() < StoreSize ||
1588 (LdSt && !LdSt->getOffset().isUndef()))
1597 if ((PSV->isGOT() || PSV->isConstantPool()))
1602 if (GlobalAddressSDNode *GA =
1605 if (GA->getOffset() % StoreSize != 0)
1609 const GlobalValue *GV = GA->getGlobal();
1621 ETy =
L->getExtensionType();
1623 ETy =
AL->getExtensionType();
1629void SystemZDAGToDAGISel::Select(SDNode *Node) {
1631 if (
Node->isMachineOpcode()) {
1633 Node->setNodeId(-1);
1637 unsigned Opcode =
Node->getOpcode();
1641 if (tryRxSBG(Node, SystemZ::ROSBG))
1647 if (tryRxSBG(Node, SystemZ::RXSBG))
1654 if (
Node->getValueType(0) == MVT::i64 &&
1657 uint64_t Val = Op1->getZExtValue();
1660 if (
Subtarget->hasMiscellaneousExtensions3()) {
1661 unsigned ChildOpcode =
Node->getOperand(0).getOpcode();
1670 auto Op0 =
Node->getOperand(0);
1672 if (Op0Op1->getZExtValue() == (
uint64_t)-1)
1677 if (Opcode ==
ISD::XOR && Op1->isAllOnes())
1680 splitLargeImmediate(Opcode, Node,
Node->getOperand(0),
1681 Val - uint32_t(Val), uint32_t(Val));
1689 if (tryRxSBG(Node, SystemZ::RNSBG))
1693 if (
Node->getValueType(0) == MVT::i64 &&
1699 EVT VecVT =
Input->getOperand(0)->getValueType(0);
1712 if (tryRISBGZero(Node))
1717 if (
Node->getValueType(0) == MVT::i128) {
1722 uint64_t Bytes[2] = { 0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL };
1723 SDNode *
Mask = loadPoolVectorConstant(APInt(128, Bytes), MVT::v16i8,
DL);
1726 MVT::v16i8,
Ops), 0);
1729 SDNode *ResNode = Res.
getNode();
1730 ReplaceNode(Node, ResNode);
1731 SelectCode(Src.getNode());
1732 SelectCode(ResNode);
1740 if (
Node->getValueType(0) == MVT::i64) {
1743 splitLargeImmediate(
ISD::OR, Node,
SDValue(), Val - uint32_t(Val),
1748 if (
Node->getValueType(0) == MVT::i128) {
1749 const APInt &Val =
Node->getAsAPIntVal();
1750 SystemZVectorConstantInfo VCI(Val);
1752 loadVectorConstant(VCI, Node);
1756 SDNode *ResNode = loadPoolVectorConstant(Val, MVT::i128, SDLoc(Node));
1757 ReplaceNode(Node, ResNode);
1762 case SystemZISD::SELECT_CCMASK: {
1769 Node->getValueType(0).isInteger() &&
1770 Node->getValueType(0).getSizeInBits() <= 64 &&
1780 CCMask = CurDAG->getTargetConstant(ConstCCValid ^ ConstCCMask,
1783 SDNode *UpdatedNode =
1784 CurDAG->UpdateNodeOperands(Node, Op1, Op0, CCValid, CCMask, Op4);
1785 if (UpdatedNode != Node) {
1787 ReplaceNode(Node, UpdatedNode);
1795 EVT VT =
Node->getValueType(0);
1797 if (ElemBitSize == 32) {
1798 if (tryGather(Node, SystemZ::VGEF))
1800 }
else if (ElemBitSize == 64) {
1801 if (tryGather(Node, SystemZ::VGEG))
1811 SystemZVectorConstantInfo VCI(BVN);
1813 loadVectorConstant(VCI, Node);
1821 if (
Imm.isZero() ||
Imm.isNegZero())
1823 SystemZVectorConstantInfo VCI(
Imm);
1826 loadVectorConstant(VCI, Node);
1831 if (tryFoldLoadStoreIntoMemOperand(Node))
1834 unsigned ElemBitSize =
Store->getValue().getValueSizeInBits();
1835 if (ElemBitSize == 32) {
1836 if (tryScatter(
Store, SystemZ::VSCEF))
1838 }
else if (ElemBitSize == 64) {
1839 if (tryScatter(
Store, SystemZ::VSCEG))
1851 AtomOp->getChain(), SDLoc(AtomOp), AtomOp->getVal(),
1852 AtomOp->getBasePtr(), AtomOp->getMemoryVT(), AtomOp->getMemOperand()));
1853 assert(St->getMemOperand()->isAtomic() &&
"Broken MMO.");
1857 if (AtomOp->getSuccessOrdering() == AtomicOrdering::SequentiallyConsistent)
1858 Chain = CurDAG->getMachineNode(SystemZ::Serialize, SDLoc(AtomOp),
1859 MVT::Other,
SDValue(Chain, 0));
1860 ReplaceNode(Node, Chain);
1869bool SystemZDAGToDAGISel::SelectInlineAsmMemoryOperand(
1871 std::vector<SDValue> &OutOps) {
1872 SystemZAddressingMode::AddrForm
Form;
1873 SystemZAddressingMode::DispRange DispRange;
1876 switch(ConstraintID) {
1879 case InlineAsm::ConstraintCode::i:
1880 case InlineAsm::ConstraintCode::Q:
1881 case InlineAsm::ConstraintCode::ZQ:
1883 Form = SystemZAddressingMode::FormBD;
1884 DispRange = SystemZAddressingMode::Disp12Only;
1886 case InlineAsm::ConstraintCode::R:
1887 case InlineAsm::ConstraintCode::ZR:
1889 Form = SystemZAddressingMode::FormBDXNormal;
1890 DispRange = SystemZAddressingMode::Disp12Only;
1892 case InlineAsm::ConstraintCode::S:
1893 case InlineAsm::ConstraintCode::ZS:
1895 Form = SystemZAddressingMode::FormBD;
1896 DispRange = SystemZAddressingMode::Disp20Only;
1898 case InlineAsm::ConstraintCode::T:
1899 case InlineAsm::ConstraintCode::m:
1900 case InlineAsm::ConstraintCode::o:
1901 case InlineAsm::ConstraintCode::p:
1902 case InlineAsm::ConstraintCode::ZT:
1907 Form = SystemZAddressingMode::FormBDXNormal;
1908 DispRange = SystemZAddressingMode::Disp20Only;
1912 if (selectBDXAddr(Form, DispRange,
Op,
Base, Disp, Index)) {
1917 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(),
DL, MVT::i32);
1924 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
1932 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
1937 OutOps.push_back(
Base);
1938 OutOps.push_back(Disp);
1939 OutOps.push_back(Index);
1949SystemZDAGToDAGISel::IsProfitableToFold(
SDValue N, SDNode *U,
1950 SDNode *Root)
const {
1953 if (
N.getOpcode() ==
ISD::LOAD &&
U->getOpcode() == SystemZISD::ICMP) {
1954 if (!
N.hasOneUse() || !
U->hasOneUse())
1961 SDNode *CCUser = *
U->user_begin();
1962 SDNode *CCRegUser =
nullptr;
1965 for (
auto *U : CCUser->
users()) {
1966 if (CCRegUser ==
nullptr)
1968 else if (CCRegUser != U)
1972 if (CCRegUser ==
nullptr)
1985 if (!IsLegalToFold(
N, U, CCRegUser, OptLevel,
false))
1995struct IPMConversion {
1996 IPMConversion(
unsigned xorValue, int64_t addValue,
unsigned bit)
1997 : XORValue(xorValue), AddValue(addValue), Bit(bit) {}
2072SDValue SystemZDAGToDAGISel::expandSelectBoolean(SDNode *Node) {
2075 if (!TrueOp || !FalseOp)
2077 if (FalseOp->getZExtValue() != 0)
2079 if (TrueOp->getSExtValue() != 1 && TrueOp->getSExtValue() != -1)
2084 if (!CCValidOp || !CCMaskOp)
2086 int CCValid = CCValidOp->getZExtValue();
2087 int CCMask = CCMaskOp->getZExtValue();
2092 SDValue Result = CurDAG->getNode(SystemZISD::IPM,
DL, MVT::i32, CCReg);
2096 CurDAG->getConstant(IPM.XORValue,
DL, MVT::i32));
2100 CurDAG->getNode(
ISD::ADD,
DL, MVT::i32, Result,
2101 CurDAG->getSignedConstant(IPM.AddValue,
DL, MVT::i32));
2103 EVT VT =
Node->getValueType(0);
2104 if (VT == MVT::i32 && IPM.Bit == 31) {
2106 Result = CurDAG->getNode(ShiftOp,
DL, MVT::i32, Result,
2107 CurDAG->getConstant(IPM.Bit,
DL, MVT::i32));
2112 if (TrueOp->getSExtValue() == 1) {
2115 CurDAG->getConstant(IPM.Bit,
DL, MVT::i32));
2117 CurDAG->getConstant(1,
DL, VT));
2123 CurDAG->getConstant(ShlAmt,
DL, MVT::i32));
2125 CurDAG->getConstant(SraAmt,
DL, MVT::i32));
2132bool SystemZDAGToDAGISel::shouldSelectForReassoc(SDNode *
N)
const {
2133 EVT VT =
N->getValueType(0);
2135 return N->getFlags().hasAllowReassociation() &&
2136 N->getFlags().hasNoSignedZeros() &&
Subtarget->hasVector() &&
2137 (VT != MVT::f32 ||
Subtarget->hasVectorEnhancements1()) &&
2138 !
N->isStrictFPOpcode();
2141void SystemZDAGToDAGISel::PreprocessISelDAG() {
2147 bool MadeChange =
false;
2150 E = CurDAG->allnodes_end();
2157 switch (
N->getOpcode()) {
2159 case SystemZISD::SELECT_CCMASK:
2160 Res = expandSelectBoolean(
N);
2165 LLVM_DEBUG(
dbgs() <<
"SystemZ DAG preprocessing replacing:\nOld: ");
2171 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
2177 CurDAG->RemoveDeadNodes();
const AArch64Subtarget & Subtarget
const TargetLowering & TLI
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
bpf unwind BPF Unwind Lower
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< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
const HexagonInstrInfo * TII
Module.h This file contains the declarations for the Module class.
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)
const TargetRegisterClass * getInlineAsmMemoryOperandRegClass(InlineAsm::ConstraintCode C) const override
const AArch64InstrInfo * getInstrInfo() const override
Class for arbitrary precision integers.
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
unsigned getID() const
getID() - Return the register class ID number.
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.
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineMemOperand * getMachineMemOperand(MachinePointerInfo PtrInfo, MachineMemOperand::Flags F, LLT MemTy, Align BaseAlignment, const MMOMetadata &Metadata=MMOMetadata(), SyncScope::ID SSID=SyncScope::System, AtomicOrdering Ordering=AtomicOrdering::NotAtomic, AtomicOrdering FailureOrdering=AtomicOrdering::NotAtomic)
getMachineMemOperand - Allocate a new MachineMemOperand.
const PseudoSourceValue * getPseudoValue() const
@ 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 the unique 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.
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
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...
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
SystemZISelDAGToDAGPass(SystemZTargetMachine &TM, CodeGenOptLevel OptLevel)
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...
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.
@ BSWAP
Byte Swap and Counting operators.
@ ATOMIC_STORE
OUTCHAIN = ATOMIC_STORE(INCHAIN, val, ptr) This corresponds to "store atomic" instruction.
@ 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.
@ BITCAST
BITCAST - This operator converts between integer, vector and FP values, as if the value was stored to...
@ 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
std::pair< Instruction *, SmallVector< Value * > > convertTo(Instruction *I, const InstructionsState &S)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
FunctionPass * createSystemZISelDagLegacyPass(SystemZTargetMachine &TM, CodeGenOptLevel OptLevel)
constexpr bool isInt(int64_t x)
Checks if an integer fits into the given bit width.
@ Known
Known to have no common set bits.
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).
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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)
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.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
DWARFExpression::Operation Op
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
@ End
Run the machine verifier once, at the end of the pipeline.
MCRegisterClass TargetRegisterClass
Implement std::hash so that hash_code can be used in STL containers.
constexpr 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.
SmallVector< unsigned, 2 > OpVals
bool isVectorConstantLegal(const SystemZSubtarget &Subtarget)