From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtp-out1.suse.de (smtp-out1.suse.de [IPv6:2001:67c:2178:6::1c]) by sourceware.org (Postfix) with ESMTPS id B5A0038515F2 for ; Wed, 7 Sep 2022 10:08:50 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B5A0038515F2 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=suse.de Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=suse.de Received: from relay2.suse.de (relay2.suse.de [149.44.160.134]) by smtp-out1.suse.de (Postfix) with ESMTP id 005C633C6B for ; Wed, 7 Sep 2022 10:08:50 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_rsa; t=1662545330; h=from:from:reply-to:date:date:to:to:cc:mime-version:mime-version: content-type:content-type; bh=zwD8TOJkoq45QYClxnmeOQ1oqVWBKNr0GOv28Pd3zuQ=; b=lMSNqjiHssnRaKxDrOuNIfoH0qR/6+ZmOFyE0jPZ3hdE7fWAYqHYQbSlhh5268CfFf2L9E nCMc/w+C8thQQ1CaarOY06ZKzXlZslrz/LkvzLFnwmJVn6IMapgqgH2NttSuUNyq2gKrAW P1ahl+HuAyfSdw9/FnYDf05N5sc8ZtY= DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=suse.de; s=susede2_ed25519; t=1662545330; h=from:from:reply-to:date:date:to:to:cc:mime-version:mime-version: content-type:content-type; bh=zwD8TOJkoq45QYClxnmeOQ1oqVWBKNr0GOv28Pd3zuQ=; b=MBGke+TRrHhDjaMcYxNXY29cHw01FEHY8eOj2NzQrv6N4Q7paRpyyFzmJ/QxMJpjdFRSuX 80bDE0BZWuZflVDA== Received: from wotan.suse.de (wotan.suse.de [10.160.0.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by relay2.suse.de (Postfix) with ESMTPS id EF2CB2C141 for ; Wed, 7 Sep 2022 10:08:49 +0000 (UTC) Date: Wed, 7 Sep 2022 10:08:49 +0000 (UTC) From: Richard Biener To: gcc-patches@gcc.gnu.org Subject: [PATCH] tree-optimization/106860 - fix profile scaling in split_loop User-Agent: Alpine 2.22 (LSU 394 2020-01-19) MIME-Version: 1.0 Content-Type: text/plain; charset=US-ASCII X-Spam-Status: No, score=-10.7 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,MISSING_MID,SPF_HELO_NONE,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: Message-ID: <20220907100849.xOAPdsnEwn4PkGeHQinC-72GhxJXJgxbUoFoDvq40kU@z> The following fixes a mistake in loop splitting which assumes loop latches have a single predecessor and that edge is from the exit test. Instead work from the single exit edge we have to find the edge towards the latch. Bootstrapped and tested on x86_64-unknown-linux-gnu, pushed. PR tree-optimization/106860 * tree-ssa-loop-split.cc (split_loop): Find the exit to latch edge from the loop exit edge instead of from the latch. Verify we're going to find it. * g++.dg/opt/pr106860.C: New testcase. --- gcc/testsuite/g++.dg/opt/pr106860.C | 23 +++++++++++++++++++++++ gcc/tree-ssa-loop-split.cc | 16 ++++++++++------ 2 files changed, 33 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/opt/pr106860.C diff --git a/gcc/testsuite/g++.dg/opt/pr106860.C b/gcc/testsuite/g++.dg/opt/pr106860.C new file mode 100644 index 00000000000..a0209dcf9da --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr106860.C @@ -0,0 +1,23 @@ +// { dg-do compile } +// { dg-options "-Ofast -ftrapv -fnon-call-exceptions -fno-tree-fre" } + +static const int N = 12; +int nSlip; + +int main () +{ + int i, j, k, fdot = 0; + int a[N][N]; + + for ( i = 1; i < nSlip; i++) + { + for ( j = i+1; j < nSlip; j++) + { + for ( k = 0; k < i; k++) + fdot += a[i][k] * a[k][j]; + a[i][j] = a[i][j] - fdot; + } + } + + return 0; +} diff --git a/gcc/tree-ssa-loop-split.cc b/gcc/tree-ssa-loop-split.cc index bccf621493b..fad4e8361b0 100644 --- a/gcc/tree-ssa-loop-split.cc +++ b/gcc/tree-ssa-loop-split.cc @@ -531,16 +531,17 @@ split_loop (class loop *loop1) tree guard_iv; tree border = NULL_TREE; affine_iv iv; + edge exit1; - if (!single_exit (loop1) + if (!(exit1 = single_exit (loop1)) + || EDGE_COUNT (exit1->src->succs) != 2 /* ??? We could handle non-empty latches when we split the latch edge (not the exit edge), and put the new exit condition in the new block. OTOH this executes some code unconditionally that might have been skipped by the original exit before. */ || !empty_block_p (loop1->latch) || !easy_exit_values (loop1) - || !number_of_iterations_exit (loop1, single_exit (loop1), &niter, - false, true) + || !number_of_iterations_exit (loop1, exit1, &niter, false, true) || niter.cmp == ERROR_MARK /* We can't yet handle loops controlled by a != predicate. */ || niter.cmp == NE_EXPR) @@ -644,10 +645,13 @@ split_loop (class loop *loop1) fix_loop_bb_probability (loop1, loop2, true_edge, false_edge); /* Fix first loop's exit probability after scaling. */ - edge exit_to_latch1 = single_pred_edge (loop1->latch); + edge exit_to_latch1; + if (EDGE_SUCC (exit1->src, 0) == exit1) + exit_to_latch1 = EDGE_SUCC (exit1->src, 1); + else + exit_to_latch1 = EDGE_SUCC (exit1->src, 0); exit_to_latch1->probability *= true_edge->probability; - single_exit (loop1)->probability - = exit_to_latch1->probability.invert (); + exit1->probability = exit_to_latch1->probability.invert (); /* Finally patch out the two copies of the condition to be always true/false (or opposite). */ -- 2.37.3