Later patches in the series add a new form of attribute that takes the
attribute number as an argument, rather than it being stored in the
global which_alternative variable.

Having both a local alternative number and a global alternative number
is likely to cause confusion.  This patch therefore gets rid of the
global variable.

The main change is to get functions like constrain_operands to return
the number of the matching alternative, or -1 if none.  The cached
versions still use static state, but at least that state is now local
to recog.c and has a different name.

Tested as described in the covering note.

gcc/
        * recog.h (extract_constrain_insn): Return an int.
        (extract_constrain_insn_cached): Likewise.
        (which_alternative): Delete.
        (which_op_alt): Delete in favor of...
        (get_opt_alt): ...this new function.
        (insn_output_fn): Add an alternative number as argument.
        * recog.c (which_alternative): Delete in favor of...
        (cached_which_alternative): ...this.
        (get_bool_attr_mask_uncached): Update accordingly.
        (extract_insn): Likewise.
        (check_asm_operands): Check the return value of constrain_operands
        directly.
        (insn_invalid_p): Update check for whether constrain_operands was
        successful.
        (extract_constrain_insn): Return the matching alternative.
        (extract_constrain_insn_cached): Likewise.
        (constrain_operands_cached): Return the alternative number,
        or -1 on failure.  Use cached_which_alternative as the cache.
        (preprocess_insn_constraints): Update comment.
        (constrain_operands): Return the alternative number on success
        and -1 on failure.  Don't assign to which_alternative.
        * genattrtab.c (write_attr_case): Make which_alternative a local
        variable, set from the result of extract_constrain_insn_cached.
        * genoutput.c (process_template): Make the output functions take
        which_alternative as argument.
        * output.h (get_insn_template): Pass the alternative number too.
        Put the instruction argument first.
        * final.c (get_insn_template): Likewise.  Pass the alternative
        number down to the output function.
        (final_scan_insn): Update call accordingly.
        (output_asm_name): Use constrain_operands_cached instead of
        which_alternative.
        * postreload.c (reload_cse_simplify_operands): Use the return
        value of extract_constrain_insn instead of which_alternative.
        * config/s390/predicates.md (execute_operation): Likewise.
        * config/m68k/m68k.md (*movdf_internal, *addsi3_5200): Likewise.
        * regrename.c (hide_operands): Take the alternative number as
        argument.  Replace use of which_op_alt with get_op_alt.
        (record_out_operands): Likewise.
        (build_def_use): Update accordingly.  Also replace which_op_alt
        with get_op_alt here.
        * caller-save.c (reg_save_code): Update check for whether
        constrain_operands was successful.
        * ira.c (setup_prohibited_mode_move_regs): Likewise.
        * postreload-gcse.c (eliminate_partially_redundant_load): Likewise.
        * ree.c (combine_reaching_defs): Likewise.
        * reload.c (can_reload_into): Likewise.
        * reload1.c (reload): Likewise.
        (reload_as_needed): Likewise.
        (gen_reload_chain_without_interm_reg_p): Likewise.
        (emit_input_reload_insns): Likewise.
        (emit_insn_if_valid_for_reload): Likewise.
        (inc_for_reload): Likewise.
        * reorg.c (fill_slots_from_thread): Likewise.
        * config/pa/pa.c (pa_can_combine_p): Likewise.
        * config/rl78/rl78.c (insn_ok_now): Likewise.
        * config/alpha/alpha.c (alpha_end_function): Update call to
        get_insn_template.
        * config/rs6000/rs6000.c (rs6000_final_prescan_insn): Likewise.
        * reg-stack.c (check_asm_stack_operands): Replace use of
        which_op_alt with get_op_alt.
        (subst_asm_stack_regs): Likewise.
        * regcprop.c (copyprop_hardreg_forward_1): Likewise.
        * sel-sched.c (get_reg_class): Likewise.
        * config/arm/arm.c (note_invalid_constants): Likewise.
        * config/i386/i386.c (ix86_attr_length_address_default): Remove
        use of global which_alternative.
        (ix86_mitigate_rop): Replace use of which_op_alt with get_op_alt.
        * config/sparc/sparc-protos.h (output_v8plus_shift)
        (output_v8plus_mult): Add which_alternative argument.
        * config/sparc/sparc.c (output_v8plus_shift, output_v8plus_mult):
        Likewise.
        * config/sparc/sparc.md (muldi3_v8plus, umulxhi_v8plus, xmulx_v8plus)
        (xmulxhi_v8plus, ashldi3_v8plus, ashrdi3_v8plus, lshrdi3_v8plus):
        Update accordingly.
        * config/vax/vax-protos.h (vax_output_int_add): Add an alternative
        number as argument.
        (vax_output_int_subtract): Likewise.
        * config/vax/vax.c (vax_output_int_add): Update accordingly.
        (vax_output_int_subtract): Likewise.  Update calls to
        get_insn_template.
        * config/vax/vax.md (add<mode>3, adcdi3, adddi3_old, sbcdi3)
        (subdi3_old): Update accordingly.

diff --git a/gcc/caller-save.c b/gcc/caller-save.c
index 084d079..5a648c1 100644
--- a/gcc/caller-save.c
+++ b/gcc/caller-save.c
@@ -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)
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 4cfae82..a85c836 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -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.  */
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index e0cdc20..ae3bfee 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -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.  */
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index cc42544..e81a368 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -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))
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 1eaf58f..1c7309b 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -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)
diff --git a/gcc/config/pa/pa.c b/gcc/config/pa/pa.c
index b8caab5..4b5d275 100644
--- a/gcc/config/pa/pa.c
+++ b/gcc/config/pa/pa.c
@@ -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)
diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c
index 9d136a4..f44dc3b 100644
--- a/gcc/config/rl78/rl78.c
+++ b/gcc/config/rl78/rl78.c
@@ -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;
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 457e9442..44f2075 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -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,
diff --git a/gcc/config/s390/predicates.md b/gcc/config/s390/predicates.md
index 893092b..0718028 100644
--- a/gcc/config/s390/predicates.md
+++ b/gcc/config/s390/predicates.md
@@ -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
diff --git a/gcc/config/sparc/sparc-protos.h b/gcc/config/sparc/sparc-protos.h
index 1431437..39c2909 100644
--- a/gcc/config/sparc/sparc-protos.h
+++ b/gcc/config/sparc/sparc-protos.h
@@ -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 *);
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index 9328723..c0bb126 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -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];
 
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 9cc74f1..5c32689 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -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")])
 
diff --git a/gcc/config/vax/vax-protos.h b/gcc/config/vax/vax-protos.h
index b9d0e5d..bf5347d 100644
--- a/gcc/config/vax/vax-protos.h
+++ b/gcc/config/vax/vax-protos.h
@@ -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 */
 
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index c059751..f323bf9 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -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:
diff --git a/gcc/config/vax/vax.md b/gcc/config/vax/vax.md
index d5caa15..8ac4663 100644
--- a/gcc/config/vax/vax.md
+++ b/gcc/config/vax/vax.md
@@ -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.
 
diff --git a/gcc/final.c b/gcc/final.c
index 2f57b1b..1a081e8 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -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]",
diff --git a/gcc/genattrtab.c b/gcc/genattrtab.c
index 2caf8f6..36fdf8b 100644
--- a/gcc/genattrtab.c
+++ b/gcc/genattrtab.c
@@ -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");
 }
 
diff --git a/gcc/genoutput.c b/gcc/genoutput.c
index ed9540d..d2e7dbc 100644
--- a/gcc/genoutput.c
+++ b/gcc/genoutput.c
@@ -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    {");
        }
diff --git a/gcc/ira.c b/gcc/ira.c
index 97edf8c..eae63a4 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -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);
        }
diff --git a/gcc/output.h b/gcc/output.h
index d485cd6..27c8df9 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -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.  */
 
diff --git a/gcc/postreload-gcse.c b/gcc/postreload-gcse.c
index f8a770e..d63e7969 100644
--- a/gcc/postreload-gcse.c
+++ b/gcc/postreload-gcse.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))
            {
diff --git a/gcc/postreload.c b/gcc/postreload.c
index 1186bc0..f8df2d7 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -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;
 
diff --git a/gcc/recog.c b/gcc/recog.c
index 028190a..04228f8 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -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)
diff --git a/gcc/recog.h b/gcc/recog.h
index 327d6c0..b15140b 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -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
 {
diff --git a/gcc/ree.c b/gcc/ree.c
index f3b79e0..c641ba7 100644
--- a/gcc/ree.c
+++ b/gcc/ree.c
@@ -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;
     }
 
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index 8cc0fa4..be9e1b2 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -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);
 
diff --git a/gcc/regcprop.c b/gcc/regcprop.c
index f0723a1..833fe6c 100644
--- a/gcc/regcprop.c
+++ b/gcc/regcprop.c
@@ -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);
                }
            }
        }
diff --git a/gcc/regrename.c b/gcc/regrename.c
index e2a1e83..4f223ab 100644
--- a/gcc/regrename.c
+++ b/gcc/regrename.c
@@ -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.  */
diff --git a/gcc/reload.c b/gcc/reload.c
index 1e96dfc..c41a7b1 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -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;
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 4f1910b..92a0050 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -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
diff --git a/gcc/reorg.c b/gcc/reorg.c
index cc68d6b..96a6a97 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -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;
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index aebc2d9..f4966ee 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -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++)

Reply via email to