diff mbox

Don't ignore compute_all_dependences failures in phiopt (PR tree-optimization/53163)

Message ID 20120430133926.GL16117@tyan-ft48-01.lab.bos.redhat.com
State New
Headers show

Commit Message

Jakub Jelinek April 30, 2012, 1:39 p.m. UTC
Hi!

compute_all_dependences in 4.7+ can fail, and cond_if_else_store_replacement
isn't prepared to handle the chrec_dont_know DDR added there in case of
failure (with NULL DDR_A/DDR_B).

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
ok for trunk/4.7?

BTW, tree-ssa-loop-prefetch.c seems to have the same problem, but no idea
how that should be handled in there...

2012-04-30  Jakub Jelinek  <jakub@redhat.com>

	PR tree-optimization/53163
	* tree-ssa-phiopt.c (cond_if_else_store_replacement): Don't ignore
	return value from compute_all_dependences.

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


	Jakub

Comments

Richard Biener May 2, 2012, 9:24 a.m. UTC | #1
On Mon, Apr 30, 2012 at 3:39 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> compute_all_dependences in 4.7+ can fail, and cond_if_else_store_replacement
> isn't prepared to handle the chrec_dont_know DDR added there in case of
> failure (with NULL DDR_A/DDR_B).
>
> Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
> ok for trunk/4.7?

Ok.

> BTW, tree-ssa-loop-prefetch.c seems to have the same problem, but no idea
> how that should be handled in there...

I think it handles it fine by treating the chrec_dont_know DDR
properly?  I suppose
failing would be an option, too, by returning a bool from
determine_loop_nest_reuse
and adjusting its single caller.

Thanks,
Richard.

> 2012-04-30  Jakub Jelinek  <jakub@redhat.com>
>
>        PR tree-optimization/53163
>        * tree-ssa-phiopt.c (cond_if_else_store_replacement): Don't ignore
>        return value from compute_all_dependences.
>
>        * gcc.c-torture/compile/pr53163.c: New test.
>
> --- gcc/tree-ssa-phiopt.c.jj    2012-04-30 08:06:18.000000000 +0200
> +++ gcc/tree-ssa-phiopt.c       2012-04-30 08:59:16.726488101 +0200
> @@ -1624,8 +1624,17 @@ cond_if_else_store_replacement (basic_bl
>   /* Compute and check data dependencies in both basic blocks.  */
>   then_ddrs = VEC_alloc (ddr_p, heap, 1);
>   else_ddrs = VEC_alloc (ddr_p, heap, 1);
> -  compute_all_dependences (then_datarefs, &then_ddrs, NULL, false);
> -  compute_all_dependences (else_datarefs, &else_ddrs, NULL, false);
> +  if (!compute_all_dependences (then_datarefs, &then_ddrs, NULL, false)
> +      || !compute_all_dependences (else_datarefs, &else_ddrs, NULL, false))
> +    {
> +      free_dependence_relations (then_ddrs);
> +      free_dependence_relations (else_ddrs);
> +      free_data_refs (then_datarefs);
> +      free_data_refs (else_datarefs);
> +      VEC_free (gimple, heap, then_stores);
> +      VEC_free (gimple, heap, else_stores);
> +      return false;
> +    }
>   blocks[0] = then_bb;
>   blocks[1] = else_bb;
>   blocks[2] = join_bb;
> --- gcc/testsuite/gcc.c-torture/compile/pr53163.c.jj    2012-04-30 09:21:40.950512562 +0200
> +++ gcc/testsuite/gcc.c-torture/compile/pr53163.c       2012-04-30 09:21:20.000000000 +0200
> @@ -0,0 +1,34 @@
> +/* PR tree-optimization/53163 */
> +
> +struct S { int s; } b, f;
> +int a, c;
> +
> +void
> +foo (void)
> +{
> +  int d, e;
> +  for (d = 4; d < 19; ++d)
> +    for (e = 2; e >= 0; e--)
> +      {
> +       a = 0;
> +       a = 1;
> +      }
> +}
> +
> +void
> +bar (void)
> +{
> +  int g, h, i;
> +  for (i = 1; i >= 0; i--)
> +    {
> +      b = f;
> +      for (g = 0; g <= 1; g++)
> +       {
> +         if (c)
> +           break;
> +         for (h = 0; h <= 1; h++)
> +           foo ();
> +         foo ();
> +       }
> +    }
> +}
>
>        Jakub
Jakub Jelinek May 2, 2012, 10:04 a.m. UTC | #2
On Wed, May 02, 2012 at 11:24:13AM +0200, Richard Guenther wrote:
> > Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
> > ok for trunk/4.7?
> 
> Ok.

Thanks.

> > BTW, tree-ssa-loop-prefetch.c seems to have the same problem, but no idea
> > how that should be handled in there...
> 
> I think it handles it fine by treating the chrec_dont_know DDR
> properly?  I suppose
> failing would be an option, too, by returning a bool from
> determine_loop_nest_reuse
> and adjusting its single caller.

IMHO it will just segfault (I don't have a testcase though).

  compute_all_dependences (datarefs, &dependences, vloops, true);                                                                                  
                                                                                                                                                   
  FOR_EACH_VEC_ELT (ddr_p, dependences, i, dep)                                                                                                    
    {                                                                                                                                              
      if (DDR_ARE_DEPENDENT (dep) == chrec_known)                                                                                                  
        continue;                                                                                                                                  
                                                                                                                                                   
      ref = (struct mem_ref *) DDR_A (dep)->aux;                                                                                                   
      refb = (struct mem_ref *) DDR_B (dep)->aux;                                                                                                  
                                                                                                                                                   
      if (DDR_ARE_DEPENDENT (dep) == chrec_dont_know                                                                                               
          || DDR_NUM_DIST_VECTS (dep) == 0)                                                                                                        
        {                                                                                                                                          
          /* If the dependence cannot be analyzed, assume that there might
           * be                                                                      
             a reuse.  */                                                                                                                          
          dist = 0;                                                                                                                                
                                                                                                                                                   
          ref->independent_p = false;                                                                                                              
          refb->independent_p = false;                                                                                                             
        }                                                                                                                                          

If compute_all_dependences above fails (returns false), then dependences
vector will contain just single chrec_dont_know element, but with DDR_A
(dep) == DDR_B (dep) == NULL.  So the above will try to dereference both and
ICE before checking chrec_dont_know (and even if it wouldn't, there is
nothing to mark independent_p = false - supposedly everything should be
no longer independent_p).

	Jakub
Richard Biener May 2, 2012, 10:19 a.m. UTC | #3
On Wed, May 2, 2012 at 12:04 PM, Jakub Jelinek <jakub@redhat.com> wrote:
> On Wed, May 02, 2012 at 11:24:13AM +0200, Richard Guenther wrote:
>> > Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
>> > ok for trunk/4.7?
>>
>> Ok.
>
> Thanks.
>
>> > BTW, tree-ssa-loop-prefetch.c seems to have the same problem, but no idea
>> > how that should be handled in there...
>>
>> I think it handles it fine by treating the chrec_dont_know DDR
>> properly?  I suppose
>> failing would be an option, too, by returning a bool from
>> determine_loop_nest_reuse
>> and adjusting its single caller.
>
> IMHO it will just segfault (I don't have a testcase though).
>
>  compute_all_dependences (datarefs, &dependences, vloops, true);
>
>  FOR_EACH_VEC_ELT (ddr_p, dependences, i, dep)
>    {
>      if (DDR_ARE_DEPENDENT (dep) == chrec_known)
>        continue;
>
>      ref = (struct mem_ref *) DDR_A (dep)->aux;
>      refb = (struct mem_ref *) DDR_B (dep)->aux;
>
>      if (DDR_ARE_DEPENDENT (dep) == chrec_dont_know
>          || DDR_NUM_DIST_VECTS (dep) == 0)
>        {
>          /* If the dependence cannot be analyzed, assume that there might
>           * be
>             a reuse.  */
>          dist = 0;
>
>          ref->independent_p = false;
>          refb->independent_p = false;
>        }
>
> If compute_all_dependences above fails (returns false), then dependences
> vector will contain just single chrec_dont_know element, but with DDR_A
> (dep) == DDR_B (dep) == NULL.  So the above will try to dereference both and
> ICE before checking chrec_dont_know (and even if it wouldn't, there is
> nothing to mark independent_p = false - supposedly everything should be
> no longer independent_p).

Hm, indeed.  Mind fixing it the way I suggested?

Thanks,
Richard.

>        Jakub
diff mbox

Patch

--- gcc/tree-ssa-phiopt.c.jj	2012-04-30 08:06:18.000000000 +0200
+++ gcc/tree-ssa-phiopt.c	2012-04-30 08:59:16.726488101 +0200
@@ -1624,8 +1624,17 @@  cond_if_else_store_replacement (basic_bl
   /* Compute and check data dependencies in both basic blocks.  */
   then_ddrs = VEC_alloc (ddr_p, heap, 1);
   else_ddrs = VEC_alloc (ddr_p, heap, 1);
-  compute_all_dependences (then_datarefs, &then_ddrs, NULL, false);
-  compute_all_dependences (else_datarefs, &else_ddrs, NULL, false);
+  if (!compute_all_dependences (then_datarefs, &then_ddrs, NULL, false)
+      || !compute_all_dependences (else_datarefs, &else_ddrs, NULL, false))
+    {
+      free_dependence_relations (then_ddrs);
+      free_dependence_relations (else_ddrs);
+      free_data_refs (then_datarefs);
+      free_data_refs (else_datarefs);
+      VEC_free (gimple, heap, then_stores);
+      VEC_free (gimple, heap, else_stores);
+      return false;
+    }
   blocks[0] = then_bb;
   blocks[1] = else_bb;
   blocks[2] = join_bb;
--- gcc/testsuite/gcc.c-torture/compile/pr53163.c.jj	2012-04-30 09:21:40.950512562 +0200
+++ gcc/testsuite/gcc.c-torture/compile/pr53163.c	2012-04-30 09:21:20.000000000 +0200
@@ -0,0 +1,34 @@ 
+/* PR tree-optimization/53163 */
+
+struct S { int s; } b, f;
+int a, c;
+
+void
+foo (void)
+{
+  int d, e;
+  for (d = 4; d < 19; ++d)
+    for (e = 2; e >= 0; e--)
+      {
+	a = 0;
+	a = 1;
+      }
+}
+
+void
+bar (void)
+{
+  int g, h, i;
+  for (i = 1; i >= 0; i--)
+    {
+      b = f;
+      for (g = 0; g <= 1; g++)
+	{
+	  if (c)
+	    break;
+	  for (h = 0; h <= 1; h++)
+	    foo ();
+	  foo ();
+	}
+    }
+}