aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>2017-03-20 09:33:11 +0000
committerAndreas Krebbel <krebbel@linux.vnet.ibm.com>2017-03-20 09:33:11 +0000
commit477999046dcffd943d5c3aa7a67247b73d047a7c (patch)
tree847bd59b1f3c3df6fda4292ba44e72ac9fff3f69
parentef971097148e4d139240ae6ca8d16d21ea448199 (diff)
S/390: PR78857: Don't use load and test if result is live.
The FP load and test instruction should not be used for a comparison if the target operand is being used afterwards. It unfortunately turns SNaNs into QNaNs. gcc/ChangeLog: 2017-03-20 Andreas Krebbel <krebbel@linux.vnet.ibm.com> PR target/78857 * config/s390/s390.md ("cmp<mode>_ccs_0"): Add a clobber of the target operand. A new splitter adds the clobber statement in case the target operand is dead anyway. gcc/testsuite/ChangeLog: 2017-03-20 Andreas Krebbel <krebbel@linux.vnet.ibm.com> PR target/78857 * gcc.target/s390/load-and-test-fp-1.c: New test. * gcc.target/s390/load-and-test-fp-2.c: New test. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@246274 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/config/s390/s390.md27
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.target/s390/load-and-test-fp-1.c17
-rw-r--r--gcc/testsuite/gcc.target/s390/load-and-test-fp-2.c16
5 files changed, 71 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 95f52b372a3..70c85b3d094 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,10 @@
+2017-03-20 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ PR target/78857
+ * config/s390/s390.md ("cmp<mode>_ccs_0"): Add a clobber of the
+ target operand. A new splitter adds the clobber statement in case
+ the target operand is dead anyway.
+
2017-03-19 Gerald Pfeifer <gerald@pfeifer.com>
* doc/install.texi (Specific) <sparc-*-linux*>: No longer refer
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 164a644b3ae..19daf317c10 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -1284,16 +1284,39 @@
; (TF|DF|SF|TD|DD|SD) instructions
+
+; load and test instructions turn SNaN into QNaN what is not
+; acceptable if the target will be used afterwards. On the other hand
+; they are quite convenient for implementing comparisons with 0.0. So
+; try to enable them via splitter if the value isn't needed anymore.
+
; ltxbr, ltdbr, ltebr, ltxtr, ltdtr
(define_insn "*cmp<mode>_ccs_0"
[(set (reg CC_REGNUM)
- (compare (match_operand:FP 0 "register_operand" "f")
- (match_operand:FP 1 "const0_operand" "")))]
+ (compare (match_operand:FP 0 "register_operand" "f")
+ (match_operand:FP 1 "const0_operand" "")))
+ (clobber (match_operand:FP 2 "register_operand" "=0"))]
"s390_match_ccmode(insn, CCSmode) && TARGET_HARD_FLOAT"
"lt<xde><bt>r\t%0,%0"
[(set_attr "op_type" "RRE")
(set_attr "type" "fsimp<mode>")])
+(define_split
+ [(set (match_operand 0 "cc_reg_operand")
+ (compare (match_operand:FP 1 "register_operand")
+ (match_operand:FP 2 "const0_operand")))]
+ "TARGET_HARD_FLOAT && REG_P (operands[1]) && dead_or_set_p (insn, operands[1])"
+ [(parallel
+ [(set (match_dup 0) (match_dup 3))
+ (clobber (match_dup 1))])]
+ {
+ /* s390_match_ccmode requires the compare to have the same CC mode
+ as the CC destination register. */
+ operands[3] = gen_rtx_COMPARE (GET_MODE (operands[0]),
+ operands[1], operands[2]);
+ })
+
+
; cxtr, cxbr, cdtr, cdbr, cebr, cdb, ceb
(define_insn "*cmp<mode>_ccs"
[(set (reg CC_REGNUM)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7a8dbc0aef0..ee5893d305a 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,9 @@
+2017-03-20 Andreas Krebbel <krebbel@linux.vnet.ibm.com>
+
+ PR target/78857
+ * gcc.target/s390/load-and-test-fp-1.c: New test.
+ * gcc.target/s390/load-and-test-fp-2.c: New test.
+
2017-03-18 Paul Thomas <pault@gcc.gnu.org>
PR fortran/79676
diff --git a/gcc/testsuite/gcc.target/s390/load-and-test-fp-1.c b/gcc/testsuite/gcc.target/s390/load-and-test-fp-1.c
new file mode 100644
index 00000000000..b9d59122242
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/load-and-test-fp-1.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mzarch" } */
+
+/* a is used after the comparison. We cannot use load and test here
+ since it would turn SNaNs into QNaNs. */
+
+double gl;
+
+double
+foo (double dummy, double a)
+{
+ if (a == 0.0)
+ gl = 1;
+ return a;
+}
+
+/* { dg-final { scan-assembler "cdbr\t" } } */
diff --git a/gcc/testsuite/gcc.target/s390/load-and-test-fp-2.c b/gcc/testsuite/gcc.target/s390/load-and-test-fp-2.c
new file mode 100644
index 00000000000..7646fdd5def
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/load-and-test-fp-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+
+/* a is not used after the comparison. So we should use load and test
+ here. */
+
+double gl;
+
+void
+bar (double a)
+{
+ if (a == 0.0)
+ gl = 1;
+}
+
+/* { dg-final { scan-assembler "ltdbr\t" } } */