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))
1659 if (tryRISBGZero(Node))
1664 if (
Node->getValueType(0) == MVT::i128) {
1669 uint64_t Bytes[2] = { 0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL };
1670 SDNode *
Mask = loadPoolVectorConstant(APInt(128, Bytes), MVT::v16i8,
DL);
1673 MVT::v16i8,
Ops), 0);
1676 SDNode *ResNode = Res.
getNode();
1677 ReplaceNode(Node, ResNode);
1678 SelectCode(Src.getNode());
1679 SelectCode(ResNode);
1687 if (
Node->getValueType(0) == MVT::i64) {
1688 uint64_t Val =
Node->getAsZExtVal();
1690 splitLargeImmediate(
ISD::OR, Node,
SDValue(), Val - uint32_t(Val),
1695 if (
Node->getValueType(0) == MVT::i128) {
1696 const APInt &Val =
Node->getAsAPIntVal();
1697 SystemZVectorConstantInfo VCI(Val);
1699 loadVectorConstant(VCI, Node);
1703 SDNode *ResNode = loadPoolVectorConstant(Val, MVT::i128, SDLoc(Node));
1704 ReplaceNode(Node, ResNode);
1709 case SystemZISD::SELECT_CCMASK: {
1715 (Subtarget->hasLoadStoreOnCond2() &&
1716 Node->getValueType(0).isInteger() &&
1717 Node->getValueType(0).getSizeInBits() <= 64 &&
1727 CCMask = CurDAG->getTargetConstant(ConstCCValid ^ ConstCCMask,
1730 SDNode *UpdatedNode =
1731 CurDAG->UpdateNodeOperands(Node, Op1, Op0, CCValid, CCMask, Op4);
1732 if (UpdatedNode != Node) {
1734 ReplaceNode(Node, UpdatedNode);
1742 EVT VT =
Node->getValueType(0);
1744 if (ElemBitSize == 32) {
1745 if (tryGather(Node, SystemZ::VGEF))
1747 }
else if (ElemBitSize == 64) {
1748 if (tryGather(Node, SystemZ::VGEG))
1756 SystemZVectorConstantInfo VCI(BVN);
1758 loadVectorConstant(VCI, Node);
1766 if (
Imm.isZero() ||
Imm.isNegZero())
1768 SystemZVectorConstantInfo VCI(Imm);
1771 loadVectorConstant(VCI, Node);
1776 if (tryFoldLoadStoreIntoMemOperand(Node))
1779 unsigned ElemBitSize =
Store->getValue().getValueSizeInBits();
1780 if (ElemBitSize == 32) {
1781 if (tryScatter(Store, SystemZ::VSCEF))
1783 }
else if (ElemBitSize == 64) {
1784 if (tryScatter(Store, SystemZ::VSCEG))
1796 AtomOp->getChain(), SDLoc(AtomOp), AtomOp->getVal(),
1797 AtomOp->getBasePtr(), AtomOp->getMemoryVT(), AtomOp->getMemOperand()));
1802 if (AtomOp->getSuccessOrdering() == AtomicOrdering::SequentiallyConsistent)
1803 Chain = CurDAG->getMachineNode(SystemZ::Serialize, SDLoc(AtomOp),
1804 MVT::Other,
SDValue(Chain, 0));
1805 ReplaceNode(Node, Chain);
1814bool SystemZDAGToDAGISel::SelectInlineAsmMemoryOperand(
1816 std::vector<SDValue> &OutOps) {
1817 SystemZAddressingMode::AddrForm
Form;
1818 SystemZAddressingMode::DispRange DispRange;
1821 switch(ConstraintID) {
1824 case InlineAsm::ConstraintCode::i:
1825 case InlineAsm::ConstraintCode::Q:
1826 case InlineAsm::ConstraintCode::ZQ:
1828 Form = SystemZAddressingMode::FormBD;
1829 DispRange = SystemZAddressingMode::Disp12Only;
1831 case InlineAsm::ConstraintCode::R:
1832 case InlineAsm::ConstraintCode::ZR:
1834 Form = SystemZAddressingMode::FormBDXNormal;
1835 DispRange = SystemZAddressingMode::Disp12Only;
1837 case InlineAsm::ConstraintCode::S:
1838 case InlineAsm::ConstraintCode::ZS:
1840 Form = SystemZAddressingMode::FormBD;
1841 DispRange = SystemZAddressingMode::Disp20Only;
1843 case InlineAsm::ConstraintCode::T:
1844 case InlineAsm::ConstraintCode::m:
1845 case InlineAsm::ConstraintCode::o:
1846 case InlineAsm::ConstraintCode::p:
1847 case InlineAsm::ConstraintCode::ZT:
1852 Form = SystemZAddressingMode::FormBDXNormal;
1853 DispRange = SystemZAddressingMode::Disp20Only;
1857 if (selectBDXAddr(Form, DispRange,
Op,
Base, Disp, Index)) {
1858 const TargetRegisterClass *TRC =
1861 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(),
DL, MVT::i32);
1868 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
1876 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
1881 OutOps.push_back(
Base);
1882 OutOps.push_back(Disp);
1883 OutOps.push_back(Index);
1893SystemZDAGToDAGISel::IsProfitableToFold(
SDValue N, SDNode *U,
1894 SDNode *Root)
const {
1897 if (
N.getOpcode() ==
ISD::LOAD &&
U->getOpcode() == SystemZISD::ICMP) {
1898 if (!
N.hasOneUse() || !
U->hasOneUse())
1905 SDNode *CCUser = *
U->user_begin();
1906 SDNode *CCRegUser =
nullptr;
1909 for (
auto *U : CCUser->
users()) {
1910 if (CCRegUser ==
nullptr)
1912 else if (CCRegUser != U)
1916 if (CCRegUser ==
nullptr)
1929 if (!IsLegalToFold(
N, U, CCRegUser, OptLevel,
false))
1939struct IPMConversion {
1940 IPMConversion(
unsigned xorValue, int64_t addValue,
unsigned bit)
1941 : XORValue(xorValue), AddValue(addValue), Bit(bit) {}
2016SDValue SystemZDAGToDAGISel::expandSelectBoolean(SDNode *Node) {
2019 if (!TrueOp || !FalseOp)
2021 if (FalseOp->getZExtValue() != 0)
2023 if (TrueOp->getSExtValue() != 1 && TrueOp->getSExtValue() != -1)
2028 if (!CCValidOp || !CCMaskOp)
2030 int CCValid = CCValidOp->getZExtValue();
2031 int CCMask = CCMaskOp->getZExtValue();
2036 SDValue Result = CurDAG->getNode(SystemZISD::IPM,
DL, MVT::i32, CCReg);
2040 CurDAG->getConstant(IPM.XORValue,
DL, MVT::i32));
2044 CurDAG->getNode(
ISD::ADD,
DL, MVT::i32, Result,
2045 CurDAG->getSignedConstant(IPM.AddValue,
DL, MVT::i32));
2047 EVT VT =
Node->getValueType(0);
2048 if (VT == MVT::i32 && IPM.Bit == 31) {
2050 Result = CurDAG->getNode(ShiftOp,
DL, MVT::i32, Result,
2051 CurDAG->getConstant(IPM.Bit,
DL, MVT::i32));
2056 if (TrueOp->getSExtValue() == 1) {
2059 CurDAG->getConstant(IPM.Bit,
DL, MVT::i32));
2061 CurDAG->getConstant(1,
DL, VT));
2067 CurDAG->getConstant(ShlAmt,
DL, MVT::i32));
2069 CurDAG->getConstant(SraAmt,
DL, MVT::i32));
2076bool SystemZDAGToDAGISel::shouldSelectForReassoc(SDNode *
N)
const {
2077 EVT VT =
N->getValueType(0);
2079 return N->getFlags().hasAllowReassociation() &&
2080 N->getFlags().hasNoSignedZeros() && Subtarget->hasVector() &&
2081 (VT != MVT::f32 || Subtarget->hasVectorEnhancements1()) &&
2082 !
N->isStrictFPOpcode();
2085void SystemZDAGToDAGISel::PreprocessISelDAG() {
2088 if (Subtarget->hasLoadStoreOnCond2())
2091 bool MadeChange =
false;
2094 E = CurDAG->allnodes_end();
2101 switch (
N->getOpcode()) {
2103 case SystemZISD::SELECT_CCMASK:
2104 Res = expandSelectBoolean(
N);
2109 LLVM_DEBUG(
dbgs() <<
"SystemZ DAG preprocessing replacing:\nOld: ");
2115 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
2121 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.
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)