diff mbox series

[pushed,RA,PR109520] : Catch error when there are no enough registers for asm insn

Message ID ade5eae2-b01d-1b8c-7c73-24e8192202fe@redhat.com
State New
Headers show
Series [pushed,RA,PR109520] : Catch error when there are no enough registers for asm insn | expand

Commit Message

Vladimir Makarov July 13, 2023, 2:52 p.m. UTC
The following patch solves

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

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

Patch

commit b175b4887f928118af997f6d4d75097a64dcec5d
Author: Vladimir N. Makarov <vmakarov@redhat.com>
Date:   Thu Jul 13 10:42:17 2023 -0400

    [RA][PR109520]: Catch error when there are no enough registers for asm insn
    
    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.

diff --git a/gcc/lra-assigns.cc b/gcc/lra-assigns.cc
index 2f95121df06..3555926af66 100644
--- a/gcc/lra-assigns.cc
+++ b/gcc/lra-assigns.cc
@@ -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)
 	{
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 9bfc88149ff..0c6912d6e7d 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -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;
diff --git a/gcc/lra-int.h b/gcc/lra-int.h
index 4dbe6672f3a..a32359e5772 100644
--- a/gcc/lra-int.h
+++ b/gcc/lra-int.h
@@ -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 *);
diff --git a/gcc/lra.cc b/gcc/lra.cc
index c8b3f139acd..563aff10b96 100644
--- a/gcc/lra.cc
+++ b/gcc/lra.cc
@@ -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);
+    }
+}
+
 
 
 /* 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
index 00000000000..d81b2555202
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr109520.c
@@ -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;
+}