Commit 04c5580f by Jan Hubicka Committed by Jan Hubicka

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
parent c409ea0d
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> 2003-04-17 DJ Delorie <dj@redhat.com>
* toplev.c (target_options): Add value field. * toplev.c (target_options): Add value field.
......
...@@ -1081,7 +1081,11 @@ subreg_hard_regno (x, check_mode) ...@@ -1081,7 +1081,11 @@ subreg_hard_regno (x, check_mode)
abort (); abort ();
if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg))) if (check_mode && ! HARD_REGNO_MODE_OK (base_regno, GET_MODE (reg)))
abort (); 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. */ /* Catch non-congruent offsets too. */
byte_offset = SUBREG_BYTE (x); byte_offset = SUBREG_BYTE (x);
if ((byte_offset % GET_MODE_SIZE (mode)) != 0) if ((byte_offset % GET_MODE_SIZE (mode)) != 0)
......
...@@ -674,22 +674,47 @@ compute_branch_probabilities () ...@@ -674,22 +674,47 @@ compute_branch_probabilities ()
FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb) FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR, NULL, next_bb)
{ {
edge e; edge e;
gcov_type total;
rtx note; rtx note;
total = bb->count; if (bb->count < 0)
if (total)
{ {
for (e = bb->succ; e; e = e->succ_next) 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))
{ {
e->probability = (e->count * REG_BR_PROB_BASE + total / 2) / total; rtx insn = bb->end;
if (e->probability < 0 || e->probability > REG_BR_PROB_BASE)
{ while (GET_CODE (insn) != CALL_INSN
error ("corrupted profile info: prob for %d-%d thought to be %d", && insn != bb->head
e->src->index, e->dest->index, e->probability); && keep_with_call_p (insn))
e->probability = REG_BR_PROB_BASE / 2; 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 + bb->count / 2) / bb->count;
if (bb->index >= 0 if (bb->index >= 0
&& any_condjump_p (bb->end) && any_condjump_p (bb->end)
&& bb->succ->succ_next) && bb->succ->succ_next)
...@@ -730,6 +755,8 @@ compute_branch_probabilities () ...@@ -730,6 +755,8 @@ compute_branch_probabilities ()
calls). */ calls). */
else else
{ {
int total = 0;
for (e = bb->succ; e; e = e->succ_next) for (e = bb->succ; e; e = e->succ_next)
if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE))) if (!(e->flags & (EDGE_COMPLEX | EDGE_FAKE)))
total ++; total ++;
...@@ -873,36 +900,13 @@ branch_prob () ...@@ -873,36 +900,13 @@ branch_prob ()
{ {
int need_exit_edge = 0, need_entry_edge = 0; int need_exit_edge = 0, need_entry_edge = 0;
int have_exit_edge = 0, have_entry_edge = 0; int have_exit_edge = 0, have_entry_edge = 0;
rtx insn;
edge e; edge e;
/* Add fake edges from entry block to the call insns that may return /* Functions returning multiple times are not handled by extra edges.
twice. The CFG is not quite correct then, as call insn plays more Instead we simply allow negative counts on edges from exit to the
role of CODE_LABEL, but for our purposes, everything should be OK, block past call and corresponding probabilities. We can't go
as we never insert code to the beginning of basic block. */ with the extra edges because that would result in flowgraph that
for (insn = bb->head; insn != NEXT_INSN (bb->end); needs to have fake edges outside the spanning tree. */
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);
}
}
}
for (e = bb->succ; e; e = e->succ_next) for (e = bb->succ; e; e = e->succ_next)
{ {
......
...@@ -2880,6 +2880,12 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) ...@@ -2880,6 +2880,12 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
if (GET_CODE (SUBREG_REG (operand)) == REG if (GET_CODE (SUBREG_REG (operand)) == REG
&& REGNO (SUBREG_REG (operand)) < FIRST_PSEUDO_REGISTER) && 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)), offset += subreg_regno_offset (REGNO (SUBREG_REG (operand)),
GET_MODE (SUBREG_REG (operand)), GET_MODE (SUBREG_REG (operand)),
SUBREG_BYTE (operand), SUBREG_BYTE (operand),
...@@ -2935,26 +2941,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) ...@@ -2935,26 +2941,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
) )
#endif #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; force_reload = 1;
} }
...@@ -5272,6 +5258,19 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn) ...@@ -5272,6 +5258,19 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
SUBREG_BYTE (orig_op1), SUBREG_BYTE (orig_op1),
GET_MODE (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 if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
|| code0 == ZERO_EXTEND || code1 == MEM) || code0 == ZERO_EXTEND || code1 == MEM)
......
...@@ -1038,6 +1038,10 @@ extern unsigned int subreg_regno_offset PARAMS ((unsigned int, ...@@ -1038,6 +1038,10 @@ extern unsigned int subreg_regno_offset PARAMS ((unsigned int,
enum machine_mode, enum machine_mode,
unsigned int, unsigned int,
enum machine_mode)); 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)); extern unsigned int subreg_regno PARAMS ((rtx));
/* 1 if RTX is a subreg containing a reg that is already known to be /* 1 if RTX is a subreg containing a reg that is already known to be
......
...@@ -3387,6 +3387,77 @@ subreg_regno_offset (xregno, xmode, offset, ymode) ...@@ -3387,6 +3387,77 @@ subreg_regno_offset (xregno, xmode, offset, ymode)
return (y_offset / (mode_multiple / nregs_multiple)) * nregs_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. */ /* Return the final regno that a subreg expression refers to. */
unsigned int unsigned int
subreg_regno (x) subreg_regno (x)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment