mirror of git://gcc.gnu.org/git/gcc.git
reload.c (find_valid_class_1): New static function.
* reload.c (find_valid_class_1): New static function. (push_reload): Use it when reloading a SYMBOL_REG as the inner of a subreg. Keep better track of needed classes for the secondary memory case. * config/i386/i386.h (LIMIT_RELOAD_CLASS): Limit INT_SSE_REGS to GENERAL_REGS. * reload1.c (replaced_subreg): New static function. (gen_reload): Use it when deciding whether to use secondary memory. * gcc.c-torture/compile/20120727-1.c: New test. From-SVN: r190252
This commit is contained in:
parent
62d6a5bbc8
commit
82ad0aaf6e
|
|
@ -1,3 +1,15 @@
|
||||||
|
2012-08-09 Bernd Schmidt <bernds@codesourcery.com>
|
||||||
|
|
||||||
|
* reload.c (find_valid_class_1): New static function.
|
||||||
|
(push_reload): Use it when reloading a SYMBOL_REG as the inner
|
||||||
|
of a subreg. Keep better track of needed classes for the
|
||||||
|
secondary memory case.
|
||||||
|
* config/i386/i386.h (LIMIT_RELOAD_CLASS): Limit INT_SSE_REGS to
|
||||||
|
GENERAL_REGS.
|
||||||
|
* reload1.c (replaced_subreg): New static function.
|
||||||
|
(gen_reload): Use it when deciding whether to use secondary
|
||||||
|
memory.
|
||||||
|
|
||||||
2012-08-09 Richard Guenther <rguenther@suse.de>
|
2012-08-09 Richard Guenther <rguenther@suse.de>
|
||||||
|
|
||||||
* tree.h (SSA_VAR_P): Simplify.
|
* tree.h (SSA_VAR_P): Simplify.
|
||||||
|
|
|
||||||
|
|
@ -1384,7 +1384,8 @@ enum reg_class
|
||||||
((MODE) == QImode && !TARGET_64BIT \
|
((MODE) == QImode && !TARGET_64BIT \
|
||||||
&& ((CLASS) == ALL_REGS || (CLASS) == GENERAL_REGS \
|
&& ((CLASS) == ALL_REGS || (CLASS) == GENERAL_REGS \
|
||||||
|| (CLASS) == LEGACY_REGS || (CLASS) == INDEX_REGS) \
|
|| (CLASS) == LEGACY_REGS || (CLASS) == INDEX_REGS) \
|
||||||
? Q_REGS : (CLASS))
|
? Q_REGS \
|
||||||
|
: (CLASS) == INT_SSE_REGS ? GENERAL_REGS : (CLASS))
|
||||||
|
|
||||||
/* If we are copying between general and FP registers, we need a memory
|
/* If we are copying between general and FP registers, we need a memory
|
||||||
location. The same is true for SSE and MMX registers. */
|
location. The same is true for SSE and MMX registers. */
|
||||||
|
|
|
||||||
73
gcc/reload.c
73
gcc/reload.c
|
|
@ -707,6 +707,55 @@ find_valid_class (enum machine_mode outer ATTRIBUTE_UNUSED,
|
||||||
|
|
||||||
return best_class;
|
return best_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* We are trying to reload a subreg of something that is not a register.
|
||||||
|
Find the largest class which has at least one register valid in
|
||||||
|
mode MODE. OUTER is the mode of the subreg, DEST_CLASS the class in
|
||||||
|
which we would eventually like to obtain the object. */
|
||||||
|
|
||||||
|
static enum reg_class
|
||||||
|
find_valid_class_1 (enum machine_mode outer ATTRIBUTE_UNUSED,
|
||||||
|
enum machine_mode mode ATTRIBUTE_UNUSED,
|
||||||
|
enum reg_class dest_class ATTRIBUTE_UNUSED)
|
||||||
|
{
|
||||||
|
int best_cost = -1;
|
||||||
|
int rclass;
|
||||||
|
int regno;
|
||||||
|
enum reg_class best_class = NO_REGS;
|
||||||
|
unsigned int best_size = 0;
|
||||||
|
int cost;
|
||||||
|
|
||||||
|
for (rclass = 1; rclass < N_REG_CLASSES; rclass++)
|
||||||
|
{
|
||||||
|
int bad = 0;
|
||||||
|
for (regno = 0; regno < FIRST_PSEUDO_REGISTER && !bad; regno++)
|
||||||
|
if (TEST_HARD_REG_BIT (reg_class_contents[rclass], regno)
|
||||||
|
&& !HARD_REGNO_MODE_OK (regno, mode))
|
||||||
|
bad = 1;
|
||||||
|
|
||||||
|
if (bad)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
cost = register_move_cost (outer, (enum reg_class) rclass, dest_class);
|
||||||
|
|
||||||
|
if ((reg_class_size[rclass] > best_size
|
||||||
|
&& (best_cost < 0 || best_cost >= cost))
|
||||||
|
|| best_cost > cost)
|
||||||
|
{
|
||||||
|
best_class = (enum reg_class) rclass;
|
||||||
|
best_size = reg_class_size[rclass];
|
||||||
|
best_cost = register_move_cost (outer, (enum reg_class) rclass,
|
||||||
|
dest_class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gcc_assert (best_size != 0);
|
||||||
|
|
||||||
|
#ifdef LIMIT_RELOAD_CLASS
|
||||||
|
best_class = LIMIT_RELOAD_CLASS (mode, best_class);
|
||||||
|
#endif
|
||||||
|
return best_class;
|
||||||
|
}
|
||||||
|
|
||||||
/* Return the number of a previously made reload that can be combined with
|
/* Return the number of a previously made reload that can be combined with
|
||||||
a new one, or n_reloads if none of the existing reloads can be used.
|
a new one, or n_reloads if none of the existing reloads can be used.
|
||||||
|
|
@ -925,6 +974,8 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
|
||||||
int secondary_in_reload = -1, secondary_out_reload = -1;
|
int secondary_in_reload = -1, secondary_out_reload = -1;
|
||||||
enum insn_code secondary_in_icode = CODE_FOR_nothing;
|
enum insn_code secondary_in_icode = CODE_FOR_nothing;
|
||||||
enum insn_code secondary_out_icode = CODE_FOR_nothing;
|
enum insn_code secondary_out_icode = CODE_FOR_nothing;
|
||||||
|
enum reg_class subreg_in_class ATTRIBUTE_UNUSED;
|
||||||
|
subreg_in_class = NO_REGS;
|
||||||
|
|
||||||
/* INMODE and/or OUTMODE could be VOIDmode if no mode
|
/* INMODE and/or OUTMODE could be VOIDmode if no mode
|
||||||
has been specified for the operand. In that case,
|
has been specified for the operand. In that case,
|
||||||
|
|
@ -1091,16 +1142,18 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
|
||||||
|
|
||||||
if (in != 0 && reload_inner_reg_of_subreg (in, inmode, false))
|
if (in != 0 && reload_inner_reg_of_subreg (in, inmode, false))
|
||||||
{
|
{
|
||||||
enum reg_class in_class = rclass;
|
|
||||||
|
|
||||||
if (REG_P (SUBREG_REG (in)))
|
if (REG_P (SUBREG_REG (in)))
|
||||||
in_class
|
subreg_in_class
|
||||||
= find_valid_class (inmode, GET_MODE (SUBREG_REG (in)),
|
= find_valid_class (inmode, GET_MODE (SUBREG_REG (in)),
|
||||||
subreg_regno_offset (REGNO (SUBREG_REG (in)),
|
subreg_regno_offset (REGNO (SUBREG_REG (in)),
|
||||||
GET_MODE (SUBREG_REG (in)),
|
GET_MODE (SUBREG_REG (in)),
|
||||||
SUBREG_BYTE (in),
|
SUBREG_BYTE (in),
|
||||||
GET_MODE (in)),
|
GET_MODE (in)),
|
||||||
REGNO (SUBREG_REG (in)));
|
REGNO (SUBREG_REG (in)));
|
||||||
|
else if (GET_CODE (SUBREG_REG (in)) == SYMBOL_REF)
|
||||||
|
subreg_in_class = find_valid_class_1 (inmode,
|
||||||
|
GET_MODE (SUBREG_REG (in)),
|
||||||
|
rclass);
|
||||||
|
|
||||||
/* This relies on the fact that emit_reload_insns outputs the
|
/* This relies on the fact that emit_reload_insns outputs the
|
||||||
instructions for input reloads of type RELOAD_OTHER in the same
|
instructions for input reloads of type RELOAD_OTHER in the same
|
||||||
|
|
@ -1108,7 +1161,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
|
||||||
RELOAD_OTHER, we are guaranteed that this inner reload will be
|
RELOAD_OTHER, we are guaranteed that this inner reload will be
|
||||||
output before the outer reload. */
|
output before the outer reload. */
|
||||||
push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), (rtx *) 0,
|
push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), (rtx *) 0,
|
||||||
in_class, VOIDmode, VOIDmode, 0, 0, opnum, type);
|
subreg_in_class, VOIDmode, VOIDmode, 0, 0, opnum, type);
|
||||||
dont_remove_subreg = 1;
|
dont_remove_subreg = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1327,13 +1380,15 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
|
||||||
So add an additional reload. */
|
So add an additional reload. */
|
||||||
|
|
||||||
#ifdef SECONDARY_MEMORY_NEEDED
|
#ifdef SECONDARY_MEMORY_NEEDED
|
||||||
/* If a memory location is needed for the copy, make one. */
|
if (subreg_in_class == NO_REGS
|
||||||
if (in != 0
|
&& in != 0
|
||||||
&& (REG_P (in)
|
&& (REG_P (in)
|
||||||
|| (GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))))
|
|| (GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))))
|
||||||
&& reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
|
&& reg_or_subregno (in) < FIRST_PSEUDO_REGISTER)
|
||||||
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
|
subreg_in_class = REGNO_REG_CLASS (reg_or_subregno (in));
|
||||||
rclass, inmode))
|
/* If a memory location is needed for the copy, make one. */
|
||||||
|
if (subreg_in_class != NO_REGS
|
||||||
|
&& SECONDARY_MEMORY_NEEDED (subreg_in_class, rclass, inmode))
|
||||||
get_secondary_mem (in, inmode, opnum, type);
|
get_secondary_mem (in, inmode, opnum, type);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8469,6 +8469,18 @@ emit_insn_if_valid_for_reload (rtx insn)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If X is not a subreg, return it unmodified. If it is a subreg,
|
||||||
|
look up whether we made a replacement for the SUBREG_REG. Return
|
||||||
|
either the replacement or the SUBREG_REG. */
|
||||||
|
|
||||||
|
static rtx
|
||||||
|
replaced_subreg (rtx x)
|
||||||
|
{
|
||||||
|
if (GET_CODE (x) == SUBREG)
|
||||||
|
return find_replacement (&SUBREG_REG (x));
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
/* Emit code to perform a reload from IN (which may be a reload register) to
|
/* Emit code to perform a reload from IN (which may be a reload register) to
|
||||||
OUT (which may also be a reload register). IN or OUT is from operand
|
OUT (which may also be a reload register). IN or OUT is from operand
|
||||||
OPNUM with reload type TYPE.
|
OPNUM with reload type TYPE.
|
||||||
|
|
@ -8479,7 +8491,7 @@ static rtx
|
||||||
gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
|
gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
|
||||||
{
|
{
|
||||||
rtx last = get_last_insn ();
|
rtx last = get_last_insn ();
|
||||||
rtx tem;
|
rtx tem, tem1, tem2;
|
||||||
|
|
||||||
/* If IN is a paradoxical SUBREG, remove it and try to put the
|
/* If IN is a paradoxical SUBREG, remove it and try to put the
|
||||||
opposite SUBREG on OUT. Likewise for a paradoxical SUBREG on OUT. */
|
opposite SUBREG on OUT. Likewise for a paradoxical SUBREG on OUT. */
|
||||||
|
|
@ -8616,14 +8628,12 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
|
||||||
|
|
||||||
#ifdef SECONDARY_MEMORY_NEEDED
|
#ifdef SECONDARY_MEMORY_NEEDED
|
||||||
/* If we need a memory location to do the move, do it that way. */
|
/* If we need a memory location to do the move, do it that way. */
|
||||||
else if ((REG_P (in)
|
else if ((tem1 = replaced_subreg (in), tem2 = replaced_subreg (out),
|
||||||
|| (GET_CODE (in) == SUBREG && REG_P (SUBREG_REG (in))))
|
(REG_P (tem1) && REG_P (tem2)))
|
||||||
&& reg_or_subregno (in) < FIRST_PSEUDO_REGISTER
|
&& REGNO (tem1) < FIRST_PSEUDO_REGISTER
|
||||||
&& (REG_P (out)
|
&& REGNO (tem2) < FIRST_PSEUDO_REGISTER
|
||||||
|| (GET_CODE (out) == SUBREG && REG_P (SUBREG_REG (out))))
|
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (tem1)),
|
||||||
&& reg_or_subregno (out) < FIRST_PSEUDO_REGISTER
|
REGNO_REG_CLASS (REGNO (tem2)),
|
||||||
&& SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (reg_or_subregno (in)),
|
|
||||||
REGNO_REG_CLASS (reg_or_subregno (out)),
|
|
||||||
GET_MODE (out)))
|
GET_MODE (out)))
|
||||||
{
|
{
|
||||||
/* Get the memory to use and rewrite both registers to its mode. */
|
/* Get the memory to use and rewrite both registers to its mode. */
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,7 @@
|
||||||
|
2012-08-09 Bernd Schmidt <bernds@codesourcery.com>
|
||||||
|
|
||||||
|
* gcc.c-torture/compile/20120727-1.c: New test.
|
||||||
|
|
||||||
2012-08-09 Tobias Burnus <burnus@net-b.de>
|
2012-08-09 Tobias Burnus <burnus@net-b.de>
|
||||||
|
|
||||||
PR fortran/54199
|
PR fortran/54199
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
union {
|
||||||
|
char *p;
|
||||||
|
float f;
|
||||||
|
} u;
|
||||||
|
|
||||||
|
void
|
||||||
|
f (void)
|
||||||
|
{
|
||||||
|
u.p = "";
|
||||||
|
u.f += 1.1;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue