diff --git a/gcc/ChangeLog b/gcc/ChangeLog index bd4ada6c179..559c1dd2c46 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2008-03-20 Richard Guenther + + * tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Remove + special casing of constant qualifiers. + * tree-ssa.c (useless_type_conversion_p_1): Instead do not + care about them in general. + * tree-ssa-ccp.c (ccp_fold): Addresses are constant or not + regardless of their type. + (fold_stmt_r): Forcefully fold *& if we end up with that. + 2008-03-20 Paul Brook * config.gcc (arm*-*-uclinux*): Remove duplicate arm/uclinux-elf.h. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 737dbba33fa..5eb84fe3d7c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,7 @@ +2008-03-20 Richard Guenther + + * gcc.dg/tree-ssa/ssa-ccp-17.c: New testcase. + 2008-03-20 Victor Kaplansky Uros Bizjak diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-17.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-17.c new file mode 100644 index 00000000000..7d769ae176a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-17.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +int foo(void) +{ + int i = 0; + char *p = (char *)&i; + return *(int *)p; +} + +struct Foo { + int i; +} f; + +int bar(void) +{ + char *p = (char *)&f; + return ((struct Foo *)p)->i; +} + +const struct Foo g; + +int foobar(void) +{ + struct Foo *p = (struct Foo *)&g; + return ((const struct Foo *)p)->i; +} + +/* { dg-final { scan-tree-dump "= i;" "ccp1" } } */ +/* { dg-final { scan-tree-dump "= f.i;" "ccp1" } } */ +/* { dg-final { scan-tree-dump "= g.i;" "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index 2a82c046999..7797de12f6b 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -947,8 +947,15 @@ ccp_fold (tree stmt) op0 = get_value (op0)->value; } + /* Conversions are useless for CCP purposes if they are + value-preserving. Thus the restrictions that + useless_type_conversion_p places for pointer type conversions do + not apply here. Substitution later will only substitute to + allowed places. */ if ((code == NOP_EXPR || code == CONVERT_EXPR) - && useless_type_conversion_p (TREE_TYPE (rhs), TREE_TYPE (op0))) + && ((POINTER_TYPE_P (TREE_TYPE (rhs)) + && POINTER_TYPE_P (TREE_TYPE (op0))) + || useless_type_conversion_p (TREE_TYPE (rhs), TREE_TYPE (op0)))) return op0; return fold_unary (code, TREE_TYPE (rhs), op0); } @@ -2160,6 +2167,11 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data) t = maybe_fold_stmt_indirect (expr, TREE_OPERAND (expr, 0), integer_zero_node); + if (!t + && TREE_CODE (TREE_OPERAND (expr, 0)) == ADDR_EXPR) + /* If we had a good reason for propagating the address here, + make sure we end up with valid gimple. See PR34989. */ + t = TREE_OPERAND (TREE_OPERAND (expr, 0), 0); break; case NOP_EXPR: diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c index 84553fbef42..e6402adce55 100644 --- a/gcc/tree-ssa-forwprop.c +++ b/gcc/tree-ssa-forwprop.c @@ -601,14 +601,8 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, tree use_stmt, propagate the ADDR_EXPR into the use of NAME and fold the result. */ if (TREE_CODE (lhs) == INDIRECT_REF && TREE_OPERAND (lhs, 0) == name - /* This will not allow stripping const qualification from - pointers which we want to allow specifically here to clean up - the IL for initialization of constant objects. */ - && (useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (lhs, 0)), - TREE_TYPE (def_rhs)) - /* So explicitly check for this here. */ - || (TYPE_QUALS (TREE_TYPE (TREE_TYPE (TREE_OPERAND (lhs, 0)))) - ^ TYPE_QUALS (TREE_TYPE (TREE_TYPE (def_rhs)))) == TYPE_QUAL_CONST) + && useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (lhs, 0)), + TREE_TYPE (def_rhs)) /* ??? This looks redundant, but is required for bogus types that can sometimes occur. */ && useless_type_conversion_p (TREE_TYPE (lhs), @@ -635,13 +629,10 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs, tree use_stmt, propagate the ADDR_EXPR into the use of NAME and fold the result. */ if (TREE_CODE (rhs) == INDIRECT_REF && TREE_OPERAND (rhs, 0) == name - /* ??? This doesn't allow stripping const qualification to - streamline the IL for reads from non-constant objects. */ - && (useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (rhs, 0)), - TREE_TYPE (def_rhs)) - /* So explicitly check for this here. */ - || (TYPE_QUALS (TREE_TYPE (TREE_TYPE (TREE_OPERAND (rhs, 0)))) - ^ TYPE_QUALS (TREE_TYPE (TREE_TYPE (def_rhs)))) == TYPE_QUAL_CONST) + && useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (rhs, 0)), + TREE_TYPE (def_rhs)) + /* ??? This looks redundant, but is required for bogus types + that can sometimes occur. */ && useless_type_conversion_p (TREE_TYPE (rhs), TREE_TYPE (TREE_OPERAND (def_rhs, 0)))) { diff --git a/gcc/tree-ssa.c b/gcc/tree-ssa.c index 128b4e87283..f7306b1833d 100644 --- a/gcc/tree-ssa.c +++ b/gcc/tree-ssa.c @@ -1117,12 +1117,8 @@ useless_type_conversion_p_1 (tree outer_type, tree inner_type) != get_alias_set (TREE_TYPE (outer_type)))) return false; - /* Do not lose casts from const qualified to non-const - qualified. */ - if ((TYPE_READONLY (TREE_TYPE (outer_type)) - != TYPE_READONLY (TREE_TYPE (inner_type))) - && TYPE_READONLY (TREE_TYPE (inner_type))) - return false; + /* We do not care for const qualification of the pointed-to types + as const qualification has no semantic value to the middle-end. */ /* Do not lose casts to restrict qualified pointers. */ if ((TYPE_RESTRICT (outer_type)