diff mbox

Fix phiopt ICE in Factor conversion in COND_EXPR (PR tree-optimization/66949)

Message ID 20151208162133.GQ3175@redhat.com
State New
Headers show

Commit Message

Marek Polacek Dec. 8, 2015, 4:21 p.m. UTC
The following is a conservative fix for this PR.  This is an ICE transpiring
in the new "Factor conversion in COND_EXPR" optimization added in r225722.

Before this optimization kicks in, we have
  <bb 2>:
  ...
  p1_32 = (short unsigned int) _20;

  <bb 3>:
  ...
  iftmp.0_18 = (short unsigned int) _20;

  <bb 4>:
  ...
  # iftmp.0_19 = PHI <iftmp.0_18(3), p1_32(2)>

after factor_out_conditional_conversion does its work, we end up with those two
def stmts removed and instead of the PHI we'll have

  # _35 = PHI <_20(3), _20(2)>
  iftmp.0_19 = (short unsigned int) _35;

That itself looks like a fine optimization, but after factor_out_conditional_conversion
there's
 320               phis = phi_nodes (bb2);
 321               phi = single_non_singleton_phi_for_edges (phis, e1, e2);
 322               gcc_assert (phi);
and phis look like
  b.2_38 = PHI <b.2_9(3), b.2_9(2)>
  _35 = PHI <_20(3), _20(2)>
so single_non_singleton_phi_for_edges returns NULL and the subsequent assert triggers.

With this patch we won't ICE (and PRE should clean this up anyway), but I don't know,
maybe I should try harder to optimize even this problematical case (not sure how hard
it would be...)?

pr66949-2.c only ICEd on powerpc64le and I have verified that this patch fixes it too.

Bootstrapped/regtested on x86_64-linux, ok for trunk?

2015-12-08  Marek Polacek  <polacek@redhat.com>

	PR tree-optimization/66949
	* tree-ssa-phiopt.c (factor_out_conditional_conversion): Return false if
	NEW_ARG0 and NEW_ARG1 are equal.

	* gcc.dg/torture/pr66949-1.c: New test.
	* gcc.dg/torture/pr66949-2.c: New test.


	Marek

Comments

Kugan Vivekanandarajah Dec. 8, 2015, 11:15 p.m. UTC | #1
On 09/12/15 03:21, Marek Polacek wrote:
> The following is a conservative fix for this PR.  This is an ICE transpiring
> in the new "Factor conversion in COND_EXPR" optimization added in r225722.
> 
> Before this optimization kicks in, we have
>   <bb 2>:
>   ...
>   p1_32 = (short unsigned int) _20;
> 
>   <bb 3>:
>   ...
>   iftmp.0_18 = (short unsigned int) _20;
> 
>   <bb 4>:
>   ...
>   # iftmp.0_19 = PHI <iftmp.0_18(3), p1_32(2)>
> 
> after factor_out_conditional_conversion does its work, we end up with those two
> def stmts removed and instead of the PHI we'll have
> 
>   # _35 = PHI <_20(3), _20(2)>
>   iftmp.0_19 = (short unsigned int) _35;
> 
> That itself looks like a fine optimization, but after factor_out_conditional_conversion
> there's
>  320               phis = phi_nodes (bb2);
>  321               phi = single_non_singleton_phi_for_edges (phis, e1, e2);
>  322               gcc_assert (phi);
> and phis look like
>   b.2_38 = PHI <b.2_9(3), b.2_9(2)>
>   _35 = PHI <_20(3), _20(2)>
> so single_non_singleton_phi_for_edges returns NULL and the subsequent assert triggers.
> 
> With this patch we won't ICE (and PRE should clean this up anyway), but I don't know,
> maybe I should try harder to optimize even this problematical case (not sure how hard
> it would be...)?

Hi Marek,

Thanks for fixing this. Yes, we can try remove the PHI in
factor_out_conditional_conversion. But as you said, it might not be
important. In any case, please let me know if you want me to try doing that.

Thanks,
Kugan


> 
> pr66949-2.c only ICEd on powerpc64le and I have verified that this patch fixes it too.
> 
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
> 
> 2015-12-08  Marek Polacek  <polacek@redhat.com>
> 
> 	PR tree-optimization/66949
> 	* tree-ssa-phiopt.c (factor_out_conditional_conversion): Return false if
> 	NEW_ARG0 and NEW_ARG1 are equal.
> 
> 	* gcc.dg/torture/pr66949-1.c: New test.
> 	* gcc.dg/torture/pr66949-2.c: New test.
> 
> diff --git gcc/testsuite/gcc.dg/torture/pr66949-1.c gcc/testsuite/gcc.dg/torture/pr66949-1.c
> index e69de29..1b765bc 100644
> --- gcc/testsuite/gcc.dg/torture/pr66949-1.c
> +++ gcc/testsuite/gcc.dg/torture/pr66949-1.c
> @@ -0,0 +1,28 @@
> +/* PR tree-optimization/66949 */
> +/* { dg-do compile } */
> +
> +int a, *b = &a, c;
> +
> +unsigned short
> +fn1 (unsigned short p1, unsigned int p2)
> +{
> +  return p2 > 1 || p1 >> p2 ? p1 : p1 << p2;
> +}
> +
> +void
> +fn2 ()
> +{
> +  int *d = &a;
> +  for (a = 0; a < -1; a = 1)
> +    ;
> +  if (a < 0)
> +    c = 0;
> +  *b = fn1 (*d || c, *d);
> +}
> +
> +int
> +main ()
> +{
> +  fn2 ();
> +  return 0;
> +}
> diff --git gcc/testsuite/gcc.dg/torture/pr66949-2.c gcc/testsuite/gcc.dg/torture/pr66949-2.c
> index e69de29..e6250a3 100644
> --- gcc/testsuite/gcc.dg/torture/pr66949-2.c
> +++ gcc/testsuite/gcc.dg/torture/pr66949-2.c
> @@ -0,0 +1,23 @@
> +/* PR tree-optimization/66949 */
> +/* { dg-do compile } */
> +
> +char a;
> +int b, c, d;
> +extern int fn2 (void);
> +
> +short
> +fn1 (short p1, short p2)
> +{
> +  return p2 == 0 ? p1 : p1 / p2;
> +}
> +
> +int
> +main (void)
> +{
> +  char e = 1;
> +  int f = 7;
> +  c = a >> f;
> +  b = fn1 (c, 0 < d <= e && fn2 ());
> +
> +  return 0;
> +}
> diff --git gcc/tree-ssa-phiopt.c gcc/tree-ssa-phiopt.c
> index 344cd2f..caac5d5 100644
> --- gcc/tree-ssa-phiopt.c
> +++ gcc/tree-ssa-phiopt.c
> @@ -477,6 +477,11 @@ factor_out_conditional_conversion (edge e0, edge e1, gphi *phi,
>  	return false;
>      }
>  
> +  /* If we were to continue, we'd create a PHI with same arguments for edges
> +     E0 and E1.  That could get us in trouble later, so punt.  */
> +  if (operand_equal_for_phi_arg_p (new_arg0, new_arg1))
> +    return false;
> +
>    /*  If arg0/arg1 have > 1 use, then this transformation actually increases
>        the number of expressions evaluated at runtime.  */
>    if (!has_single_use (arg0)
> 
> 	Marek
>
Richard Biener Dec. 9, 2015, 10:41 a.m. UTC | #2
On Tue, Dec 8, 2015 at 5:21 PM, Marek Polacek <polacek@redhat.com> wrote:
> The following is a conservative fix for this PR.  This is an ICE transpiring
> in the new "Factor conversion in COND_EXPR" optimization added in r225722.
>
> Before this optimization kicks in, we have
>   <bb 2>:
>   ...
>   p1_32 = (short unsigned int) _20;
>
>   <bb 3>:
>   ...
>   iftmp.0_18 = (short unsigned int) _20;
>
>   <bb 4>:
>   ...
>   # iftmp.0_19 = PHI <iftmp.0_18(3), p1_32(2)>
>
> after factor_out_conditional_conversion does its work, we end up with those two
> def stmts removed and instead of the PHI we'll have
>
>   # _35 = PHI <_20(3), _20(2)>
>   iftmp.0_19 = (short unsigned int) _35;
>
> That itself looks like a fine optimization, but after factor_out_conditional_conversion
> there's
>  320               phis = phi_nodes (bb2);
>  321               phi = single_non_singleton_phi_for_edges (phis, e1, e2);
>  322               gcc_assert (phi);
> and phis look like
>   b.2_38 = PHI <b.2_9(3), b.2_9(2)>
>   _35 = PHI <_20(3), _20(2)>
> so single_non_singleton_phi_for_edges returns NULL and the subsequent assert triggers.
>
> With this patch we won't ICE (and PRE should clean this up anyway), but I don't know,
> maybe I should try harder to optimize even this problematical case (not sure how hard
> it would be...)?
>
> pr66949-2.c only ICEd on powerpc64le and I have verified that this patch fixes it too.
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk?

Hmm.

Yes, there is an opportunity for optimization.

But I don't see why we have the asserts at all - they seem to be originated from
development.  IMHO factor_out_conditonal_conversion should simply return
the new PHI it generates instead of relying on
signle_non_signelton_phi_for_edges
to return it.

Richard.

> 2015-12-08  Marek Polacek  <polacek@redhat.com>
>
>         PR tree-optimization/66949
>         * tree-ssa-phiopt.c (factor_out_conditional_conversion): Return false if
>         NEW_ARG0 and NEW_ARG1 are equal.
>
>         * gcc.dg/torture/pr66949-1.c: New test.
>         * gcc.dg/torture/pr66949-2.c: New test.
>
> diff --git gcc/testsuite/gcc.dg/torture/pr66949-1.c gcc/testsuite/gcc.dg/torture/pr66949-1.c
> index e69de29..1b765bc 100644
> --- gcc/testsuite/gcc.dg/torture/pr66949-1.c
> +++ gcc/testsuite/gcc.dg/torture/pr66949-1.c
> @@ -0,0 +1,28 @@
> +/* PR tree-optimization/66949 */
> +/* { dg-do compile } */
> +
> +int a, *b = &a, c;
> +
> +unsigned short
> +fn1 (unsigned short p1, unsigned int p2)
> +{
> +  return p2 > 1 || p1 >> p2 ? p1 : p1 << p2;
> +}
> +
> +void
> +fn2 ()
> +{
> +  int *d = &a;
> +  for (a = 0; a < -1; a = 1)
> +    ;
> +  if (a < 0)
> +    c = 0;
> +  *b = fn1 (*d || c, *d);
> +}
> +
> +int
> +main ()
> +{
> +  fn2 ();
> +  return 0;
> +}
> diff --git gcc/testsuite/gcc.dg/torture/pr66949-2.c gcc/testsuite/gcc.dg/torture/pr66949-2.c
> index e69de29..e6250a3 100644
> --- gcc/testsuite/gcc.dg/torture/pr66949-2.c
> +++ gcc/testsuite/gcc.dg/torture/pr66949-2.c
> @@ -0,0 +1,23 @@
> +/* PR tree-optimization/66949 */
> +/* { dg-do compile } */
> +
> +char a;
> +int b, c, d;
> +extern int fn2 (void);
> +
> +short
> +fn1 (short p1, short p2)
> +{
> +  return p2 == 0 ? p1 : p1 / p2;
> +}
> +
> +int
> +main (void)
> +{
> +  char e = 1;
> +  int f = 7;
> +  c = a >> f;
> +  b = fn1 (c, 0 < d <= e && fn2 ());
> +
> +  return 0;
> +}
> diff --git gcc/tree-ssa-phiopt.c gcc/tree-ssa-phiopt.c
> index 344cd2f..caac5d5 100644
> --- gcc/tree-ssa-phiopt.c
> +++ gcc/tree-ssa-phiopt.c
> @@ -477,6 +477,11 @@ factor_out_conditional_conversion (edge e0, edge e1, gphi *phi,
>         return false;
>      }
>
> +  /* If we were to continue, we'd create a PHI with same arguments for edges
> +     E0 and E1.  That could get us in trouble later, so punt.  */
> +  if (operand_equal_for_phi_arg_p (new_arg0, new_arg1))
> +    return false;
> +
>    /*  If arg0/arg1 have > 1 use, then this transformation actually increases
>        the number of expressions evaluated at runtime.  */
>    if (!has_single_use (arg0)
>
>         Marek
Jeff Law Dec. 10, 2015, 10:27 p.m. UTC | #3
On 12/08/2015 09:21 AM, Marek Polacek wrote:
> The following is a conservative fix for this PR.  This is an ICE transpiring
> in the new "Factor conversion in COND_EXPR" optimization added in r225722.
>
> Before this optimization kicks in, we have
>    <bb 2>:
>    ...
>    p1_32 = (short unsigned int) _20;
>
>    <bb 3>:
>    ...
>    iftmp.0_18 = (short unsigned int) _20;
>
>    <bb 4>:
>    ...
>    # iftmp.0_19 = PHI <iftmp.0_18(3), p1_32(2)>
>
> after factor_out_conditional_conversion does its work, we end up with those two
> def stmts removed and instead of the PHI we'll have
>
>    # _35 = PHI <_20(3), _20(2)>
>    iftmp.0_19 = (short unsigned int) _35;
>
> That itself looks like a fine optimization, but after factor_out_conditional_conversion
> there's
>   320               phis = phi_nodes (bb2);
>   321               phi = single_non_singleton_phi_for_edges (phis, e1, e2);
>   322               gcc_assert (phi);
> and phis look like
>    b.2_38 = PHI <b.2_9(3), b.2_9(2)>
>    _35 = PHI <_20(3), _20(2)>
> so single_non_singleton_phi_for_edges returns NULL and the subsequent assert triggers.
Cute.
>
> With this patch we won't ICE (and PRE should clean this up anyway), but I don't know,
> maybe I should try harder to optimize even this problematical case (not sure how hard
> it would be...)?
So if this kind of situation is created by the first phiopt, then DOM 
should fix it.  As you note PRE will catch it if the second phiopt pass 
creates this degenerate PHI.  If created by the last phiopt pass, then 
hopefully coalescing would save us.

Jeff
diff mbox

Patch

diff --git gcc/testsuite/gcc.dg/torture/pr66949-1.c gcc/testsuite/gcc.dg/torture/pr66949-1.c
index e69de29..1b765bc 100644
--- gcc/testsuite/gcc.dg/torture/pr66949-1.c
+++ gcc/testsuite/gcc.dg/torture/pr66949-1.c
@@ -0,0 +1,28 @@ 
+/* PR tree-optimization/66949 */
+/* { dg-do compile } */
+
+int a, *b = &a, c;
+
+unsigned short
+fn1 (unsigned short p1, unsigned int p2)
+{
+  return p2 > 1 || p1 >> p2 ? p1 : p1 << p2;
+}
+
+void
+fn2 ()
+{
+  int *d = &a;
+  for (a = 0; a < -1; a = 1)
+    ;
+  if (a < 0)
+    c = 0;
+  *b = fn1 (*d || c, *d);
+}
+
+int
+main ()
+{
+  fn2 ();
+  return 0;
+}
diff --git gcc/testsuite/gcc.dg/torture/pr66949-2.c gcc/testsuite/gcc.dg/torture/pr66949-2.c
index e69de29..e6250a3 100644
--- gcc/testsuite/gcc.dg/torture/pr66949-2.c
+++ gcc/testsuite/gcc.dg/torture/pr66949-2.c
@@ -0,0 +1,23 @@ 
+/* PR tree-optimization/66949 */
+/* { dg-do compile } */
+
+char a;
+int b, c, d;
+extern int fn2 (void);
+
+short
+fn1 (short p1, short p2)
+{
+  return p2 == 0 ? p1 : p1 / p2;
+}
+
+int
+main (void)
+{
+  char e = 1;
+  int f = 7;
+  c = a >> f;
+  b = fn1 (c, 0 < d <= e && fn2 ());
+
+  return 0;
+}
diff --git gcc/tree-ssa-phiopt.c gcc/tree-ssa-phiopt.c
index 344cd2f..caac5d5 100644
--- gcc/tree-ssa-phiopt.c
+++ gcc/tree-ssa-phiopt.c
@@ -477,6 +477,11 @@  factor_out_conditional_conversion (edge e0, edge e1, gphi *phi,
 	return false;
     }
 
+  /* If we were to continue, we'd create a PHI with same arguments for edges
+     E0 and E1.  That could get us in trouble later, so punt.  */
+  if (operand_equal_for_phi_arg_p (new_arg0, new_arg1))
+    return false;
+
   /*  If arg0/arg1 have > 1 use, then this transformation actually increases
       the number of expressions evaluated at runtime.  */
   if (!has_single_use (arg0)