mirror of git://gcc.gnu.org/git/gcc.git
flow.c (find_basic_blocks): Calc upper bound for extra nops in max_uids_for_flow.
* flow.c (find_basic_blocks): Calc upper bound for extra nops in
max_uids_for_flow.
(find_basic_blocks_1): Add a nop to the end of a basic block when
a trailing call insn does not have abnormal control flow.
* gcse.c (pre_transpout): New variable.
(alloc_pre_mem, free_pre_mem, dump_pre_data): Bookkeeping for it.
(compute_pre_transpout): Calculate it.
(compute_pre_ppinout): Use it to eliminate impossible placements
due to abnormal control flow through calls.
(compute_pre_data): Call compute_pre_transpout.
From-SVN: r22907
This commit is contained in:
parent
58d9f9d9f2
commit
5c35539b1a
|
|
@ -1,3 +1,16 @@
|
||||||
|
Thu Oct 8 01:25:22 1998 Richard Henderson <rth@cygnus.com>
|
||||||
|
|
||||||
|
* flow.c (find_basic_blocks): Calc upper bound for extra nops in
|
||||||
|
max_uids_for_flow.
|
||||||
|
(find_basic_blocks_1): Add a nop to the end of a basic block when
|
||||||
|
a trailing call insn does not have abnormal control flow.
|
||||||
|
* gcse.c (pre_transpout): New variable.
|
||||||
|
(alloc_pre_mem, free_pre_mem, dump_pre_data): Bookkeeping for it.
|
||||||
|
(compute_pre_transpout): Calculate it.
|
||||||
|
(compute_pre_ppinout): Use it to eliminate impossible placements
|
||||||
|
due to abnormal control flow through calls.
|
||||||
|
(compute_pre_data): Call compute_pre_transpout.
|
||||||
|
|
||||||
Wed Oct 7 21:40:24 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
|
Wed Oct 7 21:40:24 1998 David S. Miller <davem@pierdol.cobaltmicro.com>
|
||||||
|
|
||||||
* config/sparc/sol2-sld-64.h (ASM_CPU_SPEC): Fix typo.
|
* config/sparc/sol2-sld-64.h (ASM_CPU_SPEC): Fix typo.
|
||||||
|
|
|
||||||
69
gcc/flow.c
69
gcc/flow.c
|
|
@ -306,6 +306,7 @@ find_basic_blocks (f, nregs, file, live_reachable_p)
|
||||||
register int i;
|
register int i;
|
||||||
rtx nonlocal_label_list = nonlocal_label_rtx_list ();
|
rtx nonlocal_label_list = nonlocal_label_rtx_list ();
|
||||||
int in_libcall_block = 0;
|
int in_libcall_block = 0;
|
||||||
|
int extra_uids_for_flow = 0;
|
||||||
|
|
||||||
/* Count the basic blocks. Also find maximum insn uid value used. */
|
/* Count the basic blocks. Also find maximum insn uid value used. */
|
||||||
|
|
||||||
|
|
@ -318,7 +319,6 @@ find_basic_blocks (f, nregs, file, live_reachable_p)
|
||||||
|
|
||||||
for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
|
for (insn = f, i = 0; insn; insn = NEXT_INSN (insn))
|
||||||
{
|
{
|
||||||
|
|
||||||
/* Track when we are inside in LIBCALL block. */
|
/* Track when we are inside in LIBCALL block. */
|
||||||
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
|
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
|
||||||
&& find_reg_note (insn, REG_LIBCALL, NULL_RTX))
|
&& find_reg_note (insn, REG_LIBCALL, NULL_RTX))
|
||||||
|
|
@ -327,13 +327,33 @@ find_basic_blocks (f, nregs, file, live_reachable_p)
|
||||||
code = GET_CODE (insn);
|
code = GET_CODE (insn);
|
||||||
if (INSN_UID (insn) > max_uid_for_flow)
|
if (INSN_UID (insn) > max_uid_for_flow)
|
||||||
max_uid_for_flow = INSN_UID (insn);
|
max_uid_for_flow = INSN_UID (insn);
|
||||||
if (code == CODE_LABEL
|
if (code == CODE_LABEL)
|
||||||
|| (GET_RTX_CLASS (code) == 'i'
|
|
||||||
&& (prev_code == JUMP_INSN
|
|
||||||
|| (prev_code == CALL_INSN
|
|
||||||
&& (nonlocal_label_list != 0 || eh_region))
|
|
||||||
|| prev_code == BARRIER)))
|
|
||||||
i++;
|
i++;
|
||||||
|
else if (GET_RTX_CLASS (code) == 'i')
|
||||||
|
{
|
||||||
|
if (prev_code == JUMP_INSN || prev_code == BARRIER)
|
||||||
|
i++;
|
||||||
|
else if (prev_code == CALL_INSN)
|
||||||
|
{
|
||||||
|
if (nonlocal_label_list != 0 || eh_region)
|
||||||
|
i++;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Else this call does not force a new block to be
|
||||||
|
created. However, it may still be the end of a basic
|
||||||
|
block if it is followed by a CODE_LABEL or a BARRIER.
|
||||||
|
|
||||||
|
To disambiguate calls which force new blocks to be
|
||||||
|
created from those which just happen to be at the end
|
||||||
|
of a block we insert nops during find_basic_blocks_1
|
||||||
|
after calls which are the last insn in a block by
|
||||||
|
chance. We must account for such insns in
|
||||||
|
max_uid_for_flow. */
|
||||||
|
|
||||||
|
extra_uids_for_flow++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* We change the code of the CALL_INSN, so that it won't start a
|
/* We change the code of the CALL_INSN, so that it won't start a
|
||||||
new block. */
|
new block. */
|
||||||
|
|
@ -360,6 +380,7 @@ find_basic_blocks (f, nregs, file, live_reachable_p)
|
||||||
These cases are rare, so we don't need too much space. */
|
These cases are rare, so we don't need too much space. */
|
||||||
max_uid_for_flow += max_uid_for_flow / 10;
|
max_uid_for_flow += max_uid_for_flow / 10;
|
||||||
#endif
|
#endif
|
||||||
|
max_uid_for_flow += extra_uids_for_flow;
|
||||||
|
|
||||||
/* Allocate some tables that last till end of compiling this function
|
/* Allocate some tables that last till end of compiling this function
|
||||||
and some needed only in find_basic_blocks and life_analysis. */
|
and some needed only in find_basic_blocks and life_analysis. */
|
||||||
|
|
@ -410,6 +431,7 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
|
||||||
int depth, pass;
|
int depth, pass;
|
||||||
int in_libcall_block = 0;
|
int in_libcall_block = 0;
|
||||||
int deleted_handler = 0;
|
int deleted_handler = 0;
|
||||||
|
int call_had_abnormal_edge = 0;
|
||||||
|
|
||||||
pass = 1;
|
pass = 1;
|
||||||
active_eh_region = (int *) alloca ((max_uid_for_flow + 1) * sizeof (int));
|
active_eh_region = (int *) alloca ((max_uid_for_flow + 1) * sizeof (int));
|
||||||
|
|
@ -456,8 +478,7 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
|
||||||
else if (code == CODE_LABEL
|
else if (code == CODE_LABEL
|
||||||
|| (GET_RTX_CLASS (code) == 'i'
|
|| (GET_RTX_CLASS (code) == 'i'
|
||||||
&& (prev_code == JUMP_INSN
|
&& (prev_code == JUMP_INSN
|
||||||
|| (prev_code == CALL_INSN
|
|| (prev_code == CALL_INSN && call_had_abnormal_edge)
|
||||||
&& (nonlocal_label_list != 0 || eh_note))
|
|
||||||
|| prev_code == BARRIER)))
|
|| prev_code == BARRIER)))
|
||||||
{
|
{
|
||||||
basic_block_head[++i] = insn;
|
basic_block_head[++i] = insn;
|
||||||
|
|
@ -466,12 +487,26 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
|
||||||
|
|
||||||
if (code == CODE_LABEL)
|
if (code == CODE_LABEL)
|
||||||
{
|
{
|
||||||
LABEL_REFS (insn) = insn;
|
LABEL_REFS (insn) = insn;
|
||||||
/* Any label that cannot be deleted
|
/* Any label that cannot be deleted
|
||||||
is considered to start a reachable block. */
|
is considered to start a reachable block. */
|
||||||
if (LABEL_PRESERVE_P (insn))
|
if (LABEL_PRESERVE_P (insn))
|
||||||
block_live[i] = 1;
|
block_live[i] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* If the previous insn was a call that did not create an
|
||||||
|
abnormal edge, we want to add a nop so that the CALL_INSN
|
||||||
|
itself is not at basic_block_end. This allows us to easily
|
||||||
|
distinguish between normal calls and those which create
|
||||||
|
abnormal edges in the flow graph. */
|
||||||
|
|
||||||
|
if (i > 0 && !call_had_abnormal_edge
|
||||||
|
&& GET_CODE (basic_block_end[i-1]) == CALL_INSN)
|
||||||
|
{
|
||||||
|
rtx nop = gen_rtx_USE (VOIDmode, const0_rtx);
|
||||||
|
nop = emit_insn_after (nop, basic_block_end[i-1]);
|
||||||
|
basic_block_end[i-1] = nop;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (GET_RTX_CLASS (code) == 'i')
|
else if (GET_RTX_CLASS (code) == 'i')
|
||||||
|
|
@ -524,6 +559,10 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
|
||||||
if (code == CALL_INSN && in_libcall_block)
|
if (code == CALL_INSN && in_libcall_block)
|
||||||
code = INSN;
|
code = INSN;
|
||||||
|
|
||||||
|
/* Record whether this call created an edge. */
|
||||||
|
if (code == CALL_INSN)
|
||||||
|
call_had_abnormal_edge = (nonlocal_label_list != 0 || eh_note);
|
||||||
|
|
||||||
if (code != NOTE)
|
if (code != NOTE)
|
||||||
prev_code = code;
|
prev_code = code;
|
||||||
|
|
||||||
|
|
|
||||||
81
gcc/gcse.c
81
gcc/gcse.c
|
|
@ -3888,6 +3888,11 @@ static sbitmap *pre_pavout;
|
||||||
static sbitmap *pre_ppin;
|
static sbitmap *pre_ppin;
|
||||||
static sbitmap *pre_ppout;
|
static sbitmap *pre_ppout;
|
||||||
|
|
||||||
|
/* Nonzero for expressions that are transparent at the end of the block.
|
||||||
|
This is only zero for expressions killed by abnormal critical edge
|
||||||
|
created by a calls. */
|
||||||
|
static sbitmap *pre_transpout;
|
||||||
|
|
||||||
/* Used while performing PRE to denote which insns are redundant. */
|
/* Used while performing PRE to denote which insns are redundant. */
|
||||||
static sbitmap pre_redundant;
|
static sbitmap pre_redundant;
|
||||||
|
|
||||||
|
|
@ -3910,6 +3915,8 @@ alloc_pre_mem (n_blocks, n_exprs)
|
||||||
pre_pavout = sbitmap_vector_alloc (n_blocks, n_exprs);
|
pre_pavout = sbitmap_vector_alloc (n_blocks, n_exprs);
|
||||||
pre_ppin = sbitmap_vector_alloc (n_blocks, n_exprs);
|
pre_ppin = sbitmap_vector_alloc (n_blocks, n_exprs);
|
||||||
pre_ppout = sbitmap_vector_alloc (n_blocks, n_exprs);
|
pre_ppout = sbitmap_vector_alloc (n_blocks, n_exprs);
|
||||||
|
|
||||||
|
pre_transpout = sbitmap_vector_alloc (n_blocks, n_exprs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Free vars used for PRE analysis. */
|
/* Free vars used for PRE analysis. */
|
||||||
|
|
@ -3920,7 +3927,6 @@ free_pre_mem ()
|
||||||
free (pre_transp);
|
free (pre_transp);
|
||||||
free (pre_comp);
|
free (pre_comp);
|
||||||
free (pre_antloc);
|
free (pre_antloc);
|
||||||
|
|
||||||
free (pre_avin);
|
free (pre_avin);
|
||||||
free (pre_avout);
|
free (pre_avout);
|
||||||
free (pre_antin);
|
free (pre_antin);
|
||||||
|
|
@ -3930,6 +3936,7 @@ free_pre_mem ()
|
||||||
free (pre_pavout);
|
free (pre_pavout);
|
||||||
free (pre_ppin);
|
free (pre_ppin);
|
||||||
free (pre_ppout);
|
free (pre_ppout);
|
||||||
|
free (pre_transpout);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Dump PRE data. */
|
/* Dump PRE data. */
|
||||||
|
|
@ -3962,6 +3969,9 @@ dump_pre_data (file)
|
||||||
pre_ppin, n_basic_blocks);
|
pre_ppin, n_basic_blocks);
|
||||||
dump_sbitmap_vector (file, "PRE placement possible on outgoing", "BB",
|
dump_sbitmap_vector (file, "PRE placement possible on outgoing", "BB",
|
||||||
pre_ppout, n_basic_blocks);
|
pre_ppout, n_basic_blocks);
|
||||||
|
|
||||||
|
dump_sbitmap_vector (file, "PRE transparent on outgoing", "BB",
|
||||||
|
pre_transpout, n_basic_blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Compute the local properties of each recorded expression.
|
/* Compute the local properties of each recorded expression.
|
||||||
|
|
@ -4129,6 +4139,57 @@ compute_pre_pavinout ()
|
||||||
fprintf (gcse_file, "partially avail expr computation: %d passes\n", passes);
|
fprintf (gcse_file, "partially avail expr computation: %d passes\n", passes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Compute transparent outgoing information for each block.
|
||||||
|
|
||||||
|
An expression is transparent to an edge unless it is killed by
|
||||||
|
the edge itself. This can only happen with abnormal control flow,
|
||||||
|
when the edge is traversed through a call. This happens with
|
||||||
|
non-local labels and exceptions.
|
||||||
|
|
||||||
|
This would not be necessary if we split the edge. While this is
|
||||||
|
normally impossible for abnormal critical edges, with some effort
|
||||||
|
it should be possible with exception handling, since we still have
|
||||||
|
control over which handler should be invoked. But due to increased
|
||||||
|
EH table sizes, this may not be worthwhile. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
compute_pre_transpout ()
|
||||||
|
{
|
||||||
|
int bb;
|
||||||
|
|
||||||
|
sbitmap_vector_ones (pre_transpout, n_basic_blocks);
|
||||||
|
|
||||||
|
for (bb = 0; bb < n_basic_blocks; ++bb)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Note that flow inserted a nop a the end of basic blocks that
|
||||||
|
end in call instructions for reasons other than abnormal
|
||||||
|
control flow. */
|
||||||
|
if (GET_CODE (BLOCK_END (bb)) != CALL_INSN)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (i = 0; i < expr_hash_table_size; i++)
|
||||||
|
{
|
||||||
|
struct expr *expr;
|
||||||
|
for (expr = expr_hash_table[i]; expr ; expr = expr->next_same_hash)
|
||||||
|
if (GET_CODE (expr->expr) == MEM)
|
||||||
|
{
|
||||||
|
rtx addr = XEXP (expr->expr, 0);
|
||||||
|
|
||||||
|
if (GET_CODE (addr) == SYMBOL_REF
|
||||||
|
&& CONSTANT_POOL_ADDRESS_P (addr))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* ??? Optimally, we would use interprocedural alias
|
||||||
|
analysis to determine if this mem is actually killed
|
||||||
|
by this call. */
|
||||||
|
RESET_BIT (pre_transpout[bb], expr->bitmap_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Compute "placement possible" information on entrance and exit of
|
/* Compute "placement possible" information on entrance and exit of
|
||||||
each block.
|
each block.
|
||||||
|
|
||||||
|
|
@ -4209,11 +4270,12 @@ compute_pre_ppinout ()
|
||||||
for (bb = 0; bb < n_basic_blocks - 1; bb++)
|
for (bb = 0; bb < n_basic_blocks - 1; bb++)
|
||||||
{
|
{
|
||||||
sbitmap_ptr ppout = pre_ppout[bb]->elms;
|
sbitmap_ptr ppout = pre_ppout[bb]->elms;
|
||||||
|
sbitmap_ptr transpout = pre_transpout[bb]->elms;
|
||||||
|
|
||||||
for (i = 0; i < size; i++)
|
for (i = 0; i < size; i++)
|
||||||
{
|
{
|
||||||
int_list_ptr succ;
|
int_list_ptr succ;
|
||||||
SBITMAP_ELT_TYPE tmp = -1L;
|
SBITMAP_ELT_TYPE tmp = *transpout;
|
||||||
|
|
||||||
for (succ = s_succs[bb]; succ != NULL; succ = succ->next)
|
for (succ = s_succs[bb]; succ != NULL; succ = succ->next)
|
||||||
{
|
{
|
||||||
|
|
@ -4226,13 +4288,14 @@ compute_pre_ppinout ()
|
||||||
ppin = pre_ppin[succ_bb]->elms + i;
|
ppin = pre_ppin[succ_bb]->elms + i;
|
||||||
tmp &= *ppin;
|
tmp &= *ppin;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*ppout != tmp)
|
if (*ppout != tmp)
|
||||||
{
|
{
|
||||||
changed = 1;
|
changed = 1;
|
||||||
*ppout++ = tmp;
|
*ppout = tmp;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
ppout++;
|
ppout++; transpout++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -4252,6 +4315,7 @@ compute_pre_data ()
|
||||||
compute_pre_avinout ();
|
compute_pre_avinout ();
|
||||||
compute_pre_antinout ();
|
compute_pre_antinout ();
|
||||||
compute_pre_pavinout ();
|
compute_pre_pavinout ();
|
||||||
|
compute_pre_transpout ();
|
||||||
compute_pre_ppinout ();
|
compute_pre_ppinout ();
|
||||||
if (gcse_file)
|
if (gcse_file)
|
||||||
fprintf (gcse_file, "\n");
|
fprintf (gcse_file, "\n");
|
||||||
|
|
@ -4376,10 +4440,7 @@ pre_insert_insn (expr, bb)
|
||||||
}
|
}
|
||||||
/* Likewise if the last insn is a call, as will happen in the presence
|
/* Likewise if the last insn is a call, as will happen in the presence
|
||||||
of exception handling. */
|
of exception handling. */
|
||||||
/* ??? The flag_exceptions test is not exact. We don't know if we are
|
else if (GET_CODE (insn) == CALL_INSN)
|
||||||
actually in an eh region. Fix flow to tell us this. */
|
|
||||||
else if (GET_CODE (insn) == CALL_INSN
|
|
||||||
&& (current_function_has_nonlocal_label || flag_exceptions))
|
|
||||||
{
|
{
|
||||||
HARD_REG_SET parm_regs;
|
HARD_REG_SET parm_regs;
|
||||||
int nparm_regs;
|
int nparm_regs;
|
||||||
|
|
@ -4409,7 +4470,7 @@ pre_insert_insn (expr, bb)
|
||||||
{
|
{
|
||||||
int regno = REGNO (XEXP (XEXP (p, 0), 0));
|
int regno = REGNO (XEXP (XEXP (p, 0), 0));
|
||||||
if (regno >= FIRST_PSEUDO_REGISTER)
|
if (regno >= FIRST_PSEUDO_REGISTER)
|
||||||
abort();
|
abort ();
|
||||||
SET_HARD_REG_BIT (parm_regs, regno);
|
SET_HARD_REG_BIT (parm_regs, regno);
|
||||||
nparm_regs++;
|
nparm_regs++;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue