summaryrefslogtreecommitdiff
path: root/lib/Target
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
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')
-rw-r--r--lib/Target/SystemZ/SystemZISelDAGToDAG.cpp46
-rw-r--r--lib/Target/SystemZ/SystemZInstrFP.td4
-rw-r--r--lib/Target/SystemZ/SystemZInstrInfo.td22
-rw-r--r--lib/Target/SystemZ/SystemZPatterns.td14
4 files changed, 86 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");
diff --git a/lib/Target/SystemZ/SystemZInstrFP.td b/lib/Target/SystemZ/SystemZInstrFP.td
index 4317306999..23a3790c4a 100644
--- a/lib/Target/SystemZ/SystemZInstrFP.td
+++ b/lib/Target/SystemZ/SystemZInstrFP.td
@@ -75,6 +75,10 @@ def : CopySign128<FP64, (CPSDRdd (EXTRACT_SUBREG FP128:$src1, subreg_high),
def : CopySign128<FP128, (CPSDRdd (EXTRACT_SUBREG FP128:$src1, subreg_high),
(EXTRACT_SUBREG FP128:$src2, subreg_high))>;
+defm LoadStoreF32 : MVCLoadStore<load, store, f32, MVCWrapper, 4>;
+defm LoadStoreF64 : MVCLoadStore<load, store, f64, MVCWrapper, 8>;
+defm LoadStoreF128 : MVCLoadStore<load, store, f128, MVCWrapper, 16>;
+
//===----------------------------------------------------------------------===//
// Load instructions
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td
index b4e5c2583b..5e13c7f346 100644
--- a/lib/Target/SystemZ/SystemZInstrInfo.td
+++ b/lib/Target/SystemZ/SystemZInstrInfo.td
@@ -294,6 +294,20 @@ let mayLoad = 1, mayStore = 1, usesCustomInserter = 1 in
[(z_mvc bdaddr12only:$dest, bdaddr12only:$src,
imm32len8:$length)]>;
+defm LoadStore8_32 : MVCLoadStore<anyextloadi8, truncstorei8, i32,
+ MVCWrapper, 1>;
+defm LoadStore16_32 : MVCLoadStore<anyextloadi16, truncstorei16, i32,
+ MVCWrapper, 2>;
+defm LoadStore32_32 : MVCLoadStore<load, store, i32, MVCWrapper, 4>;
+
+defm LoadStore8 : MVCLoadStore<anyextloadi8, truncstorei8, i64,
+ MVCWrapper, 1>;
+defm LoadStore16 : MVCLoadStore<anyextloadi16, truncstorei16, i64,
+ MVCWrapper, 2>;
+defm LoadStore32 : MVCLoadStore<anyextloadi32, truncstorei32, i64,
+ MVCWrapper, 4>;
+defm LoadStore64 : MVCLoadStore<load, store, i64, MVCWrapper, 8>;
+
//===----------------------------------------------------------------------===//
// Sign extensions
//===----------------------------------------------------------------------===//
@@ -339,6 +353,14 @@ def : Pat<(i64 (extloadi8 bdxaddr20only:$src)), (LGB bdxaddr20only:$src)>;
def : Pat<(i64 (extloadi16 bdxaddr20only:$src)), (LGH bdxaddr20only:$src)>;
def : Pat<(i64 (extloadi32 bdxaddr20only:$src)), (LGF bdxaddr20only:$src)>;
+// We want PC-relative addresses to be tried ahead of BD and BDX addresses.
+// However, BDXs have two extra operands and are therefore 6 units more
+// complex.
+let AddedComplexity = 7 in {
+ def : Pat<(i32 (extloadi16 pcrel32:$src)), (LHRL pcrel32:$src)>;
+ def : Pat<(i64 (extloadi16 pcrel32:$src)), (LGHRL pcrel32:$src)>;
+}
+
//===----------------------------------------------------------------------===//
// Zero extensions
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/SystemZ/SystemZPatterns.td b/lib/Target/SystemZ/SystemZPatterns.td
index fb6c2219df..74cc5f019a 100644
--- a/lib/Target/SystemZ/SystemZPatterns.td
+++ b/lib/Target/SystemZ/SystemZPatterns.td
@@ -65,3 +65,17 @@ multiclass InsertMem<string type, Instruction insn, RegisterOperand cls,
(load mode:$src2), cls:$src1),
(insn cls:$src1, mode:$src2)>;
}
+
+// Use MVC instruction INSN for a load of type LOAD followed by a store
+// of type STORE. VT is the type of the intermediate register and LENGTH
+// is the number of bytes to copy (which may be smaller than VT).
+multiclass MVCLoadStore<SDPatternOperator load, SDPatternOperator store,
+ ValueType vt, Instruction insn, bits<5> length> {
+ def Pat : PatFrag<(ops node:$dest, node:$src),
+ (store (vt (load node:$src)), node:$dest),
+ [{ return storeLoadCanUseMVC(N); }]>;
+
+ def : Pat<(!cast<SDPatternOperator>(NAME##"Pat") bdaddr12only:$dest,
+ bdaddr12only:$src),
+ (insn bdaddr12only:$dest, bdaddr12only:$src, length)>;
+}