The following patch solves

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127244

The patch was successfully bootstrapped and tested on x86-64, aarhc64, ppc64le

commit cf6605e1e4a1ab76a09f96635b919e53aaf48af1
Author: Vladimir N. Makarov <[email protected]>
Date:   Fri Sep 11 09:44:22 2026 -0400

    [PR 127244][LRA]: Inherit optional reload for output operands
    
    The PR reveals that optional reload for output operands is not
    inherited and this results in bad code generation. The patch fixes
    this.
    
    gcc/ChangeLog:
    
            PR rtl-optimization/127244
            * lra-constraints.cc (inheritance_pseudo_p): New function.
            (undo_optional_reloads): Keep optional reload for output
            operand if it is inherited.
    
    gcc/testsuite/ChangeLog:
    
            PR rtl-optimization/127244
            * gcc.target/i386/pr127244.c: New

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 153624b8859..16866033d50 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -8259,6 +8259,14 @@ remove_inheritance_pseudos (bitmap remove_pseudos)
   return change_p;
 }
 
+/* Return true if REGNO is an inheritance pseudo.  */
+static bool
+inheritance_pseudo_p (int regno)
+{
+  return (regno >= new_regno_start
+	  && bitmap_bit_p (&lra_inheritance_pseudos, regno));
+}
+
 /* If optional reload pseudos failed to get a hard register or was not
    inherited, it is better to remove optional reloads.  We do this
    transformation after undoing inheritance to figure out necessity to
@@ -8291,19 +8299,22 @@ undo_optional_reloads (void)
 	    insn = lra_insn_recog_data[uid]->insn;
 	    if ((set = single_set (insn)) == NULL_RTX)
 	      continue;
-	    src = SET_SRC (set);
-	    dest = SET_DEST (set);
-	    if ((! REG_P (src) && ! SUBREG_P (src))
-		|| (! REG_P (dest) && ! SUBREG_P (dest)))
+	    int src_regno = get_regno (SET_SRC (set));
+	    int dest_regno = get_regno (SET_DEST (set));
+	    if (src_regno < 0 || dest_regno < 0)
+	      continue;
+	    int restore_regno = get_regno (lra_reg_info[regno].restore_rtx);
+	    if (restore_regno < 0)
 	      continue;
-	    if (get_regno (dest) == (int) regno
-		/* Ignore insn for optional reloads itself.  */
-		&& (get_regno (lra_reg_info[regno].restore_rtx)
-		    != get_regno (src))
-		/* Check only inheritance on last inheritance pass.  */
-		&& get_regno (src) >= new_regno_start
-		/* Check that the optional reload was inherited.  */
-		&& bitmap_bit_p (&lra_inheritance_pseudos, get_regno (src)))
+	    if (((dest_regno == (int) regno
+		  /* Ignore insn for optional reloads itself.  */
+		  && restore_regno != src_regno
+		  /* Check that the optional reload was inherited.  */
+		  && inheritance_pseudo_p (src_regno))
+		 || (src_regno == (int) regno
+		     && restore_regno != dest_regno
+		     /* The optional reload is an inheritance source.  */
+		     && inheritance_pseudo_p (dest_regno))))
 	      {
 		keep_p = true;
 		break;
diff --git a/gcc/testsuite/gcc.target/i386/pr127244.c b/gcc/testsuite/gcc.target/i386/pr127244.c
new file mode 100644
index 00000000000..8582c29c431
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr127244.c
@@ -0,0 +1,57 @@
+/* PR rtl-optimization/127244 */
+/* { dg-do compile { target lp64 } } */
+/* { dg-options "-O2" } */
+
+typedef unsigned int __u32;
+
+extern unsigned long __rdgsbase_inactive (void);
+
+static inline unsigned long
+native_save_fl (void) {
+  unsigned long flags;
+  asm volatile ("# __raw_save_flags\n\tpushf ; pop %0"
+		: "=rm" (flags)
+		:
+		: "memory");
+  return flags;
+}
+
+static inline void
+native_irq_disable (void) {
+  asm volatile ("cli" : : : "memory");
+}
+
+static inline void
+native_irq_enable (void) {
+  asm volatile ("sti" : : : "memory");
+}
+
+struct cpuinfo_x86 {
+  union { __u32 x86_capability[24]; };
+};
+
+struct cpuinfo_x86 boot_cpu_data;
+
+static inline _Bool
+constant_test_bit (long nr, const volatile unsigned long *addr) {
+  return ((1UL << (nr & 63)) & addr[nr >> 6]) != 0;
+}
+
+unsigned long
+x86_gsbase_read_cpu_inactive (void) {
+  unsigned long gsbase;
+
+  if (constant_test_bit (9 * 32, (unsigned long *) boot_cpu_data.x86_capability)) {
+    unsigned long flags = native_save_fl ();
+    native_irq_disable ();
+    gsbase = __rdgsbase_inactive ();
+    if (flags & (1UL << 9))
+      native_irq_enable ();
+  }
+
+  return gsbase;
+}
+
+/* { dg-final { scan-assembler "pushf ; pop %r" } } */
+/* { dg-final { scan-assembler-not "pushf ; pop \[0-9-]*\\(%rsp\\)" } } */
+/* { dg-final { scan-assembler-not "movq\[ \t\]+\[0-9-]*\\(%rsp\\), %r" } } */

Reply via email to