===================================================================
@@ -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");
===================================================================
@@ -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;
===================================================================
@@ -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. */
===================================================================
@@ -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
===================================================================
@@ -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;
===================================================================
@@ -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)
{
===================================================================
@@ -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);
===================================================================
@@ -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)))
===================================================================
@@ -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;
}
===================================================================
@@ -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)"
===================================================================
@@ -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.