S/390: PR78857: Don't use load and test if result is live.
authorAndreas Krebbel <krebbel@linux.vnet.ibm.com>
Mon, 20 Mar 2017 09:33:11 +0000 (09:33 +0000)
committerAndreas Krebbel <krebbel@gcc.gnu.org>
Mon, 20 Mar 2017 09:33:11 +0000 (09:33 +0000)
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.

From-SVN: r246274

gcc/ChangeLog
gcc/config/s390/s390.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/s390/load-and-test-fp-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/s390/load-and-test-fp-2.c [new file with mode: 0644]

index 95f52b372a3bfdbbf175ff0806c596b5cf3c035a..70c85b3d094615c99300350cdf7d024c8e602be6 100644 (file)
@@ -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 
index 164a644b3ae82f2335996b3a7ba1c89ca1fe111c..19daf317c107659c7db7cd5294a82c1ebfca7272 100644 (file)
 
 ; (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)
index 7a8dbc0aef087ef7d6323d716607e541491d60b9..ee5893d305a6ec2b5a0319ec49fae519abab9d81 100644 (file)
@@ -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 (file)
index 0000000..b9d5912
--- /dev/null
@@ -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 (file)
index 0000000..7646fdd
--- /dev/null
@@ -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" } } */