From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1251) id 91C7D3858D20; Fri, 4 Feb 2022 09:38:30 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 91C7D3858D20 MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Roger Sayle To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-7046] [PATCH] PR rtl-optimization/101885: Prevent combine from clobbering flags X-Act-Checkin: gcc X-Git-Author: Roger Sayle X-Git-Refname: refs/heads/master X-Git-Oldrev: 5b6370295d1efaa563f6d8c45f1fb779c3db452e X-Git-Newrev: 49365d511ac9b64009b1de11ef8a941f59407f67 Message-Id: <20220204093830.91C7D3858D20@sourceware.org> Date: Fri, 4 Feb 2022 09:38:30 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 04 Feb 2022 09:38:30 -0000 https://gcc.gnu.org/g:49365d511ac9b64009b1de11ef8a941f59407f67 commit r12-7046-g49365d511ac9b64009b1de11ef8a941f59407f67 Author: Roger Sayle Date: Fri Feb 4 09:32:21 2022 +0000 [PATCH] PR rtl-optimization/101885: Prevent combine from clobbering flags This patch addresses PR rtl-optimization/101885 which is a P2 wrong code regression. In combine, if the resulting fused instruction is a parallel of two sets which fails to be recognized by the backend, combine tries to emit these as two sequential set instructions (known as split_i2i3). As each set is recognized the backend may add any necessary "clobbers". The code currently checks that any clobbers added to the first "set" don't interfere with the second set, but doesn't currently handle the case that clobbers added to the second set may interfere/kill the destination of the first set (which must be live at this point). The solution is to cut'n'paste the "clobber" logic from just a few lines earlier, suitably adjusted for the second instruction. One minor nit that may confuse a reviewer is that at this point in the code we've lost track of which set was first and which was second (combine chooses dynamically, and the recog processes that adds the clobbers may have obfuscated the original SET_DEST) so the actual test below is to confirm that any newly added clobbers (on the second set instruction) don't overlap either set0's or set1's destination. 2022-02-04 Roger Sayle gcc/ChangeLog PR rtl-optimization/101885 * combine.cc (try_combine): When splitting a parallel into two sequential sets, check not only that the first doesn't clobber the second but also that the second doesn't clobber the first. gcc/testsuite/ChangeLog PR rtl-optimization/101885 * gcc.dg/pr101885.c: New test case. Diff: --- gcc/combine.cc | 18 ++++++++++++++++++ gcc/testsuite/gcc.dg/pr101885.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/gcc/combine.cc b/gcc/combine.cc index 2d406354735..7683f8250fe 100644 --- a/gcc/combine.cc +++ b/gcc/combine.cc @@ -4017,6 +4017,24 @@ try_combine (rtx_insn *i3, rtx_insn *i2, rtx_insn *i1, rtx_insn *i0, insn_code_number = recog_for_combine (&newpat, i3, &new_i3_notes); + /* Likewise, recog_for_combine might have added clobbers to NEWPAT. + Checking that the SET0's SET_DEST and SET1's SET_DEST aren't + mentioned/clobbered, ensures NEWI2PAT's SET_DEST is live. */ + if (insn_code_number >= 0 && GET_CODE (newpat) == PARALLEL) + { + for (i = XVECLEN (newpat, 0) - 1; i >= 0; i--) + if (GET_CODE (XVECEXP (newpat, 0, i)) == CLOBBER) + { + rtx reg = XEXP (XVECEXP (newpat, 0, i), 0); + if (reg_overlap_mentioned_p (reg, SET_DEST (set0)) + || reg_overlap_mentioned_p (reg, SET_DEST (set1))) + { + undo_all (); + return 0; + } + } + } + if (insn_code_number >= 0) split_i2i3 = 1; } diff --git a/gcc/testsuite/gcc.dg/pr101885.c b/gcc/testsuite/gcc.dg/pr101885.c new file mode 100644 index 00000000000..05fd0ed3080 --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr101885.c @@ -0,0 +1,31 @@ +/* { dg-do run } */ +/* { dg-options "-O3" } */ +int a = 3, c; +short b = 5, d, f; +volatile short e; + +__attribute__((noipa)) void +foo (void) +{ +} + +int +main () +{ + for (f = 0; f != 2; f++) + { + int g = a; + if (b) + if (a) + for (a = b = 0; b <= 3; b++) + ; + for (c = 0; c != 16; ++c) + e; + } + b = d; + foo (); + if (a != 0) + __builtin_abort (); + return 0; +} +