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)
{
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;
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. */
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 *);
#include "backend.h"
#include "target.h"
#include "rtl.h"
+#include "rtl-error.h"
#include "tree.h"
#include "predict.h"
#include "df.h"
*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
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))
--- /dev/null
+/* { 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;
+}