From ce94d3547f81cc3dd105f4a3377e72cdbd2bbd2c Mon Sep 17 00:00:00 2001 From: Richard Guenther Date: Tue, 29 Jul 2008 17:09:26 +0000 Subject: [PATCH] re PR tree-optimization/36945 (PRE/SCCVN do not handle aggregate function arguments correctly) 2008-07-29 Richard Guenther 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 --- gcc/ChangeLog | 16 +++ gcc/testsuite/ChangeLog | 5 + gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-18.c | 21 +++ gcc/tree-ssa-pre.c | 151 ++++++++++----------- gcc/tree-ssa-sccvn.c | 42 ++---- gcc/tree-ssa-sccvn.h | 1 + 6 files changed, 127 insertions(+), 109 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-18.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d1929ba0cff..9d0388dd5aa 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2008-07-29 Richard Guenther + + 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 * gimplify.c (gimplify_expr): Clear TREE_SIDE_EFFECTS for diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d4e8ddb8701..79568ddab39 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-07-29 Richard Guenther + + PR tree-optimization/36945 + * gcc.dg/tree-ssa/ssa-pre-18.c: New testcase. + 2008-07-29 Jakub Jelinek 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 00000000000..5e92934f052 --- /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 c772ff2bdaf..c98a18a772c 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 42d394f5540..f6492bdafd8 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 923be193163..d648cd9bb94 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) *, -- 2.30.2