]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[PR121571, LRA]: Reprocess asm insn with different preferences when there are no...
authorVladimir N. Makarov <vmakarov@redhat.com>
Wed, 28 Jan 2026 15:52:21 +0000 (10:52 -0500)
committerVladimir N. Makarov <vmakarov@redhat.com>
Wed, 28 Jan 2026 16:01:51 +0000 (11:01 -0500)
The test for the PR contains asm insn requiring 7 general regs but
three operands can be in memory too ('g' constraint).  There are only
6 available general regs.  IRA in the test case assigns a mask reg to
one pseudo.  When LRA reloads the pseudo assigned to mask reg, it
frees general reg assigned to another pseudo in the asm and assigns
mask reg to another pseudo.  After a few iterations, we have asm all
operands of which are reload pseudos assigned to general regs and one
pseudo assigned to mask reg.  After that LRA can do nothing and
reports "not enough regs".  The patch recognizes situation when there
are not enough regs for an asm insn and makes 2nd attempt to find
reloads when memory for operands with 'g' or 'rm' constraint is
preferred.

gcc/ChangeLog:

PR target/121571
* lra-constraints.cc (process_alt_operands): Reprocess asm insn
when there are no enough regs for the asm-insn.

gcc/testsuite/ChangeLog:

PR target/121571
* gcc.target/i386/pr121571.c: New.

gcc/lra-constraints.cc
gcc/testsuite/gcc.target/i386/pr121571.c [new file with mode: 0644]

index e3cee94724313133851021e13819f3e8c3359f61..a25487be299049bd2a1791dc586d8325113c3428 100644 (file)
@@ -2232,6 +2232,8 @@ process_alt_operands (int only_alternative)
   if (only_alternative >= 0)
     preferred &= ALTERNATIVE_BIT (only_alternative);
 
+  bool prefer_memory_p = false;
+ repeat:
   for (nalt = 0; nalt < n_alternatives; nalt++)
     {
       /* Loop over operands for one constraint alternative.  */
@@ -2564,6 +2566,11 @@ process_alt_operands (int only_alternative)
                      || general_constant_p (op)
                      || spilled_pseudo_p (op))
                    win = true;
+                 if (REG_P (op) && prefer_memory_p)
+                   {
+                     badop = false;
+                     offmemok = true;
+                   }
                  cl = GENERAL_REGS;
                  cl_filter = nullptr;
                  goto reg;
@@ -2694,7 +2701,7 @@ process_alt_operands (int only_alternative)
                                   (this_alternative_exclude_start_hard_regs,
                                    hard_regno[nop]))))
                        win = true;
-                     else if (hard_regno[nop] < 0)
+                     else if (hard_regno[nop] < 0 && !prefer_memory_p)
                        {
                          if (in_class_p (op, this_alternative, NULL))
                            win = true;
@@ -2796,6 +2803,12 @@ process_alt_operands (int only_alternative)
            this_alternative_match_win = true;
          else
            {
+             if (prefer_memory_p && offmemok)
+               {
+                 winreg = false;
+                 this_alternative = NO_REGS;
+               }
+
              int const_to_mem = 0;
              bool no_regs_p;
 
@@ -3331,6 +3344,17 @@ process_alt_operands (int only_alternative)
               ira_class_hard_regs_num[all_this_alternative],
               all_used_nregs, all_reload_nregs);
          overall += LRA_MAX_REJECT;
+         if (!prefer_memory_p && INSN_CODE (curr_insn) < 0)
+           {
+             /* asm can permit memory and reg and can be not enough regs for
+                asm -- try now memory: */
+             prefer_memory_p = true;
+             if (lra_dump_file != NULL)
+               fprintf
+                 (lra_dump_file,
+                  "            Trying now memory for operands\n");
+             goto repeat;
+           }
        }
       ok_p = true;
       curr_alt_dont_inherit_ops_num = 0;
diff --git a/gcc/testsuite/gcc.target/i386/pr121571.c b/gcc/testsuite/gcc.target/i386/pr121571.c
new file mode 100644 (file)
index 0000000..5be170e
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-march=skylake-avx512 -Os" } */
+
+int a, b, c, d, e, f;
+
+void
+foo ()
+{
+  int g[2] = { e, f };
+  if ((g[0] | g[1]) != 0)
+    __asm__ (""
+             : "=r" (d), "=&r" (c), "=&r" (b), "=&r" (a)
+             : "0" (0), "g" (g), "g" (g[1]), "g" (g[0]));
+}