List valid pairs for new and delete operators.

	PR c++/94314
	* cgraphclones.c (set_new_clone_decl_and_node_flags): Drop
	DECL_IS_REPLACEABLE_OPERATOR during cloning.
	* tree-ssa-dce.c (valid_new_delete_pair_p): New function.
	(propagate_necessity): Check operator names.

	PR c++/94314
	* g++.dg/pr94314.C: Do not use dg-additional-options
	and remove not needed stdio.h include.
	* g++.dg/pr94314-2.C: Likewise.
	* g++.dg/pr94314-3.C: Likewise.
	* g++.dg/pr94314-4.C: New test.

Co-Authored-By: Jakub Jelinek <jakub@redhat.com>
parent effcb418
2020-04-16 Martin Liska <mliska@suse.cz>
Jakub Jelinek <jakub@redhat.com>
PR c++/94314
* cgraphclones.c (set_new_clone_decl_and_node_flags): Drop
DECL_IS_REPLACEABLE_OPERATOR during cloning.
* tree-ssa-dce.c (valid_new_delete_pair_p): New function.
(propagate_necessity): Check operator names.
2020-04-16 Richard Sandiford <richard.sandiford@arm.com> 2020-04-16 Richard Sandiford <richard.sandiford@arm.com>
PR rtl-optimization/94605 PR rtl-optimization/94605
......
...@@ -165,6 +165,7 @@ set_new_clone_decl_and_node_flags (cgraph_node *new_node) ...@@ -165,6 +165,7 @@ set_new_clone_decl_and_node_flags (cgraph_node *new_node)
DECL_STATIC_DESTRUCTOR (new_node->decl) = 0; DECL_STATIC_DESTRUCTOR (new_node->decl) = 0;
DECL_SET_IS_OPERATOR_NEW (new_node->decl, 0); DECL_SET_IS_OPERATOR_NEW (new_node->decl, 0);
DECL_SET_IS_OPERATOR_DELETE (new_node->decl, 0); DECL_SET_IS_OPERATOR_DELETE (new_node->decl, 0);
DECL_IS_REPLACEABLE_OPERATOR (new_node->decl) = 0;
new_node->externally_visible = 0; new_node->externally_visible = 0;
new_node->local = 1; new_node->local = 1;
...@@ -1030,6 +1031,7 @@ cgraph_node::create_version_clone_with_body ...@@ -1030,6 +1031,7 @@ cgraph_node::create_version_clone_with_body
DECL_STATIC_DESTRUCTOR (new_decl) = 0; DECL_STATIC_DESTRUCTOR (new_decl) = 0;
DECL_SET_IS_OPERATOR_NEW (new_decl, 0); DECL_SET_IS_OPERATOR_NEW (new_decl, 0);
DECL_SET_IS_OPERATOR_DELETE (new_decl, 0); DECL_SET_IS_OPERATOR_DELETE (new_decl, 0);
DECL_IS_REPLACEABLE_OPERATOR (new_decl) = 0;
/* Create the new version's call-graph node. /* Create the new version's call-graph node.
and update the edges of the new node. */ and update the edges of the new node. */
......
2020-04-16 Martin Liska <mliska@suse.cz>
Jakub Jelinek <jakub@redhat.com>
PR c++/94314
* g++.dg/pr94314.C: Do not use dg-additional-options
and remove not needed stdio.h include.
* g++.dg/pr94314-2.C: Likewise.
* g++.dg/pr94314-3.C: Likewise.
* g++.dg/pr94314-4.C: New test.
2020-04-16 Patrick Palka <ppalka@redhat.com> 2020-04-16 Patrick Palka <ppalka@redhat.com>
PR c++/94475 PR c++/94475
......
/* PR c++/94314. */ /* PR c++/94314. */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-O2 -fdump-tree-cddce-details" } */ /* { dg-options "-O2 -fdump-tree-cddce-details -fdelete-null-pointer-checks" } */
/* { dg-additional-options "-fdelete-null-pointer-checks" } */
#include <stdio.h>
struct A struct A
{ {
......
/* PR c++/94314. */ /* PR c++/94314. */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-O2 --param early-inlining-insns=100 -fdump-tree-cddce-details" } */ /* { dg-options "-O2 --param early-inlining-insns=100 -fdump-tree-cddce-details -fdelete-null-pointer-checks" } */
/* { dg-additional-options "-fdelete-null-pointer-checks" } */
#include <stdio.h>
volatile int idx; volatile int idx;
......
/* PR c++/94314. */
/* { dg-do run { target c++11 } } */
/* { dg-options "-O2 -fdump-tree-cddce-details -fdelete-null-pointer-checks" } */
int count = 0;
__attribute__((malloc, noinline)) void* operator new[](__SIZE_TYPE__ sz) {
++count;
return ::operator new(sz);
}
void operator delete[](void* ptr) noexcept {
--count;
::operator delete(ptr);
}
void operator delete[](void* ptr, __SIZE_TYPE__ sz) noexcept {
--count;
::operator delete(ptr, sz);
}
int main() {
delete[] new int[1];
if (count != 0)
__builtin_abort ();
return 0;
}
/* { dg-final { scan-tree-dump-not "Deleting : operator delete" "cddce1"} } */
/* PR c++/94314. */ /* PR c++/94314. */
/* { dg-do run } */ /* { dg-do run } */
/* { dg-options "-O2 -fdump-tree-cddce-details" } */ /* { dg-options "-O2 -fdump-tree-cddce-details -fdelete-null-pointer-checks" } */
/* { dg-additional-options "-fdelete-null-pointer-checks" } */
#include <stdio.h>
struct A struct A
{ {
......
...@@ -646,6 +646,77 @@ degenerate_phi_p (gimple *phi) ...@@ -646,6 +646,77 @@ degenerate_phi_p (gimple *phi)
return true; return true;
} }
/* Return that NEW_CALL and DELETE_CALL are a valid pair of new
and delete operators. */
static bool
valid_new_delete_pair_p (gimple *new_call, gimple *delete_call)
{
tree new_asm = DECL_ASSEMBLER_NAME (gimple_call_fndecl (new_call));
tree delete_asm = DECL_ASSEMBLER_NAME (gimple_call_fndecl (delete_call));
const char *new_name = IDENTIFIER_POINTER (new_asm);
const char *delete_name = IDENTIFIER_POINTER (delete_asm);
unsigned int new_len = IDENTIFIER_LENGTH (new_asm);
unsigned int delete_len = IDENTIFIER_LENGTH (delete_asm);
if (new_len < 5 || delete_len < 6)
return false;
if (new_name[0] == '_')
++new_name, --new_len;
if (new_name[0] == '_')
++new_name, --new_len;
if (delete_name[0] == '_')
++delete_name, --delete_len;
if (delete_name[0] == '_')
++delete_name, --delete_len;
if (new_len < 4 || delete_len < 5)
return false;
/* *_len is now just the length after initial underscores. */
if (new_name[0] != 'Z' || new_name[1] != 'n')
return false;
if (delete_name[0] != 'Z' || delete_name[1] != 'd')
return false;
/* _Znw must match _Zdl, _Zna must match _Zda. */
if ((new_name[2] != 'w' || delete_name[2] != 'l')
&& (new_name[2] != 'a' || delete_name[2] != 'a'))
return false;
/* 'j', 'm' and 'y' correspond to size_t. */
if (new_name[3] != 'j' && new_name[3] != 'm' && new_name[3] != 'y')
return false;
if (delete_name[3] != 'P' || delete_name[4] != 'v')
return false;
if (new_len == 4
|| (new_len == 18 && !memcmp (new_name + 4, "RKSt9nothrow_t", 14)))
{
/* _ZnXY or _ZnXYRKSt9nothrow_t matches
_ZdXPv, _ZdXPvY and _ZdXPvRKSt9nothrow_t. */
if (delete_len == 5)
return true;
if (delete_len == 6 && delete_name[5] == new_name[3])
return true;
if (delete_len == 19 && !memcmp (delete_name + 5, "RKSt9nothrow_t", 14))
return true;
}
else if ((new_len == 19 && !memcmp (new_name + 4, "St11align_val_t", 15))
|| (new_len == 33
&& !memcmp (new_name + 4, "St11align_val_tRKSt9nothrow_t", 29)))
{
/* _ZnXYSt11align_val_t or _ZnXYSt11align_val_tRKSt9nothrow_t matches
_ZdXPvSt11align_val_t or _ZdXPvYSt11align_val_t or or
_ZdXPvSt11align_val_tRKSt9nothrow_t. */
if (delete_len == 20 && !memcmp (delete_name + 5, "St11align_val_t", 15))
return true;
if (delete_len == 21
&& delete_name[5] == new_name[3]
&& !memcmp (delete_name + 6, "St11align_val_t", 15))
return true;
if (delete_len == 34
&& !memcmp (delete_name + 5, "St11align_val_tRKSt9nothrow_t", 29))
return true;
}
return false;
}
/* Propagate necessity using the operands of necessary statements. /* Propagate necessity using the operands of necessary statements.
Process the uses on each statement in the worklist, and add all Process the uses on each statement in the worklist, and add all
feeding statements which contribute to the calculation of this feeding statements which contribute to the calculation of this
...@@ -824,16 +895,23 @@ propagate_necessity (bool aggressive) ...@@ -824,16 +895,23 @@ propagate_necessity (bool aggressive)
|| DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC)) || DECL_FUNCTION_CODE (def_callee) == BUILT_IN_CALLOC))
|| DECL_IS_REPLACEABLE_OPERATOR_NEW_P (def_callee))) || DECL_IS_REPLACEABLE_OPERATOR_NEW_P (def_callee)))
{ {
/* Delete operators can have alignment and (or) size as next if (is_delete_operator)
arguments. When being a SSA_NAME, they must be marked {
as necessary. */ if (!valid_new_delete_pair_p (def_stmt, stmt))
if (is_delete_operator && gimple_call_num_args (stmt) >= 2) mark_operand_necessary (gimple_call_arg (stmt, 0));
for (unsigned i = 1; i < gimple_call_num_args (stmt); i++)
{ /* Delete operators can have alignment and (or) size
tree arg = gimple_call_arg (stmt, i); as next arguments. When being a SSA_NAME, they
if (TREE_CODE (arg) == SSA_NAME) must be marked as necessary. */
mark_operand_necessary (arg); if (gimple_call_num_args (stmt) >= 2)
} 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; continue;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment