aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-ssa-dce.c
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2020-10-01 10:44:27 +0200
committerRichard Biener <rguenther@suse.de>2020-10-02 11:22:20 +0200
commit0b945f959f03a6185a3130f30bfd524d01d4142c (patch)
treec61ced9467e75d017f2ef2df083b466f5b345aeb /gcc/tree-ssa-dce.c
parentb6158faacbfb7d24a1d25b3774bc4338dd849480 (diff)
downloadgcc-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.c31
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);