diff mbox

[lra] initial support of debug info and some fixes

Message ID 4E14C30F.3030607@redhat.com
State New
Headers show

Commit Message

Vladimir Makarov July 6, 2011, 8:18 p.m. UTC
The following patch contains some of my work since the last lra patch:

o initial support of debug info in LRA.
o code size improvement for i386 (changes in register banks).
o code improvement by better reallocation of non-reload pseudos in LRA.
   by using allocno class which is usually wider than preferred class 
used before.
o a fix for IRA working with reload.  Without the fix IRA+reload 
generated much
   worse code than IRA + LRA (now IRA+reload generates the same code as 
on the
   trunk).
o restoring original x86 constraints for movzbl generation (they were 
changed to
   fix some LRA testsuite degradations).

The patch was successfully bootstrapped on x86-64, IA-64, and PPC64.

2011-07-06  Vladimir Makarov <vmakarov@redhat.com>

         * lra-assigns.c (reload_pseudo_compare_func, find_hard_regno_for):
         Use lra_get_allocno_class instead of lra_get_preferred_class.
         (spill_for, assign_by_spills): Ditto.

         * lra-constraints.c (get_try_hard_regno, get_reg_class): Use
         lra_get_allocno_class instead of lra_get_preferred_class.
         (make_early_clobber_input_reload_reg, inherit_reload_reg): Ditto.
         (inherit_in_ebb): Ditto.
         (equivalence_change_p): New function.
         (lra_constraints): Call equivalence_change_p for debug insns.

         * lra-int.h (lra_get_preferred_class): Rename to
         lra_get_allocno_class and return allocno class.
         (struct lra_reg): Add comments for members insn_bitmap, nrefs, and
         freq.
         (lra_operand_data, lra_static_insn_data): Add comment about future
         changes and debug insns.

         * lra.c (debug_operand_data, debug_insn_static_data): New
         initialized varaibles.
         (free_insn_recog_data, lra_get_insn_recog_data): Add code for
         processing debug insns.
         (lra_update_insn_recog_data, invalidate_insn_data_regno_info): 
Ditto.
         (lra_update_insn_regno_info): Ditto.

         * lra-eliminations.c (lra_eliminate_regs_1): Process asm operands
         too.
         (eliminate_regs_in_insn): Process debug insns too.

         * lra-spills.c (lra_hard_reg_substitution): Process debug insns
         too.

         * lra-equivs.c (memref_used_between_p): Process debug insns too.

         * ira.c (ira_setup_eliminable_regset): Initialize dont_use_regs
         for reload.

         * reginfo.c (allocate_reg_info, resize_reg_info): Initialize
         allocno class as GENERAL_REGS.

         * config/i386/i386.md (*anddi_1, *andsi_1, *andhi_1): Restore
         correct constraints for movzb.

         * config/i386/i386.c (ix86_register_bank): Make AX as the most
         preferable.
diff mbox

Patch

Index: lra-assigns.c
===================================================================
--- lra-assigns.c	(revision 175929)
+++ lra-assigns.c	(working copy)
@@ -78,8 +78,8 @@  static int
 reload_pseudo_compare_func (const void *v1p, const void *v2p)
 {
   int r1 = *(const int *) v1p, r2 = *(const int *) v2p;
-  enum reg_class cl1 = lra_get_preferred_class (r1);
-  enum reg_class cl2 = lra_get_preferred_class (r2);
+  enum reg_class cl1 = lra_get_allocno_class (r1);
+  enum reg_class cl2 = lra_get_allocno_class (r2);
   int diff;
   
   gcc_assert (r1 >= lra_constraint_new_regno_start
@@ -292,7 +292,7 @@  find_hard_regno_for (int regno, int *cos
   bool all_p;
 
   COPY_HARD_REG_SET (conflict_set, lra_no_alloc_regs);
-  rclass = lra_get_preferred_class (regno);
+  rclass = lra_get_allocno_class (regno);
   curr_hard_regno_costs_check++;
   sparseset_clear (conflict_reload_pseudos);
   sparseset_clear (live_range_hard_reg_pseudos);
@@ -344,7 +344,7 @@  find_hard_regno_for (int regno, int *cos
 	for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
 	  SET_HARD_REG_BIT (conflict_set, i);
 #endif
-      gcc_assert (rclass == lra_get_preferred_class (curr_regno));
+      gcc_assert (rclass == lra_get_allocno_class (curr_regno));
     }
   for (curr_regno = lra_reg_info[regno].first;
        curr_regno >= 0;
@@ -642,7 +642,7 @@  spill_for (int regno, bitmap spilled_pse
   bitmap_iterator bi, bi2;
 
   gcc_assert (lra_reg_info[regno].first == regno);
-  rclass = lra_get_preferred_class (regno);
+  rclass = lra_get_allocno_class (regno);
   gcc_assert (reg_renumber[regno] < 0 && rclass != NO_REGS);
   bitmap_clear (&ignore_pseudos_bitmap);
   bitmap_clear (&best_spill_pseudos_bitmap);
@@ -737,7 +737,7 @@  spill_for (int regno, bitmap spilled_pse
 	    if (reg_renumber[reload_regno] < 0
 		&& lra_reg_info[reload_regno].first == (int) reload_regno
 		&& (hard_reg_set_intersect_p
-		    (reg_class_contents[lra_get_preferred_class (reload_regno)],
+		    (reg_class_contents[lra_get_allocno_class (reload_regno)],
 		     spilled_hard_regs)))
 	      sorted_reload_pseudos[n++] = reload_regno;
 	  qsort (sorted_reload_pseudos, n, sizeof (int), pseudo_compare_func);
@@ -950,7 +950,7 @@  assign_by_spills (void)
   for (n = 0, i = lra_constraint_new_regno_start; i < max_reg_num (); i++)
     if (reg_renumber[i] < 0
 	&& lra_reg_info[i].nrefs != 0 && lra_reg_info[i].first == i
-	&& lra_get_preferred_class (i) != NO_REGS)
+	&& lra_get_allocno_class (i) != NO_REGS)
       sorted_pseudos[n++] = i;
   bitmap_initialize (&ignore_pseudos_bitmap, &reg_obstack);
   bitmap_initialize (&spill_pseudos_bitmap, &reg_obstack);
@@ -1040,7 +1040,7 @@  assign_by_spills (void)
 	 || bitmap_bit_p (&lra_inheritance_pseudos, i))
 	&& reg_renumber[i] < 0
 	&& lra_reg_info[i].nrefs != 0 && lra_reg_info[i].first == i
-	&& lra_get_preferred_class (i) != NO_REGS)
+	&& lra_get_allocno_class (i) != NO_REGS)
       sorted_pseudos[n++] = i;
   if (n != 0 && lra_dump_file != NULL)
     fprintf (lra_dump_file, "  Reassing non-reload pseudos\n");
Index: lra-int.h
===================================================================
--- lra-int.h	(revision 175929)
+++ lra-int.h	(working copy)
@@ -38,14 +38,14 @@  lra_get_regno_hard_regno (int regno)
   return reg_renumber[regno];
 }
 
-/* Return the preferred reg class of REGNO.  If it is a reload pseudo,
-   the pseudo should finally get hard register of the preferred
+/* Return the allocno reg class of REGNO.  If it is a reload pseudo,
+   the pseudo should finally get hard register of the allocno
    class.  */
 static inline enum reg_class
-lra_get_preferred_class (int regno)
+lra_get_allocno_class (int regno)
 {
   resize_reg_info ();
-  return reg_preferred_class (regno);
+  return reg_allocno_class (regno);
 }
 
 typedef struct lra_live_range *lra_live_range_t;
@@ -86,7 +86,8 @@  struct lra_copy
 /* Common info about a register.  */
 struct lra_reg
 {
-  /* Bitmap of UIDs of insns referring the reg.  */
+  /* Bitmap of UIDs of insns (including debug insns) referring the
+     reg.  */
   bitmap_head insn_bitmap;
   /* The following fields are defined only for pseudos.  */
   /* Hard registers with which the pseudo conflicts.  */
@@ -106,6 +107,8 @@  struct lra_reg
   /* True if the pseudo should not be assigned to a stack register.  */
   bool no_stack_p;
 #endif
+  /* Number of references and execution frequencies of the register in
+     *non-debug* insns.  */
   int nrefs, freq;
   int last_reload;
   /* That is for bound pseudos only.  */
@@ -126,7 +129,8 @@  struct lra_reg
 extern struct lra_reg *lra_reg_info;
 
 /* Static info about each insn operand (common for all insns with the
-   same ICODE).  */
+   same ICODE).  Warning: if the structure is changed, the initializer
+   for debug_operand_data in lra.c should be changed too.  */
 struct lra_operand_data
 {
   /* The machine description constraint string.  */
@@ -167,7 +171,9 @@  struct lra_insn_reg
 
 /* Static part (common info for insns with the same ICODE) of LRA
    internal insn info.  It exists in at most one exemplar for each
-   non-negative ICODE.  */
+   non-negative ICODE.  Warning: if the structure is changed, the
+   initializer for debug_insn_static_data in lra.c should be changed
+   too.  */
 struct lra_static_insn_data
 {
   /* Static info about each insn operand.  */
@@ -207,13 +213,14 @@  struct lra_insn_recog_data
      negative value.  */
   int *arg_hard_regs;
 #ifdef HAVE_ATTR_enabled
-  /* Alternative enabled for the insn.  */
+  /* Alternative enabled for the insn.  NULL for debug insns.  */
   bool *alternative_enabled_p;
 #endif
-  /* The alternative should be used for the insn, -1 if invalid or
-     we should try to use any alternative.  */
+  /* The alternative should be used for the insn, -1 if invalid, or we
+     should try to use any alternative, or the insn is a debug
+     insns.  */
   int used_insn_alternative;
-  struct lra_insn_reg *regs;
+  struct lra_insn_reg *regs;  /* Always NULL for a debug insn.  */
 };
 
 typedef struct lra_insn_recog_data *lra_insn_recog_data_t;
Index: lra.c
===================================================================
--- lra.c	(revision 175929)
+++ lra.c	(working copy)
@@ -402,6 +402,37 @@  struct lra_static_insn_data *insn_code_d
    because classes in the data can be changed.  */
 struct operand_alternative *op_alt_data[CODE_FOR_nothing];
 
+/* Debug insns are represented as a special insn with one input
+   operand which is RTL expression in var_location.  */
+
+/* The following data are used as static insn operand data for all
+   debug insns.  If structure lra_operand_data is changed, the
+   initializer should be changed too.  */
+static struct lra_operand_data debug_operand_data =
+  {
+    NULL, /* alternative.  */
+    VOIDmode, /* We are not interesting int the operand mode.  */
+    OP_IN,
+    0, 0, 0 
+  };
+
+/* The following data are used as static insn data for all debug
+   insns.  If structure lra_static_insn_data is changed, the
+   initializer should be changed too.  */
+static struct lra_static_insn_data debug_insn_static_data =
+  {
+    &debug_operand_data,
+    0,  /* Duplication operands #.  */
+    -1, /* Commutative operand #.  */
+    1,  /* Operands #.  There is only one operand which is debug RTL
+	   expression.  */
+    0,  /* Duplications #.  */
+    0,  /* Alternatives #.  We are not interesting alternatives
+	   because we does not proceed debug_insns for reloads.  */
+    NULL, /* Hard registers referenced in machine description.  */
+    NULL  /* Descriptions of operands in alternatives.  */
+  };
+
 /* Called once per compiler work to initialize some LRA data related
    to insns.  */
 static void
@@ -536,7 +567,7 @@  free_insn_recog_data (lra_insn_recog_dat
   if (data->alternative_enabled_p != NULL)
     free (data->alternative_enabled_p);
 #endif
-  if (data->icode < 0)
+  if (data->icode < 0 && NONDEBUG_INSN_P (data->insn))
     {
       if (data->insn_static_data->operand_alternative != NULL)
 	free (data->insn_static_data->operand_alternative);
@@ -869,10 +900,15 @@  lra_get_insn_recog_data (rtx insn)
 		  && (INSN_CODE (insn) < 0 || data->icode == INSN_CODE (insn)));
       return data;
     }
-  icode = INSN_CODE (insn);
-  if (icode < 0)
-    /* It might be a new simple insn which is not recognized yet.  */
-    INSN_CODE (insn) = icode = recog (PATTERN (insn), insn, 0);
+  if (DEBUG_INSN_P (insn))
+    icode = -1;
+  else
+    {
+      icode = INSN_CODE (insn);
+      if (icode < 0)
+	/* It might be a new simple insn which is not recognized yet.  */
+	INSN_CODE (insn) = icode = recog (PATTERN (insn), insn, 0);
+    }
   data
     = (lra_insn_recog_data_t) xmalloc (sizeof (struct lra_insn_recog_data));
   insn_recog_data[uid] = data;
@@ -880,6 +916,18 @@  lra_get_insn_recog_data (rtx insn)
   data->used_insn_alternative = -1;
   data->icode = icode;
   data->regs = NULL;
+  if (DEBUG_INSN_P (insn))
+    {
+      data->insn_static_data = &debug_insn_static_data;
+      data->dup_loc = NULL;
+      data->arg_hard_regs = NULL;
+#ifdef HAVE_ATTR_enabled
+      data->alternative_enabled_p = NULL;
+#endif
+      data->operand_loc = (rtx **) xmalloc (sizeof (rtx *));
+      data->operand_loc[0] = &INSN_VAR_LOCATION_LOC (insn);
+      return data;
+    }
   if (icode < 0)
     {
       int nop;
@@ -1107,6 +1155,8 @@  lra_update_insn_recog_data (rtx insn)
     return lra_get_insn_recog_data (insn);
   insn_static_data = data->insn_static_data;
   data->used_insn_alternative = -1;
+  if (DEBUG_INSN_P (insn))
+    return data;
   if (data->icode < 0)
     {
       int nop;
@@ -1516,17 +1566,19 @@  invalidate_insn_data_regno_info (lra_ins
 				 int freq)
 {
   int uid;
+  bool debug_p;
   unsigned int i;
   struct lra_insn_reg *ir, *next_ir;
 
   uid = INSN_UID (insn);
+  debug_p = DEBUG_INSN_P (insn);
   for (ir = data->regs; ir != NULL; ir = next_ir)
     {
       i = ir->regno;
       next_ir = ir->next;
       free_insn_reg (ir);
       bitmap_clear_bit (&lra_reg_info[i].insn_bitmap, uid);
-      if (i >= FIRST_PSEUDO_REGISTER)
+      if (i >= FIRST_PSEUDO_REGISTER && ! debug_p)
 	{
 	  lra_reg_info[i].nrefs--;
 	  lra_reg_info[i].freq -= freq;
@@ -1571,7 +1623,7 @@  lra_update_insn_regno_info (rtx insn)
   struct lra_static_insn_data *static_data;
   enum rtx_code code;
 
-  if (! NONDEBUG_INSN_P (insn))
+  if (! INSN_P (insn))
     return;
   data = lra_get_insn_recog_data (insn);
   static_data = data->insn_static_data;
@@ -1585,7 +1637,8 @@  lra_update_insn_regno_info (rtx insn)
   if ((code = GET_CODE (PATTERN (insn))) == CLOBBER || code == USE)
     add_regs_to_insn_regno_info (data, XEXP (PATTERN (insn), 0), uid,
 				 code == USE ? OP_IN : OP_OUT, false);
-  setup_insn_reg_info (data, freq);
+  if (NONDEBUG_INSN_P (insn))
+    setup_insn_reg_info (data, freq);
 }
 
 /* Return reg info of insn given by it UID.  */
Index: lra-eliminations.c
===================================================================
--- lra-eliminations.c	(revision 175929)
+++ lra-eliminations.c	(working copy)
@@ -593,7 +593,6 @@  lra_eliminate_regs_1 (rtx x, enum machin
       return x;
 
     case CLOBBER:
-    case ASM_OPERANDS:
     case SET:
       gcc_unreachable ();
 
@@ -768,7 +767,6 @@  eliminate_regs_in_insn (rtx insn, bool r
 {
   int icode = recog_memoized (insn);
   rtx old_body = PATTERN (insn);
-  int insn_is_asm = asm_noperands (old_body) >= 0;
   rtx old_set = single_set (insn);
   rtx new_body;
   bool val;
@@ -780,14 +778,13 @@  eliminate_regs_in_insn (rtx insn, bool r
   lra_insn_recog_data_t id;
   struct lra_static_insn_data *static_id;
 
-  if (! insn_is_asm && icode < 0)
+  if (icode < 0 && asm_noperands (old_body) < 0 && ! DEBUG_INSN_P (insn))
     {
       gcc_assert (GET_CODE (PATTERN (insn)) == USE
 		  || GET_CODE (PATTERN (insn)) == CLOBBER
 		  || GET_CODE (PATTERN (insn)) == ADDR_VEC
 		  || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC
-		  || GET_CODE (PATTERN (insn)) == ASM_INPUT
-		  || DEBUG_INSN_P (insn));
+		  || GET_CODE (PATTERN (insn)) == ASM_INPUT);
       return;
     }
 
@@ -980,7 +977,7 @@  eliminate_regs_in_insn (rtx insn, bool r
       substed_operand[i] = *id->operand_loc[i];
 
       /* For an asm statement, every operand is eliminable.  */
-      if (insn_is_asm || insn_data[icode].operand[i].eliminable)
+      if (icode < 0 || insn_data[icode].operand[i].eliminable)
 	{
 	  /* Check for setting a register that we know about.  */
 	  if (static_id->operand[i].type != OP_IN
Index: lra-spills.c
===================================================================
--- lra-spills.c	(revision 175929)
+++ lra-spills.c	(working copy)
@@ -443,7 +443,7 @@  lra_hard_reg_substitution (void)
       SET_REGNO (regno_reg_rtx[i], hard_regno);
   FOR_EACH_BB (bb)
     FOR_BB_INSNS (bb, insn)
-      if (NONDEBUG_INSN_P (insn))
+      if (INSN_P (insn))
 	{
 	  lra_insn_recog_data_t id;
 	  
Index: lra-constraints.c
===================================================================
--- lra-constraints.c	(revision 175929)
+++ lra-constraints.c	(working copy)
@@ -145,7 +145,7 @@  get_secondary_mem (enum machine_mode mod
 static int new_regno_start;
 
 /* Return hard regno of REGNO or if it is was not assigned to a hard
-   register, use a hard register from its preferred class.  */
+   register, use a hard register from its allocno class.  */
 static int
 get_try_hard_regno (int regno)
 {
@@ -156,14 +156,14 @@  get_try_hard_regno (int regno)
     hard_regno = lra_get_regno_hard_regno (regno);
   if (hard_regno >= 0)
     return hard_regno;
-  rclass = lra_get_preferred_class (regno);
+  rclass = lra_get_allocno_class (regno);
   if (rclass == NO_REGS)
     return -1;
   return ira_class_hard_regs[rclass][0];
 }
 
 /* Return class of hard regno of REGNO or if it is was not assigned to
-   a hard register, return its preferred class but only for
+   a hard register, return its allocno class but only for
    non-inherited pseudos created on the current constraint pass.
    Otherwise, return NO_REGS.  */
 static enum reg_class
@@ -177,7 +177,7 @@  get_reg_class (int regno)
     return REGNO_REG_CLASS (hard_regno);
   if (regno >= new_regno_start
       && ! bitmap_bit_p (&lra_inheritance_pseudos, regno))
-    return lra_get_preferred_class (regno);
+    return lra_get_allocno_class (regno);
   return NO_REGS;
 }
 
@@ -2407,8 +2407,7 @@  make_early_clobber_input_reload_reg (rtx
 	/* It is not worth to check class subsets or to use class
 	   intersects because such cases are extremely rare.  */
 	&& (rclass
-	    == lra_get_preferred_class (REGNO (early_clobber_reload_regs[i]
-					       .new_reg))))
+	    == lra_get_allocno_class (REGNO (early_clobber_reload_regs[i].new_reg))))
       return early_clobber_reload_regs[i].new_reg;
   if (get_reload_reg (OP_IN, VOIDmode, x, rclass, "early clobbered", &new_reg))
     {
@@ -3118,6 +3117,36 @@  contains_pseudo_p (rtx x, bool spilled_p
   return false;
 }
 
+/* Process all regs in *LOC and change them on equivalent
+   substitution.  Return true if any change was done.  */
+static bool
+equivalence_change_p (rtx *loc)
+{
+  rtx subst, x = *loc;
+  bool result = false;
+  enum rtx_code code = GET_CODE (x);
+  const char *fmt;
+  int i, j;
+
+  if (code == REG && (subst = get_equiv_substitution (x)) != x)
+    {
+      *loc = subst;
+      return true;
+    }
+
+  /* Scan all the operand sub-expressions.  */
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'e')
+	result = equivalence_change_p (&XEXP (x, i)) || result;
+      else if (fmt[i] == 'E')
+	for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+	  result = equivalence_change_p (&XVECEXP (x, i, j)) || result;
+    }
+  return result;
+}
+
 /* Maximum number of constraint pass iteration number.  It is for
    preventing all LRA cycling.  */
 #define MAX_CONSTRAINT_ITERATION_NUMBER 15
@@ -3207,7 +3236,15 @@  lra_constraints (bool first_p)
 	  ("Max. number of generated reload insns per insn is achieved (%d)\n",
 	   MAX_RELOAD_INSNS_NUMBER);
       new_insns_num++;
-      if (NONDEBUG_INSN_P (curr_insn))
+      if (DEBUG_INSN_P (curr_insn))
+	{
+	  /* We need to check equivalence in debug insn and change
+	     pseudo to the equivalent value if necessary.  */
+	  curr_id = lra_get_insn_recog_data (curr_insn);
+	  if (equivalence_change_p (curr_id->operand_loc[0]))
+	    changed_p = true;
+	}
+      else if (INSN_P (curr_insn))
 	{
 	  if ((set = single_set (curr_insn)) != NULL_RTX)
 	    {
@@ -3331,7 +3368,7 @@  inherit_reload_reg (rtx reload_reg, int 
 		    rtx insn, rtx last_reload_insn)
 {
   int reload_regno = REGNO (reload_reg);
-  enum reg_class rclass = lra_get_preferred_class (reload_regno);
+  enum reg_class rclass = lra_get_allocno_class (reload_regno);
   rtx new_reg, new_insns, set, src, dst;
   basic_block bb;
 
@@ -3399,7 +3436,7 @@  inherit_in_ebb (rtx head, rtx tail)
 	}
       if (src_regno < lra_constraint_new_regno_start
 	  && dst_regno >= lra_constraint_new_regno_start
-	  && lra_get_preferred_class (dst_regno) != NO_REGS)
+	  && lra_get_allocno_class (dst_regno) != NO_REGS)
 	{
 	  /* 'reload_pseudo <- original_pseudo'.  */
 	  if (reload_insn_check[src_regno] == curr_reload_insn_check
@@ -3412,7 +3449,7 @@  inherit_in_ebb (rtx head, rtx tail)
 	}
       else if (src_regno >= lra_constraint_new_regno_start
 	       && dst_regno < lra_constraint_new_regno_start
-	       && lra_get_preferred_class (src_regno) != NO_REGS
+	       && lra_get_allocno_class (src_regno) != NO_REGS
 	       && reload_insn_check[dst_regno] == curr_reload_insn_check
 	       && (last_reload_insn = reload_insn[dst_regno]) != NULL_RTX)
 	{
Index: ira.c
===================================================================
--- ira.c	(revision 175929)
+++ ira.c	(working copy)
@@ -1818,6 +1818,8 @@  ira_setup_eliminable_regset (void)
 
   if (flag_lra)
     lra_init_elimination (&dont_use_regs);
+  else
+    CLEAR_HARD_REG_SET (dont_use_regs);
 
   COPY_HARD_REG_SET (ira_no_alloc_regs, no_unit_alloc_regs);
   IOR_HARD_REG_SET (ira_no_alloc_regs, dont_use_regs);
Index: lra-equivs.c
===================================================================
--- lra-equivs.c	(revision 175929)
+++ lra-equivs.c	(working copy)
@@ -455,7 +455,7 @@  memref_used_between_p (rtx memref, rtx s
   for (insn = NEXT_INSN (start); insn != NEXT_INSN (end);
        insn = NEXT_INSN (insn))
     {
-      if (!NONDEBUG_INSN_P (insn))
+      if (!INSN_P (insn))
 	continue;
       
       if (memref_referenced_p (memref, PATTERN (insn)))
Index: reginfo.c
===================================================================
--- reginfo.c	(revision 175929)
+++ reginfo.c	(working copy)
@@ -967,7 +967,7 @@  allocate_reg_info (void)
     {
       reg_pref[i].prefclass = GENERAL_REGS;
       reg_pref[i].altclass = ALL_REGS;
-      reg_pref[i].allocnoclass = NO_REGS;
+      reg_pref[i].allocnoclass = GENERAL_REGS;
     }
 }
 
@@ -1001,7 +1001,7 @@  resize_reg_info (void)
     {
       reg_pref[i].prefclass = GENERAL_REGS;
       reg_pref[i].altclass = ALL_REGS;
-      reg_pref[i].allocnoclass = NO_REGS;
+      reg_pref[i].allocnoclass = GENERAL_REGS;
     }
   return true;
 }
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md	(revision 175929)
+++ config/i386/i386.md	(working copy)
@@ -7672,7 +7672,7 @@ 
 (define_insn "*anddi_1"
   [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm,r,r")
 	(and:DI
-	 (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,0")
+	 (match_operand:DI 1 "nonimmediate_operand" "%0,0,0,qm")
 	 (match_operand:DI 2 "x86_64_szext_general_operand" "Z,re,rm,L")))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && ix86_binary_operator_ok (AND, DImode, operands)"
@@ -7720,7 +7720,7 @@ 
 
 (define_insn "*andsi_1"
   [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r,r")
-	(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,0")
+	(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,qm")
 		(match_operand:SI 2 "general_operand" "ri,rm,L")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (AND, SImode, operands)"
@@ -7777,7 +7777,7 @@ 
 
 (define_insn "*andhi_1"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r")
-	(and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,0")
+	(and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,qm")
 		(match_operand:HI 2 "general_operand" "rn,rm,L")))
    (clobber (reg:CC FLAGS_REG))]
   "ix86_binary_operator_ok (AND, HImode, operands)"
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 175929)
+++ config/i386/i386.c	(working copy)
@@ -27890,11 +27890,18 @@  ix86_free_from_memory (enum machine_mode
 static int
 ix86_register_bank (int hard_regno)
 {
+  /* New x86-64 int registers result in bigger code size.  Discourage
+     them.  */
   if (FIRST_REX_INT_REG <= hard_regno && hard_regno <= LAST_REX_INT_REG)
-    return 1;
+    return 2;
+  /* New x86-64 SSE registers result in bigger code size.  Discourage
+     them.  */
   if (FIRST_REX_SSE_REG <= hard_regno && hard_regno <= LAST_REX_SSE_REG)
-    return 1;
-  return 0;
+    return 2;
+  /* Usage of AX register results in smaller code.  Prefer it.  */
+  if (hard_regno == 0)
+    return 0;
+  return 1;
 }
 
 /* Implement TARGET_PREFERRED_RELOAD_CLASS.