aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-09-05 10:36:45 +0000
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-09-05 10:36:45 +0000
commit16277c4698f36a756c540fae326874774156aaed (patch)
tree640d07133c8f2ab9f909e7b2c464f96e6c1a5496 /lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
parenta83aeae350d822ec84ded34ff3fdf1e0917d3bfd (diff)
downloadexternal_llvm-16277c4698f36a756c540fae326874774156aaed.zip
external_llvm-16277c4698f36a756c540fae326874774156aaed.tar.gz
external_llvm-16277c4698f36a756c540fae326874774156aaed.tar.bz2
[SystemZ] Add NC, OC and XC
For now these are just used to handle scalar ANDs, ORs and XORs in which all operands are memory. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@190041 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/SystemZ/SystemZISelDAGToDAG.cpp')
-rw-r--r--lib/Target/SystemZ/SystemZISelDAGToDAG.cpp69
1 files changed, 50 insertions, 19 deletions
diff --git a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
index e0d5437..9d71c39 100644
--- a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
+++ b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
@@ -290,8 +290,15 @@ class SystemZDAGToDAGISel : public SelectionDAGISel {
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),
@@ -925,34 +932,27 @@ SDNode *SystemZDAGToDAGISel::splitLargeImmediate(unsigned Opcode, SDNode *Node,
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;
@@ -968,6 +968,37 @@ bool SystemZDAGToDAGISel::storeLoadCanUseMVC(SDNode *N) const {
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");