fix component_ref hashing regression

Richard Henderson rth@redhat.com
Thu Jun 24 09:42:00 GMT 2004


This is the problem I referred to this morning that I mis-identified
as a memory corruption bug.

The problem is that COMPONENT_REFs created after gimplification don't
get the new fields set.  And since operand_equal_p wasn't updated, we
get fields that compare equal, but don't hash to the same value.  

Most of the time, you couldn't see evidence of this.  What is needed
to see the bug is two hash values that are different in the absolute,
but which are congruent modulo the hash table size.  Which is kinda
rare, and made all the more so by iterative_hash_expr using pointer
values.

But in the cases that you *didn't* see evidence of the bug, we had
a CSE regression.

Kinda fixed by NOT setting the new fields when not necessary.  It's
enough to fix the bug and the regressions wrt the optimization passes
that do create new reference nodes.  We probably should still update
operand_equal_p to take into account the new fields.  Or, as I'd 
prefer, the new tree codes.


r~


        * gimplify.c (gimplify_compound_lval): Don't set ARRAY_REF or
        COMPONENT_REF variable fields unless they're non-constant.

Index: gcc/gimplify.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/gimplify.c,v
retrieving revision 2.23
diff -c -p -d -r2.23 gimplify.c
*** gcc/gimplify.c	23 Jun 2004 07:43:19 -0000	2.23
--- gcc/gimplify.c	24 Jun 2004 05:18:39 -0000
*************** gimplify_compound_lval (tree *expr_p, tr
*** 1948,1956 ****
  	     gimplified.  */
  	  if (!TREE_OPERAND (t, 2))
  	    {
! 	      TREE_OPERAND (t, 2) = unshare_expr (array_ref_low_bound (t));
! 	      if (!is_gimple_min_invariant (TREE_OPERAND (t, 2)))
  		{
  		  tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
  					is_gimple_tmp_var, fb_rvalue);
  		  ret = MIN (ret, tret);
--- 1948,1957 ----
  	     gimplified.  */
  	  if (!TREE_OPERAND (t, 2))
  	    {
! 	      tree low = unshare_expr (array_ref_low_bound (t));
! 	      if (!is_gimple_min_invariant (low))
  		{
+ 	          TREE_OPERAND (t, 2) = low;
  		  tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
  					is_gimple_tmp_var, fb_rvalue);
  		  ret = MIN (ret, tret);
*************** gimplify_compound_lval (tree *expr_p, tr
*** 1967,1975 ****
  		 type (above).  */
  	      elmt_size = size_binop (EXACT_DIV_EXPR, elmt_size, factor);
  
! 	      TREE_OPERAND (t, 3) = elmt_size;
! 	      if (!is_gimple_min_invariant (TREE_OPERAND (t, 3)))
  		{
  		  tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
  					is_gimple_tmp_var, fb_rvalue);
  		  ret = MIN (ret, tret);
--- 1968,1976 ----
  		 type (above).  */
  	      elmt_size = size_binop (EXACT_DIV_EXPR, elmt_size, factor);
  
! 	      if (!is_gimple_min_invariant (elmt_size))
  		{
+ 	          TREE_OPERAND (t, 3) = elmt_size;
  		  tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
  					is_gimple_tmp_var, fb_rvalue);
  		  ret = MIN (ret, tret);
*************** gimplify_compound_lval (tree *expr_p, tr
*** 1989,1997 ****
  	      /* Divide the offset by its alignment.  */
  	      offset = size_binop (EXACT_DIV_EXPR, offset, factor);
  
! 	      TREE_OPERAND (t, 2) = offset;
! 	      if (!is_gimple_min_invariant (TREE_OPERAND (t, 2)))
  		{
  		  tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
  					is_gimple_tmp_var, fb_rvalue);
  		  ret = MIN (ret, tret);
--- 1990,1998 ----
  	      /* Divide the offset by its alignment.  */
  	      offset = size_binop (EXACT_DIV_EXPR, offset, factor);
  
! 	      if (!is_gimple_min_invariant (offset))
  		{
+ 	          TREE_OPERAND (t, 2) = offset;
  		  tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
  					is_gimple_tmp_var, fb_rvalue);
  		  ret = MIN (ret, tret);



More information about the Gcc-patches mailing list