aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2008-07-29 17:09:26 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2008-07-29 17:09:26 +0000
commitce94d3547f81cc3dd105f4a3377e72cdbd2bbd2c (patch)
treed2185d79e36deb34f5ad3885547df3a1a15064b0
parent0f3a057aa9e5b4f6fbdbee87e8224ca9ea5a6d83 (diff)
downloadgcc-ce94d3547f81cc3dd105f4a3377e72cdbd2bbd2c.zip
gcc-ce94d3547f81cc3dd105f4a3377e72cdbd2bbd2c.tar.gz
gcc-ce94d3547f81cc3dd105f4a3377e72cdbd2bbd2c.tar.bz2
re PR tree-optimization/36945 (PRE/SCCVN do not handle aggregate function arguments correctly)
2008-07-29 Richard Guenther <rguenther@suse.de> PR tree-optimization/36945 * tree-ssa-sccvn.h (copy_reference_ops_from_ref): Declare. * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Export. Record invariant addresses un-decomposed. (copy_reference_ops_from_call): Record reference call arguments properly. Simplify. * tree-ssa-pre.c (create_component_ref_by_pieces_1): New helper split out from ... (create_component_ref_by_pieces): ... here. Simplify. Prepare for recursive invocation for call arguments. (create_expression_by_pieces): Adjust call to create_component_ref_by_pieces. (compute_avail): Process operand 2 of reference ops. * gcc.dg/tree-ssa/ssa-pre-18.c: New testcase. From-SVN: r138257
-rw-r--r--gcc/ChangeLog16
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-18.c21
-rw-r--r--gcc/tree-ssa-pre.c151
-rw-r--r--gcc/tree-ssa-sccvn.c42
-rw-r--r--gcc/tree-ssa-sccvn.h1
6 files changed, 127 insertions, 109 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d1929ba0..9d0388d 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,21 @@
2008-07-29 Richard Guenther <rguenther@suse.de>
+ PR tree-optimization/36945
+ * tree-ssa-sccvn.h (copy_reference_ops_from_ref): Declare.
+ * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Export.
+ Record invariant addresses un-decomposed.
+ (copy_reference_ops_from_call): Record reference call
+ arguments properly. Simplify.
+ * tree-ssa-pre.c (create_component_ref_by_pieces_1): New
+ helper split out from ...
+ (create_component_ref_by_pieces): ... here. Simplify.
+ Prepare for recursive invocation for call arguments.
+ (create_expression_by_pieces): Adjust call to
+ create_component_ref_by_pieces.
+ (compute_avail): Process operand 2 of reference ops.
+
+2008-07-29 Richard Guenther <rguenther@suse.de>
+
* gimplify.c (gimplify_expr): Clear TREE_SIDE_EFFECTS for
OBJ_TYPE_REF.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index d4e8ddb..79568dd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2008-07-29 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/36945
+ * gcc.dg/tree-ssa/ssa-pre-18.c: New testcase.
+
2008-07-29 Jakub Jelinek <jakub@redhat.com>
PR c++/36852
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-18.c
new file mode 100644
index 0000000..5e92934
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-18.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-pre-details" } */
+
+struct Bar { int a; int b; };
+struct Foo { int x; struct Bar y; };
+
+int __attribute__((const)) foo (struct Bar);
+
+int bar (int b)
+{
+ struct Foo f;
+ int c;
+ while (b--)
+ {
+ c = foo(f.y);
+ }
+ return c;
+}
+
+/* { dg-final { scan-tree-dump "Replaced foo \\(f.y\\)" "pre" } } */
+/* { dg-final { cleanup-tree-dump "pre" } } */
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index c772ff2..c98a18a 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -2421,64 +2421,56 @@ static VEC(gimple,heap) *inserted_exprs;
to see which expressions need to be put into GC'able memory */
static VEC(gimple, heap) *need_creation;
-/* For COMPONENT_REF's and ARRAY_REF's, we can't have any intermediates for the
- COMPONENT_REF or INDIRECT_REF or ARRAY_REF portion, because we'd end up with
- trying to rename aggregates into ssa form directly, which is a no
- no.
-
- Thus, this routine doesn't create temporaries, it just builds a
- single access expression for the array, calling
- find_or_generate_expression to build the innermost pieces.
+/* The actual worker for create_component_ref_by_pieces. */
- This function is a subroutine of create_expression_by_pieces, and
- should not be called on it's own unless you really know what you
- are doing.
-*/
static tree
-create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
- unsigned int operand,
- gimple_seq *stmts,
- gimple domstmt,
- bool in_call)
+create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
+ unsigned int *operand, gimple_seq *stmts,
+ gimple domstmt)
{
vn_reference_op_t currop = VEC_index (vn_reference_op_s, ref->operands,
- operand);
+ *operand);
tree genop;
+ ++*operand;
switch (currop->opcode)
{
case CALL_EXPR:
{
tree folded;
- unsigned int i;
- vn_reference_op_t declop = VEC_index (vn_reference_op_s,
- ref->operands, 1);
- unsigned int nargs = VEC_length (vn_reference_op_s, ref->operands) - 2;
- tree *args = XNEWVEC (tree, nargs);
-
- for (i = 0; i < nargs; i++)
+ unsigned int nargs = 0;
+ tree *args = XNEWVEC (tree, VEC_length (vn_reference_op_s,
+ ref->operands) - 1);
+ while (*operand < VEC_length (vn_reference_op_s, ref->operands))
{
- args[i] = create_component_ref_by_pieces (block, ref,
- operand + 2 + i, stmts,
- domstmt, true);
+ args[nargs] = create_component_ref_by_pieces_1 (block, ref,
+ operand, stmts,
+ domstmt);
+ nargs++;
}
folded = build_call_array (currop->type,
- TREE_CODE (declop->op0) == FUNCTION_DECL
- ? build_fold_addr_expr (declop->op0)
- : declop->op0,
+ TREE_CODE (currop->op0) == FUNCTION_DECL
+ ? build_fold_addr_expr (currop->op0)
+ : currop->op0,
nargs, args);
free (args);
return folded;
}
break;
+ case ADDR_EXPR:
+ if (currop->op0)
+ {
+ gcc_assert (is_gimple_min_invariant (currop->op0));
+ return currop->op0;
+ }
+ /* Fallthrough. */
case REALPART_EXPR:
case IMAGPART_EXPR:
case VIEW_CONVERT_EXPR:
{
tree folded;
- tree genop0 = create_component_ref_by_pieces (block, ref,
- operand + 1,
- stmts, domstmt,
- in_call);
+ tree genop0 = create_component_ref_by_pieces_1 (block, ref,
+ operand,
+ stmts, domstmt);
if (!genop0)
return NULL_TREE;
folded = fold_build1 (currop->opcode, currop->type,
@@ -2490,45 +2482,25 @@ create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
case MISALIGNED_INDIRECT_REF:
case INDIRECT_REF:
{
- /* Inside a CALL_EXPR op0 is the actual indirect_ref. */
- if (in_call)
- {
- tree folded;
- tree op0 = TREE_OPERAND (currop->op0, 0);
- pre_expr op0expr = get_or_alloc_expr_for (op0);
- tree genop0 = find_or_generate_expression (block, op0expr, stmts,
- domstmt);
- if (!genop0)
- return NULL_TREE;
- folded = fold_build1 (currop->opcode, currop->type,
- genop0);
- return folded;
- }
- else
- {
-
- tree folded;
- tree genop1 = create_component_ref_by_pieces (block, ref,
- operand + 1,
- stmts, domstmt,
- in_call);
- if (!genop1)
- return NULL_TREE;
- genop1 = fold_convert (build_pointer_type (currop->type),
- genop1);
+ tree folded;
+ tree genop1 = create_component_ref_by_pieces_1 (block, ref,
+ operand,
+ stmts, domstmt);
+ if (!genop1)
+ return NULL_TREE;
+ genop1 = fold_convert (build_pointer_type (currop->type),
+ genop1);
- folded = fold_build1 (currop->opcode, currop->type,
- genop1);
- return folded;
- }
+ folded = fold_build1 (currop->opcode, currop->type,
+ genop1);
+ return folded;
}
break;
case BIT_FIELD_REF:
{
tree folded;
- tree genop0 = create_component_ref_by_pieces (block, ref, operand + 1,
- stmts, domstmt,
- in_call);
+ tree genop0 = create_component_ref_by_pieces_1 (block, ref, operand,
+ stmts, domstmt);
pre_expr op1expr = get_or_alloc_expr_for (currop->op0);
pre_expr op2expr = get_or_alloc_expr_for (currop->op1);
tree genop1;
@@ -2553,17 +2525,14 @@ create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
case ARRAY_RANGE_REF:
case ARRAY_REF:
{
- vn_reference_op_t op0expr;
tree genop0;
tree genop1 = currop->op0;
pre_expr op1expr;
tree genop2 = currop->op1;
pre_expr op2expr;
tree genop3;
- op0expr = VEC_index (vn_reference_op_s, ref->operands, operand + 1);
- genop0 = create_component_ref_by_pieces (block, ref, operand + 1,
- stmts, domstmt,
- in_call);
+ genop0 = create_component_ref_by_pieces_1 (block, ref, operand,
+ stmts, domstmt);
if (!genop0)
return NULL_TREE;
op1expr = get_or_alloc_expr_for (genop1);
@@ -2589,8 +2558,8 @@ create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
tree op1;
tree genop2 = currop->op1;
pre_expr op2expr;
- op0 = create_component_ref_by_pieces (block, ref, operand + 1,
- stmts, domstmt, in_call);
+ op0 = create_component_ref_by_pieces_1 (block, ref, operand,
+ stmts, domstmt);
if (!op0)
return NULL_TREE;
/* op1 should be a FIELD_DECL, which are represented by
@@ -2626,11 +2595,6 @@ create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
case CONST_DECL:
case RESULT_DECL:
case FUNCTION_DECL:
- /* For ADDR_EXPR in a CALL_EXPR, op0 is actually the entire
- ADDR_EXPR, not just it's operand. */
- case ADDR_EXPR:
- if (currop->opcode == ADDR_EXPR)
- gcc_assert (currop->op0 != NULL);
return currop->op0;
default:
@@ -2638,6 +2602,26 @@ create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
}
}
+/* For COMPONENT_REF's and ARRAY_REF's, we can't have any intermediates for the
+ COMPONENT_REF or INDIRECT_REF or ARRAY_REF portion, because we'd end up with
+ trying to rename aggregates into ssa form directly, which is a no no.
+
+ Thus, this routine doesn't create temporaries, it just builds a
+ single access expression for the array, calling
+ find_or_generate_expression to build the innermost pieces.
+
+ This function is a subroutine of create_expression_by_pieces, and
+ should not be called on it's own unless you really know what you
+ are doing. */
+
+static tree
+create_component_ref_by_pieces (basic_block block, vn_reference_t ref,
+ gimple_seq *stmts, gimple domstmt)
+{
+ unsigned int op = 0;
+ return create_component_ref_by_pieces_1 (block, ref, &op, stmts, domstmt);
+}
+
/* Find a leader for an expression, or generate one using
create_expression_by_pieces if it's ANTIC but
complex.
@@ -2743,8 +2727,7 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
case REFERENCE:
{
vn_reference_t ref = PRE_EXPR_REFERENCE (expr);
- folded = create_component_ref_by_pieces (block, ref, 0, stmts,
- domstmt, false);
+ folded = create_component_ref_by_pieces (block, ref, stmts, domstmt);
}
break;
case NARY:
@@ -3616,6 +3599,8 @@ compute_avail (void)
add_to_exp_gen (block, vro->op0);
if (vro->op1 && TREE_CODE (vro->op1) == SSA_NAME)
add_to_exp_gen (block, vro->op1);
+ if (vro->op2 && TREE_CODE (vro->op2) == SSA_NAME)
+ add_to_exp_gen (block, vro->op2);
}
result = (pre_expr) pool_alloc (pre_expr_pool);
result->kind = REFERENCE;
@@ -3688,6 +3673,8 @@ compute_avail (void)
add_to_exp_gen (block, vro->op0);
if (vro->op1 && TREE_CODE (vro->op1) == SSA_NAME)
add_to_exp_gen (block, vro->op1);
+ if (vro->op2 && TREE_CODE (vro->op2) == SSA_NAME)
+ add_to_exp_gen (block, vro->op2);
}
result = (pre_expr) pool_alloc (pre_expr_pool);
result->kind = REFERENCE;
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 42d394f..f6492bd 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -557,7 +557,7 @@ shared_vuses_from_stmt (gimple stmt)
/* Copy the operations present in load/store REF into RESULT, a vector of
vn_reference_op_s's. */
-static void
+void
copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
{
if (TREE_CODE (ref) == TARGET_MEM_REF)
@@ -646,6 +646,13 @@ copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
case SSA_NAME:
temp.op0 = ref;
break;
+ case ADDR_EXPR:
+ if (is_gimple_min_invariant (ref))
+ {
+ temp.op0 = ref;
+ break;
+ }
+ /* Fallthrough. */
/* These are only interesting for their operands, their
existence, and their type. They will never be the last
ref in the chain of references (IE they require an
@@ -654,15 +661,15 @@ copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
case IMAGPART_EXPR:
case REALPART_EXPR:
case VIEW_CONVERT_EXPR:
- case ADDR_EXPR:
break;
default:
gcc_unreachable ();
-
}
VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
- if (REFERENCE_CLASS_P (ref) || TREE_CODE (ref) == ADDR_EXPR)
+ if (REFERENCE_CLASS_P (ref)
+ || (TREE_CODE (ref) == ADDR_EXPR
+ && !is_gimple_min_invariant (ref)))
ref = TREE_OPERAND (ref, 0);
else
ref = NULL_TREE;
@@ -677,7 +684,6 @@ copy_reference_ops_from_call (gimple call,
VEC(vn_reference_op_s, heap) **result)
{
vn_reference_op_s temp;
- tree callfn;
unsigned i;
/* Copy the call_expr opcode, type, function being called, and
@@ -685,33 +691,15 @@ copy_reference_ops_from_call (gimple call,
memset (&temp, 0, sizeof (temp));
temp.type = gimple_call_return_type (call);
temp.opcode = CALL_EXPR;
+ temp.op0 = gimple_call_fn (call);
VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
- /* FIXME tuples
- We make no attempt to simplify the called function because
- the typical &FUNCTION_DECL form is also used in function pointer
- cases that become constant. If we simplify the original to
- FUNCTION_DECL but not the function pointer case (which can
- happen because we have no fold functions that operate on
- vn_reference_t), we will claim they are not equivalent.
-
- An example of this behavior can be see if CALL_EXPR_FN below is
- replaced with get_callee_fndecl and gcc.dg/tree-ssa/ssa-pre-13.c
- is compiled. */
- callfn = gimple_call_fn (call);
- temp.type = TREE_TYPE (callfn);
- temp.opcode = TREE_CODE (callfn);
- temp.op0 = callfn;
- VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
-
+ /* Copy the call arguments. As they can be references as well,
+ just chain them together. */
for (i = 0; i < gimple_call_num_args (call); ++i)
{
tree callarg = gimple_call_arg (call, i);
- memset (&temp, 0, sizeof (temp));
- temp.type = TREE_TYPE (callarg);
- temp.opcode = TREE_CODE (callarg);
- temp.op0 = callarg;
- VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
+ copy_reference_ops_from_ref (callarg, result);
}
return;
}
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index 923be19..d648cd9 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -174,6 +174,7 @@ vn_nary_op_t vn_nary_op_insert_stmt (gimple, tree);
vn_nary_op_t vn_nary_op_insert_pieces (unsigned int, enum tree_code,
tree, tree, tree, tree,
tree, tree, unsigned int);
+void copy_reference_ops_from_ref (tree, VEC(vn_reference_op_s, heap) **);
void copy_reference_ops_from_call (gimple, VEC(vn_reference_op_s, heap) **);
tree vn_reference_lookup_pieces (VEC (tree, gc) *,
VEC (vn_reference_op_s, heap) *,