From patchwork Fri Jan 21 10:52:43 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Biener X-Patchwork-Id: 1582546 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=QttpH4jQ; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (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 bilbo.ozlabs.org (Postfix) with ESMTPS id 4JgGVT62wCz9s0r for ; Fri, 21 Jan 2022 21:54:57 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 253FE3857C48 for ; Fri, 21 Jan 2022 10:54:55 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 253FE3857C48 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1642762495; bh=8wkdvUK6fN9aD9pVgxqoM5U2rHc5TBTtDD0ZgGStK1w=; h=Date:To:Subject:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=QttpH4jQzvml3X4GCMNBF01YIdS8l9bUQO5nQm7wWQRVw2CzwKKewfWM8iqPxXylQ NXe2p435ZC2eUbt94/M5vOIpMp5ZLU6Wv/pCHU4XcL8Jpv8BFSvftSvsH1qH9dEZit 83PpS245b1msRRsHaalYJDREa+kLvnzi9I4SsPIE= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from smtp-out2.suse.de (smtp-out2.suse.de [195.135.220.29]) by sourceware.org (Postfix) with ESMTPS id 41D28385800A for ; Fri, 21 Jan 2022 10:52:45 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 41D28385800A Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by smtp-out2.suse.de (Postfix) with ESMTPS id 118A41F3C0 for ; Fri, 21 Jan 2022 10:52:44 +0000 (UTC) Received: from imap2.suse-dmz.suse.de (imap2.suse-dmz.suse.de [192.168.254.74]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-521) server-digest SHA512) (No client certificate requested) by imap2.suse-dmz.suse.de (Postfix) with ESMTPS id F27B213CFE for ; Fri, 21 Jan 2022 10:52:43 +0000 (UTC) Received: from dovecot-director2.suse.de ([192.168.254.65]) by imap2.suse-dmz.suse.de with ESMTPSA id vJMSOnuQ6mHxegAAMHmgww (envelope-from ) for ; Fri, 21 Jan 2022 10:52:43 +0000 Date: Fri, 21 Jan 2022 11:52:43 +0100 (CET) To: gcc-patches@gcc.gnu.org Subject: [PATCH] tree-optimization/104156 - fix unswitching compare-debug issue Message-ID: <606rn49-r77p-p7so-2qrs-pon2727n8ps3@fhfr.qr> MIME-Version: 1.0 X-Spam-Status: No, score=-11.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) 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: , X-Patchwork-Original-From: Richard Biener via Gcc-patches From: Richard Biener Reply-To: Richard Biener Errors-To: gcc-patches-bounces+incoming=patchwork.ozlabs.org@gcc.gnu.org Sender: "Gcc-patches" When hoisting guards the unswitching pass does not properly ignore debug stmts when looking for uses outside of the loop of defs produced in the skipped region. The following rectifies this by instead collecting them and resetting them after the transform. Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. 2022-01-21 Richard Biener PR tree-optimization/104156 * tree-ssa-loop-unswitch.cc (tree_unswitch_outer_loop): Collect and reset debug stmts with out-of-loop uses when hoisting guards. (find_loop_guard): Adjust. (empty_bb_without_guard_p): Likewise. Ignore debug stmts. (used_outside_loop_p): Push debug uses to a vector of debug stmts to reset. (hoist_guard): Adjust -fopt-info category. * gcc.dg/loop-unswitch-6.c: New testcase. --- gcc/testsuite/gcc.dg/loop-unswitch-6.c | 32 +++++++++++++++++ gcc/tree-ssa-loop-unswitch.cc | 50 +++++++++++++++++--------- 2 files changed, 66 insertions(+), 16 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/loop-unswitch-6.c diff --git a/gcc/testsuite/gcc.dg/loop-unswitch-6.c b/gcc/testsuite/gcc.dg/loop-unswitch-6.c new file mode 100644 index 00000000000..f70b629e054 --- /dev/null +++ b/gcc/testsuite/gcc.dg/loop-unswitch-6.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -funswitch-loops -g -fcompare-debug -fdump-tree-unswitch-details" } */ + +short a, d; +int b, c; +static int e() { + int f = -2L, g = 9, h = 0; + for (; h < 2; h++) + if (a <= 5) { + g = 0; + if (c && a) + break; + if (c - 1) + goto i; + } + if (b) { + int *j[] = {&f}; + if (d) + for (; f < 9; f++) + if (g) + for (; f; f++) + ; + i: + while (f) { + a--; + break; + } + } +} +int main() { e(); } + +/* { dg-final { scan-tree-dump-times "Guard hoisted" 1 "unswitch" } } */ diff --git a/gcc/tree-ssa-loop-unswitch.cc b/gcc/tree-ssa-loop-unswitch.cc index a405119b58a..2927f308234 100644 --- a/gcc/tree-ssa-loop-unswitch.cc +++ b/gcc/tree-ssa-loop-unswitch.cc @@ -79,9 +79,10 @@ static class loop *tree_unswitch_loop (class loop *, basic_block, tree); static bool tree_unswitch_single_loop (class loop *, int); static tree tree_may_unswitch_on (basic_block, class loop *); static bool tree_unswitch_outer_loop (class loop *); -static edge find_loop_guard (class loop *); -static bool empty_bb_without_guard_p (class loop *, basic_block); -static bool used_outside_loop_p (class loop *, tree); +static edge find_loop_guard (class loop *, vec&); +static bool empty_bb_without_guard_p (class loop *, basic_block, + vec&); +static bool used_outside_loop_p (class loop *, tree, vec&); static void hoist_guard (class loop *, edge); static bool check_exit_phi (class loop *); static tree get_vop_from_header (class loop *); @@ -536,11 +537,18 @@ tree_unswitch_outer_loop (class loop *loop) } bool changed = false; - while ((guard = find_loop_guard (loop))) + auto_vec dbg_to_reset; + while ((guard = find_loop_guard (loop, dbg_to_reset))) { if (! changed) rewrite_virtuals_into_loop_closed_ssa (loop); hoist_guard (loop, guard); + for (gimple *debug_stmt : dbg_to_reset) + { + gimple_debug_bind_reset_value (debug_stmt); + update_stmt (debug_stmt); + } + dbg_to_reset.truncate (0); changed = true; } return changed; @@ -551,7 +559,7 @@ tree_unswitch_outer_loop (class loop *loop) otherwise returns NULL. */ static edge -find_loop_guard (class loop *loop) +find_loop_guard (class loop *loop, vec &dbg_to_reset) { basic_block header = loop->header; edge guard_edge, te, fe; @@ -688,7 +696,7 @@ find_loop_guard (class loop *loop) guard_edge = NULL; goto end; } - if (!empty_bb_without_guard_p (loop, bb)) + if (!empty_bb_without_guard_p (loop, bb, dbg_to_reset)) { if (dump_enabled_p ()) dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, @@ -699,7 +707,7 @@ find_loop_guard (class loop *loop) } if (dump_enabled_p ()) - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, + dump_printf_loc (MSG_NOTE, loc, "suitable to hoist\n"); end: if (body) @@ -713,10 +721,12 @@ end: are noy used outside of the loop. KNOWN_INVARIANTS is a set of ssa names we know to be invariant, and PROCESSED is a set of ssa names for that we already tested whether they - are invariant or not. */ + are invariant or not. Uses in debug stmts outside of the loop are + pushed to DBG_TO_RESET. */ static bool -empty_bb_without_guard_p (class loop *loop, basic_block bb) +empty_bb_without_guard_p (class loop *loop, basic_block bb, + vec &dbg_to_reset) { basic_block exit_bb = single_exit (loop)->src; bool may_be_used_outside = (bb == exit_bb @@ -736,7 +746,7 @@ empty_bb_without_guard_p (class loop *loop, basic_block bb) if (virtual_operand_p (name)) continue; - if (used_outside_loop_p (loop, name)) + if (used_outside_loop_p (loop, name, dbg_to_reset)) return false; } } @@ -745,6 +755,9 @@ empty_bb_without_guard_p (class loop *loop, basic_block bb) !gsi_end_p (gsi); gsi_next (&gsi)) { gimple *stmt = gsi_stmt (gsi); + if (is_gimple_debug (stmt)) + continue; + if (gimple_has_side_effects (stmt)) return false; @@ -754,17 +767,18 @@ empty_bb_without_guard_p (class loop *loop, basic_block bb) FOR_EACH_SSA_TREE_OPERAND (name, stmt, op_iter, SSA_OP_DEF) { if (may_be_used_outside - && used_outside_loop_p (loop, name)) + && used_outside_loop_p (loop, name, dbg_to_reset)) return false; } } return true; } -/* Return true if NAME is used outside of LOOP. */ +/* Return true if NAME is used outside of LOOP. Pushes debug stmts that + have such uses to DBG_TO_RESET but do not consider such uses. */ static bool -used_outside_loop_p (class loop *loop, tree name) +used_outside_loop_p (class loop *loop, tree name, vec &dbg_to_reset) { imm_use_iterator it; use_operand_p use; @@ -773,7 +787,11 @@ used_outside_loop_p (class loop *loop, tree name) { gimple *stmt = USE_STMT (use); if (!flow_bb_inside_loop_p (loop, gimple_bb (stmt))) - return true; + { + if (!is_gimple_debug (stmt)) + return true; + dbg_to_reset.safe_push (stmt); + } } return false; @@ -847,7 +865,7 @@ hoist_guard (class loop *loop, edge guard) char buffer[64]; guard->probability.dump (buffer); - dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, + dump_printf_loc (MSG_NOTE, loc, "Moving guard %i->%i (prob %s) to bb %i, " "new preheader is %i\n", guard->src->index, guard->dest->index, @@ -949,7 +967,7 @@ hoist_guard (class loop *loop, edge guard) } if (dump_enabled_p ()) - dump_printf_loc (MSG_MISSED_OPTIMIZATION, loc, + dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, loc, "Guard hoisted\n"); free (body);