IBM Z: Prevent mach optimization on doloop patterns
authorAndreas Krebbel <krebbel@linux.ibm.com>
Wed, 17 Jun 2020 15:10:05 +0000 (17:10 +0200)
committerAndreas Krebbel <krebbel@linux.ibm.com>
Wed, 17 Jun 2020 15:11:45 +0000 (17:11 +0200)
s390_fix_long_loop_prediction is used in machine dependent
reorg. There we use single_set to distingiush between conditional
jumps and branch on count patterns.  However, single_set returns a
non-NULL value also for PARALLELs in case one of the SETs is dead.

2020-06-17  Andreas Krebbel  <krebbel@linux.ibm.com>

gcc/
* config/s390/s390.c (s390_fix_long_loop_prediction): Exit early
for PARALLELs.

gcc/testsuite/
* gcc.target/s390/20200617.c: New test.

gcc/config/s390/s390.c
gcc/testsuite/gcc.target/s390/20200617.c [new file with mode: 0644]

index 758315c0c724938851727526a380a1b020959976..bd49a897c76f2969e14ff97aa36eca4ddfb22f5e 100644 (file)
@@ -13957,8 +13957,13 @@ s390_fix_long_loop_prediction (rtx_insn *insn)
   int distance;
 
   /* This will exclude branch on count and branch on index patterns
-     since these are correctly statically predicted.  */
-  if (!set
+     since these are correctly statically predicted.
+
+     The additional check for a PARALLEL is required here since
+     single_set might be != NULL for PARALLELs where the set of the
+     iteration variable is dead.  */
+  if (GET_CODE (PATTERN (insn)) == PARALLEL
+      || !set
       || SET_DEST (set) != pc_rtx
       || GET_CODE (SET_SRC(set)) != IF_THEN_ELSE)
     return false;
diff --git a/gcc/testsuite/gcc.target/s390/20200617.c b/gcc/testsuite/gcc.target/s390/20200617.c
new file mode 100644 (file)
index 0000000..067d2e1
--- /dev/null
@@ -0,0 +1,23 @@
+/* This ICE'd before f9e1ea10e657af9fb02fafecf1a600740fd34409 because
+   a doloop pattern with a dead set of the iteration variable was
+   generated and s390_fix_long_loop_prediction then failed to
+   recognize it as branch on count pattern.  */
+
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=z10" } */
+
+int a, d, e, f;
+long b;
+long *volatile c;
+void
+fn1() {
+  for (; e; ++e)
+    if (d)
+      ;
+    else {
+      a = 0;
+      for (; a != 14; ++a)
+       *c = b && f;
+      d = 8;
+    }
+}