aboutsummaryrefslogtreecommitdiff
path: root/gcc/flow.c
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>1998-10-07 18:26:18 -0700
committerRichard Henderson <rth@gcc.gnu.org>1998-10-07 18:26:18 -0700
commit5c35539b1ab41da8800ebb1fdc983237a7d9cdd7 (patch)
tree89dcc7e1ae801c171115e2585b049fc5366cbe4d /gcc/flow.c
parent58d9f9d9f2e32f6b1d15e1e9f30a8aadc1d31d92 (diff)
downloadgcc-5c35539b1ab41da8800ebb1fdc983237a7d9cdd7.zip
gcc-5c35539b1ab41da8800ebb1fdc983237a7d9cdd7.tar.gz
gcc-5c35539b1ab41da8800ebb1fdc983237a7d9cdd7.tar.bz2
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
Diffstat (limited to 'gcc/flow.c')
-rw-r--r--gcc/flow.c69
1 files changed, 54 insertions, 15 deletions
diff --git a/gcc/flow.c b/gcc/flow.c
index d602436..773aaf2 100644
--- a/gcc/flow.c
+++ b/gcc/flow.c
@@ -306,6 +306,7 @@ find_basic_blocks (f, nregs, file, live_reachable_p)
register int i;
rtx nonlocal_label_list = nonlocal_label_rtx_list ();
int in_libcall_block = 0;
+ int extra_uids_for_flow = 0;
/* 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))
{
-
/* Track when we are inside in LIBCALL block. */
if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
&& 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);
if (INSN_UID (insn) > max_uid_for_flow)
max_uid_for_flow = INSN_UID (insn);
- 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)))
+ if (code == CODE_LABEL)
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
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. */
max_uid_for_flow += max_uid_for_flow / 10;
#endif
+ max_uid_for_flow += extra_uids_for_flow;
/* Allocate some tables that last till end of compiling this function
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 in_libcall_block = 0;
int deleted_handler = 0;
+ int call_had_abnormal_edge = 0;
pass = 1;
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
|| (GET_RTX_CLASS (code) == 'i'
&& (prev_code == JUMP_INSN
- || (prev_code == CALL_INSN
- && (nonlocal_label_list != 0 || eh_note))
+ || (prev_code == CALL_INSN && call_had_abnormal_edge)
|| prev_code == BARRIER)))
{
basic_block_head[++i] = insn;
@@ -466,12 +487,26 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
if (code == CODE_LABEL)
{
- LABEL_REFS (insn) = insn;
- /* Any label that cannot be deleted
- is considered to start a reachable block. */
- if (LABEL_PRESERVE_P (insn))
- block_live[i] = 1;
- }
+ LABEL_REFS (insn) = insn;
+ /* Any label that cannot be deleted
+ is considered to start a reachable block. */
+ if (LABEL_PRESERVE_P (insn))
+ 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')
@@ -524,6 +559,10 @@ find_basic_blocks_1 (f, nonlocal_label_list, live_reachable_p)
if (code == CALL_INSN && in_libcall_block)
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)
prev_code = code;