23#define DEBUG_TYPE "systemz-isel"
24#define PASS_NAME "SystemZ DAG->DAG Pattern Instruction Selection"
28struct SystemZAddressingMode {
63 bool IncludesDynAlloc;
65 SystemZAddressingMode(AddrForm form, DispRange dr)
66 : Form(form), DR(dr), Disp(0), IncludesDynAlloc(
false) {}
69 bool hasIndexField() {
return Form != FormBD; }
72 bool isDynAlloc() {
return Form == FormBDXDynAlloc; }
75 errs() <<
"SystemZAddressingMode " <<
this <<
'\n';
79 Base.getNode()->dump(DAG);
83 if (hasIndexField()) {
86 Index.getNode()->dump(DAG);
91 errs() <<
" Disp " << Disp;
93 errs() <<
" + ADJDYNALLOC";
119struct RxSBGOperands {
121 : Opcode(
Op), BitSize(
N.getValueSizeInBits()),
122 Mask(
allOnes(BitSize)), Input(
N), Start(64 - BitSize),
End(63),
139 return CurDAG->getTargetConstant(Imm,
SDLoc(
Node),
Node->getValueType(0));
152 bool expandAddress(SystemZAddressingMode &AM,
bool IsBase)
const;
155 bool selectAddress(
SDValue N, SystemZAddressingMode &AM)
const;
158 void getAddressOperands(
const SystemZAddressingMode &AM,
EVT VT,
160 void getAddressOperands(
const SystemZAddressingMode &AM,
EVT VT,
166 bool selectBDAddr(SystemZAddressingMode::DispRange DR,
SDValue Addr,
172 bool selectMVIAddr(SystemZAddressingMode::DispRange DR,
SDValue Addr,
178 bool selectBDXAddr(SystemZAddressingMode::AddrForm Form,
193 return selectBDAddr(SystemZAddressingMode::Disp12Only,
Addr,
Base, Disp);
196 return selectBDAddr(SystemZAddressingMode::Disp12Pair,
Addr,
Base, Disp);
199 return selectBDAddr(SystemZAddressingMode::Disp20Only,
Addr,
Base, Disp);
202 return selectBDAddr(SystemZAddressingMode::Disp20Pair,
Addr,
Base, Disp);
207 return selectMVIAddr(SystemZAddressingMode::Disp12Pair,
Addr,
Base, Disp);
210 return selectMVIAddr(SystemZAddressingMode::Disp20Pair,
Addr,
Base, Disp);
216 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
217 SystemZAddressingMode::Disp12Only,
222 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
223 SystemZAddressingMode::Disp12Pair,
228 return selectBDXAddr(SystemZAddressingMode::FormBDXDynAlloc,
229 SystemZAddressingMode::Disp12Only,
234 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
235 SystemZAddressingMode::Disp20Only,
240 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
241 SystemZAddressingMode::Disp20Only128,
246 return selectBDXAddr(SystemZAddressingMode::FormBDXNormal,
247 SystemZAddressingMode::Disp20Pair,
252 return selectBDXAddr(SystemZAddressingMode::FormBDXLA,
253 SystemZAddressingMode::Disp12Pair,
258 return selectBDXAddr(SystemZAddressingMode::FormBDXLA,
259 SystemZAddressingMode::Disp20Pair,
277 bool refineRxSBGMask(RxSBGOperands &RxSBG,
uint64_t Mask)
const;
281 bool expandRxSBG(RxSBGOperands &RxSBG)
const;
295 bool tryRxSBG(
SDNode *
N,
unsigned Opcode);
313 bool tryGather(
SDNode *
N,
unsigned Opcode);
316 bool tryScatter(
StoreSDNode *Store,
unsigned Opcode);
321 bool tryFoldLoadStoreIntoMemOperand(
SDNode *
Node);
336 bool storeLoadCanUseMVC(
SDNode *
N)
const;
341 bool storeLoadCanUseBlockBinary(
SDNode *
N,
unsigned I)
const;
345 bool storeLoadIsAligned(
SDNode *
N)
const;
356 bool shouldSelectForReassoc(
SDNode *
N)
const;
359 SystemZDAGToDAGISel() =
delete;
366 if (
F.getFnAttribute(
"fentry-call").getValueAsString() !=
"true") {
367 if (
F.hasFnAttribute(
"mnop-mcount"))
369 if (
F.hasFnAttribute(
"mrecord-mcount"))
381 std::vector<SDValue> &OutOps)
override;
386 #include "SystemZGenDAGISel.inc"
395 ID, std::make_unique<SystemZDAGToDAGISel>(TM, OptLevel)) {}
399char SystemZDAGToDAGISelLegacy::ID = 0;
405 return new SystemZDAGToDAGISelLegacy(TM, OptLevel);
411static bool selectDisp(SystemZAddressingMode::DispRange DR, int64_t Val) {
413 case SystemZAddressingMode::Disp12Only:
414 return isUInt<12>(Val);
416 case SystemZAddressingMode::Disp12Pair:
417 case SystemZAddressingMode::Disp20Only:
418 case SystemZAddressingMode::Disp20Pair:
419 return isInt<20>(Val);
421 case SystemZAddressingMode::Disp20Only128:
422 return isInt<20>(Val) && isInt<20>(Val + 8);
442 if (AM.isDynAlloc() && !AM.IncludesDynAlloc) {
444 AM.IncludesDynAlloc =
true;
454 if (AM.hasIndexField() && !AM.Index.getNode()) {
464static bool expandDisp(SystemZAddressingMode &AM,
bool IsBase,
467 int64_t TestDisp = AM.Disp + Op1;
479bool SystemZDAGToDAGISel::expandAddress(SystemZAddressingMode &AM,
482 unsigned Opcode =
N.getOpcode();
484 if (Opcode ==
ISD::TRUNCATE &&
N.getOperand(0).getValueSizeInBits() <= 64) {
486 Opcode =
N.getOpcode();
488 if (Opcode ==
ISD::ADD || CurDAG->isBaseWithConstantOffset(
N)) {
502 cast<ConstantSDNode>(Op0)->getSExtValue());
505 cast<ConstantSDNode>(Op1)->getSExtValue());
515 cast<GlobalAddressSDNode>(Anchor)->getOffset());
523static bool isValidDisp(SystemZAddressingMode::DispRange DR, int64_t Val) {
526 case SystemZAddressingMode::Disp12Only:
527 case SystemZAddressingMode::Disp20Only:
528 case SystemZAddressingMode::Disp20Only128:
531 case SystemZAddressingMode::Disp12Pair:
533 return isUInt<12>(Val);
535 case SystemZAddressingMode::Disp20Pair:
537 return !isUInt<12>(Val);
561 if (isUInt<12>(Disp))
566 if (!isInt<16>(Disp))
575 if (Index->hasOneUse())
580 unsigned IndexOpcode = Index->getOpcode();
588 if (
Base->hasOneUse())
595bool SystemZDAGToDAGISel::selectAddress(
SDValue Addr,
596 SystemZAddressingMode &AM)
const {
604 cast<ConstantSDNode>(
Addr)->getSExtValue()))
612 while (expandAddress(AM,
true) ||
613 (AM.Index.getNode() && expandAddress(AM,
false)))
617 if (AM.Form == SystemZAddressingMode::FormBDXLA &&
618 !
shouldUseLA(AM.Base.getNode(), AM.Disp, AM.Index.getNode()))
626 if (AM.isDynAlloc() && !AM.IncludesDynAlloc)
639 if (
N->getNodeId() == -1 ||
652void SystemZDAGToDAGISel::getAddressOperands(
const SystemZAddressingMode &AM,
658 Base = CurDAG->getRegister(0, VT);
662 Base = CurDAG->getTargetFrameIndex(FrameIndex, VT);
663 }
else if (
Base.getValueType() != VT) {
665 assert(VT == MVT::i32 &&
Base.getValueType() == MVT::i64 &&
666 "Unexpected truncation");
674 Disp = CurDAG->getSignedTargetConstant(AM.Disp,
SDLoc(
Base), VT);
677void SystemZDAGToDAGISel::getAddressOperands(
const SystemZAddressingMode &AM,
681 getAddressOperands(AM, VT,
Base, Disp);
684 if (!
Index.getNode())
686 Index = CurDAG->getRegister(0, VT);
689bool SystemZDAGToDAGISel::selectBDAddr(SystemZAddressingMode::DispRange DR,
692 SystemZAddressingMode AM(SystemZAddressingMode::FormBD, DR);
693 if (!selectAddress(
Addr, AM))
696 getAddressOperands(AM,
Addr.getValueType(),
Base, Disp);
700bool SystemZDAGToDAGISel::selectMVIAddr(SystemZAddressingMode::DispRange DR,
703 SystemZAddressingMode AM(SystemZAddressingMode::FormBDXNormal, DR);
704 if (!selectAddress(
Addr, AM) || AM.Index.getNode())
707 getAddressOperands(AM,
Addr.getValueType(),
Base, Disp);
711bool SystemZDAGToDAGISel::selectBDXAddr(SystemZAddressingMode::AddrForm Form,
712 SystemZAddressingMode::DispRange DR,
715 SystemZAddressingMode AM(Form, DR);
716 if (!selectAddress(
Addr, AM))
719 getAddressOperands(AM,
Addr.getValueType(),
Base, Disp, Index);
728 if (selectBDXAddr12Only(
Addr, Regs[0], Disp, Regs[1]) &&
730 for (
unsigned int I = 0;
I < 2; ++
I) {
738 Index.getOperand(1) == Elem) {
747bool SystemZDAGToDAGISel::detectOrAndInsertion(
SDValue &
Op,
755 auto *MaskNode = dyn_cast<ConstantSDNode>(
Op.getOperand(1).getNode());
760 uint64_t AndMask = MaskNode->getZExtValue();
761 if (InsertMask & AndMask)
767 if (Used != (AndMask | InsertMask)) {
768 KnownBits Known = CurDAG->computeKnownBits(
Op.getOperand(0));
773 Op =
Op.getOperand(0);
777bool SystemZDAGToDAGISel::refineRxSBGMask(RxSBGOperands &RxSBG,
780 if (RxSBG.Rotate != 0)
781 Mask = (
Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate));
783 if (
TII->isRxSBGMask(Mask, RxSBG.BitSize, RxSBG.Start, RxSBG.End)) {
793 if (RxSBG.Rotate != 0)
794 Mask = ((Mask << RxSBG.Rotate) | (Mask >> (64 - RxSBG.Rotate)));
795 return (Mask & RxSBG.Mask) != 0;
798bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG)
const {
800 unsigned Opcode =
N.getOpcode();
803 if (RxSBG.Opcode == SystemZ::RNSBG)
805 if (
N.getOperand(0).getValueSizeInBits() > 64)
807 uint64_t BitSize =
N.getValueSizeInBits();
809 if (!refineRxSBGMask(RxSBG, Mask))
811 RxSBG.Input =
N.getOperand(0);
815 if (RxSBG.Opcode == SystemZ::RNSBG)
818 auto *MaskNode = dyn_cast<ConstantSDNode>(
N.getOperand(1).getNode());
824 if (!refineRxSBGMask(RxSBG, Mask)) {
828 KnownBits Known = CurDAG->computeKnownBits(Input);
830 if (!refineRxSBGMask(RxSBG, Mask))
838 if (RxSBG.Opcode != SystemZ::RNSBG)
841 auto *MaskNode = dyn_cast<ConstantSDNode>(
N.getOperand(1).getNode());
847 if (!refineRxSBGMask(RxSBG, Mask)) {
851 KnownBits Known = CurDAG->computeKnownBits(Input);
852 Mask &= ~Known.One.getZExtValue();
853 if (!refineRxSBGMask(RxSBG, Mask))
862 if (RxSBG.BitSize != 64 ||
N.getValueType() != MVT::i64)
864 auto *CountNode = dyn_cast<ConstantSDNode>(
N.getOperand(1).getNode());
868 RxSBG.Rotate = (RxSBG.Rotate + CountNode->getZExtValue()) & 63;
869 RxSBG.Input =
N.getOperand(0);
875 RxSBG.Input =
N.getOperand(0);
879 if (RxSBG.Opcode != SystemZ::RNSBG) {
881 unsigned InnerBitSize =
N.getOperand(0).getValueSizeInBits();
882 if (!refineRxSBGMask(RxSBG,
allOnes(InnerBitSize)))
885 RxSBG.Input =
N.getOperand(0);
893 unsigned BitSize =
N.getValueSizeInBits();
894 unsigned InnerBitSize =
N.getOperand(0).getValueSizeInBits();
898 if (RxSBG.Mask == 1 && RxSBG.Rotate == 1)
899 RxSBG.Rotate += (BitSize - InnerBitSize);
904 RxSBG.Input =
N.getOperand(0);
909 auto *CountNode = dyn_cast<ConstantSDNode>(
N.getOperand(1).getNode());
913 uint64_t Count = CountNode->getZExtValue();
914 unsigned BitSize =
N.getValueSizeInBits();
915 if (Count < 1 || Count >= BitSize)
918 if (RxSBG.Opcode == SystemZ::RNSBG) {
925 if (!refineRxSBGMask(RxSBG,
allOnes(BitSize - Count) << Count))
929 RxSBG.Rotate = (RxSBG.Rotate + Count) & 63;
930 RxSBG.Input =
N.getOperand(0);
936 auto *CountNode = dyn_cast<ConstantSDNode>(
N.getOperand(1).getNode());
940 uint64_t Count = CountNode->getZExtValue();
941 unsigned BitSize =
N.getValueSizeInBits();
942 if (Count < 1 || Count >= BitSize)
945 if (RxSBG.Opcode == SystemZ::RNSBG || Opcode ==
ISD::SRA) {
953 if (!refineRxSBGMask(RxSBG,
allOnes(BitSize - Count)))
957 RxSBG.Rotate = (RxSBG.Rotate - Count) & 63;
958 RxSBG.Input =
N.getOperand(0);
967 SDNode *
N = CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF,
DL, VT);
973 if (
N.getValueType() == MVT::i32 && VT == MVT::i64)
974 return CurDAG->getTargetInsertSubreg(SystemZ::subreg_l32,
975 DL, VT, getUNDEF(
DL, MVT::i64),
N);
976 if (
N.getValueType() == MVT::i64 && VT == MVT::i32)
977 return CurDAG->getTargetExtractSubreg(SystemZ::subreg_l32,
DL, VT,
N);
978 assert(
N.getValueType() == VT &&
"Unexpected value types");
982bool SystemZDAGToDAGISel::tryRISBGZero(
SDNode *
N) {
984 EVT VT =
N->getValueType(0);
987 RxSBGOperands RISBG(SystemZ::RISBG,
SDValue(
N, 0));
989 while (expandRxSBG(RISBG))
996 if (Count == 0 || isa<ConstantSDNode>(RISBG.Input))
1001 if (Count == 1 &&
N->getOpcode() !=
ISD::AND)
1006 if (Subtarget->hasMiscellaneousExtensions4() &&
1007 RISBG.Rotate >= 1 && RISBG.Rotate <= 4 &&
1008 RISBG.Mask == (((
uint64_t)1 << 32) - 1) << RISBG.Rotate &&
1009 RISBG.Input.getOpcode() ==
ISD::ADD)
1010 if (
auto *
C = dyn_cast<ConstantSDNode>(RISBG.Input.getOperand(1)))
1011 if (isInt<20>(
C->getSExtValue()))
1017 if (RISBG.Rotate == 0) {
1018 bool PreferAnd =
false;
1024 else if (RISBG.Mask == 0xff ||
1025 RISBG.Mask == 0xffff ||
1026 RISBG.Mask == 0x7fffffff ||
1032 else if (
auto *Load = dyn_cast<LoadSDNode>(RISBG.Input)) {
1033 if (
Load->getMemoryVT() == MVT::i32 &&
1036 RISBG.Mask == 0xffffff00 &&
1037 Subtarget->hasLoadAndZeroRightmostByte())
1047 if (
N !=
New.getNode()) {
1050 ReplaceNode(
N,
New.getNode());
1054 if (!
N->isMachineOpcode())
1060 unsigned Opcode = SystemZ::RISBG;
1062 if (Subtarget->hasMiscellaneousExtensions())
1063 Opcode = SystemZ::RISBGN;
1064 EVT OpcodeVT = MVT::i64;
1065 if (VT == MVT::i32 && Subtarget->hasHighWord() &&
1070 RISBG.Start >= 32 && RISBG.End >= RISBG.Start &&
1071 ((RISBG.Start + RISBG.Rotate) & 63) >= 32 &&
1072 ((RISBG.End + RISBG.Rotate) & 63) >=
1073 ((RISBG.Start + RISBG.Rotate) & 63)) {
1074 Opcode = SystemZ::RISBMux;
1075 OpcodeVT = MVT::i32;
1080 getUNDEF(
DL, OpcodeVT),
1081 convertTo(
DL, OpcodeVT, RISBG.Input),
1082 CurDAG->getTargetConstant(RISBG.Start,
DL, MVT::i32),
1083 CurDAG->getTargetConstant(RISBG.End | 128,
DL, MVT::i32),
1084 CurDAG->getTargetConstant(RISBG.Rotate,
DL, MVT::i32)
1087 DL, VT,
SDValue(CurDAG->getMachineNode(Opcode,
DL, OpcodeVT, Ops), 0));
1088 ReplaceNode(
N,
New.getNode());
1092bool SystemZDAGToDAGISel::tryRxSBG(
SDNode *
N,
unsigned Opcode) {
1094 EVT VT =
N->getValueType(0);
1099 RxSBGOperands RxSBG[] = {
1100 RxSBGOperands(Opcode,
N->getOperand(0)),
1101 RxSBGOperands(Opcode,
N->getOperand(1))
1103 unsigned Count[] = { 0, 0 };
1104 for (
unsigned I = 0;
I < 2; ++
I)
1105 while (RxSBG[
I].Input->
hasOneUse() && expandRxSBG(RxSBG[
I]))
1117 if (Count[0] == 0 && Count[1] == 0)
1121 unsigned I = Count[0] > Count[1] ? 0 : 1;
1125 if (Opcode == SystemZ::ROSBG && (RxSBG[
I].Mask & 0xff) == 0)
1126 if (
auto *Load = dyn_cast<LoadSDNode>(Op0.
getNode()))
1127 if (
Load->getMemoryVT() == MVT::i8)
1132 if (Opcode == SystemZ::ROSBG && detectOrAndInsertion(Op0, RxSBG[
I].Mask)) {
1133 Opcode = SystemZ::RISBG;
1135 if (Subtarget->hasMiscellaneousExtensions())
1136 Opcode = SystemZ::RISBGN;
1140 convertTo(
DL, MVT::i64, Op0),
1141 convertTo(
DL, MVT::i64, RxSBG[
I].Input),
1142 CurDAG->getTargetConstant(RxSBG[
I].Start,
DL, MVT::i32),
1143 CurDAG->getTargetConstant(RxSBG[
I].
End,
DL, MVT::i32),
1144 CurDAG->getTargetConstant(RxSBG[
I].Rotate,
DL, MVT::i32)
1147 DL, VT,
SDValue(CurDAG->getMachineNode(Opcode,
DL, MVT::i64, Ops), 0));
1148 ReplaceNode(
N,
New.getNode());
1152void SystemZDAGToDAGISel::splitLargeImmediate(
unsigned Opcode,
SDNode *
Node,
1155 EVT VT =
Node->getValueType(0);
1175 SelectCode(
Upper.getNode());
1176 Upper = Handle.getValue();
1182 ReplaceNode(
Node,
Or.getNode());
1184 SelectCode(
Or.getNode());
1187void SystemZDAGToDAGISel::loadVectorConstant(
1194 EVT VT =
Node->getValueType(0);
1197 for (
unsigned OpVal : VCI.
OpVals)
1198 Ops.
push_back(CurDAG->getTargetConstant(OpVal,
DL, MVT::i32));
1202 ReplaceNode(
Node,
Op.getNode());
1206 SelectCode(BitCast.
getNode());
1208 unsigned SubRegIdx =
1209 (VT.
getSizeInBits() == 32 ? SystemZ::subreg_h32 : SystemZ::subreg_h64);
1211 Node, CurDAG->getTargetExtractSubreg(SubRegIdx,
DL, VT,
Op).getNode());
1213 SelectCode(
Op.getNode());
1220 SDValue CP = CurDAG->getTargetConstantPool(
1222 TLI->getPointerTy(CurDAG->getDataLayout()));
1224 EVT PtrVT =
CP.getValueType();
1226 SDValue(CurDAG->getMachineNode(SystemZ::LARL,
DL, PtrVT, CP), 0),
1227 CurDAG->getTargetConstant(0,
DL, PtrVT),
1228 CurDAG->getRegister(0, PtrVT),
1229 CurDAG->getEntryNode()
1231 ResNode = CurDAG->getMachineNode(SystemZ::VL,
DL, VT, MVT::Other, Ops);
1241 CurDAG->setNodeMemRefs(cast<MachineSDNode>(ResNode), {
MemOp});
1245bool SystemZDAGToDAGISel::tryGather(
SDNode *
N,
unsigned Opcode) {
1247 auto *ElemN = dyn_cast<ConstantSDNode>(ElemV);
1251 unsigned Elem = ElemN->getZExtValue();
1252 EVT VT =
N->getValueType(0);
1256 auto *
Load = dyn_cast<LoadSDNode>(
N->getOperand(1));
1257 if (!Load || !
Load->hasNUsesOfValue(1, 0))
1259 if (
Load->getMemoryVT().getSizeInBits() !=
1260 Load->getValueType(0).getSizeInBits())
1264 if (!selectBDVAddr12Only(
Load->getBasePtr(), ElemV,
Base, Disp, Index) ||
1271 CurDAG->getTargetConstant(Elem,
DL, MVT::i32),
Load->getChain()
1273 SDNode *Res = CurDAG->getMachineNode(Opcode,
DL, VT, MVT::Other, Ops);
1275 ReplaceNode(
N, Res);
1279bool SystemZDAGToDAGISel::tryScatter(
StoreSDNode *Store,
unsigned Opcode) {
1283 if (
Store->getMemoryVT().getSizeInBits() !=
Value.getValueSizeInBits())
1287 auto *ElemN = dyn_cast<ConstantSDNode>(ElemV);
1293 unsigned Elem = ElemN->getZExtValue();
1298 if (!selectBDVAddr12Only(
Store->getBasePtr(), ElemV,
Base, Disp, Index) ||
1304 Vec,
Base, Disp,
Index, CurDAG->getTargetConstant(Elem,
DL, MVT::i32),
1307 ReplaceNode(Store, CurDAG->getMachineNode(Opcode,
DL, MVT::Other, Ops));
1335 LoadNode = cast<LoadSDNode>(Load);
1338 if (!Load.hasOneUse())
1350 bool ChainCheck =
false;
1351 if (Chain == Load.getValue(1)) {
1358 const unsigned int Max = 1024;
1361 if (
Op == Load.getValue(1)) {
1374 if (
Op.getNode() != LoadNode)
1385 MVT::Other, ChainOps);
1402bool SystemZDAGToDAGISel::tryFoldLoadStoreIntoMemOperand(
SDNode *
Node) {
1412 unsigned NewOpc = 0;
1413 bool NegateOperand =
false;
1418 NegateOperand =
true;
1421 if (MemVT == MVT::i32)
1422 NewOpc = SystemZ::ASI;
1423 else if (MemVT == MVT::i64)
1424 NewOpc = SystemZ::AGSI;
1429 NegateOperand =
true;
1432 if (MemVT == MVT::i32)
1433 NewOpc = SystemZ::ALSI;
1434 else if (MemVT == MVT::i64)
1435 NewOpc = SystemZ::ALGSI;
1448 auto *OperandC = dyn_cast<ConstantSDNode>(Operand);
1451 auto OperandV = OperandC->getAPIntValue();
1453 OperandV = -OperandV;
1454 if (OperandV.getSignificantBits() > 8)
1456 Operand = CurDAG->getTargetConstant(OperandV,
DL, MemVT);
1462 SDValue Ops[] = {
Base, Disp, Operand, InputChain };
1464 CurDAG->getMachineNode(NewOpc,
DL, MVT::i32, MVT::Other, Ops);
1465 CurDAG->setNodeMemRefs(
1470 CurDAG->RemoveDeadNode(
Node);
1474bool SystemZDAGToDAGISel::canUseBlockOperation(
StoreSDNode *Store,
1477 if (
Load->getMemoryVT() !=
Store->getMemoryVT())
1481 if (
Load->isVolatile() ||
Store->isVolatile())
1485 if (
Load->isInvariant() &&
Load->isDereferenceable())
1489 const Value *V1 =
Load->getMemOperand()->getValue();
1496 int64_t End1 =
Load->getSrcValueOffset() +
Size;
1497 int64_t End2 =
Store->getSrcValueOffset() +
Size;
1498 if (V1 == V2 && End1 == End2)
1505bool SystemZDAGToDAGISel::storeLoadCanUseMVC(
SDNode *
N)
const {
1506 auto *
Store = cast<StoreSDNode>(
N);
1507 auto *
Load = cast<LoadSDNode>(
Store->getValue());
1521 return canUseBlockOperation(Store, Load);
1524bool SystemZDAGToDAGISel::storeLoadCanUseBlockBinary(
SDNode *
N,
1526 auto *StoreA = cast<StoreSDNode>(
N);
1527 auto *LoadA = cast<LoadSDNode>(StoreA->getValue().getOperand(1 -
I));
1528 auto *LoadB = cast<LoadSDNode>(StoreA->getValue().getOperand(
I));
1529 return !LoadA->isVolatile() && LoadA->getMemoryVT() == LoadB->getMemoryVT() &&
1530 canUseBlockOperation(StoreA, LoadB);
1533bool SystemZDAGToDAGISel::storeLoadIsAligned(
SDNode *
N)
const {
1535 auto *MemAccess = cast<MemSDNode>(
N);
1536 auto *LdSt = dyn_cast<LSBaseSDNode>(MemAccess);
1537 TypeSize StoreSize = MemAccess->getMemoryVT().getStoreSize();
1540 assert(MMO &&
"Expected a memory operand.");
1544 if (MemAccess->getAlign().value() < StoreSize ||
1545 (LdSt && !LdSt->getOffset().isUndef()))
1554 if ((PSV->isGOT() || PSV->isConstantPool()))
1560 dyn_cast<GlobalAddressSDNode>(
BasePtr.getOperand(0))) {
1562 if (GA->getOffset() % StoreSize != 0)
1577 if (
auto *L = dyn_cast<LoadSDNode>(
N))
1578 ETy =
L->getExtensionType();
1579 else if (
auto *AL = dyn_cast<AtomicSDNode>(
N))
1580 ETy =
AL->getExtensionType();
1586void SystemZDAGToDAGISel::Select(
SDNode *
Node) {
1588 if (
Node->isMachineOpcode()) {
1590 Node->setNodeId(-1);
1594 unsigned Opcode =
Node->getOpcode();
1598 if (tryRxSBG(
Node, SystemZ::ROSBG))
1604 if (tryRxSBG(
Node, SystemZ::RXSBG))
1611 if (
Node->getValueType(0) == MVT::i64 &&
1613 if (
auto *Op1 = dyn_cast<ConstantSDNode>(
Node->getOperand(1))) {
1614 uint64_t Val = Op1->getZExtValue();
1617 if (Subtarget->hasMiscellaneousExtensions3()) {
1618 unsigned ChildOpcode =
Node->getOperand(0).getOpcode();
1627 auto Op0 =
Node->getOperand(0);
1628 if (
auto *Op0Op1 = dyn_cast<ConstantSDNode>(Op0->
getOperand(1)))
1629 if (Op0Op1->getZExtValue() == (
uint64_t)-1)
1634 if (Opcode ==
ISD::XOR && Op1->isAllOnes())
1637 splitLargeImmediate(Opcode,
Node,
Node->getOperand(0),
1646 if (tryRxSBG(
Node, SystemZ::RNSBG))
1653 if (tryRISBGZero(
Node))
1658 if (
Node->getValueType(0) == MVT::i128) {
1663 uint64_t Bytes[2] = { 0x0706050403020100ULL, 0x0f0e0d0c0b0a0908ULL };
1667 MVT::v16i8, Ops), 0);
1671 ReplaceNode(
Node, ResNode);
1672 SelectCode(Src.getNode());
1673 SelectCode(ResNode);
1681 if (
Node->getValueType(0) == MVT::i64) {
1689 if (
Node->getValueType(0) == MVT::i128) {
1690 const APInt &Val =
Node->getAsAPIntVal();
1693 loadVectorConstant(VCI,
Node);
1697 SDNode *ResNode = loadPoolVectorConstant(Val, MVT::i128,
SDLoc(
Node));
1698 ReplaceNode(
Node, ResNode);
1709 (Subtarget->hasLoadStoreOnCond2() &&
1710 Node->getValueType(0).isInteger() &&
1711 Node->getValueType(0).getSizeInBits() <= 64 &&
1713 isInt<16>(cast<ConstantSDNode>(Op1)->getSExtValue()) &&
1715 isInt<16>(cast<ConstantSDNode>(Op0)->getSExtValue())))) {
1721 CCMask = CurDAG->getTargetConstant(ConstCCValid ^ ConstCCMask,
1725 CurDAG->UpdateNodeOperands(
Node, Op1, Op0, CCValid, CCMask, Op4);
1726 if (UpdatedNode !=
Node) {
1728 ReplaceNode(
Node, UpdatedNode);
1736 EVT VT =
Node->getValueType(0);
1738 if (ElemBitSize == 32) {
1739 if (tryGather(
Node, SystemZ::VGEF))
1741 }
else if (ElemBitSize == 64) {
1742 if (tryGather(
Node, SystemZ::VGEG))
1749 auto *BVN = cast<BuildVectorSDNode>(
Node);
1752 loadVectorConstant(VCI,
Node);
1760 if (
Imm.isZero() ||
Imm.isNegZero())
1765 loadVectorConstant(VCI,
Node);
1770 if (tryFoldLoadStoreIntoMemOperand(
Node))
1773 unsigned ElemBitSize =
Store->getValue().getValueSizeInBits();
1774 if (ElemBitSize == 32) {
1775 if (tryScatter(Store, SystemZ::VSCEF))
1777 }
else if (ElemBitSize == 64) {
1778 if (tryScatter(Store, SystemZ::VSCEG))
1785 auto *AtomOp = cast<AtomicSDNode>(
Node);
1789 StoreSDNode *St = cast<StoreSDNode>(CurDAG->getTruncStore(
1790 AtomOp->getChain(),
SDLoc(AtomOp), AtomOp->getVal(),
1791 AtomOp->getBasePtr(), AtomOp->getMemoryVT(), AtomOp->getMemOperand()));
1796 if (AtomOp->getSuccessOrdering() == AtomicOrdering::SequentiallyConsistent)
1797 Chain = CurDAG->getMachineNode(SystemZ::Serialize,
SDLoc(AtomOp),
1798 MVT::Other,
SDValue(Chain, 0));
1799 ReplaceNode(
Node, Chain);
1808bool SystemZDAGToDAGISel::SelectInlineAsmMemoryOperand(
1810 std::vector<SDValue> &OutOps) {
1811 SystemZAddressingMode::AddrForm
Form;
1812 SystemZAddressingMode::DispRange DispRange;
1815 switch(ConstraintID) {
1818 case InlineAsm::ConstraintCode::i:
1819 case InlineAsm::ConstraintCode::Q:
1820 case InlineAsm::ConstraintCode::ZQ:
1822 Form = SystemZAddressingMode::FormBD;
1823 DispRange = SystemZAddressingMode::Disp12Only;
1825 case InlineAsm::ConstraintCode::R:
1826 case InlineAsm::ConstraintCode::ZR:
1828 Form = SystemZAddressingMode::FormBDXNormal;
1829 DispRange = SystemZAddressingMode::Disp12Only;
1831 case InlineAsm::ConstraintCode::S:
1832 case InlineAsm::ConstraintCode::ZS:
1834 Form = SystemZAddressingMode::FormBD;
1835 DispRange = SystemZAddressingMode::Disp20Only;
1837 case InlineAsm::ConstraintCode::T:
1838 case InlineAsm::ConstraintCode::m:
1839 case InlineAsm::ConstraintCode::o:
1840 case InlineAsm::ConstraintCode::p:
1841 case InlineAsm::ConstraintCode::ZT:
1846 Form = SystemZAddressingMode::FormBDXNormal;
1847 DispRange = SystemZAddressingMode::Disp20Only;
1851 if (selectBDXAddr(Form, DispRange,
Op,
Base, Disp, Index)) {
1853 Subtarget->getRegisterInfo()->getPointerRegClass(*MF);
1855 SDValue RC = CurDAG->getTargetConstant(TRC->
getID(),
DL, MVT::i32);
1862 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
1870 SDValue(CurDAG->getMachineNode(TargetOpcode::COPY_TO_REGCLASS,
1875 OutOps.push_back(
Base);
1876 OutOps.push_back(Disp);
1877 OutOps.push_back(Index);
1892 if (!
N.hasOneUse() || !
U->hasOneUse())
1899 SDNode *CCUser = *
U->user_begin();
1900 SDNode *CCRegUser =
nullptr;
1902 cast<RegisterSDNode>(CCUser->
getOperand(1))->getReg() == SystemZ::CC) {
1903 for (
auto *U : CCUser->
users()) {
1904 if (CCRegUser ==
nullptr)
1906 else if (CCRegUser != U)
1910 if (CCRegUser ==
nullptr)
1923 if (!IsLegalToFold(
N, U, CCRegUser, OptLevel,
false))
1933struct IPMConversion {
1934 IPMConversion(
unsigned xorValue, int64_t addValue,
unsigned bit)
1935 : XORValue(xorValue), AddValue(addValue),
Bit(bit) {}
2011 auto *TrueOp = dyn_cast<ConstantSDNode>(
Node->getOperand(0));
2012 auto *FalseOp = dyn_cast<ConstantSDNode>(
Node->getOperand(1));
2013 if (!TrueOp || !FalseOp)
2015 if (FalseOp->getZExtValue() != 0)
2017 if (TrueOp->getSExtValue() != 1 && TrueOp->getSExtValue() != -1)
2020 auto *CCValidOp = dyn_cast<ConstantSDNode>(
Node->getOperand(2));
2021 auto *CCMaskOp = dyn_cast<ConstantSDNode>(
Node->getOperand(3));
2022 if (!CCValidOp || !CCMaskOp)
2024 int CCValid = CCValidOp->getZExtValue();
2025 int CCMask = CCMaskOp->getZExtValue();
2034 CurDAG->getConstant(
IPM.XORValue,
DL, MVT::i32));
2038 CurDAG->getNode(
ISD::ADD,
DL, MVT::i32, Result,
2039 CurDAG->getSignedConstant(
IPM.AddValue,
DL, MVT::i32));
2041 EVT VT =
Node->getValueType(0);
2042 if (VT == MVT::i32 &&
IPM.Bit == 31) {
2044 Result = CurDAG->getNode(ShiftOp,
DL, MVT::i32, Result,
2045 CurDAG->getConstant(
IPM.Bit,
DL, MVT::i32));
2050 if (TrueOp->getSExtValue() == 1) {
2053 CurDAG->getConstant(
IPM.Bit,
DL, MVT::i32));
2055 CurDAG->getConstant(1,
DL, VT));
2061 CurDAG->getConstant(ShlAmt,
DL, MVT::i32));
2063 CurDAG->getConstant(SraAmt,
DL, MVT::i32));
2070bool SystemZDAGToDAGISel::shouldSelectForReassoc(
SDNode *
N)
const {
2071 EVT VT =
N->getValueType(0);
2073 return N->getFlags().hasAllowReassociation() &&
2074 N->getFlags().hasNoSignedZeros() && Subtarget->hasVector() &&
2075 (VT != MVT::f32 || Subtarget->hasVectorEnhancements1()) &&
2076 !
N->isStrictFPOpcode();
2079void SystemZDAGToDAGISel::PreprocessISelDAG() {
2082 if (Subtarget->hasLoadStoreOnCond2())
2085 bool MadeChange =
false;
2088 E = CurDAG->allnodes_end();
2095 switch (
N->getOpcode()) {
2098 Res = expandSelectBoolean(
N);
2103 LLVM_DEBUG(
dbgs() <<
"SystemZ DAG preprocessing replacing:\nOld: ");
2109 CurDAG->ReplaceAllUsesOfValueWith(
SDValue(
N, 0), Res);
2115 CurDAG->RemoveDeadNodes();
static msgpack::DocNode getNode(msgpack::DocNode DN, msgpack::Type Type, MCValue Val)
AMDGPU Register Bank Select
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
const HexagonInstrInfo * TII
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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)
DEMANGLE_DUMP_METHOD void dump() const
Class for arbitrary precision integers.
uint64_t getZExtValue() const
Get zero extended value.
This class represents an Operation in the Expression.
A parsed version of the target data layout string in and methods for querying it.
FunctionPass class - This class is used to implement most global optimizations.
const DataLayout & getDataLayout() const
Get the data layout of the module this global belongs to.
This class is used to form a handle around another node that is persistent and is updated across invo...
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.
A description of a memory reference used in the backend.
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.
An SDNode that represents everything that will be needed to construct a MachineInstr.
MachineMemOperand * getMemOperand() const
Return a MachineMemOperand object describing the memory reference performed by operation.
const SDValue & getChain() const
bool isNonTemporal() const
EVT getMemoryVT() const
Return the type of the in-memory value.
Representation for a specific memory location.
Special value supplied for machine level alias analysis.
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.
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
iterator_range< user_iterator > users()
bool hasNUsesOfValue(unsigned NUses, unsigned Value) const
Return true if there are exactly NUSES uses of the indicated value.
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...
virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, InlineAsm::ConstraintCode ConstraintID, std::vector< SDValue > &OutOps)
SelectInlineAsmMemoryOperand - Select the specified address as a target addressing mode,...
static int getUninvalidatedNodeId(SDNode *N)
virtual bool IsProfitableToFold(SDValue N, SDNode *U, SDNode *Root) const
IsProfitableToFold - Returns true if it's profitable to fold the specific operand node N of U during ...
virtual void PreprocessISelDAG()
PreprocessISelDAG - This hook allows targets to hack on the graph before instruction selection starts...
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...
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
unsigned getID() const
Return the register class ID number.
Target - Wrapper for Target specific information.
static IntegerType * getInt128Ty(LLVMContext &C)
LLVM Value Representation.
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 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.
@ C
The default llvm calling convention, compatible with C.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
@ 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)
This is an optimization pass for GlobalISel generic memory operations.
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
FunctionPass * createSystemZISelDag(SystemZTargetMachine &TM, CodeGenOptLevel OptLevel)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
CodeGenOptLevel
Code generation optimization level.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ Or
Bitwise or logical OR of integers.
This struct is a compact representation of a valid (non-zero power of two) alignment.
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 MachinePointerInfo getConstantPool(MachineFunction &MF)
Return a MachinePointerInfo record that refers to the constant pool.
SmallVector< unsigned, 2 > OpVals
bool isVectorConstantLegal(const SystemZSubtarget &Subtarget)