emit-rtl.c (subreg_hard_regno): Check that register is representable.

* emit-rtl.c (subreg_hard_regno):  Check that register is representable.
	* reload.c (reload_inner_reg_of_subreg):  When register is not
	representable, reload the whole thing.
	(find_reloads): Likewsie.
	* rtlanal.c (subreg_representable_p):  New function.

	* profile.c (compute_branch_probabilities):  Cleanup sanity checking;
	allow negative probabilities for edges from the call to exit.
	(branch_prob): Do not add fake edges for functions that may return twice

From-SVN: r65757
This commit is contained in:
Jan Hubicka 2003-04-18 01:31:41 +02:00 committed by Jan Hubicka
parent c409ea0d30
commit 04c5580f37
6 changed files with 155 additions and 61 deletions

View File

@ -1,3 +1,15 @@
Fri Apr 18 01:28:51 CEST 2003 Jan Hubicka <jh@suse.cz>
* emit-rtl.c (subreg_hard_regno): Check that register is representable.
* reload.c (reload_inner_reg_of_subreg): When register is not
representable, reload the whole thing.
(find_reloads): Likewsie.
* rtlanal.c (subreg_representable_p): New function.
* profile.c (compute_branch_probabilities): Cleanup sanity checking;
allow negative probabilities for edges from the call to exit.
(branch_prob): Do not add fake edges for functions that may return twice
2003-04-17 DJ Delorie <dj@redhat.com>
* toplev.c (target_options): Add value field.

View File

@ -1081,7 +1081,11 @@ subreg_hard_regno (x, check_mode)
abort ();
if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
abort ();
#ifdef ENABLE_CHECKING
if (!subreg_offset_representable_p (REGNO (reg), GET_MODE (reg),
SUBREG_BYTE (x), mode))
abort ();
#endif
/* Catch non-congruent offsets too. */
byte_offset = SUBREG_BYTE (x);
if ((byte_offset % GET_MODE_SIZE (mode)) != 0)

View File

@ -674,22 +674,47 @@ compute_branch_probabilities ()
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
{
edge e;
gcov_type total;
rtx note;
total = bb->count;
if (total)
if (bb->count < 0)
{
error ("corrupted profile info: number of iterations for basic block %d thought to be %i",
bb->index, (int)bb->count);
bb->count = 0;
}
for (e = bb->succ; e; e = e->succ_next)
{
/* Function may return twice in the cased the called fucntion is
setjmp or calls fork, but we can't represent this by extra
edge from the entry, since extra edge from the exit is
already present. We get negative frequency from the entry
point. */
if ((e->count < 0
&& e->dest == EXIT_BLOCK_PTR)
|| (e->count > bb->count
&& e->dest != EXIT_BLOCK_PTR))
{
rtx insn = bb->end;
while (GET_CODE (insn) != CALL_INSN
&& insn != bb->head
&& keep_with_call_p (insn))
insn = PREV_INSN (insn);
if (GET_CODE (insn) == CALL_INSN)
e->count = e->count < 0 ? 0 : bb->count;
}
if (e->count < 0 || e->count > bb->count)
{
error ("corrupted profile info: number of executions for edge %d-%d thought to be %i",
e->src->index, e->dest->index,
(int)e->count);
e->count = bb->count / 2;
}
}
if (bb->count)
{
for (e = bb->succ; e; e = e->succ_next)
{
e->probability = (e->count * REG_BR_PROB_BASE + total / 2) / total;
if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
{
error ("corrupted profile info: prob for %d-%d thought to be %d",
e->src->index, e->dest->index, e->probability);
e->probability = REG_BR_PROB_BASE / 2;
}
}
e->probability = (e->count * REG_BR_PROB_BASE + bb->count / 2) / bb->count;
if (bb->index >= 0
&& any_condjump_p (bb->end)
&& bb->succ->succ_next)
@ -730,6 +755,8 @@ compute_branch_probabilities ()
calls). */
else
{
int total = 0;
for (e = bb->succ; e; e = e->succ_next)
if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
total ++;
@ -873,36 +900,13 @@ branch_prob ()
{
int need_exit_edge = 0, need_entry_edge = 0;
int have_exit_edge = 0, have_entry_edge = 0;
rtx insn;
edge e;
/* Add fake edges from entry block to the call insns that may return
twice. The CFG is not quite correct then, as call insn plays more
role of CODE_LABEL, but for our purposes, everything should be OK,
as we never insert code to the beginning of basic block. */
for (insn = bb->head; insn != NEXT_INSN (bb->end);
insn = NEXT_INSN (insn))
{
if (GET_CODE (insn) == CALL_INSN
&& find_reg_note (insn, REG_SETJMP, NULL))
{
if (GET_CODE (bb->head) == CODE_LABEL
|| insn != NEXT_INSN (bb->head))
{
e = split_block (bb, PREV_INSN (insn));
make_edge (ENTRY_BLOCK_PTR, e->dest, EDGE_FAKE);
break;
}
else
{
/* We should not get abort here, as call to setjmp should not
be the very first instruction of function. */
if (bb == ENTRY_BLOCK_PTR)
abort ();
make_edge (ENTRY_BLOCK_PTR, bb, EDGE_FAKE);
}
}
}
/* Functions returning multiple times are not handled by extra edges.
Instead we simply allow negative counts on edges from exit to the
block past call and corresponding probabilities. We can't go
with the extra edges because that would result in flowgraph that
needs to have fake edges outside the spanning tree. */
for (e = bb->succ; e; e = e->succ_next)
{

View File

@ -2880,6 +2880,12 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
if (GET_CODE (SUBREG_REG (operand)) == REG
&& REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER)
{
if (!subreg_offset_representable_p
(REGNO (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)),
SUBREG_BYTE (operand),
GET_MODE (operand)))
force_reload = 1;
offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)),
SUBREG_BYTE (operand),
@ -2935,26 +2941,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
)
#endif
)
/* This following hunk of code should no longer be
needed at all with SUBREG_BYTE. If you need this
code back, please explain to me why so I can
fix the real problem. -DaveM */
#if 0
/* Subreg of a hard reg which can't handle the subreg's mode
or which would handle that mode in the wrong number of
registers for subregging to work. */
|| (GET_CODE (operand) == REG
&& REGNO (operand) < FIRST_PSEUDO_REGISTER
&& ((GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (operand))
> UNITS_PER_WORD)
&& ((GET_MODE_SIZE (GET_MODE (operand))
/ UNITS_PER_WORD)
!= HARD_REGNO_NREGS (REGNO (operand),
GET_MODE (operand))))
|| ! HARD_REGNO_MODE_OK (REGNO (operand) + offset,
operand_mode[i])))
#endif
)
force_reload = 1;
}
@ -5272,6 +5258,19 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
SUBREG_BYTE (orig_op1),
GET_MODE (orig_op1))));
}
/* Plus in the index register may be created only as a result of
register remateralization for expresion like &localvar*4. Reload it.
It may be possible to combine the displacement on the outer level,
but it is probably not worthwhile to do so. */
if (context)
{
find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
opnum, ADDR_TYPE (type), ind_levels, insn);
push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
(context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
GET_MODE (x), VOIDmode, 0, 0, opnum, type);
return 1;
}
if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
|| code0 == ZERO_EXTEND || code1 == MEM)

View File

@ -1038,6 +1038,10 @@ extern unsigned int subreg_regno_offset PARAMS ((unsigned int,
enum machine_mode,
unsigned int,
enum machine_mode));
extern bool subreg_offset_representable_p PARAMS ((unsigned int,
enum machine_mode,
unsigned int,
enum machine_mode));
extern unsigned int subreg_regno PARAMS ((rtx));
/* 1 if RTX is a subreg containing a reg that is already known to be

View File

@ -3387,6 +3387,77 @@ subreg_regno_offset (xregno, xmode, offset, ymode)
return (y_offset / (mode_multiple / nregs_multiple)) * nregs_ymode;
}
/* This function returns true when the offset is representable via
subreg_offset in the given regno.
xregno - A regno of an inner hard subreg_reg (or what will become one).
xmode - The mode of xregno.
offset - The byte offset.
ymode - The mode of a top level SUBREG (or what may become one).
RETURN - The regno offset which would be used. */
bool
subreg_offset_representable_p (xregno, xmode, offset, ymode)
unsigned int xregno;
enum machine_mode xmode;
unsigned int offset;
enum machine_mode ymode;
{
int nregs_xmode, nregs_ymode;
int mode_multiple, nregs_multiple;
int y_offset;
if (xregno >= FIRST_PSEUDO_REGISTER)
abort ();
nregs_xmode = HARD_REGNO_NREGS (xregno, xmode);
nregs_ymode = HARD_REGNO_NREGS (xregno, ymode);
/* paradoxical subregs are always valid. */
if (offset == 0
&& nregs_ymode > nregs_xmode
&& (GET_MODE_SIZE (ymode) > UNITS_PER_WORD
? WORDS_BIG_ENDIAN : BYTES_BIG_ENDIAN))
return true;
/* Lowpart subregs are always valid. */
if (offset == subreg_lowpart_offset (ymode, xmode))
return true;
#ifdef ENABLE_CHECKING
/* This should always pass, otherwise we don't know how to verify the
constraint.
These conditions may be relaxed but subreg_offset would need to be
redesigned. */
if (GET_MODE_SIZE (xmode) % GET_MODE_SIZE (ymode)
|| GET_MODE_SIZE (ymode) % nregs_ymode
|| mode_for_size (GET_MODE_SIZE (ymode) / nregs_ymode,
MODE_INT, 0) == VOIDmode
|| nregs_xmode % nregs_ymode)
abort ();
#endif
/* The XMODE value can be seen as an vector of NREGS_XMODE
values. The subreg must represent an lowpart of given field.
Compute what field it is. */
offset -= subreg_lowpart_offset (mode_for_size (GET_MODE_SIZE (ymode)
/ nregs_ymode,
MODE_INT, 0), xmode);
/* size of ymode must not be greater than the size of xmode. */
mode_multiple = GET_MODE_SIZE (xmode) / GET_MODE_SIZE (ymode);
if (mode_multiple == 0)
abort ();
y_offset = offset / GET_MODE_SIZE (ymode);
nregs_multiple = nregs_xmode / nregs_ymode;
#ifdef ENABLE_CHECKING
if (offset % GET_MODE_SIZE (ymode)
|| mode_multiple % nregs_multiple)
abort ();
#endif
return (!(y_offset % (mode_multiple / nregs_multiple)));
}
/* Return the final regno that a subreg expression refers to. */
unsigned int
subreg_regno (x)