[gcc r16-9422] ifcvt: Reject hard-register destinations in multiple sets [PR126184]

Kyrylo Tkachov via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:9226f469f9e19783ac2d7fbb7498d73f75e079ac

commit r16-9422-g9226f469f9e19783ac2d7fbb7498d73f75e079ac
Author: Kyrylo Tkachov <[email protected]>
Date:   Wed Jul 22 16:45:16 2026 +0200

    ifcvt: Reject hard-register destinations in multiple sets [PR126184]
    
    noce_convert_multiple_sets keys its dependency information by destination
    register number.  Hard registers can have overlapping definitions in
    different modes.  An exact RTL replacement cannot represent the value from a
    partial or mode-changing definition.
    
    Reject hard-register destinations in the block eligibility check.  Assert
    the resulting pseudo-only invariant when dependency information is
    initialized.
    
    Add an RTL execution test with mixed-mode hard-register definitions.  It
    verifies that the block remains unconverted.
    
    Bootstrapped and regtested on aarch64-none-linux-gnu and
    x86_64-pc-linux-gnu.
    
    gcc/ChangeLog:
    
            PR rtl-optimization/126184
            * ifcvt.cc (init_noce_multiple_sets_info): Assert that destinations
            are pseudos.
            (bb_ok_for_noce_convert_multiple_sets): Reject hard-register
            destinations.
    
    gcc/testsuite/ChangeLog:
    
            PR rtl-optimization/126184
            * gcc.target/aarch64/pr126184-2.c: New test.
    
    Signed-off-by: Kyrylo Tkachov <[email protected]>
    (cherry picked from commit 7b4d5b42a78859b30c9b48fa0a426effbbd71ff7)

Diff:
---
 gcc/ifcvt.cc                                  | 14 +++--
 gcc/testsuite/gcc.target/aarch64/pr126184-2.c | 75 +++++++++++++++++++++++++++
 2 files changed, 84 insertions(+), 5 deletions(-)

diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index c151146c1b22..6f5aa72681bc 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -4156,7 +4156,7 @@ init_noce_multiple_sets_info (basic_block bb,
       rtx src = SET_SRC (set);
       rtx dest = SET_DEST (set);
 
-      gcc_checking_assert (REG_P (dest));
+      gcc_checking_assert (REG_P (dest) && !HARD_REGISTER_P (dest));
       info->need_cmov = bitmap_bit_p (bb_live_out, REGNO (dest));
 
       /* Check if the current SET's source is the same
@@ -4201,10 +4201,14 @@ bb_ok_for_noce_convert_multiple_sets (basic_block test_bb, unsigned *cost)
       rtx dest = SET_DEST (set);
       rtx src = SET_SRC (set);
 
-      /* Do not handle anything involving memory loads/stores since it might
-	 violate data-race-freedom guarantees.  Make sure we can force SRC
-	 to a register as that may be needed in try_emit_cmove_seq.  */
-      if (!REG_P (dest) || contains_mem_rtx_p (src)
+      /* Dependency rewiring is keyed by register number, so restrict
+	 destinations to pseudos.  Hard-register definitions can overlap
+	 without having the same mode.  Do not handle anything involving
+	 memory loads/stores since it might violate data-race-freedom
+	 guarantees.  Make sure we can force SRC to a register as that may
+	 be needed in try_emit_cmove_seq.  */
+      if (!REG_P (dest) || HARD_REGISTER_P (dest)
+	  || contains_mem_rtx_p (src)
 	  || !noce_can_force_operand (src))
 	return false;
 
diff --git a/gcc/testsuite/gcc.target/aarch64/pr126184-2.c b/gcc/testsuite/gcc.target/aarch64/pr126184-2.c
new file mode 100644
index 000000000000..5e0274660413
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr126184-2.c
@@ -0,0 +1,75 @@
+/* PR rtl-optimization/126184 */
+/* { dg-do run } */
+/* { dg-options "-O2 --param=max-rtl-if-conversion-unpredictable-cost=100 -fdump-rtl-ce1" } */
+
+/* Mixed-mode hard-register definitions cannot be rewired through a single
+   temporary.  Verify that the multi-set conversion rejects the block.  */
+
+unsigned long long __RTL (startwith ("ce1"))
+f (unsigned long long c, unsigned long long x, unsigned long long y)
+{
+(function "f"
+  (param "c" (DECL_RTL (reg/v:DI x4 [ c ]))
+             (DECL_RTL_INCOMING (reg/v:DI x0 [ c ])))
+  (param "x" (DECL_RTL (reg/v:DI <1> [ x ]))
+             (DECL_RTL_INCOMING (reg/v:DI x1 [ x ])))
+  (param "y" (DECL_RTL (reg/v:DI <2> [ y ]))
+             (DECL_RTL_INCOMING (reg/v:DI x2 [ y ])))
+  (insn-chain
+    (block 2
+      (edge-from entry (flags "FALLTHRU"))
+      (cnote 1 [bb 2] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 2 (set (reg/v:DI x4 [ c ]) (reg:DI x0)))
+      (cinsn 3 (set (reg/v:DI <1> [ x ]) (reg:DI x1)))
+      (cinsn 4 (set (reg/v:DI <2> [ y ]) (reg:DI x2)))
+      (cinsn 5 (set (reg:DI <3>)
+                    (plus:DI (reg/v:DI <1>) (const_int 11))))
+      (cinsn 6 (set (reg:DI <4>)
+                    (plus:DI (reg/v:DI <2>) (const_int -2))))
+      (cinsn 7 (set (reg:CC cc)
+                    (compare:CC (reg/v:DI x4) (const_int 0))))
+      (cjump_insn 8 (set (pc)
+        (if_then_else (eq (reg:CC cc) (const_int 0))
+                      (label_ref 30) (pc))))
+      (edge-to 3 (flags "FALLTHRU"))
+      (edge-to 4)
+    )
+    (block 3
+      (edge-from 2 (flags "FALLTHRU"))
+      (cnote 9 [bb 3] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 10 (set (reg/v:DI x4 [ c ])
+                     (plus:DI (reg/v:DI <1>) (const_int 1))))
+      (cinsn 11 (set (reg:DI <3>)
+                     (plus:DI (reg/v:DI x4) (reg/v:DI <2>))))
+      (cinsn 12 (set (reg:SI x4) (const_int 26)))
+      (cinsn 13 (set (reg:DI <4>)
+                     (plus:DI (reg/v:DI x4) (reg/v:DI <1>))))
+      (edge-to 4 (flags "FALLTHRU"))
+    )
+    (block 4
+      (edge-from 2)
+      (edge-from 3 (flags "FALLTHRU"))
+      (clabel 30 2)
+      (cnote 31 [bb 4] NOTE_INSN_BASIC_BLOCK)
+      (cinsn 32 (set (reg:DI <5>)
+                     (plus:DI (reg:DI <3>) (reg:DI <4>))))
+      (cinsn 33 (set (reg/i:DI x0) (reg:DI <5>)))
+      (cinsn 34 (use (reg/i:DI x0)))
+      (edge-to exit (flags "FALLTHRU"))
+    )
+  )
+  (crtl (return_rtx (reg/i:DI x0)))
+)
+}
+
+int
+main (void)
+{
+  if (f (7, 13, 17) != 70)
+    __builtin_abort ();
+  if (f (0, 13, 17) != 39)
+    __builtin_abort ();
+  return 0;
+}
+
+/* { dg-final { scan-rtl-dump-not "if-conversion succeeded through noce_convert_multiple_sets" "ce1" } } */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.