summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r--llvm/lib/Target/SystemZ/README.txt6
-rw-r--r--llvm/lib/Target/SystemZ/SystemZInstrFP.td36
-rw-r--r--llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp6
-rw-r--r--llvm/lib/Target/SystemZ/SystemZShortenInst.cpp6
4 files changed, 37 insertions, 17 deletions
diff --git a/llvm/lib/Target/SystemZ/README.txt b/llvm/lib/Target/SystemZ/README.txt
index e089047d013..cd367d60bab 100644
--- a/llvm/lib/Target/SystemZ/README.txt
+++ b/llvm/lib/Target/SystemZ/README.txt
@@ -52,12 +52,6 @@ We don't use the TEST DATA CLASS instructions.
--
-We could use the generic floating-point forms of LOAD COMPLEMENT,
-LOAD NEGATIVE and LOAD POSITIVE in cases where we don't need the
-condition codes. For example, we could use LCDFR instead of LCDBR.
-
---
-
We only use MVC, XC and CLC for constant-length block operations.
We could extend them to variable-length operations too,
using EXECUTE RELATIVE LONG.
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrFP.td b/llvm/lib/Target/SystemZ/SystemZInstrFP.td
index 27fbd7df288..b895856085e 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrFP.td
+++ b/llvm/lib/Target/SystemZ/SystemZInstrFP.td
@@ -238,26 +238,46 @@ let Predicates = [FeatureFPExtension] in {
// Unary arithmetic
//===----------------------------------------------------------------------===//
+// We prefer generic instructions during isel, because they do not
+// clobber CC and therefore give the scheduler more freedom. In cases
+// the CC is actually useful, the SystemZElimCompare pass will try to
+// convert generic instructions into opcodes that also set CC. Note
+// that lcdf / lpdf / lndf only affect the sign bit, and can therefore
+// be used with fp32 as well. This could be done for fp128, in which
+// case the operands would have to be tied.
+
// Negation (Load Complement).
let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0xF in {
- def LCEBR : UnaryRRE<"lceb", 0xB303, fneg, FP32, FP32>;
- def LCDBR : UnaryRRE<"lcdb", 0xB313, fneg, FP64, FP64>;
+ def LCEBR : UnaryRRE<"lceb", 0xB303, null_frag, FP32, FP32>;
+ def LCDBR : UnaryRRE<"lcdb", 0xB313, null_frag, FP64, FP64>;
def LCXBR : UnaryRRE<"lcxb", 0xB343, fneg, FP128, FP128>;
}
+// Generic form, which does not set CC.
+def LCDFR : UnaryRRE<"lcdf", 0xB373, fneg, FP64, FP64>;
+let isCodeGenOnly = 1 in
+ def LCDFR_32 : UnaryRRE<"lcdf", 0xB373, fneg, FP32, FP32>;
// Absolute value (Load Positive).
let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0xF in {
- def LPEBR : UnaryRRE<"lpeb", 0xB300, fabs, FP32, FP32>;
- def LPDBR : UnaryRRE<"lpdb", 0xB310, fabs, FP64, FP64>;
+ def LPEBR : UnaryRRE<"lpeb", 0xB300, null_frag, FP32, FP32>;
+ def LPDBR : UnaryRRE<"lpdb", 0xB310, null_frag, FP64, FP64>;
def LPXBR : UnaryRRE<"lpxb", 0xB340, fabs, FP128, FP128>;
}
+// Generic form, which does not set CC.
+def LPDFR : UnaryRRE<"lpdf", 0xB370, fabs, FP64, FP64>;
+let isCodeGenOnly = 1 in
+ def LPDFR_32 : UnaryRRE<"lpdf", 0xB370, fabs, FP32, FP32>;
// Negative absolute value (Load Negative).
let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0xF in {
- def LNEBR : UnaryRRE<"lneb", 0xB301, fnabs, FP32, FP32>;
- def LNDBR : UnaryRRE<"lndb", 0xB311, fnabs, FP64, FP64>;
+ def LNEBR : UnaryRRE<"lneb", 0xB301, null_frag, FP32, FP32>;
+ def LNDBR : UnaryRRE<"lndb", 0xB311, null_frag, FP64, FP64>;
def LNXBR : UnaryRRE<"lnxb", 0xB341, fnabs, FP128, FP128>;
}
+// Generic form, which does not set CC.
+def LNDFR : UnaryRRE<"lndf", 0xB371, fnabs, FP64, FP64>;
+let isCodeGenOnly = 1 in
+ def LNDFR_32 : UnaryRRE<"lndf", 0xB371, fnabs, FP32, FP32>;
// Square root.
def SQEBR : UnaryRRE<"sqeb", 0xB314, fsqrt, FP32, FP32>;
@@ -414,6 +434,6 @@ let Defs = [CC], CCValues = 0xF in {
// Peepholes
//===----------------------------------------------------------------------===//
-def : Pat<(f32 fpimmneg0), (LCEBR (LZER))>;
-def : Pat<(f64 fpimmneg0), (LCDBR (LZDR))>;
+def : Pat<(f32 fpimmneg0), (LCDFR_32 (LZER))>;
+def : Pat<(f64 fpimmneg0), (LCDFR (LZDR))>;
def : Pat<(f128 fpimmneg0), (LCXBR (LZXR))>;
diff --git a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
index 8fe86144784..1aeefa46162 100644
--- a/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZInstrInfo.cpp
@@ -1186,6 +1186,12 @@ unsigned SystemZInstrInfo::getLoadAndTest(unsigned Opcode) const {
case SystemZ::LER: return SystemZ::LTEBR;
case SystemZ::LDR: return SystemZ::LTDBR;
case SystemZ::LXR: return SystemZ::LTXBR;
+ case SystemZ::LCDFR: return SystemZ::LCDBR;
+ case SystemZ::LPDFR: return SystemZ::LPDBR;
+ case SystemZ::LNDFR: return SystemZ::LNDBR;
+ case SystemZ::LCDFR_32: return SystemZ::LCEBR;
+ case SystemZ::LPDFR_32: return SystemZ::LPEBR;
+ case SystemZ::LNDFR_32: return SystemZ::LNEBR;
// On zEC12 we prefer to use RISBGN. But if there is a chance to
// actually use the condition code, we may turn it back into RISGB.
// Note that RISBG is not really a "load-and-test" instruction,
diff --git a/llvm/lib/Target/SystemZ/SystemZShortenInst.cpp b/llvm/lib/Target/SystemZ/SystemZShortenInst.cpp
index eeb790ef679..33aa2725a97 100644
--- a/llvm/lib/Target/SystemZ/SystemZShortenInst.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZShortenInst.cpp
@@ -215,15 +215,15 @@ bool SystemZShortenInst::processBlock(MachineBasicBlock &MBB) {
break;
case SystemZ::WFLCDB:
- Changed |= shortenOn01(MI, SystemZ::LCDBR);
+ Changed |= shortenOn01(MI, SystemZ::LCDFR);
break;
case SystemZ::WFLNDB:
- Changed |= shortenOn01(MI, SystemZ::LNDBR);
+ Changed |= shortenOn01(MI, SystemZ::LNDFR);
break;
case SystemZ::WFLPDB:
- Changed |= shortenOn01(MI, SystemZ::LPDBR);
+ Changed |= shortenOn01(MI, SystemZ::LPDFR);
break;
case SystemZ::WFSQDB:
OpenPOWER on IntegriCloud