Extend DCE to remove unnecessary new/delete-pairs (PR c++/23383).

2019-07-25  Martin Liska  <mliska@suse.cz>
	    Dominik Infuhr  <dominik.infuehr@theobroma-systems.com>

	PR c++/23383
	* common.opt: Add -fallocation-dce
	* gimple.c (gimple_call_operator_delete_p): New.
	* gimple.h (gimple_call_operator_delete_p): Likewise.
	* tree-core.h (enum function_decl_type): Add OPERATOR_DELETE.
	* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Handle
	DECL_IS_OPERATOR_DELETE_P.
	(mark_all_reaching_defs_necessary_1): Likewise.
	(propagate_necessity): Likewise.
	(eliminate_unnecessary_stmts): Handle
	gimple_call_operator_delete_p.
	* tree-streamer-in.c (unpack_ts_function_decl_value_fields):
	Add packing of OPERATOR_DELETE.
	* tree-streamer-out.c (pack_ts_function_decl_value_fields):
	Similarly here.
	* tree.h (DECL_IS_OPERATOR_DELETE_P): New.
	(DECL_SET_IS_OPERATOR_DELETE): New.
	(DECL_IS_REPLACEABLE_OPERATOR_NEW_P): Likewise.
2019-07-25  Martin Liska  <mliska@suse.cz>
	    Dominik Infuhr  <dominik.infuehr@theobroma-systems.com>

	PR c++/23383
	* c-decl.c (merge_decls): Merge OPERATOR_DELETE flag.
2019-07-25  Martin Liska  <mliska@suse.cz>
	    Dominik Infuhr  <dominik.infuehr@theobroma-systems.com>

	PR c++/23383
	* decl.c (cxx_init_decl_processing): Mark delete operators
	with DECL_SET_IS_OPERATOR_DELETE.
2019-07-25  Martin Liska  <mliska@suse.cz
	    Dominik Infuhr  <dominik.infuehr@theobroma-systems.com>

	PR c++/23383
	* g++.dg/cpp1y/new1.C: New test.
2019-07-25  Martin Liska  <mliska@suse.cz>
	    Dominik Infuhr  <dominik.infuehr@theobroma-systems.com>

	PR c++/23383
	* testsuite/ext/bitmap_allocator/check_delete.cc: Add
	-fno-allocation-dce.
	* testsuite/ext/bitmap_allocator/check_new.cc: Likewise.
	* testsuite/ext/new_allocator/check_delete.cc: Likewise.
	* testsuite/ext/new_allocator/check_new.cc: Likewise.

Co-Authored-By: Dominik Infuehr <dominik.infuehr@theobroma-systems.com>

From-SVN: r273791
This commit is contained in:
Martin Liska 2019-07-25 11:36:38 +02:00 committed by Martin Liska
parent cb50701ec2
commit 6343b6bf3b
20 changed files with 201 additions and 14 deletions

View file

@ -1,3 +1,25 @@
2019-07-25 Martin Liska <mliska@suse.cz>
Dominik Infuhr <dominik.infuehr@theobroma-systems.com>
PR c++/23383
* common.opt: Add -fallocation-dce
* gimple.c (gimple_call_operator_delete_p): New.
* gimple.h (gimple_call_operator_delete_p): Likewise.
* tree-core.h (enum function_decl_type): Add OPERATOR_DELETE.
* tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Handle
DECL_IS_OPERATOR_DELETE_P.
(mark_all_reaching_defs_necessary_1): Likewise.
(propagate_necessity): Likewise.
(eliminate_unnecessary_stmts): Handle
gimple_call_operator_delete_p.
* tree-streamer-in.c (unpack_ts_function_decl_value_fields):
Add packing of OPERATOR_DELETE.
* tree-streamer-out.c (pack_ts_function_decl_value_fields):
Similarly here.
* tree.h (DECL_IS_OPERATOR_DELETE_P): New.
(DECL_SET_IS_OPERATOR_DELETE): New.
(DECL_IS_REPLACEABLE_OPERATOR_NEW_P): Likewise.
2019-07-25 Martin Liska <mliska@suse.cz>
* calls.c (maybe_warn_alloc_args_overflow): Use new macros

View file

@ -1,3 +1,9 @@
2019-07-25 Martin Liska <mliska@suse.cz>
Dominik Infuhr <dominik.infuehr@theobroma-systems.com>
PR c++/23383
* c-decl.c (merge_decls): Merge OPERATOR_DELETE flag.
2019-07-25 Martin Liska <mliska@suse.cz>
* c-decl.c (merge_decls): Use new macros

View file

@ -2641,6 +2641,8 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype)
DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
if (DECL_IS_OPERATOR_NEW_P (olddecl))
DECL_SET_IS_OPERATOR_NEW (newdecl, true);
if (DECL_IS_OPERATOR_DELETE_P (olddecl))
DECL_SET_IS_OPERATOR_DELETE (newdecl, true);
TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl);
DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);

View file

@ -2211,6 +2211,10 @@ Enum(live_patching_level) String(inline-only-static) Value(LIVE_PATCHING_INLINE_
EnumValue
Enum(live_patching_level) String(inline-clone) Value(LIVE_PATCHING_INLINE_CLONE)
fallocation-dce
Common Report Var(flag_allocation_dce) Init(1) Optimization
Tell DCE to remove unused C++ allocations.
flive-range-shrinkage
Common Report Var(flag_live_range_shrinkage) Init(0) Optimization
Relief of register pressure through live range shrinkage.

View file

@ -1,3 +1,10 @@
2019-07-25 Martin Liska <mliska@suse.cz>
Dominik Infuhr <dominik.infuehr@theobroma-systems.com>
PR c++/23383
* decl.c (cxx_init_decl_processing): Mark delete operators
with DECL_SET_IS_OPERATOR_DELETE.
2019-07-25 Martin Liska <mliska@suse.cz>
* decl.c (duplicate_decls): Use new macros

View file

@ -4363,8 +4363,10 @@ cxx_init_decl_processing (void)
opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0);
DECL_IS_MALLOC (opnew) = 1;
DECL_SET_IS_OPERATOR_NEW (opnew, true);
push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
tree opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
DECL_SET_IS_OPERATOR_DELETE (opdel, true);
opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
DECL_SET_IS_OPERATOR_DELETE (opdel, true);
if (flag_sized_deallocation)
{
/* Also push the sized deallocation variants:
@ -4376,8 +4378,10 @@ cxx_init_decl_processing (void)
deltype = cp_build_type_attribute_variant (void_ftype_ptr_size,
extvisattr);
deltype = build_exception_variant (deltype, empty_except_spec);
push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
DECL_SET_IS_OPERATOR_DELETE (opdel, true);
opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
DECL_SET_IS_OPERATOR_DELETE (opdel, true);
}
if (aligned_new_threshold)
@ -4405,8 +4409,10 @@ cxx_init_decl_processing (void)
align_type_node, NULL_TREE);
deltype = cp_build_type_attribute_variant (deltype, extvisattr);
deltype = build_exception_variant (deltype, empty_except_spec);
push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
DECL_SET_IS_OPERATOR_DELETE (opdel, true);
opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
DECL_SET_IS_OPERATOR_DELETE (opdel, true);
if (flag_sized_deallocation)
{
@ -4416,8 +4422,10 @@ cxx_init_decl_processing (void)
NULL_TREE);
deltype = cp_build_type_attribute_variant (deltype, extvisattr);
deltype = build_exception_variant (deltype, empty_except_spec);
push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW);
DECL_SET_IS_OPERATOR_DELETE (opdel, true);
opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW);
DECL_SET_IS_OPERATOR_DELETE (opdel, true);
}
}

View file

@ -2695,6 +2695,18 @@ gimple_builtin_call_types_compatible_p (const gimple *stmt, tree fndecl)
return true;
}
/* Return true when STMT is operator delete call. */
bool
gimple_call_operator_delete_p (const gcall *stmt)
{
tree fndecl;
if ((fndecl = gimple_call_fndecl (stmt)) != NULL_TREE)
return DECL_IS_OPERATOR_DELETE_P (fndecl);
return false;
}
/* Return true when STMT is builtins call. */
bool

View file

@ -1547,6 +1547,7 @@ extern alias_set_type gimple_get_alias_set (tree);
extern bool gimple_ior_addresses_taken (bitmap, gimple *);
extern bool gimple_builtin_call_types_compatible_p (const gimple *, tree);
extern combined_fn gimple_call_combined_fn (const gimple *);
extern bool gimple_call_operator_delete_p (const gcall *);
extern bool gimple_call_builtin_p (const gimple *);
extern bool gimple_call_builtin_p (const gimple *, enum built_in_class);
extern bool gimple_call_builtin_p (const gimple *, enum built_in_function);

View file

@ -1,3 +1,9 @@
2019-07-25 Martin Liska <mliska@suse.cz
Dominik Infuhr <dominik.infuehr@theobroma-systems.com>
PR c++/23383
* g++.dg/cpp1y/new1.C: New test.
2019-07-25 Eric Botcazou <ebotcazou@adacore.com>
PR testsuite/91245

View file

@ -0,0 +1,65 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-cddce-details" } */
#include <stdlib.h>
void
new_without_use() {
int *x = new int;
}
void
new_array_without_use() {
int *x = new int[5];
}
void
new_primitive() {
int *x = new int;
delete x;
}
void
new_array() {
int *x = new int[10];
delete [] x;
}
void
new_primitive_store() {
int *x = new int;
*x = 10;
delete x;
}
void
new_primitive_load() {
int *x = new int;
int tmp = *x;
delete x;
}
int
new_primitive_load_with_use() {
int *x = new int;
int tmp = *x;
delete x;
return tmp;
}
void
new_array_store() {
int *x = new int[10];
x[4] = 10;
delete [] x;
}
void
new_array_load() {
int *x = new int[10];
int tmp = x[4];
delete [] x;
}
/* { dg-final { scan-tree-dump-times "Deleting : operator delete" 5 "cddce1"} } */
/* { dg-final { scan-tree-dump-times "Deleting : _\\d+ = operator new" 7 "cddce1"} } */

View file

@ -1826,6 +1826,7 @@ enum function_decl_type
{
NONE,
OPERATOR_NEW,
OPERATOR_DELETE,
LAMBDA_FUNCTION
/* 0 values left */

View file

@ -237,6 +237,12 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive)
default:;
}
if (callee != NULL_TREE
&& flag_allocation_dce
&& DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee))
return;
/* Most, but not all function calls are required. Function calls that
produce no result and have no side effects (i.e. const pure
functions) are unnecessary. */
@ -588,6 +594,11 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED,
default:;
}
if (callee != NULL_TREE
&& (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee)
|| DECL_IS_OPERATOR_DELETE_P (callee)))
return false;
}
if (! gimple_clobber_p (def_stmt))
@ -774,7 +785,10 @@ propagate_necessity (bool aggressive)
/* If this is a call to free which is directly fed by an
allocation function do not mark that necessary through
processing the argument. */
if (gimple_call_builtin_p (stmt, BUILT_IN_FREE))
if (gimple_call_builtin_p (stmt, BUILT_IN_FREE)
|| (is_gimple_call (stmt)
&& gimple_call_operator_delete_p (as_a <gcall *> (stmt))))
{
tree ptr = gimple_call_arg (stmt, 0);
gimple *def_stmt;
@ -784,10 +798,11 @@ propagate_necessity (bool aggressive)
if (TREE_CODE (ptr) == SSA_NAME
&& is_gimple_call (def_stmt = 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_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)))
continue;
}
@ -842,6 +857,11 @@ propagate_necessity (bool aggressive)
|| DECL_FUNCTION_CODE (callee) == BUILT_IN_ASSUME_ALIGNED))
continue;
if (callee != NULL_TREE
&& (DECL_IS_REPLACEABLE_OPERATOR_NEW_P (callee)
|| DECL_IS_OPERATOR_DELETE_P (callee)))
continue;
/* Calls implicitly load from memory, their arguments
in addition may explicitly perform memory loads. */
mark_all_reaching_defs_necessary (stmt);
@ -1262,7 +1282,9 @@ eliminate_unnecessary_stmts (void)
defining statement of its argument is not necessary
(and thus is getting removed). */
if (gimple_plf (stmt, STMT_NECESSARY)
&& gimple_call_builtin_p (stmt, BUILT_IN_FREE))
&& (gimple_call_builtin_p (stmt, BUILT_IN_FREE)
|| (is_gimple_call (stmt)
&& gimple_call_operator_delete_p (as_a <gcall *> (stmt)))))
{
tree ptr = gimple_call_arg (stmt, 0);
if (TREE_CODE (ptr) == SSA_NAME)

View file

@ -334,6 +334,7 @@ unpack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
DECL_IS_RETURNS_TWICE (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_IS_MALLOC (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_SET_IS_OPERATOR_NEW (expr, (unsigned) bp_unpack_value (bp, 1));
DECL_SET_IS_OPERATOR_DELETE (expr, (unsigned) bp_unpack_value (bp, 1));
DECL_DECLARED_INLINE_P (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_STATIC_CHAIN (expr) = (unsigned) bp_unpack_value (bp, 1);
DECL_NO_INLINE_WARNING_P (expr) = (unsigned) bp_unpack_value (bp, 1);

View file

@ -296,6 +296,7 @@ pack_ts_function_decl_value_fields (struct bitpack_d *bp, tree expr)
bp_pack_value (bp, DECL_IS_RETURNS_TWICE (expr), 1);
bp_pack_value (bp, DECL_IS_MALLOC (expr), 1);
bp_pack_value (bp, DECL_IS_OPERATOR_NEW_P (expr), 1);
bp_pack_value (bp, DECL_IS_OPERATOR_DELETE_P (expr), 1);
bp_pack_value (bp, DECL_DECLARED_INLINE_P (expr), 1);
bp_pack_value (bp, DECL_STATIC_CHAIN (expr), 1);
bp_pack_value (bp, DECL_NO_INLINE_WARNING_P (expr), 1);

View file

@ -3020,9 +3020,20 @@ set_function_decl_type (tree decl, function_decl_type t, bool set)
#define DECL_IS_OPERATOR_NEW_P(NODE) \
(FUNCTION_DECL_CHECK (NODE)->function_decl.decl_type == OPERATOR_NEW)
#define DECL_IS_REPLACEABLE_OPERATOR_NEW_P(NODE) \
(DECL_IS_OPERATOR_NEW_P (NODE) && DECL_IS_MALLOC (NODE))
#define DECL_SET_IS_OPERATOR_NEW(NODE, VAL) \
set_function_decl_type (FUNCTION_DECL_CHECK (NODE), OPERATOR_NEW, VAL)
/* Nonzero in a FUNCTION_DECL means this function should be treated as
C++ operator delete. */
#define DECL_IS_OPERATOR_DELETE_P(NODE) \
(FUNCTION_DECL_CHECK (NODE)->function_decl.decl_type == OPERATOR_DELETE)
#define DECL_SET_IS_OPERATOR_DELETE(NODE, VAL) \
set_function_decl_type (FUNCTION_DECL_CHECK (NODE), OPERATOR_DELETE, VAL)
/* Nonzero in a FUNCTION_DECL means this function may return more
than once. */
#define DECL_IS_RETURNS_TWICE(NODE) \

View file

@ -1,3 +1,13 @@
2019-07-25 Martin Liska <mliska@suse.cz>
Dominik Infuhr <dominik.infuehr@theobroma-systems.com>
PR c++/23383
* testsuite/ext/bitmap_allocator/check_delete.cc: Add
-fno-allocation-dce.
* testsuite/ext/bitmap_allocator/check_new.cc: Likewise.
* testsuite/ext/new_allocator/check_delete.cc: Likewise.
* testsuite/ext/new_allocator/check_new.cc: Likewise.
2019-07-22 Jonathan Wakely <jwakely@redhat.com>
* testsuite/26_numerics/bit/bitops.count/*: Rename to ...

View file

@ -15,6 +15,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-fno-allocation-dce" }
// 20.4.1.1 allocator members
#include <cstdlib>

View file

@ -15,6 +15,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-fno-allocation-dce" }
// 20.4.1.1 allocator members
#include <cstdlib>

View file

@ -17,6 +17,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-fno-allocation-dce" }
// 20.4.1.1 allocator members
#include <cstdlib>

View file

@ -17,6 +17,8 @@
// with this library; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
// { dg-options "-fno-allocation-dce" }
// 20.4.1.1 allocator members
#include <cstdlib>