The following patch fixes

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

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

commit 56fc6a6d9edc9f9170285ef31c7f312608fad88c
Author: Vladimir N. Makarov <vmaka...@redhat.com>
Date:   Wed Nov 20 14:25:41 2024 -0500

    [PR116587][LRA]: Fix last chance reload pseudo allocation
    
    On i686 PR116587 test compilation resulted in LRA failure to find
    registers for a reload insn pseudo.  The insn requires 6 regs for 4
    reload insn pseudos where two of them require 2 regs each.  But we
    have only 5 free regs as sp is a fixed reg, bp is fixed because of
    -fno-omit-frame-pointer, bx is assigned to pic_offset_table_pseudo
    because of -fPIC.  LRA spills pic_offset_table_pseudo as the last
    chance approach to allocate registers to the reload pseudo.  Although
    it makes 2 free registers for the unallocated reload pseudo requiring
    also 2 regs, the pseudo still can not be allocated as the 2 free regs
    are disjoint.  The patch spills all pseudos conflicting with the
    unallocated reload pseudo including already allocated reload insn
    pseudos, then standard LRA code allocates spilled pseudos requiring
    more one register first and avoid situation of the disjoint regs for
    reload pseudos requiring more one reg.
    
    gcc/ChangeLog:
    
            PR target/116587
            * lra-assigns.cc (find_all_spills_for): Consider all pseudos whose
            classes intersect given pseudo class.
    
    gcc/testsuite/ChangeLog:
    
            PR target/116587
            * gcc.target/i386/pr116587.c: New test.

diff --git a/gcc/lra-assigns.cc b/gcc/lra-assigns.cc
index bcd7967ec7d..0a14bde5e74 100644
--- a/gcc/lra-assigns.cc
+++ b/gcc/lra-assigns.cc
@@ -1362,14 +1362,7 @@ find_all_spills_for (int regno)
 	    {
 	      if (live_pseudos_reg_renumber[r2->regno] >= 0
 		  && ! sparseset_bit_p (live_range_hard_reg_pseudos, r2->regno)
-		  && rclass_intersect_p[regno_allocno_class_array[r2->regno]]
-		  && ((int) r2->regno < lra_constraint_new_regno_start
-		      || bitmap_bit_p (&lra_inheritance_pseudos, r2->regno)
-		      || bitmap_bit_p (&lra_split_regs, r2->regno)
-		      || bitmap_bit_p (&lra_optional_reload_pseudos, r2->regno)
-		      /* There is no sense to consider another reload
-			 pseudo if it has the same class.  */
-		      || regno_allocno_class_array[r2->regno] != rclass))
+		  && rclass_intersect_p[regno_allocno_class_array[r2->regno]])
 		sparseset_set_bit (live_range_hard_reg_pseudos, r2->regno);
 	    }
 	}
diff --git a/gcc/testsuite/gcc.target/i386/pr116587.c b/gcc/testsuite/gcc.target/i386/pr116587.c
new file mode 100644
index 00000000000..092830002d2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr116587.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fPIC -mstackrealign -mavx512f -fharden-control-flow-redundancy -fno-omit-frame-pointer -mbmi -fkeep-gc-roots-live" } */
+
+typedef __UINT64_TYPE__ a;
+int b;
+struct c {
+  a d;
+};
+extern char e[];
+int f;
+void g();
+char *h(struct c *i, a d) {
+  while (b) {
+    if ((i->d & d) == i->d) {
+      if (f)
+        g();
+      g();
+      d &= ~i->d;
+    }
+    ++i;
+  }
+  if (d)
+    g();
+  if (f)
+    return "";
+  return e;
+}

Reply via email to