https://gcc.gnu.org/g:cf6605e1e4a1ab76a09f96635b919e53aaf48af1

commit r17-4179-gcf6605e1e4a1ab76a09f96635b919e53aaf48af1
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:
---
 gcc/lra-constraints.cc                   | 35 +++++++++++++-------
 gcc/testsuite/gcc.target/i386/pr127244.c | 57 ++++++++++++++++++++++++++++++++
 2 files changed, 80 insertions(+), 12 deletions(-)

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 153624b8859d..16866033d50c 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 000000000000..8582c29c4311
--- /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