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:
Bernd Schmidt 1998-10-06 14:38:40 -06:00 committed by Jeff Law
parent 9a07247c2a
commit a4c3ddd83a
4 changed files with 124 additions and 218 deletions

View file

@ -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.

View file

@ -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.

View file

@ -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 ();

View file

@ -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);
}
}