diff options
author | Richard Henderson <rth@cygnus.com> | 1998-10-07 18:26:18 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 1998-10-07 18:26:18 -0700 |
commit | 5c35539b1ab41da8800ebb1fdc983237a7d9cdd7 (patch) | |
tree | 89dcc7e1ae801c171115e2585b049fc5366cbe4d /gcc/flow.c | |
parent | 58d9f9d9f2e32f6b1d15e1e9f30a8aadc1d31d92 (diff) | |
download | gcc-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.c | 69 |
1 files changed, 54 insertions, 15 deletions
@@ -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; |