[patch] for PR29801

Zdenek Dvorak rakdver@atrey.karlin.mff.cuni.cz
Sat Nov 11 22:12:00 GMT 2006


Hello,

we initialize read-only virtual operands to the known constants (if
available).  However, sometimes read-only variables may appear in VDEFs
(either as in the included testcase, that is valid as long as the *p = 5
assignment is never executed; or due to oddities in our alias analysis +
virtual operand scanning).  In that case, we might change the CONSTANT
to UNDEFINED (which causes ICE in the PR testcase), or different
CONSTANT (which should cause ICE as well, but does not because
the test in set_lattice_value is wrong).

This patch makes us ignore the VDEFs of read-only vops, thus avoiding
these forbidden transition.

Bootstrapped & regtested on i686.

Zdenek

	* tree-ssa-ccp.c (get_symbol_constant_value): New function.
	(get_default_value): Use get_symbol_constant_value.
	(set_lattice_value): ICE when the value of the constant is
	changed.
	(visit_assignment): Ignore VDEFs of read-only variables.

	* gcc.dg/pr29801.c: New test.

Index: testsuite/gcc.dg/pr29801.c
===================================================================
*** testsuite/gcc.dg/pr29801.c	(revision 0)
--- testsuite/gcc.dg/pr29801.c	(revision 0)
***************
*** 0 ****
--- 1,24 ----
+ /* We used to crash in ccp here, because the initial constant value of 2
+    was changed to 5.  */
+ 
+ /* { dg-do compile } */
+ /* { dg-options "-O2 -fdump-tree-optimized" } */
+ 
+ static const int a = 2;
+ 
+ int test (int param)
+ {
+   int *p = (int *) &a;
+ 
+   if (param)
+     *p = 5;
+ 
+   return a;
+ }
+ 
+ /* Check that we return the correct (unchanged) value.  */
+ 
+ /* { dg-final { scan-tree-dump-times "return 2" 1 "optimized" } } */
+ /* { dg-final { scan-tree-dump-times "return 5" 0 "optimized" } } */
+ 
+ /* { dg-final { cleanup-tree-dump "optimized" } } */
Index: tree-ssa-ccp.c
===================================================================
*** tree-ssa-ccp.c	(revision 118690)
--- tree-ssa-ccp.c	(working copy)
*************** ccp_decl_initial_min_invariant (tree t)
*** 293,298 ****
--- 293,316 ----
    return true;
  }
  
+ /* If SYM is a constant variable with known value, return the value.
+    NULL_TREE is returned otherwise.  */
+ 
+ static tree
+ get_symbol_constant_value (tree sym)
+ {
+   if (TREE_STATIC (sym)
+       && TREE_READONLY (sym)
+       && !MTAG_P (sym))
+     {
+       tree val = DECL_INITIAL (sym);
+       if (val
+ 	  && ccp_decl_initial_min_invariant (val))
+ 	return val;
+     }
+ 
+   return NULL_TREE;
+ }
  
  /* Compute a default value for variable VAR and store it in the
     CONST_VAL array.  The following rules are used to get default
*************** get_default_value (tree var)
*** 320,325 ****
--- 338,344 ----
  {
    tree sym = SSA_NAME_VAR (var);
    prop_value_t val = { UNINITIALIZED, NULL_TREE, NULL_TREE };
+   tree cst_val;
    
    if (!do_store_ccp && !is_gimple_reg (var))
      {
*************** get_default_value (tree var)
*** 333,348 ****
        val.lattice_val = CONSTANT;
        val.value = SSA_NAME_VALUE (var);
      }
!   else if (TREE_STATIC (sym)
! 	   && TREE_READONLY (sym)
! 	   && !MTAG_P (sym)
! 	   && DECL_INITIAL (sym)
! 	   && ccp_decl_initial_min_invariant (DECL_INITIAL (sym)))
      {
        /* Globals and static variables declared 'const' take their
  	 initial value.  */
        val.lattice_val = CONSTANT;
!       val.value = DECL_INITIAL (sym);
        val.mem_ref = sym;
      }
    else
--- 352,363 ----
        val.lattice_val = CONSTANT;
        val.value = SSA_NAME_VALUE (var);
      }
!   else if ((cst_val = get_symbol_constant_value (sym)) != NULL_TREE)
      {
        /* Globals and static variables declared 'const' take their
  	 initial value.  */
        val.lattice_val = CONSTANT;
!       val.value = cst_val;
        val.mem_ref = sym;
      }
    else
*************** set_lattice_value (tree var, prop_value_
*** 415,423 ****
       value.  If *OLD_VAL and NEW_VAL are the same, return false to
       inform the caller that this was a non-transition.  */
  
!   gcc_assert (old_val->lattice_val <= new_val.lattice_val
                || (old_val->lattice_val == new_val.lattice_val
! 		  && old_val->value == new_val.value
  		  && old_val->mem_ref == new_val.mem_ref));
  
    if (old_val->lattice_val != new_val.lattice_val)
--- 430,439 ----
       value.  If *OLD_VAL and NEW_VAL are the same, return false to
       inform the caller that this was a non-transition.  */
  
!   gcc_assert (old_val->lattice_val < new_val.lattice_val
                || (old_val->lattice_val == new_val.lattice_val
! 		  && ((!old_val->value && !new_val.value)
! 		      || operand_equal_p (old_val->value, new_val.value, 0))
  		  && old_val->mem_ref == new_val.mem_ref));
  
    if (old_val->lattice_val != new_val.lattice_val)
*************** visit_assignment (tree stmt, tree *outpu
*** 1223,1229 ****
        /* Set the value of every VDEF to VAL.  */
        changed = false;
        FOR_EACH_SSA_TREE_OPERAND (vdef, stmt, i, SSA_OP_VIRTUAL_DEFS)
! 	changed |= set_lattice_value (vdef, val);
        
        /* Note that for propagation purposes, we are only interested in
  	 visiting statements that load the exact same memory reference
--- 1239,1254 ----
        /* Set the value of every VDEF to VAL.  */
        changed = false;
        FOR_EACH_SSA_TREE_OPERAND (vdef, stmt, i, SSA_OP_VIRTUAL_DEFS)
! 	{
! 	  /* See PR 29801.  We may have VDEFs for read-only variables (either
! 	     because of assignments in the parts of the program that never
! 	     get executed, or because of alias system oddities); do not
! 	     attempt to change their value.  */
! 	  if (get_symbol_constant_value (SSA_NAME_VAR (vdef)) != NULL_TREE)
! 	    continue;
! 
! 	  changed |= set_lattice_value (vdef, val);
! 	}
        
        /* Note that for propagation purposes, we are only interested in
  	 visiting statements that load the exact same memory reference



More information about the Gcc-patches mailing list