diff mbox series

Fix compare-elim.c ICE (PR rtl-optimization/82913)

Message ID 20171109195832.GE14653@tucnak
State New
Headers show
Series Fix compare-elim.c ICE (PR rtl-optimization/82913) | expand

Commit Message

Jakub Jelinek Nov. 9, 2017, 7:58 p.m. UTC
Hi!

My recent changes to compare-elim.c introduced ICE on the following
testcase.
When computing cmp->in_a_setter, I've made sure it is single_set
and therefore I've left the if (!set) return false; stuff out.
That usually works, but doesn't if an earlier try_eliminate_compare or
try_merge_compare turns that cmp->in_a_setter instruction into
a cmp + arith parallel.  In that case, previously we'd give up and
with the following patch we do as well.

In theory, in some cases we could do better than that, e.g. on this
testcase there is a SImode comparison of %eax and 0 merged by
try_eliminate_compare and then there is a DImode comparison of %rax and 0
that we ICE on.  The insn has a zero_extend of plus, and the user
of the comparison looks only at the zero flag, so in this case we could
leave the second comparison out, as zero extension shouldn't affect the zero
flag.  If the comparison user looked at some other flags like sign,
overflow, carry etc., that wouldn't be the case, so in order to optimize
away the second comparison we'd need to use some specialized CC mode like
CCZ.

Anyway, this patch doesn't do those smarts, just restores previous behavior.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2017-11-09  Jakub Jelinek  <jakub@redhat.com>

	PR rtl-optimization/82913
	* compare-elim.c (try_merge_compare): Punt if def_insn is not
	single set.

	* gcc.c-torture/compile/pr82913.c: New test.


	Jakub

Comments

Eric Botcazou Nov. 9, 2017, 11:42 p.m. UTC | #1
> Anyway, this patch doesn't do those smarts, just restores previous behavior.
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2017-11-09  Jakub Jelinek  <jakub@redhat.com>
> 
> 	PR rtl-optimization/82913
> 	* compare-elim.c (try_merge_compare): Punt if def_insn is not
> 	single set.
> 
> 	* gcc.c-torture/compile/pr82913.c: New test.

OK, thanks.
diff mbox series

Patch

--- gcc/compare-elim.c.jj	2017-11-01 22:51:37.000000000 +0100
+++ gcc/compare-elim.c	2017-11-09 11:44:18.996213647 +0100
@@ -683,6 +683,8 @@  try_merge_compare (struct comparison *cm
 
   rtx_insn *def_insn = cmp->in_a_setter;
   rtx set = single_set (def_insn);
+  if (!set)
+    return false;
 
   if (!can_merge_compare_into_arith (cmp_insn, def_insn))
     return false;
--- gcc/testsuite/gcc.c-torture/compile/pr82913.c.jj	2017-11-09 11:47:18.779031240 +0100
+++ gcc/testsuite/gcc.c-torture/compile/pr82913.c	2017-11-09 11:46:59.000000000 +0100
@@ -0,0 +1,23 @@ 
+/* PR rtl-optimization/82913 */
+
+unsigned int a;
+unsigned long int b;
+
+int
+foo (void)
+{
+  ++a;
+  b = 0;
+}
+
+unsigned long int
+bar (int x)
+{
+  if (!foo () || !a)
+    {
+      int c = a != b;
+      if (c != x)
+        return a;
+    }
+  return 0;
+}