Index: gcc/doc/md.texi
===================================================================
--- gcc/doc/md.texi	2014-10-07 13:12:12.227445290 +0100
+++ gcc/doc/md.texi	2014-10-17 15:47:34.349453560 +0100
@@ -1080,7 +1080,7 @@ the addressing register.
 * Class Preferences::   Constraints guide which hard register to put things in.
 * Modifiers::           More precise control over effects of constraints.
 * Machine Constraints:: Existing constraints for some particular machines.
-* Disable Insn Alternatives:: Disable insn alternatives using the @code{enabled} attribute.
+* Disable Insn Alternatives:: Disable insn alternatives using attributes.
 * Define Constraints::  How to define machine-specific constraints.
 * C Constraint Interface:: How to test constraints from C code.
 @end menu
@@ -4006,42 +4006,49 @@ Unsigned constant valid for BccUI instru
 @subsection Disable insn alternatives using the @code{enabled} attribute
 @cindex enabled
 
-The @code{enabled} insn attribute may be used to disable insn
-alternatives that are not available for the current subtarget.
-This is useful when adding new instructions to an existing pattern
-which are only available for certain cpu architecture levels as
-specified with the @code{-march=} option.
-
-If an insn alternative is disabled, then it will never be used.  The
-compiler treats the constraints for the disabled alternative as
-unsatisfiable.
+There are three insn attributes that may be used to selectively disable
+instruction alternatives:
 
-In order to make use of the @code{enabled} attribute a back end has to add
-in the machine description files:
+@table @code
+@item enabled
+Says whether an alternative is available on the current subtarget.
 
-@enumerate
-@item
-A definition of the @code{enabled} insn attribute.  The attribute is
-defined as usual using the @code{define_attr} command.  This
-definition should be based on other insn attributes and/or target flags.
-The attribute must be a static property of the subtarget; that is, it
-must not depend on the current operands or any other dynamic context
-(for example, the location of the insn within the body of a loop).
-
-The @code{enabled} attribute is a numeric attribute and should evaluate to
-@code{(const_int 1)} for an enabled alternative and to
-@code{(const_int 0)} otherwise.
-@item
-A definition of another insn attribute used to describe for what
-reason an insn alternative might be available or
-not.  E.g. @code{cpu_facility} as in the example below.
-@item
-An assignment for the second attribute to each insn definition
-combining instructions which are not all available under the same
-circumstances.  (Note: It obviously only makes sense for definitions
-with more than one alternative.  Otherwise the insn pattern should be
-disabled or enabled using the insn condition.)
-@end enumerate
+@item preferred_for_size
+Says whether an enabled alternative should be used in code that is
+optimized for size.
+
+@item preferred_for_speed
+Says whether an enabled alternative should be used in code that is
+optimized for speed.
+@end table
+
+All these attributes should use @code{(const_int 1)} to allow an alternative
+or @code{(const_int 0)} to disallow it.  The attributes must be a static
+property of the subtarget; they cannot for example depend on the
+current operands, on the current optimization level, on the location
+of the insn within the body of a loop, on whether register allocation
+has finished, or on the current compiler pass.
+
+The @code{enabled} attribute is a correctness property.  It tells GCC to act
+as though the disabled alternatives were never defined in the first place.
+This is useful when adding new instructions to an existing pattern in
+cases where the new instructions are only available for certain cpu
+architecture levels (typically mapped to the @code{-march=} command-line
+option).
+
+In contrast, the @code{preferred_for_size} and @code{preferred_for_speed}
+attributes are strong optimization hints rather than correctness properties.
+@code{preferred_for_size} tells GCC which alternatives to consider when
+adding or modifying an instruction that GCC wants to optimize for size.
+@code{preferred_for_speed} does the same thing for speed.  Note that things
+like code motion can lead to cases where code optimized for size uses
+alternatives that are not preferred for size, and similarly for speed.
+
+Although @code{define_insn}s can in principle specify the @code{enabled}
+attribute directly, it is often clearer to have subsiduary attributes
+for each architectural feature of interest.  The @code{define_insn}s
+can then use these subsiduary attributes to say which alternatives
+require which features.  The example below does this for @code{cpu_facility}.
 
 E.g. the following two patterns could easily be merged using the @code{enabled}
 attribute:
Index: gcc/genattr.c
===================================================================
--- gcc/genattr.c	2014-09-18 11:40:31.195691182 +0100
+++ gcc/genattr.c	2014-10-17 15:47:34.353453512 +0100
@@ -338,7 +338,9 @@ main (int argc, char **argv)
     }
 
   /* Special-purpose attributes should be tested with if, not #ifdef.  */
-  const char * const special_attrs[] = { "length", "enabled", 0 };
+  const char * const special_attrs[] = { "length", "enabled",
+					 "preferred_for_size",
+					 "preferred_for_speed", 0 };
   for (const char * const *p = special_attrs; *p; p++)
     {
       printf ("#ifndef HAVE_ATTR_%s\n"
@@ -355,9 +357,15 @@ main (int argc, char **argv)
 	"#define insn_current_length hook_int_rtx_insn_unreachable\n"
 	"#include \"insn-addr.h\"\n"
 	"#endif\n"
-	"#if !HAVE_ATTR_enabled\n"
 	"extern int hook_int_rtx_1 (rtx);\n"
+	"#if !HAVE_ATTR_enabled\n"
 	"#define get_attr_enabled hook_int_rtx_1\n"
+	"#endif\n"
+	"#if !HAVE_ATTR_preferred_for_size\n"
+	"#define get_attr_preferred_for_size hook_int_rtx_1\n"
+	"#endif\n"
+	"#if !HAVE_ATTR_preferred_for_speed\n"
+	"#define get_attr_preferred_for_speed hook_int_rtx_1\n"
 	"#endif\n");
 
   /* Output flag masks for use by reorg.
Index: gcc/recog.h
===================================================================
--- gcc/recog.h	2014-10-17 15:44:50.219398486 +0100
+++ gcc/recog.h	2014-10-17 15:47:34.357453465 +0100
@@ -389,10 +389,19 @@ struct insn_data_d
 #ifndef GENERATOR_FILE
 #include "insn-codes.h"
 
+/* An enum of boolean attributes that may only depend on the current
+   subtarget, not on things like operands or compiler phase.  */
+enum bool_attr {
+  BA_ENABLED,
+  BA_PREFERRED_FOR_SPEED,
+  BA_PREFERRED_FOR_SIZE,
+  BA_LAST = BA_PREFERRED_FOR_SIZE
+};
+
 /* Target-dependent globals.  */
 struct target_recog {
   bool x_initialized;
-  alternative_mask x_enabled_alternatives[LAST_INSN_CODE];
+  alternative_mask x_bool_attr_masks[LAST_INSN_CODE][BA_LAST + 1];
   operand_alternative *x_op_alt[LAST_INSN_CODE];
 };
 
@@ -404,6 +413,8 @@ #define this_target_recog (&default_targ
 #endif
 
 alternative_mask get_enabled_alternatives (rtx_insn *);
+alternative_mask get_preferred_alternatives (rtx_insn *);
+bool check_bool_attrs (rtx_insn *);
 
 void recog_init ();
 #endif
Index: gcc/recog.c
===================================================================
--- gcc/recog.c	2014-10-17 15:44:50.219398486 +0100
+++ gcc/recog.c	2014-10-17 15:47:34.357453465 +0100
@@ -2055,25 +2055,46 @@ mode_dependent_address_p (rtx addr, addr
   return targetm.mode_dependent_address_p (addr, addrspace);
 }
 
-/* Return the mask of operand alternatives that are allowed for INSN.
-   This mask depends only on INSN and on the current target; it does not
-   depend on things like the values of operands.  */
+/* Return true if boolean attribute ATTR is supported.  */
 
-alternative_mask
-get_enabled_alternatives (rtx_insn *insn)
+static bool
+have_bool_attr (bool_attr attr)
 {
-  /* Quick exit for asms and for targets that don't use the "enabled"
-     attribute.  */
-  int code = INSN_CODE (insn);
-  if (code < 0 || !HAVE_ATTR_enabled)
-    return ALL_ALTERNATIVES;
+  switch (attr)
+    {
+    case BA_ENABLED:
+      return HAVE_ATTR_enabled;
+    case BA_PREFERRED_FOR_SIZE:
+      return HAVE_ATTR_enabled || HAVE_ATTR_preferred_for_size;
+    case BA_PREFERRED_FOR_SPEED:
+      return HAVE_ATTR_enabled || HAVE_ATTR_preferred_for_speed;
+    }
+  gcc_unreachable ();
+}
 
-  /* Calling get_attr_enabled can be expensive, so cache the mask
-     for speed.  */
-  if (this_target_recog->x_enabled_alternatives[code])
-    return this_target_recog->x_enabled_alternatives[code];
+/* Return the value of ATTR for instruction INSN.  */
 
-  /* Temporarily install enough information for get_attr_enabled to assume
+static bool
+get_bool_attr (rtx_insn *insn, bool_attr attr)
+{
+  switch (attr)
+    {
+    case BA_ENABLED:
+      return get_attr_enabled (insn);
+    case BA_PREFERRED_FOR_SIZE:
+      return get_attr_enabled (insn) && get_attr_preferred_for_size (insn);
+    case BA_PREFERRED_FOR_SPEED:
+      return get_attr_enabled (insn) && get_attr_preferred_for_speed (insn);
+    }
+  gcc_unreachable ();
+}
+
+/* Like get_bool_attr_mask, but don't use the cache.  */
+
+static alternative_mask
+get_bool_attr_mask_uncached (rtx_insn *insn, bool_attr attr)
+{
+  /* Temporarily install enough information for get_attr_<foo> to assume
      that the insn operands are already cached.  As above, the attribute
      mustn't depend on the values of operands, so we don't provide their
      real values here.  */
@@ -2081,20 +2102,81 @@ get_enabled_alternatives (rtx_insn *insn
   int old_alternative = which_alternative;
 
   recog_data.insn = insn;
-  alternative_mask enabled = ALL_ALTERNATIVES;
-  int n_alternatives = insn_data[code].n_alternatives;
+  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;
-      if (!get_attr_enabled (insn))
-	enabled &= ~ALTERNATIVE_BIT (i);
+      if (!get_bool_attr (insn, attr))
+	mask &= ~ALTERNATIVE_BIT (i);
     }
 
   recog_data.insn = old_insn;
   which_alternative = old_alternative;
+  return mask;
+}
+
+/* Return the mask of operand alternatives that are allowed for INSN
+   by boolean attribute ATTR.  This mask depends only on INSN and on
+   the current target; it does not depend on things like the values of
+   operands.  */
+
+static alternative_mask
+get_bool_attr_mask (rtx_insn *insn, bool_attr attr)
+{
+  /* Quick exit for asms and for targets that don't use these attributes.  */
+  int code = INSN_CODE (insn);
+  if (code < 0 || !have_bool_attr (attr))
+    return ALL_ALTERNATIVES;
 
-  this_target_recog->x_enabled_alternatives[code] = enabled;
-  return enabled;
+  /* Calling get_attr_<foo> can be expensive, so cache the mask
+     for speed.  */
+  if (!this_target_recog->x_bool_attr_masks[code][attr])
+    this_target_recog->x_bool_attr_masks[code][attr]
+      = get_bool_attr_mask_uncached (insn, attr);
+  return this_target_recog->x_bool_attr_masks[code][attr];
+}
+
+/* Return the set of alternatives of INSN that are allowed by the current
+   target.  */
+
+alternative_mask
+get_enabled_alternatives (rtx_insn *insn)
+{
+  return get_bool_attr_mask (insn, BA_ENABLED);
+}
+
+/* Return the set of alternatives of INSN that are allowed by the current
+   target and are preferred for the current size/speed optimization
+   choice.  */
+
+alternative_mask
+get_preferred_alternatives (rtx_insn *insn)
+{
+  if (optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)))
+    return get_bool_attr_mask (insn, BA_PREFERRED_FOR_SPEED);
+  else
+    return get_bool_attr_mask (insn, BA_PREFERRED_FOR_SIZE);
+}
+
+/* Assert that the cached boolean attributes for INSN are still accurate.
+   The backend is required to define these attributes in a way that only
+   depends on the current target (rather than operands, compiler phase,
+   etc.).  */
+
+bool
+check_bool_attrs (rtx_insn *insn)
+{
+  int code = INSN_CODE (insn);
+  if (code >= 0)
+    for (int i = 0; i <= BA_LAST; ++i)
+      {
+	enum bool_attr attr = (enum bool_attr) i;
+	if (this_target_recog->x_bool_attr_masks[code][attr])
+	  gcc_assert (this_target_recog->x_bool_attr_masks[code][attr]
+		      == get_bool_attr_mask_uncached (insn, attr));
+      }
+  return true;
 }
 
 /* Like extract_insn, but save insn extracted and don't extract again, when
@@ -4043,8 +4125,8 @@ recog_init ()
       this_target_recog->x_initialized = true;
       return;
     }
-  memset (this_target_recog->x_enabled_alternatives, 0,
-	  sizeof (this_target_recog->x_enabled_alternatives));
+  memset (this_target_recog->x_bool_attr_masks, 0,
+	  sizeof (this_target_recog->x_bool_attr_masks));
   for (int i = 0; i < LAST_INSN_CODE; ++i)
     if (this_target_recog->x_op_alt[i])
       {
Index: gcc/ira-costs.c
===================================================================
--- gcc/ira-costs.c	2014-10-03 11:09:08.000000000 +0100
+++ gcc/ira-costs.c	2014-10-17 15:47:34.353453512 +0100
@@ -416,6 +416,7 @@ record_reg_classes (int n_alts, int n_op
 
   /* Process each alternative, each time minimizing an operand's cost
      with the cost for each operand in that alternative.  */
+  alternative_mask preferred = get_preferred_alternatives (insn);
   for (alt = 0; alt < n_alts; alt++)
     {
       enum reg_class classes[MAX_RECOG_OPERANDS];
@@ -424,7 +425,7 @@ record_reg_classes (int n_alts, int n_op
       int alt_fail = 0;
       int alt_cost = 0, op_cost_add;
 
-      if (!TEST_BIT (recog_data.enabled_alternatives, alt))
+      if (!TEST_BIT (preferred, alt))
 	{
 	  for (i = 0; i < recog_data.n_operands; i++)
 	    constraints[i] = skip_alternative (constraints[i]);
Index: gcc/ira.c
===================================================================
--- gcc/ira.c	2014-10-13 08:02:40.953138663 +0100
+++ gcc/ira.c	2014-10-17 15:47:34.353453512 +0100
@@ -1783,6 +1783,7 @@ ira_setup_alts (rtx_insn *insn, HARD_REG
   int commutative = -1;
 
   extract_insn (insn);
+  alternative_mask preferred = get_preferred_alternatives (insn);
   CLEAR_HARD_REG_SET (alts);
   insn_constraints.release ();
   insn_constraints.safe_grow_cleared (recog_data.n_operands
@@ -1812,7 +1813,7 @@ ira_setup_alts (rtx_insn *insn, HARD_REG
 	}
       for (nalt = 0; nalt < recog_data.n_alternatives; nalt++)
 	{
-	  if (!TEST_BIT (recog_data.enabled_alternatives, nalt)
+	  if (!TEST_BIT (preferred, nalt)
 	      || TEST_HARD_REG_BIT (alts, nalt))
 	    continue;
 
Index: gcc/postreload.c
===================================================================
--- gcc/postreload.c	2014-10-17 15:44:50.219398486 +0100
+++ gcc/postreload.c	2014-10-17 15:47:34.357453465 +0100
@@ -493,6 +493,7 @@ reload_cse_simplify_operands (rtx_insn *
 	  SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc));
     }
 
+  alternative_mask preferred = get_preferred_alternatives (insn);
   for (i = 0; i < recog_data.n_operands; i++)
     {
       enum machine_mode mode;
@@ -566,7 +567,7 @@ reload_cse_simplify_operands (rtx_insn *
 		     alternative yet and the operand being replaced is not
 		     a cheap CONST_INT.  */
 		  if (op_alt_regno[i][j] == -1
-		      && TEST_BIT (recog_data.enabled_alternatives, j)
+		      && TEST_BIT (preferred, j)
 		      && reg_fits_class_p (testreg, rclass, 0, mode)
 		      && (!CONST_INT_P (recog_data.operand[i])
 			  || (set_src_cost (recog_data.operand[i],
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	2014-10-13 08:02:40.985138241 +0100
+++ gcc/config/i386/i386.c	2014-10-17 15:47:34.349453560 +0100
@@ -5901,10 +5901,10 @@ ix86_legitimate_combined_insn (rtx_insn
 	  /* Operand has no constraints, anything is OK.  */
  	  win = !n_alternatives;
 
-	  alternative_mask enabled = recog_data.enabled_alternatives;
+	  alternative_mask preferred = get_preferred_alternatives (insn);
 	  for (j = 0; j < n_alternatives; j++, op_alt += n_operands)
 	    {
-	      if (!TEST_BIT (enabled, j))
+	      if (!TEST_BIT (preferred, j))
 		continue;
 	      if (op_alt[i].anything_ok
 		  || (op_alt[i].matches != -1
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c	2014-09-22 08:36:24.217790119 +0100
+++ gcc/ira-lives.c	2014-10-17 15:47:34.353453512 +0100
@@ -85,6 +85,10 @@ Software Foundation; either version 3, o
 /* The number of last call at which given allocno was saved.  */
 static int *allocno_saved_at_call;
 
+/* The value of get_preferred_alternatives for the current instruction,
+   supplemental to recog_data.  */
+static alternative_mask preferred_alternatives;
+
 /* Record the birth of hard register REGNO, updating hard_regs_live and
    hard reg conflict information for living allocnos.  */
 static void
@@ -641,10 +645,9 @@ check_and_make_def_conflict (int alt, in
       /* If there's any alternative that allows USE to match DEF, do not
 	 record a conflict.  If that causes us to create an invalid
 	 instruction due to the earlyclobber, reload must fix it up.  */
-      alternative_mask enabled = recog_data.enabled_alternatives;
       for (alt1 = 0; alt1 < recog_data.n_alternatives; alt1++)
 	{
-	  if (!TEST_BIT (enabled, alt1))
+	  if (!TEST_BIT (preferred_alternatives, alt1))
 	    continue;
 	  const operand_alternative *op_alt1
 	    = &recog_op_alt[alt1 * n_operands];
@@ -692,10 +695,9 @@ make_early_clobber_and_input_conflicts (
 
   int n_alternatives = recog_data.n_alternatives;
   int n_operands = recog_data.n_operands;
-  alternative_mask enabled = recog_data.enabled_alternatives;
   const operand_alternative *op_alt = recog_op_alt;
   for (alt = 0; alt < n_alternatives; alt++, op_alt += n_operands)
-    if (TEST_BIT (enabled, alt))
+    if (TEST_BIT (preferred_alternatives, alt))
       for (def = 0; def < n_operands; def++)
 	{
 	  def_cl = NO_REGS;
@@ -762,13 +764,13 @@ single_reg_class (const char *constraint
   enum constraint_num cn;
 
   cl = NO_REGS;
-  alternative_mask enabled = recog_data.enabled_alternatives;
+  alternative_mask preferred = preferred_alternatives;
   for (; (c = *constraints); constraints += CONSTRAINT_LEN (c, constraints))
     if (c == '#')
-      enabled &= ~ALTERNATIVE_BIT (0);
+      preferred &= ~ALTERNATIVE_BIT (0);
     else if (c == ',')
-      enabled >>= 1;
-    else if (enabled & 1)
+      preferred >>= 1;
+    else if (preferred & 1)
       switch (c)
 	{
 	case 'g':
@@ -851,13 +853,13 @@ ira_implicitly_set_insn_hard_regs (HARD_
 	  mode = (GET_CODE (op) == SCRATCH
 		  ? GET_MODE (op) : PSEUDO_REGNO_MODE (regno));
 	  cl = NO_REGS;
-	  alternative_mask enabled = recog_data.enabled_alternatives;
+	  alternative_mask preferred = preferred_alternatives;
 	  for (; (c = *p); p += CONSTRAINT_LEN (c, p))
 	    if (c == '#')
-	      enabled &= ~ALTERNATIVE_BIT (0);
+	      preferred &= ~ALTERNATIVE_BIT (0);
 	    else if (c == ',')
-	      enabled >>= 1;
-	    else if (enabled & 1)
+	      preferred >>= 1;
+	    else if (preferred & 1)
 	      {
 		cl = reg_class_for_constraint (lookup_constraint (p));
 		if (cl != NO_REGS)
@@ -1174,6 +1176,7 @@ process_bb_node_lives (ira_loop_tree_nod
 	      }
 
 	  extract_insn (insn);
+	  preferred_alternatives = get_preferred_alternatives (insn);
 	  preprocess_constraints (insn);
 	  process_single_reg_class_operands (false, freq);
 
Index: gcc/lra-int.h
===================================================================
--- gcc/lra-int.h	2014-09-22 08:36:23.153803537 +0100
+++ gcc/lra-int.h	2014-10-17 15:47:34.357453465 +0100
@@ -233,8 +233,8 @@ struct lra_insn_recog_data
      value can be NULL or points to array of the hard register numbers
      ending with a negative value.  */
   int *arg_hard_regs;
-  /* Alternative enabled for the insn.	NULL for debug insns.  */
-  alternative_mask enabled_alternatives;
+  /* Cached value of get_preferred_alternatives.  */
+  alternative_mask preferred_alternatives;
   /* The following member value is always NULL for a debug insn.  */
   struct lra_insn_reg *regs;
 };
Index: gcc/lra-constraints.c
===================================================================
--- gcc/lra-constraints.c	2014-10-03 11:05:47.521106593 +0100
+++ gcc/lra-constraints.c	2014-10-17 15:47:34.357453465 +0100
@@ -1680,14 +1680,14 @@ process_alt_operands (int only_alternati
      together, the second alternatives go together, etc.
 
      First loop over alternatives.  */
-  alternative_mask enabled = curr_id->enabled_alternatives;
+  alternative_mask preferred = curr_id->preferred_alternatives;
   if (only_alternative >= 0)
-    enabled &= ALTERNATIVE_BIT (only_alternative);
+    preferred &= ALTERNATIVE_BIT (only_alternative);
 
   for (nalt = 0; nalt < n_alternatives; nalt++)
     {
       /* Loop over operands for one constraint alternative.  */
-      if (!TEST_BIT (enabled, nalt))
+      if (!TEST_BIT (preferred, nalt))
 	continue;
 
       overall = losers = reject = reload_nregs = reload_sum = 0;
Index: gcc/lra.c
===================================================================
--- gcc/lra.c	2014-10-17 15:44:50.219398486 +0100
+++ gcc/lra.c	2014-10-17 15:47:34.357453465 +0100
@@ -917,7 +917,7 @@ lra_set_insn_recog_data (rtx_insn *insn)
       data->insn_static_data = &debug_insn_static_data;
       data->dup_loc = NULL;
       data->arg_hard_regs = NULL;
-      data->enabled_alternatives = ALL_ALTERNATIVES;
+      data->preferred_alternatives = ALL_ALTERNATIVES;
       data->operand_loc = XNEWVEC (rtx *, 1);
       data->operand_loc[0] = &INSN_VAR_LOCATION_LOC (insn);
       return data;
@@ -977,7 +977,7 @@ lra_set_insn_recog_data (rtx_insn *insn)
 	  = (insn_static_data->operand[i].constraint[0] == '=' ? OP_OUT
 	     : insn_static_data->operand[i].constraint[0] == '+' ? OP_INOUT
 	     : OP_IN);
-      data->enabled_alternatives = ALL_ALTERNATIVES;
+      data->preferred_alternatives = ALL_ALTERNATIVES;
       if (nop > 0)
 	{
 	  operand_alternative *op_alt = XCNEWVEC (operand_alternative,
@@ -1011,7 +1011,7 @@ lra_set_insn_recog_data (rtx_insn *insn)
 	  memcpy (locs, recog_data.dup_loc, n * sizeof (rtx *));
 	}
       data->dup_loc = locs;
-      data->enabled_alternatives = get_enabled_alternatives (insn);
+      data->preferred_alternatives = get_preferred_alternatives (insn);
       const operand_alternative *op_alt = preprocess_insn_constraints (icode);
       if (!insn_static_data->operand_alternative)
 	setup_operand_alternative (data, op_alt);
@@ -1202,27 +1202,7 @@ lra_update_insn_recog_data (rtx_insn *in
       n = insn_static_data->n_dups;
       if (n != 0)
 	memcpy (data->dup_loc, recog_data.dup_loc, n * sizeof (rtx *));
-#if HAVE_ATTR_enabled
-#ifdef ENABLE_CHECKING
-      {
-	int i;
-	alternative_mask enabled;
-
-	n = insn_static_data->n_alternatives;
-	enabled = data->enabled_alternatives;
-	lra_assert (n >= 0);
-	/* Cache the insn to prevent extract_insn call from
-	   get_attr_enabled.  */
-	recog_data.insn = insn;
-	for (i = 0; i < n; i++)
-	  {
-	    which_alternative = i;
-	    lra_assert (TEST_BIT (enabled, i)
-			== (bool) get_attr_enabled (insn));
-	  }
-      }
-#endif
-#endif
+      lra_assert (check_bool_attrs (insn));
     }
   return data;
 }
