NOTE_BASIC_BLOCK_BEGIN/END patches
Toshiyasu Morita
tm@netcom.com
Mon Aug 24 11:31:00 GMT 1998
Here's a patch to add NOTE_BASIC_BLOCK_BEGIN and NOTE_BASIC_BLOCK_END to
the current function; it's basically based on the code in flow.c but
hacked to add notes. It can be called multiple times; it will convert old
NOTEs to NOTE_INSN_DELETEDs.
This patch does not include modifications to any current compiler passes
to utilize the new information.
diff -rc egcs-19980816/gcc/flow.c egcs-19980816-hack/gcc/flow.c
*** egcs-19980816/gcc/flow.c Wed Jul 8 14:15:55 1998
--- egcs-19980816-hack/gcc/flow.c Fri Aug 21 12:49:34 1998
***************
*** 193,207 ****
int regset_size;
/* Element N is first insn in basic block N.
! This info lasts until we finish compiling the function. */
rtx *basic_block_head;
/* Element N is last insn in basic block N.
! This info lasts until we finish compiling the function. */
rtx *basic_block_end;
/* Element N indicates whether basic block N can be reached through a
computed jump. */
--- 193,219 ----
int regset_size;
/* Element N is first insn in basic block N.
! This info lasts until we finish compiling the function.
! Usage of this is deprecated; use new_basic_block_head instead. */
rtx *basic_block_head;
/* Element N is last insn in basic block N.
! This info lasts until we finish compiling the function.
! Usage of this is deprecated; use new_basic_block_tail instead. */
rtx *basic_block_end;
+ /* Element N is the NOTE_BASIC_BLOCK_BEGIN of block N.
+ This info should be valid for later passes of the compiler. */
+
+ rtx *new_basic_block_head;
+
+ /* Element N is the NOTE_BASIC_BLOCK_END of block N.
+ This info should be valid for later passes of the compiler. */
+
+ rtx *new_basic_block_tail;
+
/* Element N indicates whether basic block N can be reached through a
computed jump. */
***************
*** 287,292 ****
--- 299,471 ----
static void count_reg_sets_1 PROTO ((rtx));
static void count_reg_sets PROTO ((rtx));
static void count_reg_references PROTO ((rtx));
+
+ /* Holds the current block state */
+
+ typedef struct {
+
+ int in_libcall_block;
+ int nonlocal_label_list;
+ int eh_region;
+
+ } BLOCK_STATE;
+
+ /* Determines the start of a new basic block */
+
+ static int
+ check_new_block (code, prev_code, state)
+ RTX_CODE code, prev_code;
+ BLOCK_STATE *state;
+ {
+ if (code == CODE_LABEL
+ || (GET_RTX_CLASS (code) == 'i'
+ && (prev_code == JUMP_INSN
+ || (prev_code == CALL_INSN
+ && (state->nonlocal_label_list != 0 || state->eh_region)
+ && ! state->in_libcall_block)
+ || prev_code == BARRIER)))
+ return 1;
+
+ return 0;
+ }
+
+ /* Remove stale basic block notes */
+
+ static void
+ remove_basic_block_notes (start)
+ rtx start;
+ {
+ RTX_CODE curr_code;
+ rtx insn, next_insn;
+
+ for (insn = start; insn; insn = next_insn) {
+
+ curr_code = NOTE_LINE_NUMBER (insn);
+ next_insn = NEXT_INSN (insn);
+
+ if ((curr_code == NOTE_BASIC_BLOCK_BEGIN) ||
+ (curr_code == NOTE_BASIC_BLOCK_END))
+ {
+ PUT_CODE (insn, NOTE);
+ NOTE_LINE_NUMBER (insn) = NOTE_INSN_DELETED;
+ NOTE_SOURCE_FILE (insn) = 0;
+ }
+ }
+ }
+
+ /* Add first and last basic block notes */
+
+ static int
+ add_first_last_basic_block_notes(start)
+ rtx start;
+ {
+ rtx prev_insn, insn;
+
+ new_basic_block_head[0] =
+ emit_note_after (NOTE_BASIC_BLOCK_BEGIN, start);
+
+ for (prev_insn = insn = start; insn; insn = NEXT_INSN (insn))
+ prev_insn = insn;
+
+ new_basic_block_tail[0] =
+ emit_note_after (NOTE_BASIC_BLOCK_END, prev_insn);
+ }
+
+ /* Insert basic block notes into function.
+ This function is called twice; the first time with pass_flag = 0
+ to count the number of basic blocks, and the second time with
+ pass_flag = 1 to actually insert basic block notes. */
+
+ static int
+ find_new_basic_blocks_sub (start, pass_flag)
+ rtx start;
+ {
+ RTX_CODE curr_code, prev_code;
+ rtx insn;
+ BLOCK_STATE state;
+ int block_num;
+
+ if (!start)
+ return 1;
+
+ memset (&state, 0, sizeof(state));
+
+ block_num = 0;
+ prev_code = INSN;
+
+ for (insn = start; insn; insn = NEXT_INSN(insn))
+ {
+ curr_code = GET_CODE (insn);
+
+ if (curr_code == NOTE)
+ continue;
+
+ if (curr_code == CALL_INSN && find_reg_note (insn, REG_RETVAL,
NULL_RTX))
+ curr_code = INSN;
+
+ if (curr_code != NOTE)
+ prev_code = curr_code;
+ else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
+ ++state.eh_region;
+ else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_END)
+ --state.eh_region;
+
+ if (GET_RTX_CLASS (GET_CODE(insn)) == 'i'
+ && find_reg_note (insn, REG_LIBCALL, NULL_RTX))
+ state.in_libcall_block = 1;
+
+ if (check_new_block (curr_code, prev_code, &state)) {
+
+ if (pass_flag) {
+
+ if (block_num != -1)
+ new_basic_block_head[block_num] =
+ emit_note_before (NOTE_BASIC_BLOCK_END, insn);
+
+ new_basic_block_tail[++block_num] =
+ emit_note_before (NOTE_BASIC_BLOCK_BEGIN, insn);
+
+ } else
+ block_num++;
+ }
+
+ if (GET_RTX_CLASS (GET_CODE (insn)) == 'i'
+ && find_reg_note (insn, REG_RETVAL, NULL_RTX))
+ state.in_libcall_block = 0;
+
+ if (curr_code != NOTE)
+ prev_code = curr_code;
+ }
+
+ return block_num + 1;
+ }
+
+ /* Main function to mark the basic blocks.
+ This function calls routines to insert BASIC_BLOCK_START/END notes
+ at the appropriate points and updates the new_basic_block_head/tail
arrays
+ which point to aforementioned notes. This data will stay valid even
+ if other passes call emit_insn_before() on the first insn of a
+ basic block. */
+
+ int
+ find_new_basic_blocks (start)
+ rtx start;
+ {
+ int blocks_num;
+
+ remove_basic_block_notes (start);
+
+ blocks_num = find_new_basic_blocks_sub (start, 0);
+
+ new_basic_block_head = (rtx *)xmalloc (blocks_num * sizeof(rtx));
+ new_basic_block_tail = (rtx *)xmalloc (blocks_num * sizeof(rtx));
+
+ add_first_last_basic_block_notes(start);
+
+ if (blocks_num != 1)
+ find_new_basic_blocks_sub (start, 1);
+ }
+
^L
/* Find basic blocks of the current function.
F is the first insn of the function and NREGS the number of register
numbers
***************
*** 307,312 ****
--- 486,493 ----
rtx nonlocal_label_list = nonlocal_label_rtx_list ();
int in_libcall_block = 0;
+ find_new_basic_blocks(f);
+
/* Count the basic blocks. Also find maximum insn uid value used. */
{
diff -rc egcs-19980816/gcc/rtl.c egcs-19980816-hack/gcc/rtl.c
*** egcs-19980816/gcc/rtl.c Wed May 13 14:13:42 1998
--- egcs-19980816-hack/gcc/rtl.c Tue Aug 18 18:46:34 1998
***************
*** 173,179 ****
"NOTE_INSN_DELETED_LABEL",
"NOTE_INSN_FUNCTION_BEG",
"NOTE_INSN_EH_REGION_BEG",
"NOTE_INSN_EH_REGION_END",
"NOTE_REPEATED_LINE_NUMBER",
"NOTE_INSN_RANGE_START",
! "NOTE_INSN_RANGE_END", "NOTE_INSN_LIVE" };
char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV",
"REG_WAS_0",
"REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
--- 173,180 ----
"NOTE_INSN_DELETED_LABEL",
"NOTE_INSN_FUNCTION_BEG",
"NOTE_INSN_EH_REGION_BEG",
"NOTE_INSN_EH_REGION_END",
"NOTE_REPEATED_LINE_NUMBER",
"NOTE_INSN_RANGE_START",
! "NOTE_INSN_RANGE_END", "NOTE_INSN_LIVE",
! "NOTE_BASIC_BLOCK_BEGIN",
"NOTE_BASIC_BLOCK_END" };
char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV",
"REG_WAS_0",
"REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
More information about the Gcc-bugs
mailing list