From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8070 invoked by alias); 21 Nov 2017 11:14:49 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 826 invoked by uid 89); 21 Nov 2017 11:14:22 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.5 required=5.0 tests=AWL,BAYES_00,KB_WAM_FROM_NAME_SINGLEWORD,SPF_NEUTRAL,T_RP_MATCHES_RCVD autolearn=no version=3.3.2 spammy=H*c:MHil, H*c:HHHHHHHH, H*c:HHHH, H*r:4.80 X-HELO: mail.theobroma-systems.com Received: from vegas.theobroma-systems.com (HELO mail.theobroma-systems.com) (144.76.126.164) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 21 Nov 2017 11:14:21 +0000 Received: from [86.59.122.178] (port=59560 helo=dhcp-10-2-9-209.lan) by mail.theobroma-systems.com with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.80) (envelope-from ) id 1eH6VO-0001jb-JK for gcc-patches@gcc.gnu.org; Tue, 21 Nov 2017 12:14:18 +0100 From: =?utf-8?Q?Dominik_Inf=C3=BChr?= Content-Type: multipart/signed; boundary="Apple-Mail=_4DA3D9A4-FEF3-4B55-88D7-CAEBE919793D"; protocol="application/pgp-signature"; micalg=pgp-sha512 Subject: [RFC][PATCH] Extend DCE to remove unnecessary new/delete-pairs Message-Id: <8305B5F4-2A96-4698-8C2E-3255658B5C12@theobroma-systems.com> Date: Tue, 21 Nov 2017 11:35:00 -0000 To: GCC Patches Mime-Version: 1.0 (Mac OS X Mail 9.3 \(3124\)) X-IsSubscribed: yes X-SW-Source: 2017-11/txt/msg01876.txt.bz2 --Apple-Mail=_4DA3D9A4-FEF3-4B55-88D7-CAEBE919793D Content-Type: multipart/mixed; boundary="Apple-Mail=_76511938-19E6-4905-8993-8A37F8872C22" --Apple-Mail=_76511938-19E6-4905-8993-8A37F8872C22 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Content-length: 337 Hi, this patch tries to extend tree-ssa-dce.c to remove unnecessary new/delete-= pairs (it already does that for malloc/free). Clang does it too and it seem= s to be allowed by http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/= n3664.html. I=E2=80=99ve bootstrapped/regtested on aarch64-linux and x86_64= -linux. Best, Dominik --Apple-Mail=_76511938-19E6-4905-8993-8A37F8872C22 Content-Disposition: attachment; filename=dce-new-delete.diff Content-Type: application/octet-stream; name="dce-new-delete.diff" Content-Transfer-Encoding: 7bit Content-length: 14200 diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index d95a2b6ea4f..4ed8c2d191a 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -2454,6 +2454,7 @@ merge_decls (tree newdecl, tree olddecl, tree newtype, tree oldtype) TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl); DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl); DECL_IS_OPERATOR_NEW (newdecl) |= DECL_IS_OPERATOR_NEW (olddecl); + DECL_IS_OPERATOR_DELETE (newdecl) |= DECL_IS_OPERATOR_DELETE (olddecl); TREE_READONLY (newdecl) |= TREE_READONLY (olddecl); DECL_PURE_P (newdecl) |= DECL_PURE_P (olddecl); DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 54e06568e46..d1c77b1d670 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -4182,8 +4182,11 @@ cxx_init_decl_processing (void) opnew = push_cp_library_fn (VEC_NEW_EXPR, newtype, 0); DECL_IS_MALLOC (opnew) = 1; DECL_IS_OPERATOR_NEW (opnew) = 1; - 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_IS_OPERATOR_DELETE (opdel) = 1; + opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_IS_OPERATOR_DELETE (opdel) = 1; + if (flag_sized_deallocation) { /* Also push the sized deallocation variants: @@ -4195,8 +4198,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); + opdel = push_cp_library_fn (DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_IS_OPERATOR_DELETE (opdel) = 1; push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_IS_OPERATOR_DELETE (opdel) = 1; } if (aligned_new_threshold) @@ -4224,8 +4229,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_IS_OPERATOR_DELETE (opdel) = 1; + opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_IS_OPERATOR_DELETE (opdel) = 1; if (flag_sized_deallocation) { @@ -4235,8 +4242,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_IS_OPERATOR_DELETE (opdel) = 1; + opdel = push_cp_library_fn (VEC_DELETE_EXPR, deltype, ECF_NOTHROW); + DECL_IS_OPERATOR_DELETE (opdel) = 1; } } diff --git a/gcc/gimple.c b/gcc/gimple.c index c986a732004..27aab5aa3b5 100644 --- a/gcc/gimple.c +++ b/gcc/gimple.c @@ -2543,6 +2543,32 @@ gimple_builtin_call_types_compatible_p (const gimple *stmt, tree fndecl) return true; } +/* Return true when STMT is operator new call. */ + +bool +gimple_call_operator_new_p (const gimple *stmt) +{ + tree fndecl; + + if (is_gimple_call (stmt) + && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE) + return DECL_IS_OPERATOR_NEW (fndecl); + return false; +} + +/* Return true when STMT is operator delete call. */ + +bool +gimple_call_operator_delete_p (const gimple *stmt) +{ + tree fndecl; + + if (is_gimple_call (stmt) + && (fndecl = gimple_call_fndecl (stmt)) != NULL_TREE) + return DECL_IS_OPERATOR_DELETE (fndecl); + return false; +} + /* Return true when STMT is builtins call. */ bool diff --git a/gcc/gimple.h b/gcc/gimple.h index 334def89398..c9c25c2a228 100644 --- a/gcc/gimple.h +++ b/gcc/gimple.h @@ -1514,6 +1514,8 @@ 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_new_p (const gimple *); +extern bool gimple_call_operator_delete_p (const gimple *); 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); diff --git a/gcc/testsuite/g++.dg/cpp1y/new1.C b/gcc/testsuite/g++.dg/cpp1y/new1.C new file mode 100644 index 00000000000..b966cf5d7b7 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/new1.C @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cddce-details" } */ + +#include + +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" 4 "cddce1"} } */ +/* { dg-final { scan-tree-dump-times "Deleting : _\\d+ = operator new" 6 "cddce1"} } */ diff --git a/gcc/tree-core.h b/gcc/tree-core.h index aa54221253c..9a406c5d86c 100644 --- a/gcc/tree-core.h +++ b/gcc/tree-core.h @@ -1787,7 +1787,9 @@ struct GTY(()) tree_function_decl { unsigned has_debug_args_flag : 1; unsigned tm_clone_flag : 1; unsigned versioned_function : 1; - /* No bits left. */ + + unsigned operator_delete_flag : 1; + /* 31 bits left. */ }; struct GTY(()) tree_translation_unit_decl { diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c index a5f0edf7893..571a0b7bb5a 100644 --- a/gcc/tree-ssa-dce.c +++ b/gcc/tree-ssa-dce.c @@ -238,6 +238,11 @@ mark_stmt_if_obviously_necessary (gimple *stmt, bool aggressive) default:; } + + if (callee != NULL_TREE + && DECL_IS_OPERATOR_NEW (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. */ @@ -581,6 +586,11 @@ mark_all_reaching_defs_necessary_1 (ao_ref *ref ATTRIBUTE_UNUSED, default:; } + + if (callee != NULL_TREE + && (DECL_IS_OPERATOR_NEW (callee) + || DECL_IS_OPERATOR_DELETE (callee))) + return false; } if (! gimple_clobber_p (def_stmt)) @@ -767,20 +777,23 @@ 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) + || gimple_call_operator_delete_p (stmt)) { tree ptr = gimple_call_arg (stmt, 0); gimple *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_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_OPERATOR_NEW (def_callee))) { gimple *bounds_def_stmt; tree bounds; @@ -794,7 +807,24 @@ propagate_necessity (bool aggressive) && chkp_gimple_call_builtin_p (bounds_def_stmt, BUILT_IN_CHKP_BNDRET) && gimple_call_arg (bounds_def_stmt, 0) == ptr)) - continue; + { + /* For operator delete [] we need to keep size operand + alive. Otherwise this operand isn't available anymore + when we finally decide that this stmt is necessary in + eliminate_unnecessary_stmts. If it should really be + unnecessary, a later pass can clean this up. */ + if (gimple_call_operator_delete_p (stmt)) + { + for (unsigned i=1; i < gimple_call_num_args (stmt); ++i) + { + tree arg = gimple_call_arg (stmt, i); + if (TREE_CODE (arg) == SSA_NAME) + mark_operand_necessary (arg); + } + } + + continue; + } } } @@ -849,6 +879,11 @@ propagate_necessity (bool aggressive) || DECL_FUNCTION_CODE (callee) == BUILT_IN_ASSUME_ALIGNED)) continue; + if (callee != NULL_TREE + && (DECL_IS_OPERATOR_NEW (callee) + || DECL_IS_OPERATOR_DELETE (callee))) + continue; + /* Calls implicitly load from memory, their arguments in addition may explicitly perform memory loads. */ mark_all_reaching_defs_necessary (stmt); @@ -1269,7 +1304,8 @@ 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) + || gimple_call_operator_delete_p (stmt))) { tree ptr = gimple_call_arg (stmt, 0); if (TREE_CODE (ptr) == SSA_NAME) diff --git a/gcc/tree-streamer-in.c b/gcc/tree-streamer-in.c index baf0c5bf837..eb8a2aa1a93 100644 --- a/gcc/tree-streamer-in.c +++ b/gcc/tree-streamer-in.c @@ -326,6 +326,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_IS_OPERATOR_NEW (expr) = (unsigned) bp_unpack_value (bp, 1); + DECL_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); diff --git a/gcc/tree-streamer-out.c b/gcc/tree-streamer-out.c index 7f52d455f5e..a63d16deb23 100644 --- a/gcc/tree-streamer-out.c +++ b/gcc/tree-streamer-out.c @@ -287,6 +287,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 (expr), 1); + bp_pack_value (bp, DECL_IS_OPERATOR_DELETE (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); diff --git a/gcc/tree.h b/gcc/tree.h index 0ec092aa812..88d7e73fd09 100644 --- a/gcc/tree.h +++ b/gcc/tree.h @@ -2866,6 +2866,11 @@ extern void decl_fini_priority_insert (tree, priority_type); #define DECL_IS_OPERATOR_NEW(NODE) \ (FUNCTION_DECL_CHECK (NODE)->function_decl.operator_new_flag) +/* Nonzero in a FUNCTION_DECL means this function should be treated as + C++ operator delete. */ +#define DECL_IS_OPERATOR_DELETE(NODE) \ + (FUNCTION_DECL_CHECK (NODE)->function_decl.operator_delete_flag) + /* Nonzero in a FUNCTION_DECL means this function may return more than once. */ #define DECL_IS_RETURNS_TWICE(NODE) \ diff --git a/libstdc++-v3/testsuite/ext/bitmap_allocator/check_delete.cc b/libstdc++-v3/testsuite/ext/bitmap_allocator/check_delete.cc index bc36ed595e0..10e26615fb7 100644 --- a/libstdc++-v3/testsuite/ext/bitmap_allocator/check_delete.cc +++ b/libstdc++-v3/testsuite/ext/bitmap_allocator/check_delete.cc @@ -15,6 +15,8 @@ // with this library; see the file COPYING3. If not see // . +// { dg-options "-fno-tree-dce" } + // 20.4.1.1 allocator members #include diff --git a/libstdc++-v3/testsuite/ext/bitmap_allocator/check_new.cc b/libstdc++-v3/testsuite/ext/bitmap_allocator/check_new.cc index 073d588f3b9..7efd325bec2 100644 --- a/libstdc++-v3/testsuite/ext/bitmap_allocator/check_new.cc +++ b/libstdc++-v3/testsuite/ext/bitmap_allocator/check_new.cc @@ -15,6 +15,8 @@ // with this library; see the file COPYING3. If not see // . +// { dg-options "-fno-tree-dce" } + // 20.4.1.1 allocator members #include diff --git a/libstdc++-v3/testsuite/ext/new_allocator/check_delete.cc b/libstdc++-v3/testsuite/ext/new_allocator/check_delete.cc index ce6c1da3e27..30390c266d0 100644 --- a/libstdc++-v3/testsuite/ext/new_allocator/check_delete.cc +++ b/libstdc++-v3/testsuite/ext/new_allocator/check_delete.cc @@ -17,6 +17,8 @@ // with this library; see the file COPYING3. If not see // . +// { dg-options "-fno-tree-dce" } + // 20.4.1.1 allocator members #include diff --git a/libstdc++-v3/testsuite/ext/new_allocator/check_new.cc b/libstdc++-v3/testsuite/ext/new_allocator/check_new.cc index d410f5f7feb..18396482d9a 100644 --- a/libstdc++-v3/testsuite/ext/new_allocator/check_new.cc +++ b/libstdc++-v3/testsuite/ext/new_allocator/check_new.cc @@ -17,6 +17,8 @@ // with this library; see the file COPYING3. If not see // . +// { dg-options "-fno-tree-dce" } + // 20.4.1.1 allocator members #include --Apple-Mail=_76511938-19E6-4905-8993-8A37F8872C22-- --Apple-Mail=_4DA3D9A4-FEF3-4B55-88D7-CAEBE919793D Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename=signature.asc Content-Type: application/pgp-signature; name=signature.asc Content-Description: Message signed with OpenPGP using GPGMail Content-length: 842 -----BEGIN PGP SIGNATURE----- Comment: GPGTools - https://gpgtools.org iQIcBAEBCgAGBQJaFAqJAAoJEEE5Cbo4kew80ZcQAL1gjTXJSUyUpkMQZj8LKwzK ZXbx0Y8JW0074QaHWs3A+ZoJPg+VFh44Aa06RIpl2NS0P/uZMN9uKM8EQBmvLQw3 NDCy+TDZE7S66eepSSAy2QSm9V3wkfgg8VNiIIrZEcjtpF+GyYraBvhwoAZQQzLN Y63nirpTXpiyt6kmyn4vcG8DJLtIzavdVWWp4zJWah6+4FEr8nEPUhhwa/tWPuiV 0XXhI9lhvaqi1Uczh2B8XDJ0zACw1USEpCqKKjSD8WPCmsFExuIuXlRdlfxfjrGP IEnBoU+V2BsEw+OrcKbN+lUa+cuo/8rUWQFo9zZw0pYtqvq0Zwp/BpUddwAl8hj1 4Tf2NaYRrjKO4WFsM736dK0OsyopmiQefGyxfiWhOHZreTe2bG5GDDSFxamHuU40 K/lvRE3osGat6Nv8pzKX05t2pIlt+wGkIe8K5BUbpLkhq/acG0HfaabIYd5ySj8Y LFwloHbAlQbYoS4Ws6iwmsmYrkOiPXyQJRQh0MvypX7XpcMAM9GYN0eGLfbrtOFE I9f/2CjLKWzWSDDKc0zy4uSyhpiECeZVeJTOjCF5gdZP7lGakisAk6+SQS4/FerQ EfzMSnqQ3z6uuGUMVvyKyCyO5/1NWxmwQ5z50jZ2HCAucE0/CpTzcENH9EjeRDkB BCPpxtYEzplX8Z5mI5lR =oWHt -----END PGP SIGNATURE----- --Apple-Mail=_4DA3D9A4-FEF3-4B55-88D7-CAEBE919793D--