| Message ID | aV4V7nphHQrrafpp@tucnak |
|---|---|
| State | New |
| Headers |
Return-Path: <gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id 2D9B14BA2E1F for <patchwork@sourceware.org>; Wed, 7 Jan 2026 08:15:30 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2D9B14BA2E1F Authentication-Results: sourceware.org; dkim=pass (1024-bit key, unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256 header.s=mimecast20190719 header.b=F3c9laAL X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTP id E68194BA2E1E for <gcc-patches@gcc.gnu.org>; Wed, 7 Jan 2026 08:14:48 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E68194BA2E1E Authentication-Results: sourceware.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E68194BA2E1E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.129.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767773689; cv=none; b=HVAyDI3G189QUMHCAgKzLkoRM+nH1pC8SvrcuMv7gWM/tgB/ToByszBF1AaUbLuc0ifDVCUZabD4OVdypMUPmUlaNXJteP9wiXFW5uTYx4Bf/XP8XOAev0ztscfe52a3qzjio+yryPGbw/3VCqYnNJ7E1kZ3BmZxbxfyVK/xc/k= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1767773689; c=relaxed/simple; bh=H3d8gWRYgRZoesTMWFpKI6KEpf/De2N+mh0VrqyAHj4=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=nHg/xalEt/gQ55UKCMyFOSMsbT+RwCBy7j6en+mxI6NIrZJpRQ9c2DuNMskdZ5Qhmmn6r/XmGiJykjLeYEPhoeU0XAaExifDV5O4obLT2N4bpuE7C4woubw4HOMUc4gcI0HfZY1S3RRYOHojNl6nojFy0rYZgcZrEo9h13p1JAk= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E68194BA2E1E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1767773688; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type; bh=X5QMB3YW37uiyK9pk/H5M4oknD3vLj9TrAkuDCwsrH0=; b=F3c9laALJmTexTBYapyWIPM+le+AtaoYsdJxuhG9x1s5MXnhyqoFpVUvmuHBye93korCCb 7FXc2oXkctYkWmGeaubUfCG+YQQNtUz1wi03ddO/wnjXobtBy5F13YjMSWLvDKJZIiLcn5 7xivBqb9ceGUY93+lEqbx5r7FqqjI8I= Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-121-N6nZqCSkPNOcWUwZ2UUPvw-1; Wed, 07 Jan 2026 03:14:44 -0500 X-MC-Unique: N6nZqCSkPNOcWUwZ2UUPvw-1 X-Mimecast-MFC-AGG-ID: N6nZqCSkPNOcWUwZ2UUPvw_1767773683 Received: from mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.12]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 3390218005A7; Wed, 7 Jan 2026 08:14:43 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.44.32.27]) by mx-prod-int-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 21EC319560A2; Wed, 7 Jan 2026 08:14:41 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.18.1/8.18.1) with ESMTPS id 6078EdY61148990 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Wed, 7 Jan 2026 09:14:39 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.18.1/8.18.1/Submit) id 6078EcDo1148986; Wed, 7 Jan 2026 09:14:38 +0100 Date: Wed, 7 Jan 2026 09:14:38 +0100 From: Jakub Jelinek <jakub@redhat.com> To: Richard Biener <rguenther@suse.de>, Segher Boessenkool <segher@kernel.crashing.org>, Jeff Law <jeffreyalaw@gmail.com> Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] combine: Fix up serious regression in try_combine [PR121773] Message-ID: <aV4V7nphHQrrafpp@tucnak> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.0 on 10.30.177.12 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: s_NYm4Y93pi-ju1SOyU9aEPakP8zLttkbyFzj-ZAu1U_1767773683 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset=us-ascii Content-Disposition: inline X-Spam-Status: No, score=-3.6 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_MSPIKE_H2, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_PASS, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> Reply-To: Jakub Jelinek <jakub@redhat.com> Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org |
| Series |
combine: Fix up serious regression in try_combine [PR121773]
|
|
Commit Message
Jakub Jelinek
Jan. 7, 2026, 8:14 a.m. UTC
Hi!
Back in April last year I've changed try_combine's condition when trying to
split two independent sets by moving one of them to i2. Previously this was
testing !modified_between_p (SET_DEST (setN), i2, i3) and I've changed it
to SET_DEST (setN) != pc_rtx && !reg_used_between_p (SET_DEST (set1), i2, i3)
on the assumption written in the r15-9131-g19ba913517b5e2a00 commit
message:
"The following patch replaces the modified_between_p
tests with reg_used_between_p, my understanding is that
modified_between_p is a subset of reg_used_between_p, so one
doesn't need both."
That assumption is wrong though, neither of these is a subset of the
other and I don't see any APIs which test both. We need to avoid moving
a set from i3 to i2 both in case where the REG (or SUBREG_REG of SUBREG or
MEM or whatever else) is set/modified between i2 and i3 exclusive, as shown
by the testcase in PR121773 (which I'm not including because my ARM neon
knowledge is limited). We have i2 insn 18 and i3 insn 7 after the current
try_combine modifications:
(insn 18 5 19 2 (set (reg:SI 104 [ _6 ])
(const_int 305419896 [0x12345678])) "include/arm_neon.h":7467:22 542 {*arm_movsi_vfp}
(expr_list:REG_EQUAL (const_int 305419896 [0x12345678])
(nil)))
(insn 19 18 21 2 (set (reg:SI 105 [ _6+4 ])
(const_int 538968064 [0x20200000])) "include/arm_neon.h":7467:22 542 {*arm_movsi_vfp}
(nil))
(insn 21 19 7 2 (set (reg:DI 101 [ _5 ])
(const_int 0 [0])) "include/arm_neon.h":607:14 -1
(nil))
(insn 7 21 8 2 (parallel [
(set (pc)
(pc))
(set (subreg:SI (reg:DI 101 [ _5 ]) 0)
(const_int 610839792 [0x2468acf0]))
]) "include/arm_neon.h":607:14 17 {addsi3_compare_op1}
(expr_list:REG_DEAD (reg:SI 104 [ _6 ])
(nil)))
The second set can't be moved to the i2 location, because (reg:DI 101)
is modified in insn 21 and so if setting half of it to 610839792 is
moved from insn 7 where it modifies what was previously 0 into a location
where it overwrites something and is later overwritten in insn 21, we get
different behavior.
And the second case is mentioned in the PR119291 commit log:
(insn 22 21 23 4 (set (reg:SI 104 [ _7 ])
(const_int 0 [0])) "pr119291.c":25:15 96 {*movsi_internal}
(nil))
(insn 23 22 24 4 (set (reg/v:SI 117 [ e ])
(reg/v:SI 116 [ e ])) 96 {*movsi_internal}
(expr_list:REG_DEAD (reg/v:SI 116 [ e ])
(nil)))
(note 24 23 25 4 NOTE_INSN_DELETED)
(insn 25 24 26 4 (parallel [
(set (pc)
(pc))
(set (reg/v:SI 116 [ e ])
(const_int 0 [0]))
]) "pr119291.c":28:13 977 {*negsi_2}
(expr_list:REG_DEAD (reg:SI 104 [ _7 ])
(nil)))
i2 is insn 22, i3 is insn 25 after in progress modifications and the
second set can't be moved to i2 location, because (reg/v:SI 116) is used
in insn 23, so with it being set to 0 around insn 22 insn 23 will see
a different value.
So, I'm afraid we need both the modified_between_p and reg_used_between_p
check. We don't need the SET_DEST (setN) != pc_rtx checks, those were
added because modified_between_p (pc_rtx, i2, i3) returns true if start
is not the same as end, but reg_used_between_p doesn't behave like that.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk
and release branches?
2026-01-06 Jakub Jelinek <jakub@redhat.com>
PR rtl-optimization/119291
PR rtl-optimization/121773
* combine.cc (try_combine): Check that SET_DEST (setN) is neither
modified_between_p nor reg_used_between_p instead of just not
reg_used_between_p or pc_rtx.
Jakub
Comments
On Wed, 7 Jan 2026, Jakub Jelinek wrote: > Hi! > > Back in April last year I've changed try_combine's condition when trying to > split two independent sets by moving one of them to i2. Previously this was > testing !modified_between_p (SET_DEST (setN), i2, i3) and I've changed it > to SET_DEST (setN) != pc_rtx && !reg_used_between_p (SET_DEST (set1), i2, i3) > on the assumption written in the r15-9131-g19ba913517b5e2a00 commit > message: > "The following patch replaces the modified_between_p > tests with reg_used_between_p, my understanding is that > modified_between_p is a subset of reg_used_between_p, so one > doesn't need both." > That assumption is wrong though, neither of these is a subset of the > other and I don't see any APIs which test both. We need to avoid moving > a set from i3 to i2 both in case where the REG (or SUBREG_REG of SUBREG or > MEM or whatever else) is set/modified between i2 and i3 exclusive, as shown > by the testcase in PR121773 (which I'm not including because my ARM neon > knowledge is limited). We have i2 insn 18 and i3 insn 7 after the current > try_combine modifications: > (insn 18 5 19 2 (set (reg:SI 104 [ _6 ]) > (const_int 305419896 [0x12345678])) "include/arm_neon.h":7467:22 542 {*arm_movsi_vfp} > (expr_list:REG_EQUAL (const_int 305419896 [0x12345678]) > (nil))) > (insn 19 18 21 2 (set (reg:SI 105 [ _6+4 ]) > (const_int 538968064 [0x20200000])) "include/arm_neon.h":7467:22 542 {*arm_movsi_vfp} > (nil)) > (insn 21 19 7 2 (set (reg:DI 101 [ _5 ]) > (const_int 0 [0])) "include/arm_neon.h":607:14 -1 > (nil)) > (insn 7 21 8 2 (parallel [ > (set (pc) > (pc)) > (set (subreg:SI (reg:DI 101 [ _5 ]) 0) > (const_int 610839792 [0x2468acf0])) > ]) "include/arm_neon.h":607:14 17 {addsi3_compare_op1} > (expr_list:REG_DEAD (reg:SI 104 [ _6 ]) > (nil))) > The second set can't be moved to the i2 location, because (reg:DI 101) > is modified in insn 21 and so if setting half of it to 610839792 is > moved from insn 7 where it modifies what was previously 0 into a location > where it overwrites something and is later overwritten in insn 21, we get > different behavior. > And the second case is mentioned in the PR119291 commit log: > (insn 22 21 23 4 (set (reg:SI 104 [ _7 ]) > (const_int 0 [0])) "pr119291.c":25:15 96 {*movsi_internal} > (nil)) > (insn 23 22 24 4 (set (reg/v:SI 117 [ e ]) > (reg/v:SI 116 [ e ])) 96 {*movsi_internal} > (expr_list:REG_DEAD (reg/v:SI 116 [ e ]) > (nil))) > (note 24 23 25 4 NOTE_INSN_DELETED) > (insn 25 24 26 4 (parallel [ > (set (pc) > (pc)) > (set (reg/v:SI 116 [ e ]) > (const_int 0 [0])) > ]) "pr119291.c":28:13 977 {*negsi_2} > (expr_list:REG_DEAD (reg:SI 104 [ _7 ]) > (nil))) > i2 is insn 22, i3 is insn 25 after in progress modifications and the > second set can't be moved to i2 location, because (reg/v:SI 116) is used > in insn 23, so with it being set to 0 around insn 22 insn 23 will see > a different value. > > So, I'm afraid we need both the modified_between_p and reg_used_between_p > check. We don't need the SET_DEST (setN) != pc_rtx checks, those were > added because modified_between_p (pc_rtx, i2, i3) returns true if start > is not the same as end, but reg_used_between_p doesn't behave like that. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk > and release branches? OK. Richard. > 2026-01-06 Jakub Jelinek <jakub@redhat.com> > > PR rtl-optimization/119291 > PR rtl-optimization/121773 > * combine.cc (try_combine): Check that SET_DEST (setN) is neither > modified_between_p nor reg_used_between_p instead of just not > reg_used_between_p or pc_rtx. > > --- gcc/combine.cc.jj 2026-01-02 09:56:09.924340621 +0100 > +++ gcc/combine.cc 2026-01-06 19:34:48.689525955 +0100 > @@ -4028,7 +4028,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, > && !(GET_CODE (SET_DEST (set1)) == SUBREG > && find_reg_note (i2, REG_DEAD, > SUBREG_REG (SET_DEST (set1)))) > - && SET_DEST (set1) != pc_rtx > + && !modified_between_p (SET_DEST (set1), i2, i3) > && !reg_used_between_p (SET_DEST (set1), i2, i3))) > /* If I3 is a jump, ensure that set0 is a jump so that > we do not create invalid RTL. */ > @@ -4044,7 +4044,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, > && !(GET_CODE (SET_DEST (set0)) == SUBREG > && find_reg_note (i2, REG_DEAD, > SUBREG_REG (SET_DEST (set0)))) > - && SET_DEST (set0) != pc_rtx > + && !modified_between_p (SET_DEST (set0), i2, i3) > && !reg_used_between_p (SET_DEST (set0), i2, i3))) > /* If I3 is a jump, ensure that set1 is a jump so that > we do not create invalid RTL. */ > > Jakub > >
--- gcc/combine.cc.jj 2026-01-02 09:56:09.924340621 +0100 +++ gcc/combine.cc 2026-01-06 19:34:48.689525955 +0100 @@ -4028,7 +4028,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, && !(GET_CODE (SET_DEST (set1)) == SUBREG && find_reg_note (i2, REG_DEAD, SUBREG_REG (SET_DEST (set1)))) - && SET_DEST (set1) != pc_rtx + && !modified_between_p (SET_DEST (set1), i2, i3) && !reg_used_between_p (SET_DEST (set1), i2, i3))) /* If I3 is a jump, ensure that set0 is a jump so that we do not create invalid RTL. */ @@ -4044,7 +4044,7 @@ try_combine (rtx_insn *i3, rtx_insn *i2, && !(GET_CODE (SET_DEST (set0)) == SUBREG && find_reg_note (i2, REG_DEAD, SUBREG_REG (SET_DEST (set0)))) - && SET_DEST (set0) != pc_rtx + && !modified_between_p (SET_DEST (set0), i2, i3) && !reg_used_between_p (SET_DEST (set0), i2, i3))) /* If I3 is a jump, ensure that set1 is a jump so that we do not create invalid RTL. */