loop.c (count_one_set): New static function, broken out of count_loop_regs_set
* loop.c (count_one_set): New static function, broken out of count_loop_regs_set (count_loop_regs_set): Call it. * global.c (mark_reg_store): Handle clobbers here by not calling set_preference. (mark_reg_clobber): Just call mark_reg_store after ensuring SETTER is in fact a clobber. * integrate.c (process_reg_param): New function, broken out of expand_inline_function. (expand_inline_function): Call it. From-SVN: r22875
This commit is contained in:
parent
9a07247c2a
commit
a4c3ddd83a
4 changed files with 124 additions and 218 deletions
|
@ -23,6 +23,18 @@ Tue Oct 6 17:00:42 1998 J"orn Rennecke <amylaar@cygnus.co.uk>
|
|||
|
||||
Tue Oct 6 01:36:00 1998 Bernd Schmidt <crux@Pool.Informatik.RWTH-Aachen.DE>
|
||||
|
||||
* loop.c (count_one_set): New static function, broken out of
|
||||
count_loop_regs_set
|
||||
(count_loop_regs_set): Call it.
|
||||
* global.c (mark_reg_store): Handle clobbers here by not calling
|
||||
set_preference.
|
||||
(mark_reg_clobber): Just call mark_reg_store after ensuring SETTER
|
||||
is in fact a clobber.
|
||||
* integrate.c (process_reg_param): New function, broken out of
|
||||
expand_inline_function.
|
||||
(expand_inline_function): Call it.
|
||||
|
||||
|
||||
* i386.md (addsidi3_1): Delete unused variable temp.
|
||||
(addsidi3_2): Likewise.
|
||||
(clstrstrsi): Delete unused variable addr1.
|
||||
|
|
69
gcc/global.c
69
gcc/global.c
|
@ -1323,16 +1323,13 @@ record_conflicts (allocno_vec, len)
|
|||
if so, we do nothing.
|
||||
|
||||
SETTER is 0 if this register was modified by an auto-increment (i.e.,
|
||||
a REG_INC note was found for it).
|
||||
|
||||
CLOBBERs are processed here by calling mark_reg_clobber. */
|
||||
a REG_INC note was found for it). */
|
||||
|
||||
static void
|
||||
mark_reg_store (orig_reg, setter)
|
||||
rtx orig_reg, setter;
|
||||
mark_reg_store (reg, setter)
|
||||
rtx reg, setter;
|
||||
{
|
||||
register int regno;
|
||||
register rtx reg = orig_reg;
|
||||
|
||||
/* WORD is which word of a multi-register group is being stored.
|
||||
For the case where the store is actually into a SUBREG of REG.
|
||||
|
@ -1349,16 +1346,9 @@ mark_reg_store (orig_reg, setter)
|
|||
if (GET_CODE (reg) != REG)
|
||||
return;
|
||||
|
||||
if (setter && GET_CODE (setter) == CLOBBER)
|
||||
{
|
||||
/* A clobber of a register should be processed here too. */
|
||||
mark_reg_clobber (orig_reg, setter);
|
||||
return;
|
||||
}
|
||||
|
||||
regs_set[n_regs_set++] = reg;
|
||||
|
||||
if (setter)
|
||||
if (setter && GET_CODE (setter) != CLOBBER)
|
||||
set_preference (reg, SET_SRC (setter));
|
||||
|
||||
regno = REGNO (reg);
|
||||
|
@ -1396,55 +1386,8 @@ static void
|
|||
mark_reg_clobber (reg, setter)
|
||||
rtx reg, setter;
|
||||
{
|
||||
register int regno;
|
||||
|
||||
/* WORD is which word of a multi-register group is being stored.
|
||||
For the case where the store is actually into a SUBREG of REG.
|
||||
Except we don't use it; I believe the entire REG needs to be
|
||||
made live. */
|
||||
int word = 0;
|
||||
|
||||
if (GET_CODE (setter) != CLOBBER)
|
||||
return;
|
||||
|
||||
if (GET_CODE (reg) == SUBREG)
|
||||
{
|
||||
word = SUBREG_WORD (reg);
|
||||
reg = SUBREG_REG (reg);
|
||||
}
|
||||
|
||||
if (GET_CODE (reg) != REG)
|
||||
return;
|
||||
|
||||
regs_set[n_regs_set++] = reg;
|
||||
|
||||
regno = REGNO (reg);
|
||||
|
||||
/* Either this is one of the max_allocno pseudo regs not allocated,
|
||||
or it is or has a hardware reg. First handle the pseudo-regs. */
|
||||
if (regno >= FIRST_PSEUDO_REGISTER)
|
||||
{
|
||||
if (reg_allocno[regno] >= 0)
|
||||
{
|
||||
SET_ALLOCNO_LIVE (reg_allocno[regno]);
|
||||
record_one_conflict (regno);
|
||||
}
|
||||
}
|
||||
|
||||
if (reg_renumber[regno] >= 0)
|
||||
regno = reg_renumber[regno] /* + word */;
|
||||
|
||||
/* Handle hardware regs (and pseudos allocated to hard regs). */
|
||||
if (regno < FIRST_PSEUDO_REGISTER && ! fixed_regs[regno])
|
||||
{
|
||||
register int last = regno + HARD_REGNO_NREGS (regno, GET_MODE (reg));
|
||||
while (regno < last)
|
||||
{
|
||||
record_one_conflict (regno);
|
||||
SET_HARD_REG_BIT (hard_regs_live, regno);
|
||||
regno++;
|
||||
}
|
||||
}
|
||||
if (GET_CODE (setter) == CLOBBER)
|
||||
mark_reg_store (reg, setter);
|
||||
}
|
||||
|
||||
/* Record that REG has conflicts with all the regs currently live.
|
||||
|
|
149
gcc/integrate.c
149
gcc/integrate.c
|
@ -59,25 +59,31 @@ extern struct obstack *function_maybepermanent_obstack;
|
|||
: (8 * (8 + list_length (DECL_ARGUMENTS (DECL)))))
|
||||
#endif
|
||||
|
||||
static rtx initialize_for_inline PROTO((tree, int, int, int, int));
|
||||
static void finish_inline PROTO((tree, rtx));
|
||||
static void adjust_copied_decl_tree PROTO((tree));
|
||||
static tree copy_decl_list PROTO((tree));
|
||||
static tree copy_decl_tree PROTO((tree));
|
||||
static void copy_decl_rtls PROTO((tree));
|
||||
static void save_constants PROTO((rtx *));
|
||||
static void note_modified_parmregs PROTO((rtx, rtx));
|
||||
static rtx copy_for_inline PROTO((rtx));
|
||||
static void integrate_parm_decls PROTO((tree, struct inline_remap *, rtvec));
|
||||
static void integrate_decl_tree PROTO((tree, int, struct inline_remap *));
|
||||
static rtx initialize_for_inline PROTO((tree, int, int, int, int));
|
||||
static void finish_inline PROTO((tree, rtx));
|
||||
static void adjust_copied_decl_tree PROTO((tree));
|
||||
static tree copy_decl_list PROTO((tree));
|
||||
static tree copy_decl_tree PROTO((tree));
|
||||
static void copy_decl_rtls PROTO((tree));
|
||||
static void save_constants PROTO((rtx *));
|
||||
static void note_modified_parmregs PROTO((rtx, rtx));
|
||||
static rtx copy_for_inline PROTO((rtx));
|
||||
static void integrate_parm_decls PROTO((tree, struct inline_remap *,
|
||||
rtvec));
|
||||
static void integrate_decl_tree PROTO((tree, int,
|
||||
struct inline_remap *));
|
||||
static void save_constants_in_decl_trees PROTO ((tree));
|
||||
static void subst_constants PROTO((rtx *, rtx, struct inline_remap *));
|
||||
static void restore_constants PROTO((rtx *));
|
||||
static void set_block_origin_self PROTO((tree));
|
||||
static void set_decl_origin_self PROTO((tree));
|
||||
static void set_block_abstract_flags PROTO((tree, int));
|
||||
static void subst_constants PROTO((rtx *, rtx,
|
||||
struct inline_remap *));
|
||||
static void restore_constants PROTO((rtx *));
|
||||
static void set_block_origin_self PROTO((tree));
|
||||
static void set_decl_origin_self PROTO((tree));
|
||||
static void set_block_abstract_flags PROTO((tree, int));
|
||||
static void process_reg_param PROTO((struct inline_remap *, rtx,
|
||||
rtx));
|
||||
|
||||
void set_decl_abstract_flags PROTO((tree, int));
|
||||
|
||||
void set_decl_abstract_flags PROTO((tree, int));
|
||||
static tree copy_and_set_decl_abstract_origin PROTO((tree));
|
||||
|
||||
/* Returns the Ith entry in the label_map contained in MAP. If the
|
||||
|
@ -1300,6 +1306,38 @@ int global_const_equiv_map_size;
|
|||
&& REGNO (XEXP (X, 0)) >= FIRST_VIRTUAL_REGISTER \
|
||||
&& REGNO (XEXP (X, 0)) <= LAST_VIRTUAL_REGISTER)
|
||||
|
||||
/* Called to set up a mapping for the case where a parameter is in a
|
||||
register. If it is read-only and our argument is a constant, set up the
|
||||
constant equivalence.
|
||||
|
||||
If LOC is REG_USERVAR_P, the usual case, COPY must also have that flag set
|
||||
if it is a register.
|
||||
|
||||
Also, don't allow hard registers here; they might not be valid when
|
||||
substituted into insns. */
|
||||
static void
|
||||
process_reg_param (map, loc, copy)
|
||||
struct inline_remap *map;
|
||||
rtx loc, copy;
|
||||
{
|
||||
if ((GET_CODE (copy) != REG && GET_CODE (copy) != SUBREG)
|
||||
|| (GET_CODE (copy) == REG && REG_USERVAR_P (loc)
|
||||
&& ! REG_USERVAR_P (copy))
|
||||
|| (GET_CODE (copy) == REG
|
||||
&& REGNO (copy) < FIRST_PSEUDO_REGISTER))
|
||||
{
|
||||
rtx temp = copy_to_mode_reg (GET_MODE (loc), copy);
|
||||
REG_USERVAR_P (temp) = REG_USERVAR_P (loc);
|
||||
if ((CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
|
||||
&& REGNO (temp) < map->const_equiv_map_size)
|
||||
{
|
||||
map->const_equiv_map[REGNO (temp)] = copy;
|
||||
map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
|
||||
}
|
||||
copy = temp;
|
||||
}
|
||||
map->reg_map[REGNO (loc)] = copy;
|
||||
}
|
||||
/* Integrate the procedure defined by FNDECL. Note that this function
|
||||
may wind up calling itself. Since the static variables are not
|
||||
reentrant, we do not assign them until after the possibility
|
||||
|
@ -1610,87 +1648,16 @@ expand_inline_function (fndecl, parms, target, ignore, type,
|
|||
;
|
||||
}
|
||||
else if (GET_CODE (loc) == REG)
|
||||
{
|
||||
/* This is the good case where the parameter is in a register.
|
||||
If it is read-only and our argument is a constant, set up the
|
||||
constant equivalence.
|
||||
|
||||
If LOC is REG_USERVAR_P, the usual case, COPY must also have
|
||||
that flag set if it is a register.
|
||||
|
||||
Also, don't allow hard registers here; they might not be valid
|
||||
when substituted into insns. */
|
||||
|
||||
if ((GET_CODE (copy) != REG && GET_CODE (copy) != SUBREG)
|
||||
|| (GET_CODE (copy) == REG && REG_USERVAR_P (loc)
|
||||
&& ! REG_USERVAR_P (copy))
|
||||
|| (GET_CODE (copy) == REG
|
||||
&& REGNO (copy) < FIRST_PSEUDO_REGISTER))
|
||||
{
|
||||
temp = copy_to_mode_reg (GET_MODE (loc), copy);
|
||||
REG_USERVAR_P (temp) = REG_USERVAR_P (loc);
|
||||
if ((CONSTANT_P (copy) || FIXED_BASE_PLUS_P (copy))
|
||||
&& REGNO (temp) < map->const_equiv_map_size)
|
||||
{
|
||||
map->const_equiv_map[REGNO (temp)] = copy;
|
||||
map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
|
||||
}
|
||||
copy = temp;
|
||||
}
|
||||
map->reg_map[REGNO (loc)] = copy;
|
||||
}
|
||||
process_reg_param (map, loc, copy);
|
||||
else if (GET_CODE (loc) == CONCAT)
|
||||
{
|
||||
/* This is the good case where the parameter is in a
|
||||
pair of separate pseudos.
|
||||
If it is read-only and our argument is a constant, set up the
|
||||
constant equivalence.
|
||||
|
||||
If LOC is REG_USERVAR_P, the usual case, COPY must also have
|
||||
that flag set if it is a register.
|
||||
|
||||
Also, don't allow hard registers here; they might not be valid
|
||||
when substituted into insns. */
|
||||
rtx locreal = gen_realpart (GET_MODE (XEXP (loc, 0)), loc);
|
||||
rtx locimag = gen_imagpart (GET_MODE (XEXP (loc, 0)), loc);
|
||||
rtx copyreal = gen_realpart (GET_MODE (locreal), copy);
|
||||
rtx copyimag = gen_imagpart (GET_MODE (locimag), copy);
|
||||
|
||||
if ((GET_CODE (copyreal) != REG && GET_CODE (copyreal) != SUBREG)
|
||||
|| (GET_CODE (copyreal) == REG && REG_USERVAR_P (locreal)
|
||||
&& ! REG_USERVAR_P (copyreal))
|
||||
|| (GET_CODE (copyreal) == REG
|
||||
&& REGNO (copyreal) < FIRST_PSEUDO_REGISTER))
|
||||
{
|
||||
temp = copy_to_mode_reg (GET_MODE (locreal), copyreal);
|
||||
REG_USERVAR_P (temp) = REG_USERVAR_P (locreal);
|
||||
if ((CONSTANT_P (copyreal) || FIXED_BASE_PLUS_P (copyreal))
|
||||
&& REGNO (temp) < map->const_equiv_map_size)
|
||||
{
|
||||
map->const_equiv_map[REGNO (temp)] = copyreal;
|
||||
map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
|
||||
}
|
||||
copyreal = temp;
|
||||
}
|
||||
map->reg_map[REGNO (locreal)] = copyreal;
|
||||
|
||||
if ((GET_CODE (copyimag) != REG && GET_CODE (copyimag) != SUBREG)
|
||||
|| (GET_CODE (copyimag) == REG && REG_USERVAR_P (locimag)
|
||||
&& ! REG_USERVAR_P (copyimag))
|
||||
|| (GET_CODE (copyimag) == REG
|
||||
&& REGNO (copyimag) < FIRST_PSEUDO_REGISTER))
|
||||
{
|
||||
temp = copy_to_mode_reg (GET_MODE (locimag), copyimag);
|
||||
REG_USERVAR_P (temp) = REG_USERVAR_P (locimag);
|
||||
if ((CONSTANT_P (copyimag) || FIXED_BASE_PLUS_P (copyimag))
|
||||
&& REGNO (temp) < map->const_equiv_map_size)
|
||||
{
|
||||
map->const_equiv_map[REGNO (temp)] = copyimag;
|
||||
map->const_age_map[REGNO (temp)] = CONST_AGE_PARM;
|
||||
}
|
||||
copyimag = temp;
|
||||
}
|
||||
map->reg_map[REGNO (locimag)] = copyimag;
|
||||
process_reg_param (map, locreal, copyreal);
|
||||
process_reg_param (map, locimag, copyimag);
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
|
|
112
gcc/loop.c
112
gcc/loop.c
|
@ -3313,6 +3313,51 @@ find_single_use_in_loop (insn, x, usage)
|
|||
}
|
||||
}
|
||||
|
||||
/* Count and record any set in X which is contained in INSN. Update
|
||||
MAY_NOT_MOVE and LAST_SET for any register set in X. */
|
||||
|
||||
static void
|
||||
count_one_set (insn, x, may_not_move, last_set)
|
||||
rtx insn, x;
|
||||
varray_type may_not_move;
|
||||
rtx *last_set;
|
||||
{
|
||||
if (GET_CODE (x) == CLOBBER && GET_CODE (XEXP (x, 0)) == REG)
|
||||
/* Don't move a reg that has an explicit clobber.
|
||||
It's not worth the pain to try to do it correctly. */
|
||||
VARRAY_CHAR (may_not_move, REGNO (XEXP (x, 0))) = 1;
|
||||
|
||||
if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
|
||||
{
|
||||
rtx dest = SET_DEST (x);
|
||||
while (GET_CODE (dest) == SUBREG
|
||||
|| GET_CODE (dest) == ZERO_EXTRACT
|
||||
|| GET_CODE (dest) == SIGN_EXTRACT
|
||||
|| GET_CODE (dest) == STRICT_LOW_PART)
|
||||
dest = XEXP (dest, 0);
|
||||
if (GET_CODE (dest) == REG)
|
||||
{
|
||||
register int regno = REGNO (dest);
|
||||
/* If this is the first setting of this reg
|
||||
in current basic block, and it was set before,
|
||||
it must be set in two basic blocks, so it cannot
|
||||
be moved out of the loop. */
|
||||
if (VARRAY_INT (n_times_set, regno) > 0
|
||||
&& last_set[regno] == 0)
|
||||
VARRAY_CHAR (may_not_move, regno) = 1;
|
||||
/* If this is not first setting in current basic block,
|
||||
see if reg was used in between previous one and this.
|
||||
If so, neither one can be moved. */
|
||||
if (last_set[regno] != 0
|
||||
&& reg_used_between_p (dest, last_set[regno], insn))
|
||||
VARRAY_CHAR (may_not_move, regno) = 1;
|
||||
if (VARRAY_INT (n_times_set, regno) < 127)
|
||||
++VARRAY_INT (n_times_set, regno);
|
||||
last_set[regno] = insn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment N_TIMES_SET at the index of each register
|
||||
that is modified by an insn between FROM and TO.
|
||||
If the value of an element of N_TIMES_SET becomes 127 or more,
|
||||
|
@ -3359,76 +3404,15 @@ count_loop_regs_set (from, to, may_not_move, single_usage, count_ptr, nregs)
|
|||
find_single_use_in_loop (insn, REG_NOTES (insn), single_usage);
|
||||
}
|
||||
|
||||
if (GET_CODE (PATTERN (insn)) == CLOBBER
|
||||
&& GET_CODE (XEXP (PATTERN (insn), 0)) == REG)
|
||||
/* Don't move a reg that has an explicit clobber.
|
||||
We might do so sometimes, but it's not worth the pain. */
|
||||
VARRAY_CHAR (may_not_move, REGNO (XEXP (PATTERN (insn), 0))) = 1;
|
||||
|
||||
if (GET_CODE (PATTERN (insn)) == SET
|
||||
|| GET_CODE (PATTERN (insn)) == CLOBBER)
|
||||
{
|
||||
dest = SET_DEST (PATTERN (insn));
|
||||
while (GET_CODE (dest) == SUBREG
|
||||
|| GET_CODE (dest) == ZERO_EXTRACT
|
||||
|| GET_CODE (dest) == SIGN_EXTRACT
|
||||
|| GET_CODE (dest) == STRICT_LOW_PART)
|
||||
dest = XEXP (dest, 0);
|
||||
if (GET_CODE (dest) == REG)
|
||||
{
|
||||
register int regno = REGNO (dest);
|
||||
/* If this is the first setting of this reg
|
||||
in current basic block, and it was set before,
|
||||
it must be set in two basic blocks, so it cannot
|
||||
be moved out of the loop. */
|
||||
if (VARRAY_INT (n_times_set, regno) > 0
|
||||
&& last_set[regno] == 0)
|
||||
VARRAY_CHAR (may_not_move, regno) = 1;
|
||||
/* If this is not first setting in current basic block,
|
||||
see if reg was used in between previous one and this.
|
||||
If so, neither one can be moved. */
|
||||
if (last_set[regno] != 0
|
||||
&& reg_used_between_p (dest, last_set[regno], insn))
|
||||
VARRAY_CHAR (may_not_move, regno) = 1;
|
||||
if (VARRAY_INT (n_times_set, regno) < 127)
|
||||
++VARRAY_INT (n_times_set, regno);
|
||||
last_set[regno] = insn;
|
||||
}
|
||||
}
|
||||
count_one_set (insn, PATTERN (insn), may_not_move, last_set);
|
||||
else if (GET_CODE (PATTERN (insn)) == PARALLEL)
|
||||
{
|
||||
register int i;
|
||||
for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
|
||||
{
|
||||
register rtx x = XVECEXP (PATTERN (insn), 0, i);
|
||||
if (GET_CODE (x) == CLOBBER && GET_CODE (XEXP (x, 0)) == REG)
|
||||
/* Don't move a reg that has an explicit clobber.
|
||||
It's not worth the pain to try to do it correctly. */
|
||||
VARRAY_CHAR (may_not_move, REGNO (XEXP (x, 0))) = 1;
|
||||
|
||||
if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
|
||||
{
|
||||
dest = SET_DEST (x);
|
||||
while (GET_CODE (dest) == SUBREG
|
||||
|| GET_CODE (dest) == ZERO_EXTRACT
|
||||
|| GET_CODE (dest) == SIGN_EXTRACT
|
||||
|| GET_CODE (dest) == STRICT_LOW_PART)
|
||||
dest = XEXP (dest, 0);
|
||||
if (GET_CODE (dest) == REG)
|
||||
{
|
||||
register int regno = REGNO (dest);
|
||||
if (VARRAY_INT (n_times_set, regno) > 0
|
||||
&& last_set[regno] == 0)
|
||||
VARRAY_CHAR (may_not_move, regno) = 1;
|
||||
if (last_set[regno] != 0
|
||||
&& reg_used_between_p (dest, last_set[regno], insn))
|
||||
VARRAY_CHAR (may_not_move, regno) = 1;
|
||||
if (VARRAY_INT (n_times_set, regno) < 127)
|
||||
++VARRAY_INT (n_times_set, regno);
|
||||
last_set[regno] = insn;
|
||||
}
|
||||
}
|
||||
}
|
||||
count_one_set (insn, XVECEXP (PATTERN (insn), 0, i),
|
||||
may_not_move, last_set);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue