From patchwork Thu May 6 10:53:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Biener X-Patchwork-Id: 1474909 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4FbVn60PY1z9sW4 for ; Thu, 6 May 2021 20:53:44 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DD66D388C026; Thu, 6 May 2021 10:53:41 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mx2.suse.de (mx2.suse.de [195.135.220.15]) by sourceware.org (Postfix) with ESMTPS id 2CFA5388A838 for ; Thu, 6 May 2021 10:53:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 2CFA5388A838 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=rguenther@suse.de X-Virus-Scanned: by amavisd-new at test-mx.suse.de Received: from relay2.suse.de (unknown [195.135.221.27]) by mx2.suse.de (Postfix) with ESMTP id 0AA0EB1D6; Thu, 6 May 2021 10:53:38 +0000 (UTC) Date: Thu, 6 May 2021 12:53:37 +0200 (CEST) From: Richard Biener To: gcc-patches@gcc.gnu.org Subject: [PATCH] tree-optimization/100434 - DSE aggregate call LHS Message-ID: User-Agent: Alpine 2.21 (LSU 202 2017-01-01) MIME-Version: 1.0 X-Spam-Status: No, score=-11.4 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: jakub@redhat.com, ebotcazou@adacore.com Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" This makes DSE consider aggregate LHS of calls as dead, for pure or const calls the whole stmt and for others by removing the LHS. Bootstrapped and tested on x86_64-unknown-linux-gnu. I wonder if there's a more canonical test for call LHS that cannot be removed than + if (gimple_call_return_slot_opt_p (as_a (stmt)) + && (TREE_ADDRESSABLE (TREE_TYPE (gimple_call_fntype (stmt))) + || !poly_int_tree_p + (TYPE_SIZE (TREE_TYPE (gimple_call_fntype (stmt)))))) + return; ? Richard. 2021-05-05 Richard Biener PR tree-optimization/100434 * tree-ssa-dse.c (initialize_ao_ref_for_dse): Handle call LHS. (dse_optimize_stmt): Handle call LHS by dropping the LHS or the whole call if it doesn't have other side-effects. (pass_dse::execute): Adjust. * gcc.dg/tree-ssa/ssa-dse-43.c: New testcase. --- gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-43.c | 22 +++++ gcc/tree-ssa-dse.c | 107 +++++++++++++-------- 2 files changed, 87 insertions(+), 42 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-43.c diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-43.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-43.c new file mode 100644 index 00000000000..f8785e9da46 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-43.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-dse1-details" } */ + +struct X { int x; }; +struct X x; + +extern struct X foo (void); +void bar() +{ + x = foo(); + x = (struct X){}; +} + +extern struct X __attribute__((const)) foo2 (int); +void bar2() +{ + x = foo2 (1); + x = foo2 (2); +} + +/* { dg-final { scan-tree-dump-times "Deleted dead store in call LHS: x = foo " 1 "dse1" } } */ +/* { dg-final { scan-tree-dump-times "Deleted dead store: x = foo2 " 1 "dse1" } } */ diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c index 63c876a1ff2..c3939a6417f 100644 --- a/gcc/tree-ssa-dse.c +++ b/gcc/tree-ssa-dse.c @@ -140,10 +140,13 @@ initialize_ao_ref_for_dse (gimple *stmt, ao_ref *write) break; } } - else if (is_gimple_assign (stmt)) + else if (tree lhs = gimple_get_lhs (stmt)) { - ao_ref_init (write, gimple_assign_lhs (stmt)); - return true; + if (TREE_CODE (lhs) != SSA_NAME) + { + ao_ref_init (write, lhs); + return true; + } } return false; } @@ -1035,7 +1038,7 @@ delete_dead_or_redundant_assignment (gimple_stmt_iterator *gsi, const char *type post dominates the first store, then the first store is dead. */ static void -dse_optimize_stmt (gimple_stmt_iterator *gsi, sbitmap live_bytes) +dse_optimize_stmt (function *fun, gimple_stmt_iterator *gsi, sbitmap live_bytes) { gimple *stmt = gsi_stmt (*gsi); @@ -1113,49 +1116,69 @@ dse_optimize_stmt (gimple_stmt_iterator *gsi, sbitmap live_bytes) } } - if (is_gimple_assign (stmt)) + bool by_clobber_p = false; + + /* Check if this statement stores zero to a memory location, + and if there is a subsequent store of zero to the same + memory location. If so, remove the subsequent store. */ + if (gimple_assign_single_p (stmt) + && initializer_zerop (gimple_assign_rhs1 (stmt))) + dse_optimize_redundant_stores (stmt); + + /* Self-assignments are zombies. */ + if (is_gimple_assign (stmt) + && operand_equal_p (gimple_assign_rhs1 (stmt), + gimple_assign_lhs (stmt), 0)) + ; + else { - bool by_clobber_p = false; - - /* Check if this statement stores zero to a memory location, - and if there is a subsequent store of zero to the same - memory location. If so, remove the subsequent store. */ - if (gimple_assign_single_p (stmt) - && initializer_zerop (gimple_assign_rhs1 (stmt))) - dse_optimize_redundant_stores (stmt); - - /* Self-assignments are zombies. */ - if (operand_equal_p (gimple_assign_rhs1 (stmt), - gimple_assign_lhs (stmt), 0)) - ; - else - { - bool byte_tracking_enabled - = setup_live_bytes_from_ref (&ref, live_bytes); - enum dse_store_status store_status; - store_status = dse_classify_store (&ref, stmt, - byte_tracking_enabled, - live_bytes, &by_clobber_p); - if (store_status == DSE_STORE_LIVE) - return; + bool byte_tracking_enabled + = setup_live_bytes_from_ref (&ref, live_bytes); + enum dse_store_status store_status; + store_status = dse_classify_store (&ref, stmt, + byte_tracking_enabled, + live_bytes, &by_clobber_p); + if (store_status == DSE_STORE_LIVE) + return; - if (store_status == DSE_STORE_MAYBE_PARTIAL_DEAD) - { - maybe_trim_partially_dead_store (&ref, live_bytes, stmt); - return; - } + if (store_status == DSE_STORE_MAYBE_PARTIAL_DEAD) + { + maybe_trim_partially_dead_store (&ref, live_bytes, stmt); + return; } + } - /* Now we know that use_stmt kills the LHS of stmt. */ + /* Now we know that use_stmt kills the LHS of stmt. */ - /* But only remove *this_2(D) ={v} {CLOBBER} if killed by - another clobber stmt. */ - if (gimple_clobber_p (stmt) - && !by_clobber_p) - return; + /* But only remove *this_2(D) ={v} {CLOBBER} if killed by + another clobber stmt. */ + if (gimple_clobber_p (stmt) + && !by_clobber_p) + return; - delete_dead_or_redundant_assignment (gsi, "dead", need_eh_cleanup); + if (is_gimple_call (stmt) + && (gimple_has_side_effects (stmt) + || (stmt_could_throw_p (fun, stmt) + && !fun->can_delete_dead_exceptions))) + { + /* Make sure we do not remove a return slot we cannot reconstruct + later. */ + if (gimple_call_return_slot_opt_p (as_a (stmt)) + && (TREE_ADDRESSABLE (TREE_TYPE (gimple_call_fntype (stmt))) + || !poly_int_tree_p + (TYPE_SIZE (TREE_TYPE (gimple_call_fntype (stmt)))))) + return; + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, " Deleted dead store in call LHS: "); + print_gimple_stmt (dump_file, stmt, 0, dump_flags); + fprintf (dump_file, "\n"); + } + gimple_call_set_lhs (stmt, NULL_TREE); + update_stmt (stmt); } + else + delete_dead_or_redundant_assignment (gsi, "dead", need_eh_cleanup); } namespace { @@ -1194,7 +1217,7 @@ pass_dse::execute (function *fun) need_eh_cleanup = BITMAP_ALLOC (NULL); auto_sbitmap live_bytes (param_dse_max_object_size); - renumber_gimple_stmt_uids (cfun); + renumber_gimple_stmt_uids (fun); calculate_dominance_info (CDI_DOMINATORS); @@ -1211,7 +1234,7 @@ pass_dse::execute (function *fun) gimple *stmt = gsi_stmt (gsi); if (gimple_vdef (stmt)) - dse_optimize_stmt (&gsi, live_bytes); + dse_optimize_stmt (fun, &gsi, live_bytes); else if (def_operand_p def_p = single_ssa_def_operand (stmt, SSA_OP_DEF)) {