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