diff options
author | Richard Henderson <rth@redhat.com> | 2001-07-28 19:10:42 -0700 |
---|---|---|
committer | Richard Henderson <rth@gcc.gnu.org> | 2001-07-28 19:10:42 -0700 |
commit | a20612aa8b221eff034088038287f16449bb9e09 (patch) | |
tree | e6828ba8212c1bd787e1ea3b54680bdef5677a3b /gcc/function.c | |
parent | 594280a3964b64125bc6259ee2fda308dfc01d36 (diff) | |
download | gcc-a20612aa8b221eff034088038287f16449bb9e09.zip gcc-a20612aa8b221eff034088038287f16449bb9e09.tar.gz gcc-a20612aa8b221eff034088038287f16449bb9e09.tar.bz2 |
dwarf2out.c (dw_val_class_offset): New.
* dwarf2out.c (dw_val_class_offset): New.
(struct dw_ranges_struct, dw_ranges_ref): New.
(ranges_table, ranges_table_allocated): New.
(ranges_table_in_use, RANGES_TABLE_INCREMENT): New.
(add_AT_offset, add_ranges, output_ranges): New.
(print_die, output_die): Handle dw_val_class_offset.
(attr_checksum, size_of_die, value_format): Likewise.
(gen_lexical_block_die): Handle non-contiguous blocks.
(gen_block_die): Likewise.
(dwarf2out_finish): Add a DW_AT_entry_pc to the compilation unit
if needed. Dump the ranges table.
* final.c (final_start_function): Remove unnecessary notes and
rebuild the block tree before numbering the blocks.
* function.c (reorder_blocks_0): Walk the existing block tree
to unmark all blocks.
(reorder_blocks_1): Create block fragments when duplicate block
notes are seen.
(reorder_fix_fragments): New.
(reorder_blocks): Call it.
* tree.h (BLOCK_FRAGMENT_ORIGIN, BLOCK_FRAGMENT_CHAIN): New.
From-SVN: r44444
Diffstat (limited to 'gcc/function.c')
-rw-r--r-- | gcc/function.c | 127 |
1 files changed, 94 insertions, 33 deletions
diff --git a/gcc/function.c b/gcc/function.c index 98894ba..4dec34e 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -278,8 +278,9 @@ static void pad_below PARAMS ((struct args_size *, enum machine_mode, static rtx round_trampoline_addr PARAMS ((rtx)); static rtx adjust_trampoline_addr PARAMS ((rtx)); static tree *identify_blocks_1 PARAMS ((rtx, tree *, tree *, tree *)); -static void reorder_blocks_0 PARAMS ((rtx)); +static void reorder_blocks_0 PARAMS ((tree)); static void reorder_blocks_1 PARAMS ((rtx, tree, varray_type *)); +static void reorder_fix_fragments PARAMS ((tree)); static tree blocks_nreverse PARAMS ((tree)); static int all_blocks PARAMS ((tree, tree *)); static tree *get_block_vector PARAMS ((tree, int *)); @@ -5819,8 +5820,11 @@ identify_blocks_1 (insns, block_vector, end_block_vector, orig_block_stack) return block_vector; } -/* Identify BLOCKs referenced by more than one - NOTE_INSN_BLOCK_{BEG,END}, and create duplicate blocks. */ +/* Identify BLOCKs referenced by more than one NOTE_INSN_BLOCK_{BEG,END}, + and create duplicate blocks. */ +/* ??? Need an option to either create block fragments or to create + abstract origin duplicates of a source block. It really depends + on what optimization has been performed. */ void reorder_blocks () @@ -5833,47 +5837,34 @@ reorder_blocks () VARRAY_TREE_INIT (block_stack, 10, "block_stack"); + /* Reset the TREE_ASM_WRITTEN bit for all blocks. */ + reorder_blocks_0 (block); + /* Prune the old trees away, so that they don't get in the way. */ BLOCK_SUBBLOCKS (block) = NULL_TREE; BLOCK_CHAIN (block) = NULL_TREE; - reorder_blocks_0 (get_insns ()); + /* Recreate the block tree from the note nesting. */ reorder_blocks_1 (get_insns (), block, &block_stack); - BLOCK_SUBBLOCKS (block) = blocks_nreverse (BLOCK_SUBBLOCKS (block)); + /* Remove deleted blocks from the block fragment chains. */ + reorder_fix_fragments (block); + VARRAY_FREE (block_stack); } -/* Helper function for reorder_blocks. Process the insn chain beginning - at INSNS. Recurse for CALL_PLACEHOLDER insns. */ +/* Helper function for reorder_blocks. Reset TREE_ASM_WRITTEN. */ static void -reorder_blocks_0 (insns) - rtx insns; +reorder_blocks_0 (block) + tree block; { - rtx insn; - - for (insn = insns; insn; insn = NEXT_INSN (insn)) + while (block) { - if (GET_CODE (insn) == NOTE) - { - if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG) - { - tree block = NOTE_BLOCK (insn); - TREE_ASM_WRITTEN (block) = 0; - } - } - else if (GET_CODE (insn) == CALL_INSN - && GET_CODE (PATTERN (insn)) == CALL_PLACEHOLDER) - { - rtx cp = PATTERN (insn); - reorder_blocks_0 (XEXP (cp, 0)); - if (XEXP (cp, 1)) - reorder_blocks_0 (XEXP (cp, 1)); - if (XEXP (cp, 2)) - reorder_blocks_0 (XEXP (cp, 2)); - } + TREE_ASM_WRITTEN (block) = 0; + reorder_blocks_0 (BLOCK_SUBBLOCKS (block)); + block = BLOCK_CHAIN (block); } } @@ -5892,12 +5883,26 @@ reorder_blocks_1 (insns, current_block, p_block_stack) if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG) { tree block = NOTE_BLOCK (insn); - /* If we have seen this block before, copy it. */ + + /* If we have seen this block before, that means it now + spans multiple address regions. Create a new fragment. */ if (TREE_ASM_WRITTEN (block)) { - block = copy_node (block); - NOTE_BLOCK (insn) = block; + tree new_block = copy_node (block); + tree origin; + + origin = (BLOCK_FRAGMENT_ORIGIN (block) + ? BLOCK_FRAGMENT_ORIGIN (block) + : block); + BLOCK_FRAGMENT_ORIGIN (new_block) = origin; + BLOCK_FRAGMENT_CHAIN (new_block) + = BLOCK_FRAGMENT_CHAIN (origin); + BLOCK_FRAGMENT_CHAIN (origin) = new_block; + + NOTE_BLOCK (insn) = new_block; + block = new_block; } + BLOCK_SUBBLOCKS (block) = 0; TREE_ASM_WRITTEN (block) = 1; BLOCK_SUPERCONTEXT (block) = current_block; @@ -5928,6 +5933,62 @@ reorder_blocks_1 (insns, current_block, p_block_stack) } } +/* Rationalize BLOCK_FRAGMENT_ORIGIN. If an origin block no longer + appears in the block tree, select one of the fragments to become + the new origin block. */ + +static void +reorder_fix_fragments (block) + tree block; +{ + while (block) + { + tree dup_origin = BLOCK_FRAGMENT_ORIGIN (block); + tree new_origin = NULL_TREE; + + if (dup_origin) + { + if (! TREE_ASM_WRITTEN (dup_origin)) + { + new_origin = BLOCK_FRAGMENT_CHAIN (dup_origin); + + /* Find the first of the remaining fragments. There must + be at least one -- the current block. */ + while (! TREE_ASM_WRITTEN (new_origin)) + new_origin = BLOCK_FRAGMENT_CHAIN (new_origin); + BLOCK_FRAGMENT_ORIGIN (new_origin) = NULL_TREE; + } + } + else if (! dup_origin) + new_origin = block; + + /* Re-root the rest of the fragments to the new origin. In the + case that DUP_ORIGIN was null, that means BLOCK was the origin + of a chain of fragments and we want to remove those fragments + that didn't make it to the output. */ + if (new_origin) + { + tree *pp = &BLOCK_FRAGMENT_CHAIN (new_origin); + tree chain = *pp; + + while (chain) + { + if (TREE_ASM_WRITTEN (chain)) + { + BLOCK_FRAGMENT_ORIGIN (chain) = new_origin; + *pp = chain; + pp = &BLOCK_FRAGMENT_CHAIN (chain); + } + chain = BLOCK_FRAGMENT_CHAIN (chain); + } + *pp = NULL_TREE; + } + + reorder_fix_fragments (BLOCK_SUBBLOCKS (block)); + block = BLOCK_CHAIN (block); + } +} + /* Reverse the order of elements in the chain T of blocks, and return the new head of the chain (old last element). */ |