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.
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;
--- /dev/null
+/* 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;
+ }
+}