bool selectBDAddr(SystemZAddressingMode::DispRange DR, SDValue Addr,
SDValue &Base, SDValue &Disp);
+ // Try to match Addr as a FormBDX address with displacement type DR.
+ // Return true on success and if the result had no index. Store the
+ // base and displacement in Base and Disp respectively.
+ bool selectMVIAddr(SystemZAddressingMode::DispRange DR, SDValue Addr,
+ SDValue &Base, SDValue &Disp);
+
// Try to match Addr as a FormBDX* address of form Form with
// displacement type DR. Return true on success, storing the base,
// displacement and index in Base, Disp and Index respectively.
return selectBDAddr(SystemZAddressingMode::Disp20Pair, Addr, Base, Disp);
}
+ // MVI matching routines used by SystemZOperands.td.
+ bool selectMVIAddr12Pair(SDValue Addr, SDValue &Base, SDValue &Disp) {
+ return selectMVIAddr(SystemZAddressingMode::Disp12Pair, Addr, Base, Disp);
+ }
+ bool selectMVIAddr20Pair(SDValue Addr, SDValue &Base, SDValue &Disp) {
+ return selectMVIAddr(SystemZAddressingMode::Disp20Pair, Addr, Base, Disp);
+ }
+
// BDX matching routines used by SystemZOperands.td.
bool selectBDXAddr12Only(SDValue Addr, SDValue &Base, SDValue &Disp,
SDValue &Index) {
SDNode *splitLargeImmediate(unsigned Opcode, SDNode *Node, SDValue Op0,
uint64_t UpperVal, uint64_t LowerVal);
+ // N is a (store (load Y), X) pattern. Return true if it can use an MVC
+ // from Y to X.
bool storeLoadCanUseMVC(SDNode *N) const;
+ // N is a (store (op (load A[0]), (load A[1])), X) pattern. Return true
+ // if A[1 - I] == X and if N can use a block operation like NC from A[I]
+ // to X.
+ bool storeLoadCanUseBlockBinary(SDNode *N, unsigned I) const;
+
public:
SystemZDAGToDAGISel(SystemZTargetMachine &TM, CodeGenOpt::Level OptLevel)
: SelectionDAGISel(TM, OptLevel),
return true;
}
+bool SystemZDAGToDAGISel::selectMVIAddr(SystemZAddressingMode::DispRange DR,
+ SDValue Addr, SDValue &Base,
+ SDValue &Disp) {
+ SystemZAddressingMode AM(SystemZAddressingMode::FormBDXNormal, DR);
+ if (!selectAddress(Addr, AM) || AM.Index.getNode())
+ return false;
+
+ getAddressOperands(AM, Addr.getValueType(), Base, Disp);
+ return true;
+}
+
bool SystemZDAGToDAGISel::selectBDXAddr(SystemZAddressingMode::AddrForm Form,
SystemZAddressingMode::DispRange DR,
SDValue Addr, SDValue &Base,
return Or.getNode();
}
-// N is a (store (load ...), ...) pattern. Return true if it can use MVC.
-bool SystemZDAGToDAGISel::storeLoadCanUseMVC(SDNode *N) const {
- StoreSDNode *Store = cast<StoreSDNode>(N);
- LoadSDNode *Load = cast<LoadSDNode>(Store->getValue().getNode());
+// Return true if Load and Store:
+// - are loads and stores of the same size;
+// - do not partially overlap; and
+// - can be decomposed into what are logically individual character accesses
+// without changing the semantics.
+static bool canUseBlockOperation(StoreSDNode *Store, LoadSDNode *Load,
+ AliasAnalysis *AA) {
+ // Check that the two memory operands have the same size.
+ if (Load->getMemoryVT() != Store->getMemoryVT())
+ return false;
- // MVC is logically a bytewise copy, so can't be used for volatile accesses.
+ // Volatility stops an access from being decomposed.
if (Load->isVolatile() || Store->isVolatile())
return false;
- // Prefer not to use MVC if either address can use ... RELATIVE LONG
- // instructions.
- assert(Load->getMemoryVT() == Store->getMemoryVT() &&
- "Should already have checked that the types match");
- uint64_t Size = Load->getMemoryVT().getStoreSize();
- if (Size > 1 && Size <= 8) {
- // Prefer LHRL, LRL and LGRL.
- if (Load->getBasePtr().getOpcode() == SystemZISD::PCREL_WRAPPER)
- return false;
- // Prefer STHRL, STRL and STGRL.
- if (Store->getBasePtr().getOpcode() == SystemZISD::PCREL_WRAPPER)
- return false;
- }
-
// There's no chance of overlap if the load is invariant.
if (Load->isInvariant())
return true;
// If both operands are aligned, they must be equal or not overlap.
+ uint64_t Size = Load->getMemoryVT().getStoreSize();
if (Load->getAlignment() >= Size && Store->getAlignment() >= Size)
return true;
AliasAnalysis::Location(V2, End2, Store->getTBAAInfo()));
}
+bool SystemZDAGToDAGISel::storeLoadCanUseMVC(SDNode *N) const {
+ StoreSDNode *Store = cast<StoreSDNode>(N);
+ LoadSDNode *Load = cast<LoadSDNode>(Store->getValue());
+
+ // Prefer not to use MVC if either address can use ... RELATIVE LONG
+ // instructions.
+ uint64_t Size = Load->getMemoryVT().getStoreSize();
+ if (Size > 1 && Size <= 8) {
+ // Prefer LHRL, LRL and LGRL.
+ if (Load->getBasePtr().getOpcode() == SystemZISD::PCREL_WRAPPER)
+ return false;
+ // Prefer STHRL, STRL and STGRL.
+ if (Store->getBasePtr().getOpcode() == SystemZISD::PCREL_WRAPPER)
+ return false;
+ }
+
+ return canUseBlockOperation(Store, Load, AA);
+}
+
+bool SystemZDAGToDAGISel::storeLoadCanUseBlockBinary(SDNode *N,
+ unsigned I) const {
+ StoreSDNode *StoreA = cast<StoreSDNode>(N);
+ LoadSDNode *LoadA = cast<LoadSDNode>(StoreA->getValue().getOperand(1 - I));
+ LoadSDNode *LoadB = cast<LoadSDNode>(StoreA->getValue().getOperand(I));
+ if (LoadA->isVolatile() ||
+ LoadA->getMemoryVT() != StoreA->getMemoryVT() ||
+ LoadA->getBasePtr() != StoreA->getBasePtr())
+ return false;
+ return canUseBlockOperation(StoreA, LoadB, AA);
+}
+
SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) {
// Dump information about the Node being selected
DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n");