summaryrefslogtreecommitdiff
path: root/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-07-09 09:46:39 +0000
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-07-09 09:46:39 +0000
commit2e015ef9bb40e5d9f98db9a9509b9986873089ea (patch)
treeb728ba79dcd6a132edb728055829e0bb6dce5d40 /lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
parentf6ea5e0d8007234fc74c1ff6ac2c3ca316c41d92 (diff)
downloadllvm-2e015ef9bb40e5d9f98db9a9509b9986873089ea.tar.gz
llvm-2e015ef9bb40e5d9f98db9a9509b9986873089ea.tar.bz2
llvm-2e015ef9bb40e5d9f98db9a9509b9986873089ea.tar.xz
[SystemZ] Use MVC for simple load/store pairs
Look for patterns of the form (store (load ...), ...) in which the two locations are known not to partially overlap. (Identical locations are OK.) These sequences are better implemented by MVC unless either the load or the store could use RELATIVE LONG instructions. The testcase showed that we weren't using LHRL and LGHRL for extload16, only sextloadi16. The patch fixes that too. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@185919 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target/SystemZ/SystemZISelDAGToDAG.cpp')
-rw-r--r--lib/Target/SystemZ/SystemZISelDAGToDAG.cpp46
1 files changed, 46 insertions, 0 deletions
diff --git a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
index f10ba23b6f..0891adc0e3 100644
--- a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
+++ b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "SystemZTargetMachine.h"
+#include "llvm/Analysis/AliasAnalysis.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
@@ -209,6 +210,8 @@ class SystemZDAGToDAGISel : public SelectionDAGISel {
SDNode *splitLargeImmediate(unsigned Opcode, SDNode *Node, SDValue Op0,
uint64_t UpperVal, uint64_t LowerVal);
+ bool storeLoadCanUseMVC(SDNode *N) const;
+
public:
SystemZDAGToDAGISel(SystemZTargetMachine &TM, CodeGenOpt::Level OptLevel)
: SelectionDAGISel(TM, OptLevel),
@@ -533,6 +536,49 @@ 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());
+
+ // MVC is logically a bytewise copy, so can't be used for volatile accesses.
+ 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.
+ if (Load->getAlignment() >= Size && Store->getAlignment() >= Size)
+ return true;
+
+ // Otherwise we need to check whether there's an alias.
+ const Value *V1 = Load->getSrcValue();
+ const Value *V2 = Store->getSrcValue();
+ if (!V1 || !V2)
+ return false;
+
+ int64_t End1 = Load->getSrcValueOffset() + Size;
+ int64_t End2 = Store->getSrcValueOffset() + Size;
+ return !AA->alias(AliasAnalysis::Location(V1, End1, Load->getTBAAInfo()),
+ AliasAnalysis::Location(V2, End2, Store->getTBAAInfo()));
+}
+
SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) {
// Dump information about the Node being selected
DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n");