]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[RA][PR109520]: Catch error when there are no enough registers for asm insn
authorVladimir N. Makarov <vmakarov@redhat.com>
Thu, 13 Jul 2023 14:42:17 +0000 (10:42 -0400)
committerVladimir N. Makarov <vmakarov@redhat.com>
Thu, 13 Jul 2023 14:47:59 +0000 (10:47 -0400)
Asm insn unlike other insns can have so many operands whose
constraints can not be satisfied.  It results in LRA cycling for such
test case.  The following patch catches such situation and reports the
problem.

PR middle-end/109520

gcc/ChangeLog:

* lra-int.h (lra_insn_recog_data): Add member asm_reloads_num.
(lra_asm_insn_error): New prototype.
* lra.cc: Include rtl_error.h.
(lra_set_insn_recog_data): Initialize asm_reloads_num.
(lra_asm_insn_error): New func whose code is taken from ...
* lra-assigns.cc (lra_split_hard_reg_for): ... here.  Use lra_asm_insn_error.
* lra-constraints.cc (curr_insn_transform): Check reloads nummber for asm.

gcc/testsuite/ChangeLog:

* gcc.target/i386/pr109520.c: New test.

gcc/lra-assigns.cc
gcc/lra-constraints.cc
gcc/lra-int.h
gcc/lra.cc
gcc/testsuite/gcc.target/i386/pr109520.c [new file with mode: 0644]

index 2f95121df06eeaf7f94dc5cf3a5e0c8323110be0..3555926af6695642b0c7b685ecfabd5fa6d00a99 100644 (file)
@@ -1851,20 +1851,8 @@ lra_split_hard_reg_for (void)
       insn = lra_insn_recog_data[u]->insn;
       if (asm_noperands (PATTERN (insn)) >= 0)
        {
-         lra_asm_error_p = asm_p = true;
-         error_for_asm (insn,
-                        "%<asm%> operand has impossible constraints");
-         /* Avoid further trouble with this insn.  */
-         if (JUMP_P (insn))
-           {
-             ira_nullify_asm_goto (insn);
-             lra_update_insn_regno_info (insn);
-           }
-         else
-           {
-             PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
-             lra_set_insn_deleted (insn);
-           }
+         asm_p = true;
+         lra_asm_insn_error (insn);
        }
       else if (!asm_p)
        {
index 9bfc88149ff6b93182869a9047832826c9aaf6c2..0c6912d6e7dbd67d0560faad4d14e3fa0c8d2398 100644 (file)
@@ -4813,6 +4813,10 @@ curr_insn_transform (bool check_only_p)
       lra_update_operator_dups (curr_id);
       /* Something changes -- process the insn.         */
       lra_update_insn_regno_info (curr_insn);
+      if (asm_noperands (PATTERN (curr_insn)) >= 0
+         && ++curr_id->asm_reloads_num >= FIRST_PSEUDO_REGISTER)
+       /* Most probably there are no enough registers to satisfy asm insn: */
+       lra_asm_insn_error (curr_insn);
     }
   lra_process_new_insns (curr_insn, before, after, "Inserting insn reload");
   return change_p;
index 4dbe6672f3ae41d0e92ec78947882636dae6dd2b..a32359e57729ec7cba9f8302302c1de7e200646d 100644 (file)
@@ -209,6 +209,9 @@ public:
      debug insn.  LRA_NON_CLOBBERED_ALT means ignoring any earlier
      clobbers for the insn.  */
   int used_insn_alternative;
+  /* Defined for asm insn and it is how many times we already generated reloads
+     for the asm insn.  */
+  int asm_reloads_num;
   /* SP offset before the insn relative to one at the func start.  */
   poly_int64 sp_offset;
   /* The insn itself.  */
@@ -307,6 +310,7 @@ extern void lra_delete_dead_insn (rtx_insn *);
 extern void lra_emit_add (rtx, rtx, rtx);
 extern void lra_emit_move (rtx, rtx);
 extern void lra_update_dups (lra_insn_recog_data_t, signed char *);
+extern void lra_asm_insn_error (rtx_insn *insn);
 
 extern void lra_process_new_insns (rtx_insn *, rtx_insn *, rtx_insn *,
                                   const char *);
index c8b3f139acd79266b138f991125d7d7e8a736408..563aff10b9658b5a26dfeaad741633aaf7df009c 100644 (file)
@@ -106,6 +106,7 @@ along with GCC; see the file COPYING3.      If not see
 #include "backend.h"
 #include "target.h"
 #include "rtl.h"
+#include "rtl-error.h"
 #include "tree.h"
 #include "predict.h"
 #include "df.h"
@@ -536,6 +537,27 @@ lra_update_dups (lra_insn_recog_data_t id, signed char *nops)
        *id->dup_loc[i] = *id->operand_loc[nop];
 }
 
+/* Report asm insn error and modify the asm insn.  */
+void
+lra_asm_insn_error (rtx_insn *insn)
+{
+  lra_asm_error_p = true;
+  error_for_asm (insn,
+                "%<asm%> operand has impossible constraints"
+                " or there are not enough registers");
+  /* Avoid further trouble with this insn.  */
+  if (JUMP_P (insn))
+    {
+      ira_nullify_asm_goto (insn);
+      lra_update_insn_regno_info (insn);
+    }
+  else
+    {
+      PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
+      lra_set_insn_deleted (insn);
+    }
+}
+
 \f
 
 /* This page contains code dealing with info about registers in the
@@ -973,6 +995,7 @@ lra_set_insn_recog_data (rtx_insn *insn)
   lra_insn_recog_data[uid] = data;
   data->insn = insn;
   data->used_insn_alternative = LRA_UNKNOWN_ALT;
+  data->asm_reloads_num = 0;
   data->icode = icode;
   data->regs = NULL;
   if (DEBUG_INSN_P (insn))
diff --git a/gcc/testsuite/gcc.target/i386/pr109520.c b/gcc/testsuite/gcc.target/i386/pr109520.c
new file mode 100644 (file)
index 0000000..d81b255
--- /dev/null
@@ -0,0 +1,48 @@
+/* { dg-do compile  { target { ! ia32 } } } */
+/* { dg-options "-O0" } */
+
+int
+foo (int a0, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8,
+     int a9, int a10, int a11, int a12, int a13, int a14, int a15, int a16)
+{
+  register int v0 asm ("rax") = a3;
+  register int v1 asm ("rbx") = a4;
+  register int v2 asm ("rcx") = a5;
+  register int v3 asm ("rdx") = a6;
+  register int v4 asm ("rsi") = a7;
+  register int v5 asm ("rdi") = a8;
+  register int v6 asm ("r8") = a9;
+  register int v7 asm ("r9") = a10;
+  register int v8 asm ("r10") = a11;
+  register int v9 asm ("r11") = a12;
+  register int v10 asm ("r12") = a13;
+  register int v11 asm ("r13") = a14;
+  register int v12 asm ("r14") = a15;
+  register int v13 asm ("r15") = a16;
+  int x;
+  
+  v0 += a0;
+  v1 += a1;
+  v2 += a2;
+  v0 |= a0;
+  v1 |= a1;
+  v2 |= a2;
+  v0 ^= a0;
+  v1 ^= a1;
+  v2 ^= a2;
+  v0 &= a0;
+  v1 &= a1;
+  v2 &= a2;
+  asm goto ("": "=r" (x) : : : lab); /* { dg-error "operand has impossible constraints" } */
+  a1 ^= a0;
+  a2 = a1;
+  a0 |= a2;
+  a0 |= x;
+ lab:
+  v0 += x + a0 + a1 + a2;
+  v1 -= a0 - a1 - a2;
+  v2 |= a0 | a1 | a2;
+  v3 |= a0 & a1 & a2;
+  v4 ^= a0 ^ a1 ^ a2;
+  return  v0 + v1 + v2 + v3 + v4 + v5 + v6 + v7 + v8 + v9 + v10 + v11 + v12 + v13 + a0 + a1 + a2;
+}