[PATCH] Fix CCP regression wrt global constant initializers
Richard Guenther
rguenther@suse.de
Fri Feb 5 15:24:00 GMT 2010
As noted in PR42952 we miss propagation of the constant address
in 4.5 due to type system interactions. Fixed with the following.
Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.
Richard.
2010-02-04 Richard Guenther <rguenther@suse.de>
* tree-ssa-ccp.c (get_symbol_constant_value): Strip all
conversions.
(fold_const_aggregate_ref): Likewise.
(ccp_fold_stmt): Substitute loads.
(maybe_fold_reference): Verify types before substituting.
Unshare properly.
(fold_gimple_assign): Unshare properly.
(fold_stmt_1): Insert conversion if necessary before replacing
the RHS.
* gcc.dg/tree-ssa/ssa-ccp-28.c: New testcase.
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-28.c
===================================================================
*** gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-28.c (revision 0)
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-28.c (revision 0)
***************
*** 0 ****
--- 1,26 ----
+ /* { dg-do run } */
+ /* { dg-options "-O -fdump-tree-ccp1" } */
+
+ extern void abort (void);
+
+ static int g[1];
+
+ static int * const p = &g[0];
+ static int * const q = &g[0];
+
+ int main(void)
+ {
+ g[0] = 1;
+ *p = 0;
+ *p = *q;
+ if (g[0] != 0)
+ abort ();
+ return 0;
+ }
+
+ /* We should have replaced all loads from p and q with the constant
+ initial value. */
+
+ /* { dg-final { scan-tree-dump-times "= p;" 0 "ccp1" } } */
+ /* { dg-final { scan-tree-dump-times "= q;" 0 "ccp1" } } */
+ /* { dg-final { cleanup-tree-dump "ccp1" } } */
Index: gcc/tree-ssa-ccp.c
===================================================================
*** gcc/tree-ssa-ccp.c (revision 156493)
--- gcc/tree-ssa-ccp.c (working copy)
*************** get_symbol_constant_value (tree sym)
*** 283,289 ****
tree val = DECL_INITIAL (sym);
if (val)
{
! STRIP_USELESS_TYPE_CONVERSION (val);
if (is_gimple_min_invariant (val))
{
if (TREE_CODE (val) == ADDR_EXPR)
--- 283,289 ----
tree val = DECL_INITIAL (sym);
if (val)
{
! STRIP_NOPS (val);
if (is_gimple_min_invariant (val))
{
if (TREE_CODE (val) == ADDR_EXPR)
*************** fold_const_aggregate_ref (tree t)
*** 1297,1303 ****
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
if (tree_int_cst_equal (cfield, idx))
{
! STRIP_USELESS_TYPE_CONVERSION (cval);
if (TREE_CODE (cval) == ADDR_EXPR)
{
tree base = get_base_address (TREE_OPERAND (cval, 0));
--- 1297,1303 ----
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (ctor), cnt, cfield, cval)
if (tree_int_cst_equal (cfield, idx))
{
! STRIP_NOPS (cval);
if (TREE_CODE (cval) == ADDR_EXPR)
{
tree base = get_base_address (TREE_OPERAND (cval, 0));
*************** fold_const_aggregate_ref (tree t)
*** 1346,1352 ****
/* FIXME: Handle bit-fields. */
&& ! DECL_BIT_FIELD (cfield))
{
! STRIP_USELESS_TYPE_CONVERSION (cval);
if (TREE_CODE (cval) == ADDR_EXPR)
{
tree base = get_base_address (TREE_OPERAND (cval, 0));
--- 1346,1352 ----
/* FIXME: Handle bit-fields. */
&& ! DECL_BIT_FIELD (cfield))
{
! STRIP_NOPS (cval);
if (TREE_CODE (cval) == ADDR_EXPR)
{
tree base = get_base_address (TREE_OPERAND (cval, 0));
*************** ccp_fold_stmt (gimple_stmt_iterator *gsi
*** 1552,1557 ****
--- 1552,1579 ----
return changed;
}
+ case GIMPLE_ASSIGN:
+ {
+ tree lhs = gimple_assign_lhs (stmt);
+ prop_value_t *val;
+
+ /* If we have a load that turned out to be constant replace it
+ as we cannot propagate into all uses in all cases. */
+ if (gimple_assign_single_p (stmt)
+ && TREE_CODE (lhs) == SSA_NAME
+ && (val = get_value (lhs))
+ && val->lattice_val == CONSTANT)
+ {
+ tree rhs = unshare_expr (val->value);
+ if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
+ rhs = fold_convert (TREE_TYPE (lhs), rhs);
+ gimple_assign_set_rhs_from_tree (gsi, rhs);
+ return true;
+ }
+
+ return false;
+ }
+
default:
return false;
}
*************** maybe_fold_reference (tree expr, bool is
*** 2412,2420 ****
&& DECL_P (*t))
{
tree tem = get_symbol_constant_value (*t);
! if (tem)
{
! *t = tem;
tem = maybe_fold_reference (expr, is_lhs);
if (tem)
return tem;
--- 2434,2443 ----
&& DECL_P (*t))
{
tree tem = get_symbol_constant_value (*t);
! if (tem
! && useless_type_conversion_p (TREE_TYPE (*t), TREE_TYPE (tem)))
{
! *t = unshare_expr (tem);
tem = maybe_fold_reference (expr, is_lhs);
if (tem)
return tem;
*************** fold_gimple_assign (gimple_stmt_iterator
*** 2824,2830 ****
}
else if (DECL_P (rhs))
! return get_symbol_constant_value (rhs);
/* If we couldn't fold the RHS, hand over to the generic
fold routines. */
--- 2847,2853 ----
}
else if (DECL_P (rhs))
! return unshare_expr (get_symbol_constant_value (rhs));
/* If we couldn't fold the RHS, hand over to the generic
fold routines. */
*************** fold_stmt_1 (gimple_stmt_iterator *gsi,
*** 3035,3041 ****
{
unsigned old_num_ops = gimple_num_ops (stmt);
tree new_rhs = fold_gimple_assign (gsi);
! if (new_rhs != NULL_TREE
&& (!inplace
|| get_gimple_rhs_num_ops (TREE_CODE (new_rhs)) < old_num_ops))
{
--- 3058,3069 ----
{
unsigned old_num_ops = gimple_num_ops (stmt);
tree new_rhs = fold_gimple_assign (gsi);
! tree lhs = gimple_assign_lhs (stmt);
! if (new_rhs
! && !useless_type_conversion_p (TREE_TYPE (lhs),
! TREE_TYPE (new_rhs)))
! new_rhs = fold_convert (TREE_TYPE (lhs), new_rhs);
! if (new_rhs
&& (!inplace
|| get_gimple_rhs_num_ops (TREE_CODE (new_rhs)) < old_num_ops))
{
More information about the Gcc-patches
mailing list