24#define DEBUG_TYPE "systemz-isel"
25#define PASS_NAME "SystemZ DAG->DAG Pattern Instruction Selection"
29struct SystemZAddressingMode {
64 bool IncludesDynAlloc;
66 SystemZAddressingMode(AddrForm form, DispRange dr)
67 : Form(form), DR(dr), Disp(0), IncludesDynAlloc(
false) {}
70 bool hasIndexField() {
return Form != FormBD; }
73 bool isDynAlloc() {
return Form == FormBDXDynAlloc; }
76 errs() <<
"SystemZAddressingMode " <<
this <<
'\n';
80 Base.getNode()->dump(DAG);
84 if (hasIndexField()) {
87 Index.getNode()->dump(DAG);
92 errs() <<
" Disp " << Disp;
94 errs() <<
" + ADJDYNALLOC";
120struct RxSBGOperands {
122 : Opcode(
Op), BitSize(
N.getValueSizeInBits()),
123 Mask(
allOnes(BitSize)),
Input(
N), Start(64 - BitSize), End(63),
140 return CurDAG->getTargetConstant(Imm,
SDLoc(
Node),
Node->getValueType(0));
153 bool expandAddress(SystemZAddressingMode &AM,
bool IsBase)
const;
156 bool selectAddress(
SDValue N, SystemZAddressingMode &AM)
const;
159 void getAddressOperands(
const SystemZAddressingMode &AM,
EVT VT,
161 void getAddressOperands(
const SystemZAddressingMode &AM,
EVT VT,
167 bool selectBDAddr(SystemZAddressingMode::DispRange DR,
SDValue Addr,
173 bool selectMVIAddr(SystemZAddressingMode::DispRange DR,
SDValue Addr,
179 bool selectBDXAddr(SystemZAddressingMode::AddrForm Form,
180 SystemZAddressingMode::DispRange DR,
SDValue Addr,
194 return selectBDAddr(SystemZAddressingMode::Disp12Only, Addr,
Base, Disp);
197 return selectBDAddr(SystemZAddressingMode::Disp12Pair, Addr,
Base, Disp);
200 return selectBDAddr(SystemZAddressingMode::Disp20Only, Addr,
Base, Disp);
203 return selectBDAddr(SystemZAddressingMode::Disp20Pair, Addr,
Base, Disp);
208 return selectMVIAddr(SystemZAddressingMode::Disp12Pair, Addr,
Base, Disp);
211 return selectMVIAddr(SystemZAddressingMode::Disp20Pair, Addr,
Base, Disp);
217 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
218 SystemZAddressingMode::Disp12Only,
219 Addr,
Base, Disp, Index);
223 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
224 SystemZAddressingMode::Disp12Pair,
225 Addr,
Base, Disp, Index);
229 return selectBDXAddr(SystemZAddressingMode::FormBDXDynAlloc,
230 SystemZAddressingMode::Disp12Only,
231 Addr,
Base, Disp, Index);
235 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
236 SystemZAddressingMode::Disp20Only,
237 Addr,
Base, Disp, Index);
241 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
242 SystemZAddressingMode::Disp20Only128,
243 Addr,
Base, Disp, Index);
247 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
248 SystemZAddressingMode::Disp20Pair,
249 Addr,
Base, Disp, Index);
253 return selectBDXAddr(SystemZAddressingMode::FormBDXLA,
254 SystemZAddressingMode::Disp12Pair,
255 Addr,
Base, Disp, Index);
259 return selectBDXAddr(SystemZAddressingMode::FormBDXLA,
260 SystemZAddressingMode::Disp20Pair,
261 Addr,
Base, Disp, Index);
278 bool refineRxSBGMask(RxSBGOperands &RxSBG,
uint64_t Mask)
const;
282 bool expandRxSBG(RxSBGOperands &RxSBG)
const;
296 bool tryRxSBG(
SDNode *
N,
unsigned Opcode);
314 bool tryGather(
SDNode *
N,
unsigned Opcode);
317 bool tryScatter(
StoreSDNode *Store,
unsigned Opcode);
322 bool tryFoldLoadStoreIntoMemOperand(
SDNode *
Node);
337 bool storeLoadCanUseMVC(
SDNode *
N)
const;
342 bool storeLoadCanUseBlockBinary(
SDNode *
N,
unsigned I)
const;
346 bool storeLoadIsAligned(
SDNode *
N)
const;
357 bool shouldSelectForReassoc(
SDNode *
N)
const;
360 SystemZDAGToDAGISel() =
delete;
367 if (
F.getFnAttribute(
"fentry-call").getValueAsString() !=
"true") {
368 if (
F.hasFnAttribute(
"mnop-mcount"))
370 if (
F.hasFnAttribute(
"mrecord-mcount"))
373 if (
F.getParent()->getStackProtectorGuard() !=
"global") {
374 if (
F.getParent()->hasStackProtectorGuardRecord())
376 "mstack-protector-guard=global");
384 bool SelectInlineAsmMemoryOperand(
const SDValue &
Op,
386 std::vector<SDValue> &OutOps)
override;
388 void PreprocessISelDAG()
override;
391 #include "SystemZGenDAGISel.inc"
400 ID, std::make_unique<SystemZDAGToDAGISel>(TM, OptLevel)) {}
404char SystemZDAGToDAGISelLegacy::ID = 0;
410 return new SystemZDAGToDAGISelLegacy(TM, OptLevel);
416static bool selectDisp(SystemZAddressingMode::DispRange DR, int64_t Val) {
418 case SystemZAddressingMode::Disp12Only:
421 case SystemZAddressingMode::Disp12Pair:
422 case SystemZAddressingMode::Disp20Only:
423 case SystemZAddressingMode::Disp20Pair:
426 case SystemZAddressingMode::Disp20Only128:
447 if (AM.isDynAlloc() && !AM.IncludesDynAlloc) {
449 AM.IncludesDynAlloc =
true;
459 if (AM.hasIndexField() && !AM.Index.
getNode()) {
469static bool expandDisp(SystemZAddressingMode &AM,
bool IsBase,
472 int64_t TestDisp = AM.Disp + Op1;
484bool SystemZDAGToDAGISel::expandAddress(SystemZAddressingMode &AM,
489 if (Opcode ==
ISD::TRUNCATE &&
N.getOperand(0).getValueSizeInBits() <= 64) {
491 Opcode =
N.getOpcode();
493 if (Opcode ==
ISD::ADD || CurDAG->isBaseWithConstantOffset(
N)) {
500 if (Op0Code == SystemZISD::ADJDYNALLOC)
502 if (Op1Code == SystemZISD::ADJDYNALLOC)
515 if (Opcode == SystemZISD::PCREL_OFFSET) {
528static bool isValidDisp(SystemZAddressingMode::DispRange DR, int64_t Val) {
531 case SystemZAddressingMode::Disp12Only:
532 case SystemZAddressingMode::Disp20Only:
533 case SystemZAddressingMode::Disp20Only128:
536 case SystemZAddressingMode::Disp12Pair:
540 case SystemZAddressingMode::Disp20Pair:
580 if (Index->hasOneUse())
585 unsigned IndexOpcode = Index->getOpcode();
593 if (
Base->hasOneUse())
600bool SystemZDAGToDAGISel::selectAddress(
SDValue Addr,
601 SystemZAddressingMode &AM)
const {
612 else if (Addr.
getOpcode() == SystemZISD::ADJDYNALLOC &&
617 while (expandAddress(AM,
true) ||
618 (AM.Index.
getNode() && expandAddress(AM,
false)))
622 if (AM.Form == SystemZAddressingMode::FormBDXLA &&
631 if (AM.isDynAlloc() && !AM.IncludesDynAlloc)
644 if (
N->getNodeId() == -1 ||
657void SystemZDAGToDAGISel::getAddressOperands(
const SystemZAddressingMode &AM,
663 Base = CurDAG->getRegister(0, VT);
667 Base = CurDAG->getTargetFrameIndex(FrameIndex, VT);
668 }
else if (
Base.getValueType() != VT) {
670 assert(VT == MVT::i32 &&
Base.getValueType() == MVT::i64 &&
671 "Unexpected truncation");
679 Disp = CurDAG->getSignedTargetConstant(AM.Disp, SDLoc(
Base), VT);
682void SystemZDAGToDAGISel::getAddressOperands(
const SystemZAddressingMode &AM,
686 getAddressOperands(AM, VT,
Base, Disp);
689 if (!
Index.getNode())
691 Index = CurDAG->getRegister(0, VT);
694bool SystemZDAGToDAGISel::selectBDAddr(SystemZAddressingMode::DispRange DR,
697 SystemZAddressingMode AM(SystemZAddressingMode::FormBD, DR);
698 if (!selectAddress(Addr, AM))
705bool SystemZDAGToDAGISel::selectMVIAddr(SystemZAddressingMode::DispRange DR,
708 SystemZAddressingMode AM(SystemZAddressingMode::FormBDXNormal, DR);
709 if (!selectAddress(Addr, AM) || AM.Index.
getNode())
716bool SystemZDAGToDAGISel::selectBDXAddr(SystemZAddressingMode::AddrForm Form,
717 SystemZAddressingMode::DispRange DR,
720 SystemZAddressingMode AM(Form, DR);
721 if (!selectAddress(Addr, AM))
728bool SystemZDAGToDAGISel::selectBDVAddr12Only(
SDValue Addr,
SDValue Elem,
733 if (selectBDXAddr12Only(Addr, Regs[0], Disp, Regs[1]) &&
735 for (
unsigned int I = 0;
I < 2; ++
I) {
743 Index.getOperand(1) == Elem) {
752bool SystemZDAGToDAGISel::detectOrAndInsertion(
SDValue &
Op,
753 uint64_t InsertMask)
const {
765 uint64_t AndMask = MaskNode->getZExtValue();
766 if (InsertMask & AndMask)
772 if (Used != (AndMask | InsertMask)) {
773 KnownBits Known = CurDAG->computeKnownBits(
Op.getOperand(0));
778 Op =
Op.getOperand(0);
782bool SystemZDAGToDAGISel::refineRxSBGMask(RxSBGOperands &RxSBG,
783 uint64_t Mask)
const {
784 const SystemZInstrInfo *
TII = getInstrInfo();
785 if (RxSBG.Rotate != 0)
786 Mask = (
Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate));
788 if (
TII->isRxSBGMask(Mask, RxSBG.BitSize, RxSBG.Start, RxSBG.End)) {
798 if (RxSBG.Rotate != 0)
799 Mask = ((Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate)));
800 return (Mask & RxSBG.Mask) != 0;
803bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG)
const {
805 unsigned Opcode =
N.getOpcode();
808 if (RxSBG.Opcode == SystemZ::RNSBG)
810 if (
N.getOperand(0).getValueSizeInBits() > 64)
812 uint64_t BitSize =
N.getValueSizeInBits();
814 if (!refineRxSBGMask(RxSBG, Mask))
820 if (RxSBG.Opcode == SystemZ::RNSBG)
828 uint64_t
Mask = MaskNode->getZExtValue();
829 if (!refineRxSBGMask(RxSBG, Mask)) {
833 KnownBits Known = CurDAG->computeKnownBits(Input);
835 if (!refineRxSBGMask(RxSBG, Mask))
843 if (RxSBG.Opcode != SystemZ::RNSBG)
851 uint64_t
Mask = ~MaskNode->getZExtValue();
852 if (!refineRxSBGMask(RxSBG, Mask)) {
856 KnownBits Known = CurDAG->computeKnownBits(Input);
857 Mask &= ~Known.One.getZExtValue();
858 if (!refineRxSBGMask(RxSBG, Mask))
867 if (RxSBG.BitSize != 64 ||
N.getValueType() != MVT::i64)
873 RxSBG.Rotate = (RxSBG.Rotate + CountNode->getZExtValue()) & 63;
884 if (RxSBG.Opcode != SystemZ::RNSBG) {
886 unsigned InnerBitSize =
N.getOperand(0).getValueSizeInBits();
887 if (!refineRxSBGMask(RxSBG,
allOnes(InnerBitSize)))
898 unsigned BitSize =
N.getValueSizeInBits();
899 unsigned InnerBitSize =
N.getOperand(0).getValueSizeInBits();
903 if (RxSBG.Mask == 1 && RxSBG.Rotate == 1)
904 RxSBG.Rotate += (BitSize - InnerBitSize);
918 uint64_t
Count = CountNode->getZExtValue();
919 unsigned BitSize =
N.getValueSizeInBits();
923 if (RxSBG.Opcode == SystemZ::RNSBG) {
934 RxSBG.Rotate = (RxSBG.Rotate +
Count) & 63;
945 uint64_t
Count = CountNode->getZExtValue();
946 unsigned BitSize =
N.getValueSizeInBits();
950 if (RxSBG.Opcode == SystemZ::RNSBG || Opcode ==
ISD::SRA) {
962 RxSBG.Rotate = (RxSBG.Rotate -
Count) & 63;
971SDValue SystemZDAGToDAGISel::getUNDEF(
const SDLoc &
DL, EVT VT)
const {
972 SDNode *
N = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
976SDValue SystemZDAGToDAGISel::convertTo(
const SDLoc &
DL, EVT VT,
978 if (
N.getValueType() == MVT::i32 && VT == MVT::i64)
979 return CurDAG->getTargetInsertSubreg(SystemZ::subreg_l32,
980 DL, VT, getUNDEF(
DL, MVT::i64),
N);
981 if (
N.getValueType() == MVT::i64 && VT == MVT::i32)
982 return CurDAG->getTargetExtractSubreg(SystemZ::subreg_l32,
DL, VT,
N);
983 assert(
N.getValueType() == VT &&
"Unexpected value types");
987bool SystemZDAGToDAGISel::tryRISBGZero(SDNode *
N) {
989 EVT VT =
N->getValueType(0);
992 RxSBGOperands RISBG(SystemZ::RISBG,
SDValue(
N, 0));
994 while (expandRxSBG(RISBG))
1011 if (Subtarget->hasMiscellaneousExtensions4() &&
1012 RISBG.Rotate >= 1 && RISBG.Rotate <= 4 &&
1013 RISBG.Mask == (((uint64_t)1 << 32) - 1) << RISBG.Rotate &&
1014 RISBG.Input.getOpcode() ==
ISD::ADD)
1022 if (RISBG.Rotate == 0) {
1023 bool PreferAnd =
false;
1029 else if (RISBG.Mask == 0xff ||
1030 RISBG.Mask == 0xffff ||
1031 RISBG.Mask == 0x7fffffff ||
1038 if (
Load->getMemoryVT() == MVT::i32 &&
1041 RISBG.Mask == 0xffffff00 &&
1042 Subtarget->hasLoadAndZeroRightmostByte())
1052 if (
N !=
New.getNode()) {
1055 ReplaceNode(
N,
New.getNode());
1059 if (!
N->isMachineOpcode())
1065 unsigned Opcode = SystemZ::RISBG;
1067 if (Subtarget->hasMiscellaneousExtensions())
1068 Opcode = SystemZ::RISBGN;
1069 EVT OpcodeVT = MVT::i64;
1070 if (VT == MVT::i32 && Subtarget->hasHighWord() &&
1075 RISBG.Start >= 32 && RISBG.End >= RISBG.Start &&
1076 ((RISBG.Start + RISBG.Rotate) & 63) >= 32 &&
1077 ((RISBG.End + RISBG.Rotate) & 63) >=
1078 ((RISBG.Start + RISBG.Rotate) & 63)) {
1079 Opcode = SystemZ::RISBMux;
1080 OpcodeVT = MVT::i32;
1085 getUNDEF(
DL, OpcodeVT),
1086 convertTo(
DL, OpcodeVT, RISBG.Input),
1087 CurDAG->getTargetConstant(RISBG.Start,
DL, MVT::i32),
1088 CurDAG->getTargetConstant(RISBG.End | 128,
DL, MVT::i32),
1089 CurDAG->getTargetConstant(RISBG.Rotate,
DL, MVT::i32)
1092 DL, VT,
SDValue(CurDAG->getMachineNode(Opcode,
DL, OpcodeVT,
Ops), 0));
1093 ReplaceNode(
N,
New.getNode());
1097bool SystemZDAGToDAGISel::tryRxSBG(SDNode *
N,
unsigned Opcode) {
1099 EVT VT =
N->getValueType(0);
1104 RxSBGOperands RxSBG[] = {
1105 RxSBGOperands(Opcode,
N->getOperand(0)),
1106 RxSBGOperands(Opcode,
N->getOperand(1))
1108 unsigned Count[] = { 0, 0 };
1109 for (
unsigned I = 0;
I < 2; ++
I)
1110 while (RxSBG[
I].Input->
hasOneUse() && expandRxSBG(RxSBG[
I]))
1130 if (Opcode == SystemZ::ROSBG && (RxSBG[
I].Mask & 0xff) == 0)
1132 if (
Load->getMemoryVT() == MVT::i8)
1137 if (Opcode == SystemZ::ROSBG && detectOrAndInsertion(Op0, RxSBG[
I].Mask)) {
1138 Opcode = SystemZ::RISBG;
1140 if (Subtarget->hasMiscellaneousExtensions())
1141 Opcode = SystemZ::RISBGN;
1145 convertTo(
DL, MVT::i64, Op0),
1146 convertTo(
DL, MVT::i64, RxSBG[
I].Input),
1147 CurDAG->getTargetConstant(RxSBG[
I].Start,
DL, MVT::i32),
1148 CurDAG->getTargetConstant(RxSBG[
I].End,
DL, MVT::i32),
1149 CurDAG->getTargetConstant(RxSBG[
I].Rotate,
DL, MVT::i32)
1152 DL, VT,
SDValue(CurDAG->getMachineNode(Opcode,
DL, MVT::i64,
Ops), 0));
1153 ReplaceNode(
N,
New.getNode());
1157void SystemZDAGToDAGISel::splitLargeImmediate(
unsigned Opcode, SDNode *Node,
1158 SDValue Op0, uint64_t UpperVal,
1159 uint64_t LowerVal) {
1160 EVT VT =
Node->getValueType(0);
1179 HandleSDNode Handle(
Upper);
1180 SelectCode(
Upper.getNode());
1181 Upper = Handle.getValue();
1187 ReplaceNode(Node,
Or.getNode());
1189 SelectCode(
Or.getNode());
1192void SystemZDAGToDAGISel::loadVectorConstant(
1193 const SystemZVectorConstantInfo &VCI, SDNode *Node) {
1195 VCI.
Opcode == SystemZISD::REPLICATE ||
1196 VCI.
Opcode == SystemZISD::ROTATE_MASK) &&
1199 EVT VT =
Node->getValueType(0);
1202 for (
unsigned OpVal : VCI.
OpVals)
1203 Ops.push_back(CurDAG->getTargetConstant(OpVal,
DL, MVT::i32));
1207 ReplaceNode(Node,
Op.getNode());
1210 ReplaceNode(Node, BitCast.
getNode());
1211 SelectCode(BitCast.
getNode());
1213 unsigned SubRegIdx = (VT.
getSizeInBits() == 16 ? SystemZ::subreg_h16
1215 : SystemZ::subreg_h64);
1217 Node, CurDAG->getTargetExtractSubreg(SubRegIdx,
DL, VT,
Op).getNode());
1219 SelectCode(
Op.getNode());
1222SDNode *SystemZDAGToDAGISel::loadPoolVectorConstant(APInt Val, EVT VT, SDLoc
DL) {
1226 SDValue CP = CurDAG->getTargetConstantPool(
1227 ConstantInt::get(Type::getInt128Ty(*CurDAG->getContext()), Val),
1228 TLI->getPointerTy(CurDAG->getDataLayout()));
1232 SDValue(CurDAG->getMachineNode(SystemZ::LARL,
DL, PtrVT, CP), 0),
1233 CurDAG->getTargetConstant(0,
DL, PtrVT),
1234 CurDAG->getRegister(0, PtrVT),
1235 CurDAG->getEntryNode()
1237 ResNode = CurDAG->getMachineNode(SystemZ::VL,
DL, VT, MVT::Other,
Ops);
1242 MachineFunction& MF = CurDAG->getMachineFunction();
1243 MachineMemOperand *MemOp =
1251bool SystemZDAGToDAGISel::tryGather(SDNode *
N,
unsigned Opcode) {
1257 unsigned Elem = ElemN->getZExtValue();
1258 EVT VT =
N->getValueType(0);
1263 if (!Load || !
Load->hasNUsesOfValue(1, 0))
1265 if (
Load->getMemoryVT().getSizeInBits() !=
1266 Load->getValueType(0).getSizeInBits())
1270 if (!selectBDVAddr12Only(
Load->getBasePtr(), ElemV,
Base, Disp, Index) ||
1277 CurDAG->getTargetConstant(Elem,
DL, MVT::i32),
Load->getChain()
1279 SDNode *Res = CurDAG->getMachineNode(Opcode,
DL, VT, MVT::Other,
Ops);
1281 ReplaceNode(
N, Res);
1285bool SystemZDAGToDAGISel::tryScatter(StoreSDNode *Store,
unsigned Opcode) {
1289 if (
Store->getMemoryVT().getSizeInBits() !=
Value.getValueSizeInBits())
1299 unsigned Elem = ElemN->getZExtValue();
1304 if (!selectBDVAddr12Only(
Store->getBasePtr(), ElemV,
Base, Disp, Index) ||
1310 Vec,
Base, Disp,
Index, CurDAG->getTargetConstant(Elem,
DL, MVT::i32),
1313 ReplaceNode(Store, CurDAG->getMachineNode(Opcode,
DL, MVT::Other,
Ops));
1344 if (!Load.hasOneUse())
1356 bool ChainCheck =
false;
1357 if (Chain == Load.getValue(1)) {
1364 const unsigned int Max = 1024;
1367 if (
Op == Load.getValue(1)) {
1380 if (
Op.getNode() != LoadNode)
1391 MVT::Other, ChainOps);
1408bool SystemZDAGToDAGISel::tryFoldLoadStoreIntoMemOperand(SDNode *Node) {
1412 SDLoc
DL(StoreNode);
1418 unsigned NewOpc = 0;
1419 bool NegateOperand =
false;
1423 case SystemZISD::SSUBO:
1424 NegateOperand =
true;
1426 case SystemZISD::SADDO:
1427 if (MemVT == MVT::i32)
1428 NewOpc = SystemZ::ASI;
1429 else if (MemVT == MVT::i64)
1430 NewOpc = SystemZ::AGSI;
1434 case SystemZISD::USUBO:
1435 NegateOperand =
true;
1437 case SystemZISD::UADDO:
1438 if (MemVT == MVT::i32)
1439 NewOpc = SystemZ::ALSI;
1440 else if (MemVT == MVT::i64)
1441 NewOpc = SystemZ::ALGSI;
1447 LoadSDNode *LoadNode =
nullptr;
1457 auto OperandV = OperandC->getAPIntValue();
1459 OperandV = -OperandV;
1460 if (OperandV.getSignificantBits() > 8)
1462 Operand = CurDAG->getTargetConstant(OperandV,
DL, MemVT);
1470 CurDAG->getMachineNode(NewOpc,
DL, MVT::i32, MVT::Other,
Ops);
1471 CurDAG->setNodeMemRefs(
1476 CurDAG->RemoveDeadNode(Node);
1480bool SystemZDAGToDAGISel::canUseBlockOperation(StoreSDNode *Store,
1481 LoadSDNode *Load)
const {
1483 if (
Load->getMemoryVT() !=
Store->getMemoryVT())
1487 if (
Load->isVolatile() ||
Store->isVolatile())
1491 if (
Load->isInvariant() &&
Load->isDereferenceable())
1495 const Value *V1 =
Load->getMemOperand()->getValue();
1496 const Value *V2 =
Store->getMemOperand()->getValue();
1501 uint64_t
Size =
Load->getMemoryVT().getStoreSize();
1502 int64_t End1 =
Load->getSrcValueOffset() +
Size;
1503 int64_t End2 =
Store->getSrcValueOffset() +
Size;
1504 if (V1 == V2 && End1 == End2)
1507 return BatchAA->isNoAlias(MemoryLocation(V1, End1,
Load->getAAInfo()),
1508 MemoryLocation(V2, End2,
Store->getAAInfo()));
1511bool SystemZDAGToDAGISel::storeLoadCanUseMVC(SDNode *
N)
const {
1517 uint64_t
Size =
Load->getMemoryVT().getStoreSize();
1527 return canUseBlockOperation(Store, Load);
1530bool SystemZDAGToDAGISel::storeLoadCanUseBlockBinary(SDNode *
N,
1535 return !LoadA->isVolatile() && LoadA->getMemoryVT() == LoadB->getMemoryVT() &&
1536 canUseBlockOperation(StoreA, LoadB);
1539bool SystemZDAGToDAGISel::storeLoadIsAligned(SDNode *
N)
const {
1543 TypeSize StoreSize = MemAccess->getMemoryVT().getStoreSize();
1545 MachineMemOperand *MMO = MemAccess->getMemOperand();
1546 assert(MMO &&
"Expected a memory operand.");
1550 if (MemAccess->getAlign().value() < StoreSize ||
1551 (LdSt && !LdSt->getOffset().isUndef()))
1560 if ((PSV->isGOT() || PSV->isConstantPool()))
1565 if (GlobalAddressSDNode *GA =
1568 if (GA->getOffset() % StoreSize != 0)
1572 const GlobalValue *GV = GA->getGlobal();
1584 ETy =
L->getExtensionType();
1586 ETy =
AL->getExtensionType();
1592void SystemZDAGToDAGISel::Select(SDNode *Node) {
1594 if (
Node->isMachineOpcode()) {
1596 Node->setNodeId(-1);
1600 unsigned Opcode =
Node->getOpcode();
1604 if (tryRxSBG(Node, SystemZ::ROSBG))
1610 if (tryRxSBG(Node, SystemZ::RXSBG))
1617 if (
Node->getValueType(0) == MVT::i64 &&
1620 uint64_t Val = Op1->getZExtValue();
1623 if (Subtarget->hasMiscellaneousExtensions3()) {
1624 unsigned ChildOpcode =
Node->getOperand(0).getOpcode();
1626 if (Val == (uint64_t)-1 && Opcode ==
ISD::XOR)
1633 auto Op0 =
Node->getOperand(0);
1635 if (Op0Op1->getZExtValue() == (uint64_t)-1)
1640 if (Opcode ==
ISD::XOR && Op1->isAllOnes())
1643 splitLargeImmediate(Opcode, Node,
Node->getOperand(0),
1644 Val - uint32_t(Val), uint32_t(Val));
1652 if (tryRxSBG(Node, SystemZ::RNSBG))
1656 if (
Node->getValueType(0) == MVT::i64 &&
1658 SDValue Input =
Node->getOperand(0)->getOperand(0);
1675 if (tryRISBGZero(Node))
1680 if (
Node->getValueType(0) == MVT::i128) {
1685 uint64_t Bytes[2] = { 0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL };
1686 SDNode *
Mask = loadPoolVectorConstant(APInt(128, Bytes), MVT::v16i8,
DL);
1689 MVT::v16i8,
Ops), 0);
1692 SDNode *ResNode = Res.
getNode();
1693 ReplaceNode(Node, ResNode);
1694 SelectCode(Src.getNode());
1695 SelectCode(ResNode);
1703 if (
Node->getValueType(0) == MVT::i64) {
1704 uint64_t Val =
Node->getAsZExtVal();
1706 splitLargeImmediate(
ISD::OR, Node,
SDValue(), Val - uint32_t(Val),
1711 if (
Node->getValueType(0) == MVT::i128) {
1712 const APInt &Val =
Node->getAsAPIntVal();
1713 SystemZVectorConstantInfo VCI(Val);
1715 loadVectorConstant(VCI, Node);
1719 SDNode *ResNode = loadPoolVectorConstant(Val, MVT::i128, SDLoc(Node));
1720 ReplaceNode(Node, ResNode);
1725 case SystemZISD::SELECT_CCMASK: {
1731 (Subtarget->hasLoadStoreOnCond2() &&
1732 Node->getValueType(0).isInteger() &&
1733 Node->getValueType(0).getSizeInBits() <= 64 &&
1743 CCMask = CurDAG->getTargetConstant(ConstCCValid ^ ConstCCMask,
1746 SDNode *UpdatedNode =
1747 CurDAG->UpdateNodeOperands(Node, Op1, Op0, CCValid, CCMask, Op4);
1748 if (UpdatedNode != Node) {
1750 ReplaceNode(Node, UpdatedNode);
1758 EVT VT =
Node->getValueType(0);
1760 if (ElemBitSize == 32) {
1761 if (tryGather(Node, SystemZ::VGEF))
1763 }
else if (ElemBitSize == 64) {
1764 if (tryGather(Node, SystemZ::VGEG))
1772 SystemZVectorConstantInfo VCI(BVN);
1774 loadVectorConstant(VCI, Node);
1782 if (
Imm.isZero() ||
Imm.isNegZero())
1784 SystemZVectorConstantInfo VCI(Imm);
1787 loadVectorConstant(VCI, Node);
1792 if (tryFoldLoadStoreIntoMemOperand(Node))
1795 unsigned ElemBitSize =
Store->getValue().getValueSizeInBits();
1796 if (ElemBitSize == 32) {
1797 if (tryScatter(Store, SystemZ::VSCEF))
1799 }
else if (ElemBitSize == 64) {
1800 if (tryScatter(Store, SystemZ::VSCEG))
1812 AtomOp->getChain(), SDLoc(AtomOp), AtomOp->getVal(),
1813 AtomOp->getBasePtr(), AtomOp->getMemoryVT(), AtomOp->getMemOperand()));
1818 if (AtomOp->getSuccessOrdering() == AtomicOrdering::SequentiallyConsistent)
1819 Chain = CurDAG->getMachineNode(SystemZ::Serialize, SDLoc(AtomOp),
1820 MVT::Other,
SDValue(Chain, 0));
1821 ReplaceNode(Node, Chain);
1830bool SystemZDAGToDAGISel::SelectInlineAsmMemoryOperand(
1832 std::vector<SDValue> &OutOps) {
1833 SystemZAddressingMode::AddrForm
Form;
1834 SystemZAddressingMode::DispRange DispRange;
1837 switch(ConstraintID) {
1840 case InlineAsm::ConstraintCode::i:
1841 case InlineAsm::ConstraintCode::Q:
1842 case InlineAsm::ConstraintCode::ZQ:
1844 Form = SystemZAddressingMode::FormBD;
1845 DispRange = SystemZAddressingMode::Disp12Only;
1847 case InlineAsm::ConstraintCode::R:
1848 case InlineAsm::ConstraintCode::ZR:
1850 Form = SystemZAddressingMode::FormBDXNormal;
1851 DispRange = SystemZAddressingMode::Disp12Only;
1853 case InlineAsm::ConstraintCode::S:
1854 case InlineAsm::ConstraintCode::ZS:
1856 Form = SystemZAddressingMode::FormBD;
1857 DispRange = SystemZAddressingMode::Disp20Only;
1859 case InlineAsm::ConstraintCode::T:
1860 case InlineAsm::ConstraintCode::m:
1861 case InlineAsm::ConstraintCode::o:
1862 case InlineAsm::ConstraintCode::p:
1863 case InlineAsm::ConstraintCode::ZT:
1868 Form = SystemZAddressingMode::FormBDXNormal;
1869 DispRange = SystemZAddressingMode::Disp20Only;
1873 if (selectBDXAddr(Form, DispRange,
Op,
Base, Disp, Index)) {
1874 const TargetRegisterClass *TRC =
1877 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(),
DL, MVT::i32);
1884 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
1892 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
1897 OutOps.push_back(
Base);
1898 OutOps.push_back(Disp);
1899 OutOps.push_back(Index);
1909SystemZDAGToDAGISel::IsProfitableToFold(
SDValue N, SDNode *U,
1910 SDNode *Root)
const {
1913 if (
N.getOpcode() ==
ISD::LOAD &&
U->getOpcode() == SystemZISD::ICMP) {
1914 if (!
N.hasOneUse() || !
U->hasOneUse())
1921 SDNode *CCUser = *
U->user_begin();
1922 SDNode *CCRegUser =
nullptr;
1925 for (
auto *U : CCUser->
users()) {
1926 if (CCRegUser ==
nullptr)
1928 else if (CCRegUser != U)
1932 if (CCRegUser ==
nullptr)
1945 if (!IsLegalToFold(
N, U, CCRegUser, OptLevel,
false))
1955struct IPMConversion {
1956 IPMConversion(
unsigned xorValue, int64_t addValue,
unsigned bit)
1957 : XORValue(xorValue), AddValue(addValue), Bit(bit) {}
2032SDValue SystemZDAGToDAGISel::expandSelectBoolean(SDNode *Node) {
2035 if (!TrueOp || !FalseOp)
2037 if (FalseOp->getZExtValue() != 0)
2039 if (TrueOp->getSExtValue() != 1 && TrueOp->getSExtValue() != -1)
2044 if (!CCValidOp || !CCMaskOp)
2046 int CCValid = CCValidOp->getZExtValue();
2047 int CCMask = CCMaskOp->getZExtValue();
2052 SDValue Result = CurDAG->getNode(SystemZISD::IPM,
DL, MVT::i32, CCReg);
2056 CurDAG->getConstant(IPM.XORValue,
DL, MVT::i32));
2060 CurDAG->getNode(
ISD::ADD,
DL, MVT::i32, Result,
2061 CurDAG->getSignedConstant(IPM.AddValue,
DL, MVT::i32));
2063 EVT VT =
Node->getValueType(0);
2064 if (VT == MVT::i32 && IPM.Bit == 31) {
2066 Result = CurDAG->getNode(ShiftOp,
DL, MVT::i32, Result,
2067 CurDAG->getConstant(IPM.Bit,
DL, MVT::i32));
2072 if (TrueOp->getSExtValue() == 1) {
2075 CurDAG->getConstant(IPM.Bit,
DL, MVT::i32));
2077 CurDAG->getConstant(1,
DL, VT));
2083 CurDAG->getConstant(ShlAmt,
DL, MVT::i32));
2085 CurDAG->getConstant(SraAmt,
DL, MVT::i32));
2092bool SystemZDAGToDAGISel::shouldSelectForReassoc(SDNode *
N)
const {
2093 EVT VT =
N->getValueType(0);
2095 return N->getFlags().hasAllowReassociation() &&
2096 N->getFlags().hasNoSignedZeros() && Subtarget->hasVector() &&
2097 (VT != MVT::f32 || Subtarget->hasVectorEnhancements1()) &&
2098 !
N->isStrictFPOpcode();
2101void SystemZDAGToDAGISel::PreprocessISelDAG() {
2104 if (Subtarget->hasLoadStoreOnCond2())
2107 bool MadeChange =
false;
2110 E = CurDAG->allnodes_end();
2117 switch (
N->getOpcode()) {
2119 case SystemZISD::SELECT_CCMASK:
2120 Res = expandSelectBoolean(
N);
2125 LLVM_DEBUG(
dbgs() <<
"SystemZ DAG preprocessing replacing:\nOld: ");
2131 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
2137 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
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)
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 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.
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.
EVT getValueType(unsigned ResNo) const
Return the type of a specified result.
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.
@ 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
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.
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.
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)