diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-08-13 14:22:19 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2008-08-13 14:22:19 +0000 |
commit | 5768aeb3c88117d813e1b958c58a5c871bf43667 (patch) | |
tree | a132b33918fa2aabf5676cd2cede6a9b1320407a /gcc | |
parent | 5519c0df626b0baf3d1372f60d00be068d464d7b (diff) | |
download | gcc-5768aeb3c88117d813e1b958c58a5c871bf43667.tar.gz |
2008-08-13 Richard Guenther <rguenther@suse.de>
* tree.h (maybe_fold_offset_to_address): Declare.
* tree-ssa-ccp.c (surely_varying_stmt_p): Fix typo in last commit.
(ccp_fold): Handle pointer conversions the same as fold_stmt.
Likewise for POINTER_PLUS_EXPR.
(maybe_fold_offset_to_reference): Enable disabled code.
(maybe_fold_offset_to_address): New function.
(fold_stmt_r): Use it.
(fold_gimple_assign): Likewise.
* gimplify.c (gimplify_conversion): Use maybe_fold_offset_to_address.
(gimplify_expr): Likewise.
* gcc.dg/tree-ssa/ssa-ccp-21.c: New testcase.
* gcc.dg/tree-ssa/ssa-ccp-22.c: Likewise.
* gcc.dg/tree-ssa/ssa-ccp-23.c: Likewise.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@139061 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 13 | ||||
-rw-r--r-- | gcc/gimplify.c | 36 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-21.c | 25 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-22.c | 15 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-23.c | 19 | ||||
-rw-r--r-- | gcc/tree-ssa-ccp.c | 134 | ||||
-rw-r--r-- | gcc/tree.h | 1 |
8 files changed, 192 insertions, 57 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f07113a13e2..fa88d55ee27 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,16 @@ +2008-08-13 Richard Guenther <rguenther@suse.de> + + * tree.h (maybe_fold_offset_to_address): Declare. + * tree-ssa-ccp.c (surely_varying_stmt_p): Fix typo in last commit. + (ccp_fold): Handle pointer conversions the same as fold_stmt. + Likewise for POINTER_PLUS_EXPR. + (maybe_fold_offset_to_reference): Enable disabled code. + (maybe_fold_offset_to_address): New function. + (fold_stmt_r): Use it. + (fold_gimple_assign): Likewise. + * gimplify.c (gimplify_conversion): Use maybe_fold_offset_to_address. + (gimplify_expr): Likewise. + 2008-08-13 Manuel Lopez-Ibanez <manu@gcc.gnu.org> * toplev.h (pedwarn_at): Fix declaration. diff --git a/gcc/gimplify.c b/gcc/gimplify.c index 753aa591e40..43c8df991fc 100644 --- a/gcc/gimplify.c +++ b/gcc/gimplify.c @@ -1842,17 +1842,13 @@ gimplify_conversion (tree *expr_p) /* Attempt to avoid NOP_EXPR by producing reference to a subtype. For example this fold (subclass *)&A into &A->subclass avoiding a need for statement. */ - if (TREE_CODE (*expr_p) == NOP_EXPR + if (CONVERT_EXPR_P (*expr_p) && POINTER_TYPE_P (TREE_TYPE (*expr_p)) && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (*expr_p, 0))) - && (tem = maybe_fold_offset_to_reference + && (tem = maybe_fold_offset_to_address (TREE_OPERAND (*expr_p, 0), - integer_zero_node, TREE_TYPE (TREE_TYPE (*expr_p))))) - { - tree ptr_type = build_pointer_type (TREE_TYPE (tem)); - if (useless_type_conversion_p (TREE_TYPE (*expr_p), ptr_type)) - *expr_p = build_fold_addr_expr_with_type (tem, ptr_type); - } + integer_zero_node, TREE_TYPE (*expr_p))) != NULL_TREE) + *expr_p = tem; /* If we still have a conversion at the toplevel, then canonicalize some constructs. */ @@ -6735,30 +6731,24 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p, The second is gimple immediate saving a need for extra statement. */ if (TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST - && (tmp = maybe_fold_offset_to_reference + && (tmp = maybe_fold_offset_to_address (TREE_OPERAND (*expr_p, 0), TREE_OPERAND (*expr_p, 1), - TREE_TYPE (TREE_TYPE (*expr_p))))) - { - tree ptr_type = build_pointer_type (TREE_TYPE (tmp)); - if (useless_type_conversion_p (TREE_TYPE (*expr_p), ptr_type)) - { - *expr_p = build_fold_addr_expr_with_type (tmp, ptr_type); - break; - } - } + TREE_TYPE (*expr_p)))) + { + *expr_p = tmp; + break; + } /* Convert (void *)&a + 4 into (void *)&a[1]. */ if (TREE_CODE (TREE_OPERAND (*expr_p, 0)) == NOP_EXPR && TREE_CODE (TREE_OPERAND (*expr_p, 1)) == INTEGER_CST && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p, 0),0))) - && (tmp = maybe_fold_offset_to_reference + && (tmp = maybe_fold_offset_to_address (TREE_OPERAND (TREE_OPERAND (*expr_p, 0), 0), TREE_OPERAND (*expr_p, 1), - TREE_TYPE (TREE_TYPE - (TREE_OPERAND (TREE_OPERAND (*expr_p, 0), - 0)))))) + TREE_TYPE (TREE_OPERAND (TREE_OPERAND (*expr_p, 0), + 0))))) { - tmp = build_fold_addr_expr (tmp); *expr_p = fold_convert (TREE_TYPE (*expr_p), tmp); break; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d036b781439..951f82ea67b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2008-08-13 Richard Guenther <rguenther@suse.de> + + * gcc.dg/tree-ssa/ssa-ccp-21.c: New testcase. + * gcc.dg/tree-ssa/ssa-ccp-22.c: Likewise. + * gcc.dg/tree-ssa/ssa-ccp-23.c: Likewise. + 2008-08-13 Samuel Tardieu <sam@rfc1149.net> PR ada/36777 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-21.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-21.c new file mode 100644 index 00000000000..3b23c36238e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-21.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +struct A { + struct B { + int i; + } b; +} a; + +int foo (void) +{ + struct B *p = &a.b; + struct A *q = (struct A *) p; + return q->b.i; +} + +int bar (void) +{ + struct A *p = &a; + struct B *q = (struct B *) p; + return q->i; +} + +/* { dg-final { scan-tree-dump-times "a.b.i" 2 "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-22.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-22.c new file mode 100644 index 00000000000..01d11ecac87 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-22.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +/* Make sure we propagate through builtins. */ + +int foo (unsigned b) +{ + unsigned t = -1; + int x = b <= t; + long l = __builtin_expect (x, 0); + return l; +} + +/* { dg-final { scan-tree-dump "return 1;" "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-23.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-23.c new file mode 100644 index 00000000000..ac7f068cfd1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-23.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +/* Make sure we propagate through POINTER_PLUS_EXPRs. */ + +struct A { + int i[2]; +} a; + +int foo (void) +{ + struct A *p = &a; + int *q = (int *)p; + int *x = q + 1; + return *x; +} + +/* { dg-final { scan-tree-dump "a.i\\\[1\\\]" "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c index af102cd25e1..ff8af4f14dd 100644 --- a/gcc/tree-ssa-ccp.c +++ b/gcc/tree-ssa-ccp.c @@ -630,7 +630,7 @@ surely_varying_stmt_p (gimple stmt) tree fndecl; if (!gimple_call_lhs (stmt) || ((fndecl = gimple_call_fndecl (stmt)) != NULL_TREE - && DECL_BUILT_IN (fndecl))) + && !DECL_BUILT_IN (fndecl))) return true; } @@ -988,18 +988,26 @@ ccp_fold (gimple stmt) useless_type_conversion_p places for pointer type conversions do not apply here. Substitution later will only substitute to allowed places. */ - if ((subcode == NOP_EXPR || subcode == CONVERT_EXPR) - && ((POINTER_TYPE_P (TREE_TYPE (lhs)) - && POINTER_TYPE_P (TREE_TYPE (op0)) - /* Do not allow differences in volatile qualification - as this might get us confused as to whether a - propagation destination statement is volatile - or not. See PR36988. */ - && (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (lhs))) - == TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (op0))))) - || useless_type_conversion_p (TREE_TYPE (lhs), - TREE_TYPE (op0)))) - return op0; + if (IS_CONVERT_EXPR_CODE_P (subcode) + && POINTER_TYPE_P (TREE_TYPE (lhs)) + && POINTER_TYPE_P (TREE_TYPE (op0)) + /* Do not allow differences in volatile qualification + as this might get us confused as to whether a + propagation destination statement is volatile + or not. See PR36988. */ + && (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (lhs))) + == TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (op0))))) + { + tree tem; + /* Still try to generate a constant of correct type. */ + if (!useless_type_conversion_p (TREE_TYPE (lhs), + TREE_TYPE (op0)) + && ((tem = maybe_fold_offset_to_address + (op0, integer_zero_node, TREE_TYPE (lhs))) + != NULL_TREE)) + return tem; + return op0; + } return fold_unary (subcode, gimple_expr_type (stmt), op0); } @@ -1025,6 +1033,18 @@ ccp_fold (gimple stmt) op1 = val->value; } + /* Fold &foo + CST into an invariant reference if possible. */ + if (gimple_assign_rhs_code (stmt) == POINTER_PLUS_EXPR + && TREE_CODE (op0) == ADDR_EXPR + && TREE_CODE (op1) == INTEGER_CST) + { + tree lhs = gimple_assign_lhs (stmt); + tree tem = maybe_fold_offset_to_address (op0, op1, + TREE_TYPE (lhs)); + if (tem != NULL_TREE) + return tem; + } + return fold_binary (subcode, gimple_expr_type (stmt), op0, op1); } @@ -1948,15 +1968,15 @@ maybe_fold_offset_to_reference (tree base, tree offset, tree orig_type) so it needs to be removed and new COMPONENT_REF constructed. The wrong COMPONENT_REF are often constructed by folding the (type *)&object within the expression (type *)&object+offset */ - if (handled_component_p (base) && 0) + if (handled_component_p (base)) { HOST_WIDE_INT sub_offset, size, maxsize; tree newbase; newbase = get_ref_base_and_extent (base, &sub_offset, &size, &maxsize); gcc_assert (newbase); - gcc_assert (!(sub_offset & (BITS_PER_UNIT - 1))); - if (size == maxsize) + if (size == maxsize + && !(sub_offset & (BITS_PER_UNIT - 1))) { base = newbase; if (sub_offset) @@ -1988,6 +2008,63 @@ maybe_fold_offset_to_reference (tree base, tree offset, tree orig_type) return ret; } +/* Attempt to express (ORIG_TYPE)&BASE+OFFSET as &BASE->field_of_orig_type + or &BASE[index] or by combination of those. + + Before attempting the conversion strip off existing component refs. */ + +tree +maybe_fold_offset_to_address (tree addr, tree offset, tree orig_type) +{ + tree t; + + gcc_assert (POINTER_TYPE_P (TREE_TYPE (addr)) + && POINTER_TYPE_P (orig_type)); + + t = maybe_fold_offset_to_reference (addr, offset, TREE_TYPE (orig_type)); + if (t != NULL_TREE) + { + tree orig = addr; + tree ptr_type; + + /* For __builtin_object_size to function correctly we need to + make sure not to fold address arithmetic so that we change + reference from one array to another. This would happen for + example for + + struct X { char s1[10]; char s2[10] } s; + char *foo (void) { return &s.s2[-4]; } + + where we need to avoid generating &s.s1[6]. As the C and + C++ frontends create different initial trees + (char *) &s.s1 + -4 vs. &s.s1[-4] we have to do some + sophisticated comparisons here. Note that checking for the + condition after the fact is easier than trying to avoid doing + the folding. */ + STRIP_NOPS (orig); + if (TREE_CODE (orig) == ADDR_EXPR) + orig = TREE_OPERAND (orig, 0); + if ((TREE_CODE (orig) == ARRAY_REF + || (TREE_CODE (orig) == COMPONENT_REF + && TREE_CODE (TREE_TYPE (TREE_OPERAND (orig, 1))) == ARRAY_TYPE)) + && (TREE_CODE (t) == ARRAY_REF + || (TREE_CODE (t) == COMPONENT_REF + && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 1))) == ARRAY_TYPE)) + && !operand_equal_p (TREE_CODE (orig) == ARRAY_REF + ? TREE_OPERAND (orig, 0) : orig, + TREE_CODE (t) == ARRAY_REF + ? TREE_OPERAND (t, 0) : t, 0)) + return NULL_TREE; + + ptr_type = build_pointer_type (TREE_TYPE (t)); + if (!useless_type_conversion_p (orig_type, ptr_type)) + return NULL_TREE; + return build_fold_addr_expr_with_type (t, ptr_type); + } + + return NULL_TREE; +} + /* A subroutine of fold_stmt_r. Attempt to simplify *(BASE+OFFSET). Return the simplified expression, or NULL if nothing could be done. */ @@ -2223,16 +2300,10 @@ fold_stmt_r (tree *expr_p, int *walk_subtrees, void *data) if (POINTER_TYPE_P (TREE_TYPE (expr)) && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (expr, 0))) - && (t = maybe_fold_offset_to_reference - (TREE_OPERAND (expr, 0), - integer_zero_node, - TREE_TYPE (TREE_TYPE (expr))))) - { - tree ptr_type = build_pointer_type (TREE_TYPE (t)); - if (!useless_type_conversion_p (TREE_TYPE (expr), ptr_type)) - return NULL_TREE; - t = build_fold_addr_expr_with_type (t, ptr_type); - } + && (t = maybe_fold_offset_to_address (TREE_OPERAND (expr, 0), + integer_zero_node, + TREE_TYPE (TREE_TYPE (expr))))) + return t; break; /* ??? Could handle more ARRAY_REFs here, as a variant of INDIRECT_REF. @@ -2715,15 +2786,10 @@ fold_gimple_assign (gimple_stmt_iterator *si) && POINTER_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt)))) { tree type = gimple_expr_type (stmt); - tree t = maybe_fold_offset_to_reference (gimple_assign_rhs1 (stmt), - integer_zero_node, - TREE_TYPE (type)); + tree t = maybe_fold_offset_to_address (gimple_assign_rhs1 (stmt), + integer_zero_node, type); if (t) - { - tree ptr_type = build_pointer_type (TREE_TYPE (t)); - if (useless_type_conversion_p (type, ptr_type)) - return build_fold_addr_expr_with_type (t, ptr_type); - } + return t; } break; diff --git a/gcc/tree.h b/gcc/tree.h index 5f5b37d4ef8..3f8065da736 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -4744,6 +4744,7 @@ extern void fold_undefer_overflow_warnings (bool, const_gimple, int); extern void fold_undefer_and_ignore_overflow_warnings (void); extern bool fold_deferring_overflow_warnings_p (void); extern tree maybe_fold_offset_to_reference (tree, tree, tree); +extern tree maybe_fold_offset_to_address (tree, tree, tree); extern tree maybe_fold_stmt_addition (tree, tree, tree); extern tree force_fit_type_double (tree, unsigned HOST_WIDE_INT, HOST_WIDE_INT, |