diff options
author | Richard Biener <rguenther@suse.de> | 2020-10-01 10:44:27 +0200 |
---|---|---|
committer | Richard Biener <rguenther@suse.de> | 2020-10-02 11:22:20 +0200 |
commit | 0b945f959f03a6185a3130f30bfd524d01d4142c (patch) | |
tree | c61ced9467e75d017f2ef2df083b466f5b345aeb /gcc/tree-ssa-dce.c | |
parent | b6158faacbfb7d24a1d25b3774bc4338dd849480 (diff) | |
download | gcc-0b945f959f03a6185a3130f30bfd524d01d4142c.zip gcc-0b945f959f03a6185a3130f30bfd524d01d4142c.tar.gz gcc-0b945f959f03a6185a3130f30bfd524d01d4142c.tar.bz2 |
make use of CALL_FROM_NEW_OR_DELETE_P
This fixes points-to analysis and DCE to only consider new/delete
operator calls from new or delete expressions and not direct calls.
2020-10-01 Richard Biener <rguenther@suse.de>
* gimple.h (GF_CALL_FROM_NEW_OR_DELETE): New call flag.
(gimple_call_set_from_new_or_delete): New.
(gimple_call_from_new_or_delete): Likewise.
* gimple.c (gimple_build_call_from_tree): Set
GF_CALL_FROM_NEW_OR_DELETE appropriately.
* ipa-icf-gimple.c (func_checker::compare_gimple_call):
Compare gimple_call_from_new_or_delete.
* tree-ssa-dce.c (mark_all_reaching_defs_necessary_1): Make
sure to only consider new/delete calls from new or delete
expressions.
(propagate_necessity): Likewise.
(eliminate_unnecessary_stmts): Likewise.
* tree-ssa-structalias.c (find_func_aliases_for_call):
Likewise.
* g++.dg/tree-ssa/pta-delete-1.C: New testcase.
Diffstat (limited to 'gcc/tree-ssa-dce.c')
-rw-r--r-- | gcc/tree-ssa-dce.c | 31 |
1 files changed, 18 insertions, 13 deletions
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index fae5ae7..c9e0c8f 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -593,9 +593,9 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED, /* We want to skip statments that do not constitute stores but have a virtual definition. */ - if (is_gimple_call (def_stmt)) + if (gcall *call = dyn_cast <gcall *> (def_stmt)) { - tree callee = gimple_call_fndecl (def_stmt); + tree callee = gimple_call_fndecl (call); if (callee != NULL_TREE && fndecl_built_in_p (callee, BUILT_IN_NORMAL)) switch (DECL_FUNCTION_CODE (callee)) @@ -612,7 +612,8 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED, if (callee != NULL_TREE && (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee) - || DECL_IS_REPLACEABLE_OPERATOR_DELETE_P (callee))) + || DECL_IS_REPLACEABLE_OPERATOR_DELETE_P (callee)) + && gimple_call_from_new_or_delete (call)) return false; } @@ -875,23 +876,25 @@ propagate_necessity (bool aggressive) processing the argument. */ bool is_delete_operator = (is_gimple_call (stmt) + && gimple_call_from_new_or_delete (as_a <gcall *> (stmt)) && gimple_call_replaceable_operator_delete_p (as_a <gcall *> (stmt))); if (is_delete_operator || gimple_call_builtin_p (stmt, BUILT_IN_FREE)) { tree ptr = gimple_call_arg (stmt, 0); - gimple *def_stmt; + gcall *def_stmt; tree def_callee; /* If the pointer we free is defined by an allocation function do not add the call to the worklist. */ if (TREE_CODE (ptr) == SSA_NAME - && is_gimple_call (def_stmt = SSA_NAME_DEF_STMT (ptr)) + && (def_stmt = dyn_cast <gcall *> (SSA_NAME_DEF_STMT (ptr))) && (def_callee = gimple_call_fndecl (def_stmt)) && ((DECL_BUILT_IN_CLASS (def_callee) == BUILT_IN_NORMAL && (DECL_FUNCTION_CODE (def_callee) == BUILT_IN_ALIGNED_ALLOC || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_MALLOC || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC)) - || DECL_IS_REPLACEABLE_OPERATOR_NEW_P (def_callee))) + || (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (def_callee) + && gimple_call_from_new_or_delete (def_stmt)))) { if (is_delete_operator) { @@ -947,9 +950,9 @@ propagate_necessity (bool aggressive) in 1). By keeping a global visited bitmap for references we walk for 2) we avoid quadratic behavior for those. */ - if (is_gimple_call (stmt)) + if (gcall *call = dyn_cast <gcall *> (stmt)) { - tree callee = gimple_call_fndecl (stmt); + tree callee = gimple_call_fndecl (call); unsigned i; /* Calls to functions that are merely acting as barriers @@ -972,22 +975,23 @@ propagate_necessity (bool aggressive) if (callee != NULL_TREE && (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee) - || DECL_IS_REPLACEABLE_OPERATOR_DELETE_P (callee))) + || DECL_IS_REPLACEABLE_OPERATOR_DELETE_P (callee)) + && gimple_call_from_new_or_delete (call)) continue; /* Calls implicitly load from memory, their arguments in addition may explicitly perform memory loads. */ - mark_all_reaching_defs_necessary (stmt); - for (i = 0; i < gimple_call_num_args (stmt); ++i) + mark_all_reaching_defs_necessary (call); + for (i = 0; i < gimple_call_num_args (call); ++i) { - tree arg = gimple_call_arg (stmt, i); + tree arg = gimple_call_arg (call, i); if (TREE_CODE (arg) == SSA_NAME || is_gimple_min_invariant (arg)) continue; if (TREE_CODE (arg) == WITH_SIZE_EXPR) arg = TREE_OPERAND (arg, 0); if (!ref_may_be_aliased (arg)) - mark_aliased_reaching_defs_necessary (stmt, arg); + mark_aliased_reaching_defs_necessary (call, arg); } } else if (gimple_assign_single_p (stmt)) @@ -1397,6 +1401,7 @@ eliminate_unnecessary_stmts (void) if (gimple_plf (stmt, STMT_NECESSARY) && (gimple_call_builtin_p (stmt, BUILT_IN_FREE) || (is_gimple_call (stmt) + && gimple_call_from_new_or_delete (as_a <gcall *> (stmt)) && gimple_call_replaceable_operator_delete_p (as_a <gcall *> (stmt))))) { tree ptr = gimple_call_arg (stmt, 0); |