Hi, This patch adjusts alloc-free removal algorithm in DCE to take into account BUILT_IN_CHKP_BNDRET call returning bounds of allocated memory.
Bootstrapped and tested on linux-x86_64. Thanks, Ilya -- gcc/ 2014-06-03 Ilya Enkovich <ilya.enkov...@intel.com> * tree-ssa-dce.c: Include target.h. (propagate_necessity): For free call fed by alloc check bounds are also provided by the same alloc. (eliminate_unnecessary_stmts): Handle BUILT_IN_CHKP_BNDRET used by free calls. diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index 13a71ce..59a0b71 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -73,6 +73,7 @@ along with GCC; see the file COPYING3. If not see #include "flags.h" #include "cfgloop.h" #include "tree-scalar-evolution.h" +#include "target.h" static struct stmt_stats { @@ -778,7 +779,23 @@ propagate_necessity (bool aggressive) && DECL_BUILT_IN_CLASS (def_callee) == BUILT_IN_NORMAL && (DECL_FUNCTION_CODE (def_callee) == BUILT_IN_MALLOC || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC)) - continue; + { + tree retfndecl + = targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDRET); + gimple bounds_def_stmt; + tree bounds; + + /* For instrumented calls we should also check used + bounds are returned by the same allocation call. */ + if (!gimple_call_with_bounds_p (stmt) + || ((bounds = gimple_call_arg (stmt, 1)) + && TREE_CODE (bounds) == SSA_NAME + && (bounds_def_stmt = SSA_NAME_DEF_STMT (bounds)) + && is_gimple_call (bounds_def_stmt) + && gimple_call_fndecl (bounds_def_stmt) == retfndecl + && gimple_call_arg (bounds_def_stmt, 0) == ptr)) + continue; + } } FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE) @@ -1204,6 +1221,23 @@ eliminate_unnecessary_stmts (void) && !gimple_plf (def_stmt, STMT_NECESSARY)) gimple_set_plf (stmt, STMT_NECESSARY, false); } + /* We did not propagate necessity for free calls fed + by allocation function to allow unnecessary + alloc-free sequence elimination. For instrumented + calls it also means we did not mark bounds producer + as necessary and it is time to do it in case free + call is not removed. */ + if (gimple_call_with_bounds_p (stmt)) + { + gimple bounds_def_stmt; + tree bounds = gimple_call_arg (stmt, 1); + gcc_assert (TREE_CODE (bounds) == SSA_NAME); + bounds_def_stmt = SSA_NAME_DEF_STMT (bounds); + if (bounds_def_stmt + && !gimple_plf (bounds_def_stmt, STMT_NECESSARY)) + gimple_set_plf (bounds_def_stmt, STMT_NECESSARY, + gimple_plf (stmt, STMT_NECESSARY)); + } } /* If GSI is not necessary then remove it. */ @@ -1216,6 +1250,7 @@ eliminate_unnecessary_stmts (void) else if (is_gimple_call (stmt)) { tree name = gimple_call_lhs (stmt); + tree retfn = targetm.builtin_chkp_function (BUILT_IN_CHKP_BNDRET); notice_special_calls (stmt); @@ -1233,7 +1268,9 @@ eliminate_unnecessary_stmts (void) && DECL_FUNCTION_CODE (call) != BUILT_IN_CALLOC && DECL_FUNCTION_CODE (call) != BUILT_IN_ALLOCA && (DECL_FUNCTION_CODE (call) - != BUILT_IN_ALLOCA_WITH_ALIGN)))) + != BUILT_IN_ALLOCA_WITH_ALIGN))) + /* Avoid doing so for bndret calls for the same reason. */ + && (!retfn || gimple_call_fndecl (stmt) != retfn)) { something_changed = true; if (dump_file && (dump_flags & TDF_DETAILS))