Patchwork Fix wrong code generated by FRE

login
register
mail settings
Submitter Eric Botcazou
Date Dec. 15, 2010, 12:08 p.m.
Message ID <201012151308.56233.ebotcazou@adacore.com>
Download mbox | patch
Permalink /patch/75640/
State New
Headers show

Comments

Eric Botcazou - Dec. 15, 2010, 12:08 p.m.
Hi,

this is a regression present on mainline/4.5 branch.  The compiler generates 
wrong code at -O and above (for platforms that still use SJLJ exceptions).

The problem is FRE computing that:

  D.2449_11 = P8b_3->d;

loads 0 after:

  P8b_3->r{off: D.2453_9 * 4} = {};

although the 'd' and 'r' components don't overlap.


  /* 2) Assignment from an empty CONSTRUCTOR.  */
  else if (is_gimple_reg_type (vr->type)
	   && gimple_assign_single_p (def_stmt)
	   && gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR
	   && CONSTRUCTOR_NELTS (gimple_assign_rhs1 (def_stmt)) == 0)
    {
      tree base2;
      HOST_WIDE_INT offset2, size2, maxsize2;
      base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
				       &offset2, &size2, &maxsize2);
      if (operand_equal_p (base, base2, 0)
	  && offset2 <= offset
	  && offset2 + size2 >= offset + maxsize)
	{
	  tree val = fold_convert (vr->type, integer_zero_node);
	  unsigned int value_id = get_or_alloc_constant_value_id (val);
	  return vn_reference_insert_pieces (vuse, vr->set, vr->type,
					     VEC_copy (vn_reference_op_s,
						       heap, vr->operands),
					     val, value_id);
	}
    }

(gdb) p debug_gimple_stmt(def_stmt)
# .MEM_21 = VDEF <.MEM_24>
P8b_3->r{off: D.2453_9 * 4} = {};

(gdb) p debug_generic_expr(base2)
*P8b_3
$46 = void
(gdb) p offset2
$47 = 0
(gdb) p size2
$48 = 192
(gdb) p maxsize2
$49 = -1


Tested on x86_64-suse-linux, OK for the mainline and 4.5 branch when reopened?


2010-12-15  Eric Botcazou  <ebotcazou@adacore.com>

	* tree-ssa-sccvn.c (vn_reference_lookup_3): Always punt if the call to
	get_ref_base_and_extent returns -1 as the max size.


2010-12-15  Eric Botcazou  <ebotcazou@adacore.com>

	* gnat.dg/opt13.adb: New test.
	* gnat.dg/opt13_pkg.ad[sb]: New helper.
Richard Guenther - Dec. 16, 2010, 11:23 a.m.
On Wed, Dec 15, 2010 at 1:08 PM, Eric Botcazou <ebotcazou@adacore.com> wrote:
> Hi,
>
> this is a regression present on mainline/4.5 branch.  The compiler generates
> wrong code at -O and above (for platforms that still use SJLJ exceptions).
>
> The problem is FRE computing that:
>
>  D.2449_11 = P8b_3->d;
>
> loads 0 after:
>
>  P8b_3->r{off: D.2453_9 * 4} = {};
>
> although the 'd' and 'r' components don't overlap.
>
>
>  /* 2) Assignment from an empty CONSTRUCTOR.  */
>  else if (is_gimple_reg_type (vr->type)
>           && gimple_assign_single_p (def_stmt)
>           && gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR
>           && CONSTRUCTOR_NELTS (gimple_assign_rhs1 (def_stmt)) == 0)
>    {
>      tree base2;
>      HOST_WIDE_INT offset2, size2, maxsize2;
>      base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
>                                       &offset2, &size2, &maxsize2);
>      if (operand_equal_p (base, base2, 0)
>          && offset2 <= offset
>          && offset2 + size2 >= offset + maxsize)
>        {
>          tree val = fold_convert (vr->type, integer_zero_node);
>          unsigned int value_id = get_or_alloc_constant_value_id (val);
>          return vn_reference_insert_pieces (vuse, vr->set, vr->type,
>                                             VEC_copy (vn_reference_op_s,
>                                                       heap, vr->operands),
>                                             val, value_id);
>        }
>    }
>
> (gdb) p debug_gimple_stmt(def_stmt)
> # .MEM_21 = VDEF <.MEM_24>
> P8b_3->r{off: D.2453_9 * 4} = {};
>
> (gdb) p debug_generic_expr(base2)
> *P8b_3
> $46 = void
> (gdb) p offset2
> $47 = 0
> (gdb) p size2
> $48 = 192
> (gdb) p maxsize2
> $49 = -1
>
>
> Tested on x86_64-suse-linux, OK for the mainline and 4.5 branch when reopened?

Oops.  Thanks for fixing.

Yes, the patch is ok, with the test adjusted to maxsize2 !=/== -1 (which is
the canonical form we use elsewhere).

Thanks,
Richard.

>
> 2010-12-15  Eric Botcazou  <ebotcazou@adacore.com>
>
>        * tree-ssa-sccvn.c (vn_reference_lookup_3): Always punt if the call to
>        get_ref_base_and_extent returns -1 as the max size.
>
>
> 2010-12-15  Eric Botcazou  <ebotcazou@adacore.com>
>
>        * gnat.dg/opt13.adb: New test.
>        * gnat.dg/opt13_pkg.ad[sb]: New helper.
>
>
> --
> Eric Botcazou
>

Patch

Index: tree-ssa-sccvn.c
===================================================================
--- tree-ssa-sccvn.c	(revision 167721)
+++ tree-ssa-sccvn.c	(working copy)
@@ -1339,6 +1339,7 @@  vn_reference_lookup_3 (ao_ref *ref, tree
       size2 = TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 2)) * 8;
       if ((unsigned HOST_WIDE_INT)size2 / 8
 	  == TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 2))
+	  && maxsize2 >= 0
 	  && operand_equal_p (base, base2, 0)
 	  && offset2 <= offset
 	  && offset2 + size2 >= offset + maxsize)
@@ -1362,7 +1363,8 @@  vn_reference_lookup_3 (ao_ref *ref, tree
       HOST_WIDE_INT offset2, size2, maxsize2;
       base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
 				       &offset2, &size2, &maxsize2);
-      if (operand_equal_p (base, base2, 0)
+      if (maxsize2 >= 0
+	  && operand_equal_p (base, base2, 0)
 	  && offset2 <= offset
 	  && offset2 + size2 >= offset + maxsize)
 	{
@@ -1383,7 +1385,7 @@  vn_reference_lookup_3 (ao_ref *ref, tree
 	       || handled_component_p (gimple_assign_rhs1 (def_stmt))))
     {
       tree base2;
-      HOST_WIDE_INT offset2, size2;
+      HOST_WIDE_INT offset2, size2, maxsize2;
       int i, j;
       VEC (vn_reference_op_s, heap) *rhs = NULL;
       vn_reference_op_t vro;
@@ -1396,8 +1398,9 @@  vn_reference_lookup_3 (ao_ref *ref, tree
       base2 = ao_ref_base (&lhs_ref);
       offset2 = lhs_ref.offset;
       size2 = lhs_ref.size;
-      if ((base != base2
-	   && !operand_equal_p (base, base2, 0))
+      maxsize2 = lhs_ref.max_size;
+      if (maxsize2 < 0
+	  || (base != base2 && !operand_equal_p (base, base2, 0))
 	  || offset2 > offset
 	  || offset2 + size2 < offset + maxsize)
 	return (void *)-1;