ira-int.h (ira_allocno): Add "wmode" field.

gcc/
2014-09-26  David Sherwood  <david.sherwood@arm.com>

	* ira-int.h (ira_allocno): Add "wmode" field.
	* ira-build.c (create_insn_allocnos): Add new "parent" function
	parameter.
	* ira-conflicts.c (ira_build_conflicts): Add conflicts for registers
	that cannot be accessed in wmode.

From-SVN: r215707
This commit is contained in:
David Sherwood 2014-09-30 08:04:32 +00:00 committed by Richard Sandiford
parent 4176084b61
commit d1bb282efb
4 changed files with 56 additions and 13 deletions

View file

@ -1,3 +1,11 @@
2014-09-30 David Sherwood <david.sherwood@arm.com>
* ira-int.h (ira_allocno): Add "wmode" field.
* ira-build.c (create_insn_allocnos): Add new "parent" function
parameter.
* ira-conflicts.c (ira_build_conflicts): Add conflicts for registers
that cannot be accessed in wmode.
2014-09-30 Markus Trippelsdorf <markus@trippelsdorf.de> 2014-09-30 Markus Trippelsdorf <markus@trippelsdorf.de>
* data-streamer.c (bp_unpack_var_len_int): Avoid signed * data-streamer.c (bp_unpack_var_len_int): Avoid signed

View file

@ -524,6 +524,7 @@ ira_create_allocno (int regno, bool cap_p,
ALLOCNO_BAD_SPILL_P (a) = false; ALLOCNO_BAD_SPILL_P (a) = false;
ALLOCNO_ASSIGNED_P (a) = false; ALLOCNO_ASSIGNED_P (a) = false;
ALLOCNO_MODE (a) = (regno < 0 ? VOIDmode : PSEUDO_REGNO_MODE (regno)); ALLOCNO_MODE (a) = (regno < 0 ? VOIDmode : PSEUDO_REGNO_MODE (regno));
ALLOCNO_WMODE (a) = ALLOCNO_MODE (a);
ALLOCNO_PREFS (a) = NULL; ALLOCNO_PREFS (a) = NULL;
ALLOCNO_COPIES (a) = NULL; ALLOCNO_COPIES (a) = NULL;
ALLOCNO_HARD_REG_COSTS (a) = NULL; ALLOCNO_HARD_REG_COSTS (a) = NULL;
@ -893,6 +894,7 @@ create_cap_allocno (ira_allocno_t a)
parent = ALLOCNO_LOOP_TREE_NODE (a)->parent; parent = ALLOCNO_LOOP_TREE_NODE (a)->parent;
cap = ira_create_allocno (ALLOCNO_REGNO (a), true, parent); cap = ira_create_allocno (ALLOCNO_REGNO (a), true, parent);
ALLOCNO_MODE (cap) = ALLOCNO_MODE (a); ALLOCNO_MODE (cap) = ALLOCNO_MODE (a);
ALLOCNO_WMODE (cap) = ALLOCNO_WMODE (a);
aclass = ALLOCNO_CLASS (a); aclass = ALLOCNO_CLASS (a);
ira_set_allocno_class (cap, aclass); ira_set_allocno_class (cap, aclass);
ira_create_allocno_objects (cap); ira_create_allocno_objects (cap);
@ -1859,9 +1861,9 @@ static basic_block curr_bb;
/* This recursive function creates allocnos corresponding to /* This recursive function creates allocnos corresponding to
pseudo-registers containing in X. True OUTPUT_P means that X is pseudo-registers containing in X. True OUTPUT_P means that X is
a lvalue. */ an lvalue. PARENT corresponds to the parent expression of X. */
static void static void
create_insn_allocnos (rtx x, bool output_p) create_insn_allocnos (rtx x, rtx outer, bool output_p)
{ {
int i, j; int i, j;
const char *fmt; const char *fmt;
@ -1876,7 +1878,15 @@ create_insn_allocnos (rtx x, bool output_p)
ira_allocno_t a; ira_allocno_t a;
if ((a = ira_curr_regno_allocno_map[regno]) == NULL) if ((a = ira_curr_regno_allocno_map[regno]) == NULL)
a = ira_create_allocno (regno, false, ira_curr_loop_tree_node); {
a = ira_create_allocno (regno, false, ira_curr_loop_tree_node);
if (outer != NULL && GET_CODE (outer) == SUBREG)
{
enum machine_mode wmode = GET_MODE (outer);
if (GET_MODE_SIZE (wmode) > GET_MODE_SIZE (ALLOCNO_WMODE (a)))
ALLOCNO_WMODE (a) = wmode;
}
}
ALLOCNO_NREFS (a)++; ALLOCNO_NREFS (a)++;
ALLOCNO_FREQ (a) += REG_FREQ_FROM_BB (curr_bb); ALLOCNO_FREQ (a) += REG_FREQ_FROM_BB (curr_bb);
@ -1887,25 +1897,25 @@ create_insn_allocnos (rtx x, bool output_p)
} }
else if (code == SET) else if (code == SET)
{ {
create_insn_allocnos (SET_DEST (x), true); create_insn_allocnos (SET_DEST (x), NULL, true);
create_insn_allocnos (SET_SRC (x), false); create_insn_allocnos (SET_SRC (x), NULL, false);
return; return;
} }
else if (code == CLOBBER) else if (code == CLOBBER)
{ {
create_insn_allocnos (XEXP (x, 0), true); create_insn_allocnos (XEXP (x, 0), NULL, true);
return; return;
} }
else if (code == MEM) else if (code == MEM)
{ {
create_insn_allocnos (XEXP (x, 0), false); create_insn_allocnos (XEXP (x, 0), NULL, false);
return; return;
} }
else if (code == PRE_DEC || code == POST_DEC || code == PRE_INC || else if (code == PRE_DEC || code == POST_DEC || code == PRE_INC ||
code == POST_INC || code == POST_MODIFY || code == PRE_MODIFY) code == POST_INC || code == POST_MODIFY || code == PRE_MODIFY)
{ {
create_insn_allocnos (XEXP (x, 0), true); create_insn_allocnos (XEXP (x, 0), NULL, true);
create_insn_allocnos (XEXP (x, 0), false); create_insn_allocnos (XEXP (x, 0), NULL, false);
return; return;
} }
@ -1913,10 +1923,10 @@ create_insn_allocnos (rtx x, bool output_p)
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{ {
if (fmt[i] == 'e') if (fmt[i] == 'e')
create_insn_allocnos (XEXP (x, i), output_p); create_insn_allocnos (XEXP (x, i), x, output_p);
else if (fmt[i] == 'E') else if (fmt[i] == 'E')
for (j = 0; j < XVECLEN (x, i); j++) for (j = 0; j < XVECLEN (x, i); j++)
create_insn_allocnos (XVECEXP (x, i, j), output_p); create_insn_allocnos (XVECEXP (x, i, j), x, output_p);
} }
} }
@ -1935,7 +1945,7 @@ create_bb_allocnos (ira_loop_tree_node_t bb_node)
ira_assert (bb != NULL); ira_assert (bb != NULL);
FOR_BB_INSNS_REVERSE (bb, insn) FOR_BB_INSNS_REVERSE (bb, insn)
if (NONDEBUG_INSN_P (insn)) if (NONDEBUG_INSN_P (insn))
create_insn_allocnos (PATTERN (insn), false); create_insn_allocnos (PATTERN (insn), NULL, false);
/* It might be a allocno living through from one subloop to /* It might be a allocno living through from one subloop to
another. */ another. */
EXECUTE_IF_SET_IN_REG_SET (df_get_live_in (bb), FIRST_PSEUDO_REGISTER, i, bi) EXECUTE_IF_SET_IN_REG_SET (df_get_live_in (bb), FIRST_PSEUDO_REGISTER, i, bi)

View file

@ -774,6 +774,27 @@ ira_build_conflicts (void)
temp_hard_reg_set); temp_hard_reg_set);
} }
/* Now we deal with paradoxical subreg cases where certain registers
cannot be accessed in the widest mode. */
enum machine_mode outer_mode = ALLOCNO_WMODE (a);
enum machine_mode inner_mode = ALLOCNO_MODE (a);
if (GET_MODE_SIZE (outer_mode) > GET_MODE_SIZE (inner_mode))
{
enum reg_class aclass = ALLOCNO_CLASS (a);
for (int j = ira_class_hard_regs_num[aclass] - 1; j >= 0; --j)
{
int inner_regno = ira_class_hard_regs[aclass][j];
int outer_regno = simplify_subreg_regno (inner_regno,
inner_mode, 0,
outer_mode);
if (outer_regno < 0
|| !in_hard_reg_set_p (reg_class_contents[aclass],
outer_mode, outer_regno))
SET_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj),
inner_regno);
}
}
if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0) if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
{ {
int regno; int regno;

View file

@ -283,6 +283,9 @@ struct ira_allocno
/* Mode of the allocno which is the mode of the corresponding /* Mode of the allocno which is the mode of the corresponding
pseudo-register. */ pseudo-register. */
ENUM_BITFIELD (machine_mode) mode : 8; ENUM_BITFIELD (machine_mode) mode : 8;
/* Widest mode of the allocno which in at least one case could be
for paradoxical subregs where wmode > mode. */
ENUM_BITFIELD (machine_mode) wmode : 8;
/* Register class which should be used for allocation for given /* Register class which should be used for allocation for given
allocno. NO_REGS means that we should use memory. */ allocno. NO_REGS means that we should use memory. */
ENUM_BITFIELD (reg_class) aclass : 16; ENUM_BITFIELD (reg_class) aclass : 16;
@ -315,7 +318,7 @@ struct ira_allocno
number (0, ...) - 2. Value -1 is used for allocnos spilled by the number (0, ...) - 2. Value -1 is used for allocnos spilled by the
reload (at this point pseudo-register has only one allocno) which reload (at this point pseudo-register has only one allocno) which
did not get stack slot yet. */ did not get stack slot yet. */
short int hard_regno; int hard_regno : 16;
/* Allocnos with the same regno are linked by the following member. /* Allocnos with the same regno are linked by the following member.
Allocnos corresponding to inner loops are first in the list (it Allocnos corresponding to inner loops are first in the list (it
corresponds to depth-first traverse of the loops). */ corresponds to depth-first traverse of the loops). */
@ -436,6 +439,7 @@ struct ira_allocno
#define ALLOCNO_BAD_SPILL_P(A) ((A)->bad_spill_p) #define ALLOCNO_BAD_SPILL_P(A) ((A)->bad_spill_p)
#define ALLOCNO_ASSIGNED_P(A) ((A)->assigned_p) #define ALLOCNO_ASSIGNED_P(A) ((A)->assigned_p)
#define ALLOCNO_MODE(A) ((A)->mode) #define ALLOCNO_MODE(A) ((A)->mode)
#define ALLOCNO_WMODE(A) ((A)->wmode)
#define ALLOCNO_PREFS(A) ((A)->allocno_prefs) #define ALLOCNO_PREFS(A) ((A)->allocno_prefs)
#define ALLOCNO_COPIES(A) ((A)->allocno_copies) #define ALLOCNO_COPIES(A) ((A)->allocno_copies)
#define ALLOCNO_HARD_REG_COSTS(A) ((A)->hard_reg_costs) #define ALLOCNO_HARD_REG_COSTS(A) ((A)->hard_reg_costs)