2000-03-18 Mark Mitchell <mark@codesourcery.com>
+ * emit-rtl.c (remove_unncessary_notes): Check that all
+ NOTE_INSN_BLOCK_BEG and NOTE_INSN_BLOCK_END notes have an
+ associated NOTE_BLOCK.
+ * function.h (identify_blocks): Update comments.
+ (reorder_blocks): Declare.
+ * function.c (identify_blocks): Don't take paramters.
+ (reorder_blocks): Don't take parameters.
+ * loop.h (find_loop_tree_blocks): Remove.
+ (unroll_block_trees): Likewise.
+ * loop.c (loop_optimize): Don't call find_loop_tree_blocks. Use
+ reorder_blocks instead of unroll_block_trees.h
+ * sibcall.c (optimize_sibling_and_tail_recursive_calls): Likewise.
+ * stmt.c (find_loop_tree_blocks): Remove.
+ (unroll_block_trees): Likewise.
+ * toplev.c (rest_of_compilation): Don't call find_loop_tree_blocks
+ in whole-function mode.
+ * tree.h (reorder_blocks): Remove declaration.
+
* expr.c: Include intl.h.
* Makefile.in (expr.o): Depend on intl.h.
rtx insn;
rtx next;
- /* Remove NOTE_INSN_DELETED notes. We must not remove the first
- instruction in the function because the compiler depends on the
- first instruction being a note. */
+ /* We must not remove the first instruction in the function because
+ the compiler depends on the first instruction being a note. */
for (insn = NEXT_INSN (get_insns ()); insn; insn = next)
{
/* Remember what's next. */
if (GET_CODE (insn) != NOTE)
continue;
+ /* By now, all notes indicating lexical blocks should have
+ NOTE_BLOCK filled in. */
+ if ((NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
+ || NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
+ && NOTE_BLOCK (insn) == NULL_TREE)
+ abort ();
+
+ /* Remove NOTE_INSN_DELETED notes. */
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_DELETED)
remove_insn (insn);
else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END)
return tramp;
}
\f
-/* The functions identify_blocks and reorder_blocks provide a way to
- reorder the tree of BLOCK nodes, for optimizers that reshuffle or
- duplicate portions of the RTL code. Call identify_blocks before
- changing the RTL, and call reorder_blocks after. */
-
/* Put all this function's BLOCK nodes including those that are chained
onto the first block into a vector, and return it.
Also store in each NOTE for the beginning or end of a block
and INSNS, the insn chain of the function. */
void
-identify_blocks (block, insns)
- tree block;
- rtx insns;
+identify_blocks ()
{
int n_blocks;
tree *block_vector, *last_block_vector;
tree *block_stack;
+ tree block = DECL_INITIAL (current_function_decl);
if (block == 0)
return;
block_vector = get_block_vector (block, &n_blocks);
block_stack = (tree *) xmalloc (n_blocks * sizeof (tree));
- last_block_vector = identify_blocks_1 (insns, block_vector + 1,
- block_vector + n_blocks, block_stack);
+ last_block_vector = identify_blocks_1 (get_insns (),
+ block_vector + 1,
+ block_vector + n_blocks,
+ block_stack);
/* If we didn't use all of the subblocks, we've misplaced block notes. */
/* ??? This appears to happen all the time. Latent bugs elsewhere? */
return block_vector;
}
-/* Given a revised instruction chain, rebuild the tree structure of
- BLOCK nodes to correspond to the new order of RTL. The new block
- tree is inserted below TOP_BLOCK. Returns the current top-level
- block. */
+/* Identify BLOCKs referenced by more than one
+ NOTE_INSN_BLOCK_{BEG,END}, and create duplicate blocks. */
-tree
-reorder_blocks (block, insns)
- tree block;
- rtx insns;
+void
+reorder_blocks ()
{
- tree current_block = block;
+ tree block = DECL_INITIAL (current_function_decl);
varray_type block_stack;
if (block == NULL_TREE)
- return NULL_TREE;
+ return;
VARRAY_TREE_INIT (block_stack, 10, "block_stack");
- /* Prune the old trees away, so that it doesn't get in the way. */
- BLOCK_SUBBLOCKS (current_block) = 0;
- BLOCK_CHAIN (current_block) = 0;
+ /* 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_1 (insns, current_block, &block_stack);
+ reorder_blocks_1 (get_insns (), block, &block_stack);
- BLOCK_SUBBLOCKS (current_block)
- = blocks_nreverse (BLOCK_SUBBLOCKS (current_block));
+ BLOCK_SUBBLOCKS (block)
+ = blocks_nreverse (BLOCK_SUBBLOCKS (block));
VARRAY_FREE (block_stack);
-
- return current_block;
}
/* Helper function for reorder_blocks. Process the insn chain beginning
/* Nonzero if this function is being processed in function-at-a-time
mode. In other words, if all tree structure for this function,
- including the BLOCK tree is created, before RTL generation
+ including the BLOCK tree, is created before RTL generation
commences. */
int x_whole_function_mode_p;
/* Pointer to chain of `struct function' for containing functions. */
extern struct function *outer_function_chain;
-/* Put all this function's BLOCK nodes into a vector and return it.
- Also store in each NOTE for the beginning or end of a block
- the index of that block in the vector. */
-extern void identify_blocks PARAMS ((tree, rtx));
+/* Set NOTE_BLOCK for each block note in the current function. */
+extern void identify_blocks PARAMS ((void));
+
+/* Identify BLOCKs referenced by more than one NOTE_INSN_BLOCK_{BEG,END},
+ and create duplicate blocks. */
+extern void reorder_blocks PARAMS ((void));
/* Set BLOCK_NUMBER for all the blocks in FN. */
extern void number_blocks PARAMS ((tree));
if (uid_luid[i] == 0)
uid_luid[i] = uid_luid[i - 1];
- /* If debugging and unrolling loops, we must replicate the tree
- nodes corresponding to the BLOCKs inside the loop, so that the
- original one to one mapping will remain. We sometimes unroll
- loops even when unroll_p is false, so we must always do this when
- debugging. */
- if (write_symbols != NO_DEBUG)
- find_loop_tree_blocks ();
-
/* Determine if the function has indirect jump. On some systems
this prevents low overhead loop instructions from being used. */
indirect_jump_in_function = indirect_jump_in_function_p (f);
scan_loop (loop, unroll_p, bct_p);
}
- /* Replicate the BLOCKs. */
+ /* If there were lexical blocks inside the loop, they have been
+ replicated. We will now have more than one NOTE_INSN_BLOCK_BEG
+ and NOTE_INSN_BLOCK_END for each such block. We must duplicate
+ the BLOCKs as well. */
if (write_symbols != NO_DEBUG)
- unroll_block_trees ();
+ reorder_blocks ();
end_alias_analysis ();
int loop_insn_first_p PARAMS ((rtx, rtx));
-/* Forward declarations for non-static functions declared in stmt.c. */
-void find_loop_tree_blocks PARAMS ((void));
-void unroll_block_trees PARAMS ((void));
CALL_PLACEHOLDER alternatives that we didn't emit. Rebuild the
lexical block tree to correspond to the notes that still exist. */
if (replaced_call_placeholder)
- unroll_block_trees ();
+ reorder_blocks ();
/* This information will be invalid after inline expansion. Kill it now. */
free_basic_block_vars (0);
}
}
\f
-/* These routines are used by the loop unrolling code. They copy BLOCK trees
- so that the debugging info will be correct for the unrolled loop. */
-
-void
-find_loop_tree_blocks ()
-{
- identify_blocks (DECL_INITIAL (current_function_decl), get_insns ());
-}
-
-void
-unroll_block_trees ()
-{
- tree block = DECL_INITIAL (current_function_decl);
-
- reorder_blocks (block, get_insns ());
-}
/* First, make sure that NOTE_BLOCK is set correctly for each
NOTE_INSN_BLOCK_BEG/NOTE_INSN_BLOCK_END note. */
- find_loop_tree_blocks ();
+ if (!cfun->x_whole_function_mode_p)
+ identify_blocks ();
/* Then remove any notes we don't need. That will make iterating
over the instruction sequence faster, and allow the garbage
/* In function-at-a-time mode, we do not attempt to keep the BLOCK
tree in sensible shape. So, we just recalculate it here. */
if (cfun->x_whole_function_mode_p)
- unroll_block_trees ();
+ reorder_blocks ();
/* If we are reconsidering an inline function
at the end of compilation, skip the stuff for making it inline. */
extern void preserve_temp_slots PARAMS ((struct rtx_def *));
extern void preserve_rtl_expr_temps PARAMS ((tree));
extern int aggregate_value_p PARAMS ((tree));
-extern tree reorder_blocks PARAMS ((tree,
- struct rtx_def *));
extern void free_temps_for_rtl_expr PARAMS ((tree));
extern void instantiate_virtual_regs PARAMS ((tree, struct rtx_def *));
extern void unshare_all_rtl PARAMS ((tree, struct rtx_def *));