@@ -142,9 +142,9 @@ reg_save_code (int reg, machine_mode mode)
if (ok)
{
extract_insn (saveinsn);
- ok = constrain_operands (1, get_enabled_alternatives (saveinsn));
+ ok = constrain_operands (1, get_enabled_alternatives (saveinsn)) >= 0;
extract_insn (restinsn);
- ok &= constrain_operands (1, get_enabled_alternatives (restinsn));
+ ok &= constrain_operands (1, get_enabled_alternatives (restinsn)) >= 0;
}
if (! ok)
@@ -8335,7 +8335,7 @@ alpha_end_function (FILE *file, const char *fnname, tree decl ATTRIBUTE_UNUSED)
if (!INSN_P (insn))
insn = prev_active_insn (insn);
if (insn && CALL_P (insn))
- output_asm_insn (get_insn_template (CODE_FOR_nop, NULL), NULL);
+ output_asm_insn (get_insn_template (NULL, CODE_FOR_nop, 0), NULL);
#if TARGET_ABI_OPEN_VMS
/* Write the linkage entries. */
@@ -17105,7 +17105,7 @@ note_invalid_constants (rtx_insn *insn, HOST_WIDE_INT address, int do_pushes)
{
int opno;
- extract_constrain_insn (insn);
+ int alt = extract_constrain_insn (insn);
if (recog_data.n_alternatives == 0)
return;
@@ -17114,7 +17114,7 @@ note_invalid_constants (rtx_insn *insn, HOST_WIDE_INT address, int do_pushes)
this insn. */
preprocess_constraints (insn);
- const operand_alternative *op_alt = which_op_alt ();
+ const operand_alternative *op_alt = get_op_alt (alt);
for (opno = 0; opno < recog_data.n_operands; opno++)
{
/* Things we need to fix can only occur in inputs. */
@@ -27630,11 +27630,10 @@ ix86_attr_length_address_default (rtx_insn *insn)
rtx op = recog_data.operand[i];
if (MEM_P (op))
{
- constrain_operands_cached (insn, reload_completed);
- if (which_alternative != -1)
+ int alt = constrain_operands_cached (insn, reload_completed);
+ if (alt != -1)
{
const char *constraints = recog_data.constraints[i];
- int alt = which_alternative;
while (*constraints == '=' || *constraints == '+')
constraints++;
@@ -45354,7 +45353,7 @@ ix86_mitigate_rop (void)
continue;
extract_insn (insn);
- constrain_operands_cached (insn, reload_completed);
+ int alt = constrain_operands_cached (insn, reload_completed);
int opno0, opno1;
int modrm = ix86_get_modrm_for_rop (insn, recog_data.operand,
recog_data.n_operands, &opno0,
@@ -45366,12 +45365,12 @@ ix86_mitigate_rop (void)
rtx oldreg = recog_data.operand[opno1];
preprocess_constraints (insn);
- const operand_alternative *alt = which_op_alt ();
+ const operand_alternative *op_alt = get_op_alt (alt);
int i;
for (i = 0; i < recog_data.n_operands; i++)
if (i != opno1
- && alt[i].earlyclobber
+ && op_alt[i].earlyclobber
&& reg_overlap_mentioned_p (recog_data.operand[i],
oldreg))
break;
@@ -45383,7 +45382,7 @@ ix86_mitigate_rop (void)
fprintf (dump_file,
"attempting to fix modrm byte in insn %d:"
" reg %d class %s", INSN_UID (insn), REGNO (oldreg),
- reg_class_names[alt[opno1].cl]);
+ reg_class_names[op_alt[opno1].cl]);
HARD_REG_SET unavailable;
REG_SET_TO_HARD_REG_SET (unavailable, &live);
@@ -45392,7 +45391,7 @@ ix86_mitigate_rop (void)
IOR_HARD_REG_SET (unavailable, fixed_reg_set);
IOR_HARD_REG_SET (unavailable, output_risky);
IOR_COMPL_HARD_REG_SET (unavailable,
- reg_class_contents[alt[opno1].cl]);
+ reg_class_contents[op_alt[opno1].cl]);
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (!TEST_HARD_REG_BIT (unavailable, i))
@@ -283,7 +283,7 @@
"@
fmove%.d %f1,%0
#"
- "&& reload_completed && (extract_constrain_insn_cached (insn), which_alternative == 1)"
+ "&& reload_completed && extract_constrain_insn_cached (insn) == 1"
[(const_int 0)]
{
m68k_emit_move_double (operands);
@@ -2514,7 +2514,9 @@
return "";
}
}
- "&& reload_completed && (extract_constrain_insn_cached (insn), which_alternative == 5) && !operands_match_p (operands[0], operands[1])"
+ "&& reload_completed
+ && extract_constrain_insn_cached (insn) == 5
+ && !operands_match_p (operands[0], operands[1])"
[(set (match_dup 0)
(match_dup 2))
(set (match_dup 0)
@@ -9133,7 +9133,8 @@ pa_can_combine_p (rtx_insn *new_rtx, rtx_insn *anchor, rtx_insn *floater,
basic_block bb = BLOCK_FOR_INSN (anchor);
if (insn_code_number < 0
|| (extract_insn (new_rtx),
- !constrain_operands (1, get_preferred_alternatives (new_rtx, bb))))
+ (constrain_operands
+ (1, get_preferred_alternatives (new_rtx, bb)) < 0)))
return 0;
if (reversed)
@@ -2494,7 +2494,7 @@ insn_ok_now (rtx_insn * insn)
if (recog (pattern, insn, 0) > -1)
{
extract_insn (insn);
- if (constrain_operands (1, get_preferred_alternatives (insn)))
+ if (constrain_operands (1, get_preferred_alternatives (insn)) >= 0)
{
#if DEBUG_ALLOC
fprintf (stderr, "\033[32m");
@@ -2523,7 +2523,7 @@ insn_ok_now (rtx_insn * insn)
if (recog (pattern, insn, 0) > -1)
{
extract_insn (insn);
- if (constrain_operands (0, get_preferred_alternatives (insn)))
+ if (constrain_operands (0, get_preferred_alternatives (insn)) >= 0)
{
cfun->machine->virt_insns_ok = 0;
return false;
@@ -34021,7 +34021,8 @@ rs6000_final_prescan_insn (rtx_insn *insn, rtx *operand ATTRIBUTE_UNUSED,
if (insn_code_number < 0)
return;
- temp = get_insn_template (insn_code_number, insn);
+ int alt = extract_constrain_insn_cached (insn);
+ temp = get_insn_template (insn, insn_code_number, alt);
if (get_attr_cell_micro (insn) == CELL_MICRO_ALWAYS)
warning_at (location, OPT_mwarn_cell_microcode,
@@ -414,9 +414,7 @@
if (icode < 0)
return false;
- extract_constrain_insn (insn);
-
- return which_alternative >= 0;
+ return extract_constrain_insn (insn) >= 0;
})
;; Return true if OP is a store multiple operation. It is known to be a
@@ -73,8 +73,8 @@ extern const char *output_ubranch (rtx, rtx_insn *);
extern const char *output_cbranch (rtx, rtx, int, int, int, rtx_insn *);
extern const char *output_return (rtx_insn *);
extern const char *output_sibcall (rtx_insn *, rtx);
-extern const char *output_v8plus_shift (rtx_insn *, rtx *, const char *);
-extern const char *output_v8plus_mult (rtx_insn *, rtx *, const char *);
+extern const char *output_v8plus_shift (rtx_insn *, rtx *, const char *, int);
+extern const char *output_v8plus_mult (rtx_insn *, rtx *, const char *, int);
extern const char *output_v9branch (rtx, rtx, int, int, int, int, rtx_insn *);
extern const char *output_probe_stack_range (rtx, rtx);
extern const char *output_cbcond (rtx, rtx, rtx_insn *);
@@ -9781,7 +9781,8 @@ sparc_check_64 (rtx x, rtx_insn *insn)
OPERANDS are its operands and OPCODE is the mnemonic to be used. */
const char *
-output_v8plus_shift (rtx_insn *insn, rtx *operands, const char *opcode)
+output_v8plus_shift (rtx_insn *insn, rtx *operands, const char *opcode,
+ int which_alternative)
{
static char asm_code[60];
@@ -12011,7 +12012,8 @@ sparc_preferred_reload_class (rtx x, reg_class_t rclass)
OPERANDS are its operands and OPCODE is the mnemonic to be used. */
const char *
-output_v8plus_mult (rtx_insn *insn, rtx *operands, const char *opcode)
+output_v8plus_mult (rtx_insn *insn, rtx *operands, const char *opcode,
+ int which_alternative)
{
char mulstr[32];
@@ -4044,7 +4044,7 @@
(clobber (match_scratch:SI 3 "=&h,X"))
(clobber (match_scratch:SI 4 "=&h,X"))]
"TARGET_V8PLUS"
- "* return output_v8plus_mult (insn, operands, \"mulx\");"
+ "* return output_v8plus_mult (insn, operands, \"mulx\", which_alternative);"
[(set_attr "type" "multi")
(set_attr "length" "9,8")])
@@ -4484,7 +4484,7 @@
(clobber (match_scratch:SI 3 "=&h,X"))
(clobber (match_scratch:SI 4 "=&h,X"))]
"TARGET_VIS3 && ! TARGET_ARCH64"
- "* return output_v8plus_mult (insn, operands, \"umulxhi\");"
+ "* return output_v8plus_mult (insn, operands, \"umulxhi\", which_alternative);"
[(set_attr "type" "imul")
(set_attr "length" "9,8")])
@@ -4528,7 +4528,7 @@
(clobber (match_scratch:SI 3 "=&h,X"))
(clobber (match_scratch:SI 4 "=&h,X"))]
"TARGET_VIS3 && ! TARGET_ARCH64"
- "* return output_v8plus_mult (insn, operands, \"xmulx\");"
+ "* return output_v8plus_mult (insn, operands, \"xmulx\", which_alternative);"
[(set_attr "type" "imul")
(set_attr "length" "9,8")])
@@ -4578,7 +4578,7 @@
(clobber (match_scratch:SI 3 "=&h,X"))
(clobber (match_scratch:SI 4 "=&h,X"))]
"TARGET_VIS3 && !TARGET_ARCH64"
- "* return output_v8plus_mult (insn, operands, \"xmulxhi\");"
+ "* return output_v8plus_mult (insn, operands, \"xmulxhi\", which_alternative);"
[(set_attr "type" "imul")
(set_attr "length" "9,8")])
@@ -5952,7 +5952,7 @@
(match_operand:SI 2 "arith_operand" "rI,rI,rI")))
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
- "* return output_v8plus_shift (insn ,operands, \"sllx\");"
+ "* return output_v8plus_shift (insn ,operands, \"sllx\", which_alternative);"
[(set_attr "type" "multi")
(set_attr "length" "5,5,6")])
@@ -6061,7 +6061,7 @@
(match_operand:SI 2 "arith_operand" "rI,rI,rI")))
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
- "* return output_v8plus_shift (insn, operands, \"srax\");"
+ "* return output_v8plus_shift (insn, operands, \"srax\", which_alternative);"
[(set_attr "type" "multi")
(set_attr "length" "5,5,6")])
@@ -6150,7 +6150,7 @@
(match_operand:SI 2 "arith_operand" "rI,rI,rI")))
(clobber (match_scratch:SI 3 "=X,X,&h"))]
"TARGET_V8PLUS"
- "* return output_v8plus_shift (insn, operands, \"srlx\");"
+ "* return output_v8plus_shift (insn, operands, \"srlx\", which_alternative);"
[(set_attr "type" "multi")
(set_attr "length" "5,5,6")])
@@ -29,8 +29,8 @@ extern void print_operand (FILE *, rtx, int);
extern void vax_notice_update_cc (rtx, rtx);
extern void vax_expand_addsub_di_operands (rtx *, enum rtx_code);
extern const char * vax_output_int_move (rtx, rtx *, machine_mode);
-extern const char * vax_output_int_add (rtx, rtx *, machine_mode);
-extern const char * vax_output_int_subtract (rtx, rtx *, machine_mode);
+extern const char * vax_output_int_add (rtx, int, rtx *, machine_mode);
+extern const char * vax_output_int_subtract (rtx, int, rtx *, machine_mode);
extern const char * vax_output_movmemsi (rtx, rtx *);
#endif /* RTX_CODE */
@@ -1340,7 +1340,7 @@ vax_output_int_move (rtx insn ATTRIBUTE_UNUSED, rtx *operands,
which are not modified very often. */
const char *
-vax_output_int_add (rtx insn, rtx *operands, machine_mode mode)
+vax_output_int_add (rtx insn, int alt, rtx *operands, machine_mode mode)
{
switch (mode)
{
@@ -1367,7 +1367,7 @@ vax_output_int_add (rtx insn, rtx *operands, machine_mode mode)
/* No reason to add a 0 to the low part and thus no carry, so just
emit the appropriate add/sub instruction. */
if (low[2] == const0_rtx)
- return vax_output_int_add (NULL, operands, SImode);
+ return vax_output_int_add (NULL, alt, operands, SImode);
/* Are we doing addition or subtraction? */
sub = CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0;
@@ -1421,7 +1421,7 @@ vax_output_int_add (rtx insn, rtx *operands, machine_mode mode)
output_asm_insn (pattern, low);
if (!carry)
/* If CARRY is 0, we don't have any carry value to worry about. */
- return get_insn_template (CODE_FOR_addsi3, insn);
+ return get_insn_template (insn, CODE_FOR_addsi3, alt);
/* %0 = C + %1 + %2 */
if (!rtx_equal_p (operands[0], operands[1]))
output_asm_insn ((operands[1] == const0_rtx
@@ -1550,7 +1550,7 @@ vax_output_int_add (rtx insn, rtx *operands, machine_mode mode)
}
const char *
-vax_output_int_subtract (rtx insn, rtx *operands, machine_mode mode)
+vax_output_int_subtract (rtx insn, int alt, rtx *operands, machine_mode mode)
{
switch (mode)
{
@@ -1603,7 +1603,10 @@ vax_output_int_subtract (rtx insn, rtx *operands, machine_mode mode)
if (low[2] == constm1_rtx)
pattern = "decl %0";
else if (low[2] == const0_rtx)
- pattern = get_insn_template (CODE_FOR_movsi, insn), carry = 0;
+ {
+ pattern = get_insn_template (insn, CODE_FOR_movsi, alt);
+ carry = 0;
+ }
else
pattern = "subl3 %2,%1,%0";
}
@@ -1616,7 +1619,7 @@ vax_output_int_subtract (rtx insn, rtx *operands, machine_mode mode)
return "sbwc %2,%0";
/* %0 = %2 - %1 - C */
}
- return get_insn_template (CODE_FOR_subsi3, insn);
+ return get_insn_template (insn, CODE_FOR_subsi3, alt);
}
default:
@@ -371,7 +371,8 @@
(plus:VAXint (match_operand:VAXint 1 "general_operand" "nrmT")
(match_operand:VAXint 2 "general_operand" "nrmT")))]
""
- "* return vax_output_int_add (insn, operands, <MODE>mode);")
+ "* return vax_output_int_add (insn, which_alternative, operands,
+ <MODE>mode);")
(define_expand "adddi3"
[(set (match_operand:DI 0 "nonimmediate_operand" "=g")
@@ -385,7 +386,7 @@
(plus:DI (match_operand:DI 1 "general_addsub_di_operand" "%0")
(match_operand:DI 2 "general_addsub_di_operand" "nRr")))]
"TARGET_QMATH"
- "* return vax_output_int_add (insn, operands, DImode);")
+ "* return vax_output_int_add (insn, which_alternative, operands, DImode);")
;; The add-with-carry (adwc) instruction only accepts two operands.
(define_insn "adddi3_old"
@@ -393,7 +394,7 @@
(plus:DI (match_operand:DI 1 "general_operand" "%0,ro>")
(match_operand:DI 2 "general_operand" "Fsro,Fs")))]
"!TARGET_QMATH"
- "* return vax_output_int_add (insn, operands, DImode);")
+ "* return vax_output_int_add (insn, which_alternative, operands, DImode);")
;;- All kinds of subtract instructions.
@@ -427,7 +428,8 @@
(minus:DI (match_operand:DI 1 "general_addsub_di_operand" "0,I")
(match_operand:DI 2 "general_addsub_di_operand" "nRr,Rr")))]
"TARGET_QMATH"
- "* return vax_output_int_subtract (insn, operands, DImode);")
+ "* return vax_output_int_subtract (insn, which_alternative,
+ operands, DImode);")
;; The subtract-with-carry (sbwc) instruction only takes two operands.
(define_insn "subdi3_old"
@@ -435,7 +437,8 @@
(minus:DI (match_operand:DI 1 "general_operand" "0,or>")
(match_operand:DI 2 "general_operand" "Fsor,Fs")))]
"!TARGET_QMATH"
- "* return vax_output_int_subtract (insn, operands, DImode);")
+ "* return vax_output_int_subtract (insn, which_alternative,
+ operands, DImode);")
;;- Multiply instructions.
@@ -2061,19 +2061,27 @@ final (rtx_insn *first, FILE *file, int optimize_p)
}
}
+/* Return the output code for alternative ALT of insn_code CODE.
+ If CODE uses an output function, INSN is the specific instruction
+ we want to generate, otherwise it is unused and can be null.
+
+ Note that an output function might write text directly to the
+ asm output file and simply return "". */
+
const char *
-get_insn_template (int code, rtx insn)
+get_insn_template (rtx insn, int code, int alt)
{
switch (insn_data[code].output_format)
{
case INSN_OUTPUT_FORMAT_SINGLE:
return insn_data[code].output.single;
case INSN_OUTPUT_FORMAT_MULTI:
- return insn_data[code].output.multi[which_alternative];
+ return insn_data[code].output.multi[alt];
case INSN_OUTPUT_FORMAT_FUNCTION:
gcc_assert (insn);
return (*insn_data[code].output.function) (recog_data.operand,
- as_a <rtx_insn *> (insn));
+ as_a <rtx_insn *> (insn),
+ alt);
default:
gcc_unreachable ();
@@ -2916,7 +2924,8 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
print_rtx_head = "";
}
- if (! constrain_operands_cached (insn, 1))
+ int alt = constrain_operands_cached (insn, 1);
+ if (alt < 0)
fatal_insn_not_found (insn);
/* Some target machines need to prescan each insn before
@@ -2944,7 +2953,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
current_output_insn = debug_insn = insn;
/* Find the proper template for this insn. */
- templ = get_insn_template (insn_code_number, insn);
+ templ = get_insn_template (insn, insn_code_number, alt);
/* If the C code returns 0, it means that it is a jump insn
which follows a deleted test insn, and that test insn
@@ -3422,7 +3431,8 @@ output_asm_name (void)
ASM_COMMENT_START, INSN_UID (debug_insn),
insn_data[num].name);
if (insn_data[num].n_alternatives > 1)
- fprintf (asm_out_file, "/%d", which_alternative + 1);
+ fprintf (asm_out_file, "/%d",
+ constrain_operands_cached (debug_insn, 1) + 1);
if (HAVE_ATTR_length)
fprintf (asm_out_file, "\t[length = %d]",
@@ -4278,31 +4278,41 @@ write_attr_case (FILE *outf, struct attr_desc *attr, struct attr_value *av,
must_extract = must_constrain = address_used = 0;
walk_attr_value (av->value);
+ int code_indent = indent + 2;
if (must_constrain)
{
+ code_indent += 2;
write_indent (outf, indent + 2);
- fprintf (outf, "extract_constrain_insn_cached (insn);\n");
+ fprintf (outf, "{\n");
+ write_indent (outf, code_indent);
+ fprintf (outf, "int which_alternative ATTRIBUTE_UNUSED = "
+ "extract_constrain_insn_cached (insn);\n");
}
else if (must_extract)
{
- write_indent (outf, indent + 2);
+ write_indent (outf, code_indent);
fprintf (outf, "extract_insn_cached (insn);\n");
}
attrs_to_cache = 0;
if (av->num_insns == 1)
- write_attr_set (outf, attr, indent + 2, av->value, prefix, suffix,
+ write_attr_set (outf, attr, code_indent, av->value, prefix, suffix,
known_true, av->first_insn->def->insn_code,
av->first_insn->def->insn_index, 0);
else
- write_attr_set (outf, attr, indent + 2, av->value, prefix, suffix,
+ write_attr_set (outf, attr, code_indent, av->value, prefix, suffix,
known_true, -2, 0, 0);
if (strncmp (prefix, "return", 6))
{
- write_indent (outf, indent + 2);
+ write_indent (outf, code_indent);
fprintf (outf, "break;\n");
}
+ if (code_indent != indent + 2)
+ {
+ write_indent (outf, indent + 2);
+ fprintf (outf, "}\n");
+ }
fprintf (outf, "\n");
}
@@ -627,7 +627,9 @@ process_template (struct data *d, const char *template_code)
d->output_format = INSN_OUTPUT_FORMAT_FUNCTION;
puts ("\nstatic const char *");
- printf ("output_%d (rtx *operands ATTRIBUTE_UNUSED, rtx_insn *insn ATTRIBUTE_UNUSED)\n",
+ printf ("output_%d (rtx *operands ATTRIBUTE_UNUSED,"
+ " rtx_insn *insn ATTRIBUTE_UNUSED,"
+ " int which_alternative ATTRIBUTE_UNUSED)\n",
d->code_number);
puts ("{");
print_md_ptr_loc (template_code);
@@ -656,7 +658,9 @@ process_template (struct data *d, const char *template_code)
d->output_format = INSN_OUTPUT_FORMAT_FUNCTION;
puts ("\nstatic const char *");
printf ("output_%d (rtx *operands ATTRIBUTE_UNUSED, "
- "rtx_insn *insn ATTRIBUTE_UNUSED)\n", d->code_number);
+ "rtx_insn *insn ATTRIBUTE_UNUSED, "
+ "int which_alternative ATTRIBUTE_UNUSED)\n",
+ d->code_number);
puts ("{");
puts (" switch (which_alternative)\n {");
}
@@ -1755,7 +1755,7 @@ setup_prohibited_mode_move_regs (void)
extract_insn (move_insn);
/* We don't know whether the move will be in code that is optimized
for size or speed, so consider all enabled alternatives. */
- if (! constrain_operands (1, get_enabled_alternatives (move_insn)))
+ if (constrain_operands (1, get_enabled_alternatives (move_insn)) < 0)
continue;
CLEAR_HARD_REG_BIT (ira_prohibited_mode_move_regs[i], j);
}
@@ -149,7 +149,7 @@ extern int only_leaf_regs_used (void);
extern void leaf_renumber_regs_insn (rtx);
/* Locate the proper template for the given insn-code. */
-extern const char *get_insn_template (int, rtx);
+extern const char *get_insn_template (rtx, int, int);
/* Functions in varasm.c. */
@@ -1087,8 +1087,8 @@ eliminate_partially_redundant_load (basic_block bb, rtx_insn *insn,
rtx_insn *move = gen_move_insn (copy_rtx (dest),
copy_rtx (avail_reg));
extract_insn (move);
- if (! constrain_operands (1, get_preferred_alternatives (insn,
- pred_bb))
+ if (constrain_operands (1, get_preferred_alternatives (insn,
+ pred_bb)) < 0
|| reg_killed_on_edge (avail_reg, pred)
|| reg_used_on_edge (dest, pred))
{
@@ -391,7 +391,7 @@ reload_cse_simplify_operands (rtx_insn *insn, rtx testreg)
/* Array of alternatives, sorted in order of decreasing desirability. */
int *alternative_order;
- extract_constrain_insn (insn);
+ int alt = extract_constrain_insn (insn);
if (recog_data.n_alternatives == 0 || recog_data.n_operands == 0)
return 0;
@@ -583,7 +583,7 @@ reload_cse_simplify_operands (rtx_insn *insn, rtx testreg)
/* Record all alternatives which are better or equal to the currently
matching one in the alternative_order array. */
for (i = j = 0; i < recog_data.n_alternatives; i++)
- if (alternative_reject[i] <= alternative_reject[which_alternative])
+ if (alternative_reject[i] <= alternative_reject[alt])
alternative_order[j++] = i;
recog_data.n_alternatives = j;
@@ -78,10 +78,10 @@ const operand_alternative *recog_op_alt;
static operand_alternative asm_op_alt[MAX_RECOG_OPERANDS
* MAX_RECOG_ALTERNATIVES];
-/* On return from `constrain_operands', indicate which alternative
- was satisfied. */
+/* Used by constrain_operands_cached to record the matching alternative.
+ Only valid if nonnegative. */
-int which_alternative;
+static int cached_which_alternative;
/* Nonzero after end of reload pass.
Set to 1 or 0 by toplev.c.
@@ -148,8 +148,7 @@ check_asm_operands (rtx x)
/* ??? Doh! We've not got the wrapping insn. Cook one up. */
rtx_insn *insn = make_insn_raw (x);
extract_insn (insn);
- constrain_operands (1, get_enabled_alternatives (insn));
- return which_alternative >= 0;
+ return constrain_operands (1, get_enabled_alternatives (insn)) >= 0;
}
noperands = asm_noperands (x);
@@ -352,7 +351,7 @@ insn_invalid_p (rtx_insn *insn, bool in_group)
{
extract_insn (insn);
- if (! constrain_operands (1, get_preferred_alternatives (insn)))
+ if (constrain_operands (1, get_preferred_alternatives (insn)) < 0)
return 1;
}
@@ -2070,20 +2069,20 @@ get_bool_attr_mask_uncached (rtx_insn *insn, bool_attr attr)
mustn't depend on the values of operands, so we don't provide their
real values here. */
rtx_insn *old_insn = recog_data.insn;
- int old_alternative = which_alternative;
+ int old_alternative = cached_which_alternative;
recog_data.insn = insn;
alternative_mask mask = ALL_ALTERNATIVES;
int n_alternatives = insn_data[INSN_CODE (insn)].n_alternatives;
for (int i = 0; i < n_alternatives; i++)
{
- which_alternative = i;
+ cached_which_alternative = i;
if (!get_bool_attr (insn, attr))
mask &= ~ALTERNATIVE_BIT (i);
}
recog_data.insn = old_insn;
- which_alternative = old_alternative;
+ cached_which_alternative = old_alternative;
return mask;
}
@@ -2179,36 +2178,43 @@ extract_insn_cached (rtx_insn *insn)
}
/* Do uncached extract_insn, constrain_operands and complain about failures.
+ Return the number of the matching alternative.
+
This should be used when extracting a pre-existing constrained instruction
if the caller wants to know which alternative was chosen. */
-void
+int
extract_constrain_insn (rtx_insn *insn)
{
extract_insn (insn);
- if (!constrain_operands (reload_completed, get_enabled_alternatives (insn)))
+ int alt = constrain_operands (reload_completed,
+ get_enabled_alternatives (insn));
+ if (alt < 0)
fatal_insn_not_found (insn);
+ return alt;
}
/* Do cached extract_insn, constrain_operands and complain about failures.
+ Return the number of the matching alternative.
+
Used by insn_attrtab. */
-void
+int
extract_constrain_insn_cached (rtx_insn *insn)
{
extract_insn_cached (insn);
- if (which_alternative == -1
- && !constrain_operands (reload_completed,
- get_enabled_alternatives (insn)))
+ int alt = constrain_operands_cached (insn, reload_completed);
+ if (alt < 0)
fatal_insn_not_found (insn);
+ return alt;
}
-/* Do cached constrain_operands on INSN and complain about failures. */
+/* Do cached constrain_operands on INSN. Return -1 on failure. */
int
constrain_operands_cached (rtx_insn *insn, int strict)
{
- if (which_alternative == -1)
- return constrain_operands (strict, get_enabled_alternatives (insn));
- else
- return 1;
+ if (cached_which_alternative == -1)
+ cached_which_alternative
+ = constrain_operands (strict, get_enabled_alternatives (insn));
+ return cached_which_alternative;
}
/* Analyze INSN and fill in recog_data. */
@@ -2310,7 +2316,7 @@ extract_insn (rtx_insn *insn)
gcc_assert (recog_data.n_alternatives <= MAX_RECOG_ALTERNATIVES);
recog_data.insn = NULL;
- which_alternative = -1;
+ cached_which_alternative = -1;
}
/* Fill in OP_ALT_BASE for an instruction that has N_OPERANDS operands,
@@ -2439,7 +2445,7 @@ preprocess_insn_constraints (unsigned int icode)
int n_operands = insn_data[icode].n_operands;
if (n_operands == 0)
return 0;
- /* Always provide at least one alternative so that which_op_alt ()
+ /* Always provide at least one alternative so that get_op_alt ()
works correctly. If the instruction has 0 alternatives (i.e. all
constraint strings are empty) then each operand in this alternative
will have anything_ok set. */
@@ -2479,16 +2485,12 @@ preprocess_constraints (rtx_insn *insn)
}
}
-/* Check the operands of an insn against the insn's operand constraints
- and return 1 if they match any of the alternatives in ALTERNATIVES.
+/* Check the operands of an insn against the insn's operand constraints.
+ Return the matching alternative number on success, otherwise return -1.
The information about the insn's operands, constraints, operand modes
etc. is obtained from the global variables set up by extract_insn.
- WHICH_ALTERNATIVE is set to a number which indicates which
- alternative of constraints was matched: 0 for the first alternative,
- 1 for the next, etc.
-
In addition, when two operands are required to match
and it happens that the output operand is (reg) while the
input operand is --(reg) or ++(reg) (a pre-inc or pre-dec),
@@ -2523,9 +2525,8 @@ constrain_operands (int strict, alternative_mask alternatives)
struct funny_match funny_match[MAX_RECOG_OPERANDS];
int funny_match_index;
- which_alternative = 0;
if (recog_data.n_operands == 0 || recog_data.n_alternatives == 0)
- return 1;
+ return 0;
for (c = 0; c < recog_data.n_operands; c++)
{
@@ -2533,6 +2534,7 @@ constrain_operands (int strict, alternative_mask alternatives)
matching_operands[c] = -1;
}
+ int which_alternative = 0;
do
{
int seen_earlyclobber_at = -1;
@@ -2806,14 +2808,14 @@ constrain_operands (int strict, alternative_mask alternatives)
if (strchr (recog_data.constraints[opno], '<') == NULL
&& strchr (recog_data.constraints[opno], '>')
== NULL)
- return 0;
+ return -1;
break;
default:
break;
}
}
- return 1;
+ return which_alternative;
}
}
@@ -2821,13 +2823,12 @@ constrain_operands (int strict, alternative_mask alternatives)
}
while (which_alternative < recog_data.n_alternatives);
- which_alternative = -1;
/* If we are about to reject this, but we are not to test strictly,
try a very loose test. Only return failure if it fails also. */
if (strict == 0)
return constrain_operands (-1, alternatives);
else
- return 0;
+ return -1;
}
/* Return true iff OPERAND (assumed to be a REG rtx)
@@ -132,8 +132,8 @@ extern void add_clobbers (rtx, int);
extern int added_clobbers_hard_reg_p (int);
extern void insn_extract (rtx_insn *);
extern void extract_insn (rtx_insn *);
-extern void extract_constrain_insn (rtx_insn *insn);
-extern void extract_constrain_insn_cached (rtx_insn *);
+extern int extract_constrain_insn (rtx_insn *insn);
+extern int extract_constrain_insn_cached (rtx_insn *);
extern void extract_insn_cached (rtx_insn *);
extern void preprocess_constraints (int, int, const char **,
operand_alternative *);
@@ -186,10 +186,6 @@ skip_alternative (const char *p)
/* Nonzero means volatile operands are recognized. */
extern int volatile_ok;
-/* Set by constrain_operands to the number of the alternative that
- matched. */
-extern int which_alternative;
-
/* The following vectors hold the results from insn_extract. */
struct recog_data_d
@@ -257,22 +253,21 @@ extern struct recog_data_d recog_data;
extern const operand_alternative *recog_op_alt;
/* Return a pointer to an array in which index OP describes the constraints
- on operand OP of the current instruction alternative (which_alternative).
+ on operand OP for alternative ALT of the current instruction.
Only valid after calling preprocess_constraints and constrain_operands. */
inline static const operand_alternative *
-which_op_alt ()
+get_op_alt (int alt)
{
- gcc_checking_assert (IN_RANGE (which_alternative, 0,
- recog_data.n_alternatives - 1));
- return &recog_op_alt[which_alternative * recog_data.n_operands];
+ gcc_checking_assert (IN_RANGE (alt, 0, recog_data.n_alternatives - 1));
+ return &recog_op_alt[alt * recog_data.n_operands];
}
/* A table defined in insn-output.c that give information about
each insn-code value. */
typedef int (*insn_operand_predicate_fn) (rtx, machine_mode);
-typedef const char * (*insn_output_fn) (rtx *, rtx_insn *);
+typedef const char * (*insn_output_fn) (rtx *, rtx_insn *, int);
struct insn_gen_fn
{
@@ -840,7 +840,7 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state)
if (recog_memoized (insn) == -1)
return false;
extract_insn (insn);
- if (!constrain_operands (1, get_preferred_alternatives (insn, bb)))
+ if (constrain_operands (1, get_preferred_alternatives (insn, bb)) < 0)
return false;
}
@@ -467,20 +467,20 @@ check_asm_stack_operands (rtx_insn *insn)
/* Find out what the constraints require. If no constraint
alternative matches, this asm is malformed. */
- extract_constrain_insn (insn);
+ int alt = extract_constrain_insn (insn);
preprocess_constraints (insn);
get_asm_operands_in_out (body, &n_outputs, &n_inputs);
- if (which_alternative < 0)
+ if (alt < 0)
{
malformed_asm = 1;
/* Avoid further trouble with this insn. */
PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
return 0;
}
- const operand_alternative *op_alt = which_op_alt ();
+ const operand_alternative *op_alt = get_op_alt (alt);
/* Strip SUBREGs here to make the following code simpler. */
for (i = 0; i < recog_data.n_operands; i++)
@@ -2002,10 +2002,10 @@ subst_asm_stack_regs (rtx_insn *insn, stack_ptr regstack)
/* Find out what the constraints required. If no constraint
alternative matches, that is a compiler bug: we should have caught
such an insn in check_asm_stack_operands. */
- extract_constrain_insn (insn);
+ int alt = extract_constrain_insn (insn);
preprocess_constraints (insn);
- const operand_alternative *op_alt = which_op_alt ();
+ const operand_alternative *op_alt = get_op_alt (alt);
get_asm_operands_in_out (body, &n_outputs, &n_inputs);
@@ -769,9 +769,9 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
}
set = single_set (insn);
- extract_constrain_insn (insn);
+ int alt = extract_constrain_insn (insn);
preprocess_constraints (insn);
- const operand_alternative *op_alt = which_op_alt ();
+ const operand_alternative *op_alt = get_op_alt (alt);
n_ops = recog_data.n_operands;
is_asm = asm_noperands (PATTERN (insn)) >= 0;
@@ -870,8 +870,9 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
}
/* We need to re-extract as validate_change clobbers
recog_data. */
- extract_constrain_insn (insn);
+ alt = extract_constrain_insn (insn);
preprocess_constraints (insn);
+ op_alt = get_op_alt (alt);
}
/* Otherwise, try all valid registers and see if its valid. */
@@ -896,8 +897,9 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
}
/* We need to re-extract as validate_change clobbers
recog_data. */
- extract_constrain_insn (insn);
+ alt = extract_constrain_insn (insn);
preprocess_constraints (insn);
+ op_alt = get_op_alt (alt);
}
}
}
@@ -1480,18 +1480,18 @@ scan_rtx (rtx_insn *insn, rtx *loc, enum reg_class cl, enum scan_actions action,
}
/* Hide operands of the current insn (of which there are N_OPS) by
- substituting cc0 for them.
- Previous values are stored in the OLD_OPERANDS and OLD_DUPS.
- For every bit set in DO_NOT_HIDE, we leave the operand alone.
- If INOUT_AND_EC_ONLY is set, we only do this for OP_INOUT type operands
- and earlyclobbers. */
+ substituting cc0 for them. ALT is the number of the matching
+ alternative. Previous values are stored in the OLD_OPERANDS and
+ OLD_DUPS. For every bit set in DO_NOT_HIDE, we leave the operand
+ alone. If INOUT_AND_EC_ONLY is set, we only do this for OP_INOUT
+ type operands and earlyclobbers. */
static void
-hide_operands (int n_ops, rtx *old_operands, rtx *old_dups,
+hide_operands (int alt, int n_ops, rtx *old_operands, rtx *old_dups,
unsigned HOST_WIDE_INT do_not_hide, bool inout_and_ec_only)
{
int i;
- const operand_alternative *op_alt = which_op_alt ();
+ const operand_alternative *op_alt = get_op_alt (alt);
for (i = 0; i < n_ops; i++)
{
old_operands[i] = recog_data.operand[i];
@@ -1536,13 +1536,15 @@ restore_operands (rtx_insn *insn, int n_ops, rtx *old_operands, rtx *old_dups)
/* For each output operand of INSN, call scan_rtx to create a new
open chain. Do this only for normal or earlyclobber outputs,
depending on EARLYCLOBBER. If INSN_INFO is nonnull, use it to
- record information about the operands in the insn. */
+ record information about the operands in the insn. ALT is the
+ number of the matching alternative. */
static void
-record_out_operands (rtx_insn *insn, bool earlyclobber, insn_rr_info *insn_info)
+record_out_operands (rtx_insn *insn, int alt, bool earlyclobber,
+ insn_rr_info *insn_info)
{
int n_ops = recog_data.n_operands;
- const operand_alternative *op_alt = which_op_alt ();
+ const operand_alternative *op_alt = get_op_alt (alt);
int i;
@@ -1634,9 +1636,9 @@ build_def_use (basic_block bb)
to be marked unrenamable or even cause us to abort the entire
basic block. */
- extract_constrain_insn (insn);
+ int alt = extract_constrain_insn (insn);
preprocess_constraints (insn);
- const operand_alternative *op_alt = which_op_alt ();
+ const operand_alternative *op_alt = get_op_alt (alt);
n_ops = recog_data.n_operands;
untracked_operands = 0;
@@ -1692,22 +1694,22 @@ build_def_use (basic_block bb)
/* Step 1a: Mark hard registers that are clobbered in this insn,
outside an operand, as live. */
- hide_operands (n_ops, old_operands, old_dups, untracked_operands,
- false);
+ hide_operands (alt, n_ops, old_operands, old_dups,
+ untracked_operands, false);
note_stores (PATTERN (insn), note_sets_clobbers, &clobber_code);
restore_operands (insn, n_ops, old_operands, old_dups);
/* Step 1b: Begin new chains for earlyclobbered writes inside
operands. */
- record_out_operands (insn, true, insn_info);
+ record_out_operands (insn, alt, true, insn_info);
/* Step 2: Mark chains for which we have reads outside operands
as unrenamable.
We do this by munging all operands into CC0, and closing
everything remaining. */
- hide_operands (n_ops, old_operands, old_dups, untracked_operands,
- false);
+ hide_operands (alt, n_ops, old_operands, old_dups,
+ untracked_operands, false);
scan_rtx (insn, &PATTERN (insn), NO_REGS, mark_all_read, OP_IN);
restore_operands (insn, n_ops, old_operands, old_dups);
@@ -1801,20 +1803,20 @@ build_def_use (basic_block bb)
the previous insn at the latest, as such operands cannot
possibly overlap with any input operands. */
- hide_operands (n_ops, old_operands, old_dups, untracked_operands,
- true);
+ hide_operands (alt, n_ops, old_operands, old_dups,
+ untracked_operands, true);
scan_rtx (insn, &PATTERN (insn), NO_REGS, terminate_write, OP_IN);
restore_operands (insn, n_ops, old_operands, old_dups);
/* Step 6a: Mark hard registers that are set in this insn,
outside an operand, as live. */
- hide_operands (n_ops, old_operands, old_dups, untracked_operands,
- false);
+ hide_operands (alt, n_ops, old_operands, old_dups,
+ untracked_operands, false);
note_stores (PATTERN (insn), note_sets_clobbers, &set_code);
restore_operands (insn, n_ops, old_operands, old_dups);
/* Step 6b: Begin new chains for writes inside operands. */
- record_out_operands (insn, false, insn_info);
+ record_out_operands (insn, alt, false, insn_info);
/* Step 6c: Record destination regs in REG_FRAME_RELATED_EXPR
notes for update. */
@@ -910,7 +910,7 @@ can_reload_into (rtx in, int regno, machine_mode mode)
if (recog_memoized (test_insn) >= 0)
{
extract_insn (test_insn);
- r = constrain_operands (1, get_enabled_alternatives (test_insn));
+ r = constrain_operands (1, get_enabled_alternatives (test_insn)) >= 0;
}
recog_data = save_recog_data;
return r;
@@ -1248,7 +1248,7 @@ reload (rtx_insn *first, int global)
if (asm_noperands (PATTERN (insn)) >= 0)
{
extract_insn (insn);
- if (!constrain_operands (1, get_enabled_alternatives (insn)))
+ if (constrain_operands (1, get_enabled_alternatives (insn)) < 0)
{
error_for_asm (insn,
"%<asm%> operand has impossible constraints");
@@ -4712,8 +4712,8 @@ reload_as_needed (int live_known)
&& GET_CODE (PATTERN (p)) != USE
&& (recog_memoized (p) < 0
|| (extract_insn (p),
- !(constrain_operands (1,
- get_enabled_alternatives (p))))))
+ (constrain_operands
+ (1, get_enabled_alternatives (p)) < 0))))
{
error_for_asm (insn,
"%<asm%> operand requires "
@@ -4796,8 +4796,8 @@ reload_as_needed (int live_known)
if (n)
{
extract_insn (p);
- n = constrain_operands (1,
- get_enabled_alternatives (p));
+ n = constrain_operands
+ (1, get_enabled_alternatives (p)) >= 0;
}
/* If the constraints were not met, then
@@ -5717,7 +5717,8 @@ gen_reload_chain_without_interm_reg_p (int r1, int r2)
/* We want constrain operands to treat this insn strictly in
its validity determination, i.e., the way it would after
reload has completed. */
- result = constrain_operands (1, get_enabled_alternatives (insn));
+ result =
+ constrain_operands (1, get_enabled_alternatives (insn)) >= 0;
}
delete_insns_since (last);
@@ -7387,7 +7388,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
autoincrement addressing mode, then the resulting insn
is ill-formed and we must reject this optimization. */
extract_insn (temp);
- if (constrain_operands (1, get_enabled_alternatives (temp))
+ if (constrain_operands (1, get_enabled_alternatives (temp)) >= 0
&& (!AUTO_INC_DEC || ! find_reg_note (temp, REG_INC, reloadreg)))
{
/* If the previous insn is an output reload, the source is
@@ -8571,7 +8572,7 @@ emit_insn_if_valid_for_reload (rtx pat)
/* We want constrain operands to treat this insn strictly in its
validity determination, i.e., the way it would after reload has
completed. */
- if (constrain_operands (1, get_enabled_alternatives (insn)))
+ if (constrain_operands (1, get_enabled_alternatives (insn)) >= 0)
return insn;
}
@@ -9204,7 +9205,7 @@ inc_for_reload (rtx reloadreg, rtx in, rtx value, int inc_amount)
if (code >= 0)
{
extract_insn (add_insn);
- if (constrain_operands (1, get_enabled_alternatives (add_insn)))
+ if (constrain_operands (1, get_enabled_alternatives (add_insn)) >= 0)
{
/* If this is a pre-increment and we have incremented the value
where it lives, copy the incremented value to RELOADREG to
@@ -2708,7 +2708,8 @@ fill_slots_from_thread (rtx_jump_insn *insn, rtx condition,
if (recog_memoized (ninsn) < 0
|| (extract_insn (ninsn),
- !constrain_operands (1, get_preferred_alternatives (ninsn))))
+ (constrain_operands
+ (1, get_preferred_alternatives (ninsn)) < 0)))
{
delete_related_insns (ninsn);
return;
@@ -985,11 +985,11 @@ get_reg_class (rtx_insn *insn)
{
int i, n_ops;
- extract_constrain_insn (insn);
+ int alt = extract_constrain_insn (insn);
preprocess_constraints (insn);
n_ops = recog_data.n_operands;
- const operand_alternative *op_alt = which_op_alt ();
+ const operand_alternative *op_alt = get_op_alt (alt);
if (asm_noperands (PATTERN (insn)) > 0)
{
for (i = 0; i < n_ops; i++)