diff mbox

[2/5] Add preferred_for_{size,speed} attributes

Message ID 87zjcuah0u.fsf@e105548-lin.cambridge.arm.com
State New
Headers show

Commit Message

Richard Sandiford Oct. 17, 2014, 2:48 p.m. UTC
This is the main patch, to add new preferred_for_size and
preferred_for_speed attributes that can be used to selectively disable
alternatives when optimising for size or speed.  As explained in the
docs, the new attributes are just optimisation hints and it is possible
that "size-only" alternatives will sometimes end up in a block that's
optimised for speed, or vice versa.

The patch deals with code that directly accesses the enabled_attributes
mask and that ought to take size/speed choices into account.  The next
patch deals with indirect uses.  Note that I'm not making reload support
these attributes for hopefully obvious reasons :-)

Richard


gcc/
	* doc/md.texi: Document "preferred_for_size" and "preferred_for_speed"
	attributes.
	* genattr.c (main): Handle "preferred_for_size" and
	"preferred_for_speed" in the same way as "enabled".
	* recog.h (bool_attr): New enum.
	(target_recog): Replace x_enabled_alternatives with x_bool_attr_masks.
	(get_preferred_alternatives, check_bool_attrs): Declare.
	* recog.c (have_bool_attr, get_bool_attr, get_bool_attr_mask_uncached)
	(get_bool_attr_mask, get_preferred_alternatives, check_bool_attrs):
	New functions.
	(get_enabled_alternatives): Use get_bool_attr_mask.
	* ira-costs.c (record_reg_classes): Use get_preferred_alternatives
	instead of recog_data.enabled_alternatives.
	* ira.c (ira_setup_alts): Likewise.
	* postreload.c (reload_cse_simplify_operands): Likewise.
	* config/i386/i386.c (ix86_legitimate_combined_insn): Likewise.
	* ira-lives.c (preferred_alternatives): New variable.
	(process_bb_node_lives): Set it.
	(check_and_make_def_conflict, make_early_clobber_and_input_conflicts)
	(single_reg_class, ira_implicitly_set_insn_hard_regs): Use it instead
	of recog_data.enabled_alternatives.
	* lra-int.h (lra_insn_recog_data): Replace enabled_alternatives
	to preferred_alternatives.
	* lra-constraints.c (process_alt_operands): Update accordingly.
	* lra.c (lra_set_insn_recog_data): Likewise.
	(lra_update_insn_recog_data): Assert check_bool_attrs.

Comments

Vladimir Makarov Oct. 21, 2014, 2:56 p.m. UTC | #1
On 10/17/2014 10:48 AM, Richard Sandiford wrote:
> This is the main patch, to add new preferred_for_size and
> preferred_for_speed attributes that can be used to selectively disable
> alternatives when optimising for size or speed.  As explained in the
> docs, the new attributes are just optimisation hints and it is possible
> that "size-only" alternatives will sometimes end up in a block that's
> optimised for speed, or vice versa.
>
> The patch deals with code that directly accesses the enabled_attributes
> mask and that ought to take size/speed choices into account.  The next
> patch deals with indirect uses.  Note that I'm not making reload support
> these attributes for hopefully obvious reasons :-)
>
> Richard
>
>
> gcc/
> 	* doc/md.texi: Document "preferred_for_size" and "preferred_for_speed"
> 	attributes.
> 	* genattr.c (main): Handle "preferred_for_size" and
> 	"preferred_for_speed" in the same way as "enabled".
> 	* recog.h (bool_attr): New enum.
> 	(target_recog): Replace x_enabled_alternatives with x_bool_attr_masks.
> 	(get_preferred_alternatives, check_bool_attrs): Declare.
> 	* recog.c (have_bool_attr, get_bool_attr, get_bool_attr_mask_uncached)
> 	(get_bool_attr_mask, get_preferred_alternatives, check_bool_attrs):
> 	New functions.
> 	(get_enabled_alternatives): Use get_bool_attr_mask.
> 	* ira-costs.c (record_reg_classes): Use get_preferred_alternatives
> 	instead of recog_data.enabled_alternatives.
> 	* ira.c (ira_setup_alts): Likewise.
> 	* postreload.c (reload_cse_simplify_operands): Likewise.
> 	* config/i386/i386.c (ix86_legitimate_combined_insn): Likewise.
> 	* ira-lives.c (preferred_alternatives): New variable.
> 	(process_bb_node_lives): Set it.
> 	(check_and_make_def_conflict, make_early_clobber_and_input_conflicts)
> 	(single_reg_class, ira_implicitly_set_insn_hard_regs): Use it instead
> 	of recog_data.enabled_alternatives.
> 	* lra-int.h (lra_insn_recog_data): Replace enabled_alternatives
> 	to preferred_alternatives.
> 	* lra-constraints.c (process_alt_operands): Update accordingly.
> 	* lra.c (lra_set_insn_recog_data): Likewise.
> 	(lra_update_insn_recog_data): Assert check_bool_attrs.
>
>
Thanks for picking this up and making a systematic solution, Richard. 
All  RA-related changes are ok for me.  I guess other changes
(genattrr.c, recog.[ch], md.texi and i386.c) are obvious but I have no
power to approve them.
Jeff Law Oct. 21, 2014, 5:28 p.m. UTC | #2
On 10/17/14 14:48, Richard Sandiford wrote:
> This is the main patch, to add new preferred_for_size and
> preferred_for_speed attributes that can be used to selectively disable
> alternatives when optimising for size or speed.  As explained in the
> docs, the new attributes are just optimisation hints and it is possible
> that "size-only" alternatives will sometimes end up in a block that's
> optimised for speed, or vice versa.
>
> The patch deals with code that directly accesses the enabled_attributes
> mask and that ought to take size/speed choices into account.  The next
> patch deals with indirect uses.  Note that I'm not making reload support
> these attributes for hopefully obvious reasons :-)
>
> Richard
>
>
> gcc/
> 	* doc/md.texi: Document "preferred_for_size" and "preferred_for_speed"
> 	attributes.
> 	* genattr.c (main): Handle "preferred_for_size" and
> 	"preferred_for_speed" in the same way as "enabled".
> 	* recog.h (bool_attr): New enum.
> 	(target_recog): Replace x_enabled_alternatives with x_bool_attr_masks.
> 	(get_preferred_alternatives, check_bool_attrs): Declare.
> 	* recog.c (have_bool_attr, get_bool_attr, get_bool_attr_mask_uncached)
> 	(get_bool_attr_mask, get_preferred_alternatives, check_bool_attrs):
> 	New functions.
> 	(get_enabled_alternatives): Use get_bool_attr_mask.
> 	* ira-costs.c (record_reg_classes): Use get_preferred_alternatives
> 	instead of recog_data.enabled_alternatives.
> 	* ira.c (ira_setup_alts): Likewise.
> 	* postreload.c (reload_cse_simplify_operands): Likewise.
> 	* config/i386/i386.c (ix86_legitimate_combined_insn): Likewise.
> 	* ira-lives.c (preferred_alternatives): New variable.
> 	(process_bb_node_lives): Set it.
> 	(check_and_make_def_conflict, make_early_clobber_and_input_conflicts)
> 	(single_reg_class, ira_implicitly_set_insn_hard_regs): Use it instead
> 	of recog_data.enabled_alternatives.
> 	* lra-int.h (lra_insn_recog_data): Replace enabled_alternatives
> 	to preferred_alternatives.
> 	* lra-constraints.c (process_alt_operands): Update accordingly.
> 	* lra.c (lra_set_insn_recog_data): Likewise.
> 	(lra_update_insn_recog_data): Assert check_bool_attrs.
>
OK for the trunk.

THanks,
Jeff
H.J. Lu Aug. 3, 2015, 2:53 p.m. UTC | #3
On Fri, Oct 17, 2014 at 7:48 AM, Richard Sandiford
<richard.sandiford@arm.com> wrote:
> This is the main patch, to add new preferred_for_size and
> preferred_for_speed attributes that can be used to selectively disable
> alternatives when optimising for size or speed.  As explained in the
> docs, the new attributes are just optimisation hints and it is possible
> that "size-only" alternatives will sometimes end up in a block that's
> optimised for speed, or vice versa.
>
> The patch deals with code that directly accesses the enabled_attributes
> mask and that ought to take size/speed choices into account.  The next
> patch deals with indirect uses.  Note that I'm not making reload support
> these attributes for hopefully obvious reasons :-)
>
> Richard
>
>
> gcc/
>         * doc/md.texi: Document "preferred_for_size" and "preferred_for_speed"
>         attributes.
>         * genattr.c (main): Handle "preferred_for_size" and
>         "preferred_for_speed" in the same way as "enabled".
>         * recog.h (bool_attr): New enum.
>         (target_recog): Replace x_enabled_alternatives with x_bool_attr_masks.
>         (get_preferred_alternatives, check_bool_attrs): Declare.
>         * recog.c (have_bool_attr, get_bool_attr, get_bool_attr_mask_uncached)
>         (get_bool_attr_mask, get_preferred_alternatives, check_bool_attrs):
>         New functions.
>         (get_enabled_alternatives): Use get_bool_attr_mask.
>         * ira-costs.c (record_reg_classes): Use get_preferred_alternatives
>         instead of recog_data.enabled_alternatives.
>         * ira.c (ira_setup_alts): Likewise.
>         * postreload.c (reload_cse_simplify_operands): Likewise.
>         * config/i386/i386.c (ix86_legitimate_combined_insn): Likewise.
>         * ira-lives.c (preferred_alternatives): New variable.
>         (process_bb_node_lives): Set it.
>         (check_and_make_def_conflict, make_early_clobber_and_input_conflicts)
>         (single_reg_class, ira_implicitly_set_insn_hard_regs): Use it instead
>         of recog_data.enabled_alternatives.
>         * lra-int.h (lra_insn_recog_data): Replace enabled_alternatives
>         to preferred_alternatives.
>         * lra-constraints.c (process_alt_operands): Update accordingly.
>         * lra.c (lra_set_insn_recog_data): Likewise.
>         (lra_update_insn_recog_data): Assert check_bool_attrs.
>

This caused:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67029
diff mbox

Patch

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;
 }