From patchwork Wed Jul 6 20:18:23 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Makarov X-Patchwork-Id: 103574 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 6B228B6F00 for ; Thu, 7 Jul 2011 06:18:55 +1000 (EST) Received: (qmail 7128 invoked by alias); 6 Jul 2011 20:18:53 -0000 Received: (qmail 7114 invoked by uid 22791); 6 Jul 2011 20:18:46 -0000 X-SWARE-Spam-Status: No, hits=-6.2 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, TW_VZ, TW_ZB, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 06 Jul 2011 20:18:25 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p66KIOHs014913 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 6 Jul 2011 16:18:24 -0400 Received: from toll.yyz.redhat.com (toll.yyz.redhat.com [10.15.16.165]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p66KIOsC018375 for ; Wed, 6 Jul 2011 16:18:24 -0400 Message-ID: <4E14C30F.3030607@redhat.com> Date: Wed, 06 Jul 2011 16:18:23 -0400 From: Vladimir Makarov User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.17) Gecko/20110428 Fedora/3.1.10-1.fc14 Thunderbird/3.1.10 MIME-Version: 1.0 To: gcc-patches Subject: [lra] initial support of debug info and some fixes X-IsSubscribed: yes Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org 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 * 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. 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, ®_obstack); bitmap_initialize (&spill_pseudos_bitmap, ®_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.