aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-pre.c
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2009-04-04 09:34:32 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2009-04-04 09:34:32 +0000
commitaa7069aa9faf250b01c10bb7c2c442d329c0bab8 (patch)
tree9008d47a69f8bfcbddab1535dfb7516d4a030aff /gcc/tree-ssa-pre.c
parentcd15ad3e604aaa74991b72dcbf74ab61fe2fc9c4 (diff)
downloadgcc-aa7069aa9faf250b01c10bb7c2c442d329c0bab8.zip
gcc-aa7069aa9faf250b01c10bb7c2c442d329c0bab8.tar.gz
gcc-aa7069aa9faf250b01c10bb7c2c442d329c0bab8.tar.bz2
re PR c++/8781 (Pessimization of C++ (functional) code)
2009-04-04 Richard Guenther <rguenther@suse.de> PR tree-optimization/8781 PR tree-optimization/37892 * tree-ssa-sccvn.h (vn_reference_fold_indirect): Declare. * tree-ssa-sccvn.c (vn_reference_fold_indirect): New function. (valueize_refs): Call it for *& valueizations. (shared_reference_ops_from_ref): Rename to ... (valueize_shared_reference_ops_from_ref): ... this and valueize. (shared_reference_ops_from_call): Rename to ... (valueize_shared_reference_ops_from_call): ... this and valueize. (vn_reference_lookup): Update. (visit_reference_op_call): Likewise. * tree-ssa-pre.c (phi_translate_1): Fold *&. (eliminate): Value-replace the call address in call statements. * g++.dg/tree-ssa/pr8781.C: New testcase. * gcc.dg/tree-ssa/ssa-pre-25.c: Likewise. From-SVN: r145533
Diffstat (limited to 'gcc/tree-ssa-pre.c')
-rw-r--r--gcc/tree-ssa-pre.c36
1 files changed, 33 insertions, 3 deletions
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index c1cbe0c..ed326e4 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -1563,11 +1563,12 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
tree newvuse = vuse;
VEC (vn_reference_op_s, heap) *newoperands = NULL;
bool changed = false;
- unsigned int i;
+ unsigned int i, j;
vn_reference_op_t operand;
vn_reference_t newref;
- for (i = 0; VEC_iterate (vn_reference_op_s, operands, i, operand); i++)
+ for (i = 0, j = 0;
+ VEC_iterate (vn_reference_op_s, operands, i, operand); i++, j++)
{
pre_expr opresult;
pre_expr leader;
@@ -1642,7 +1643,13 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
newop.op0 = op0;
newop.op1 = op1;
newop.op2 = op2;
- VEC_replace (vn_reference_op_s, newoperands, i, &newop);
+ VEC_replace (vn_reference_op_s, newoperands, j, &newop);
+ /* If it transforms from an SSA_NAME to an address, fold with
+ a preceding indirect reference. */
+ if (j > 0 && op0 && TREE_CODE (op0) == ADDR_EXPR
+ && VEC_index (vn_reference_op_s,
+ newoperands, j - 1)->opcode == INDIRECT_REF)
+ vn_reference_fold_indirect (&newoperands, &j);
}
if (i != VEC_length (vn_reference_op_s, operands))
{
@@ -4098,6 +4105,29 @@ eliminate (void)
todo = TODO_cleanup_cfg;
}
}
+ /* Visit indirect calls and turn them into direct calls if
+ possible. */
+ if (gimple_code (stmt) == GIMPLE_CALL
+ && TREE_CODE (gimple_call_fn (stmt)) == SSA_NAME)
+ {
+ tree fn = VN_INFO (gimple_call_fn (stmt))->valnum;
+ if (TREE_CODE (fn) == ADDR_EXPR
+ && TREE_CODE (TREE_OPERAND (fn, 0)) == FUNCTION_DECL)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Replacing call target with ");
+ print_generic_expr (dump_file, fn, 0);
+ fprintf (dump_file, " in ");
+ print_gimple_stmt (dump_file, stmt, 0, 0);
+ }
+
+ gimple_call_set_fn (stmt, fn);
+ update_stmt (stmt);
+ if (maybe_clean_or_replace_eh_stmt (stmt, stmt))
+ gimple_purge_dead_eh_edges (b);
+ }
+ }
}
}