mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-10 08:00:28 +08:00
Flow rewrite to use basic block structures and edge lists.
From-SVN: r25450
This commit is contained in:
parent
001e880a26
commit
e881bb1b1b
153
gcc/ChangeLog
153
gcc/ChangeLog
@ -1,3 +1,156 @@
|
||||
Thu Feb 25 23:43:59 1999 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
Flow rewrite to use basic block structures and edge lists:
|
||||
|
||||
* basic-block.h (x_basic_block_head, x_basic_block_end): Kill.
|
||||
(basic_block_computed_jump_target, basic_block_live_at_start): Kill.
|
||||
(struct edge_def): New.
|
||||
(struct basic_block_def): New.
|
||||
(basic_block_info): New.
|
||||
(BLOCK_HEAD, BLOCK_END): Update.
|
||||
(ENTRY_BLOCK_PTR, EXIT_BLOCK_PTR): New.
|
||||
(uid_block_number): Kill.
|
||||
(basic_block_for_insn, BLOCK_FOR_INSN): New.
|
||||
(BLOCK_NUM): Update.
|
||||
* flow.c (XNMALLOC): Kill.
|
||||
(max_uid_for_flow): Kill.
|
||||
(uid_block_number): Kill.
|
||||
(uid_volatile): Turn into a bitmap.
|
||||
(SET_INSN_VOLATILE): New.
|
||||
(basic_block_info): New.
|
||||
(entry_exit_blocks): New.
|
||||
(x_basic_block_head, x_basic_block_end): Kill.
|
||||
(basic_block_computed_jump_target, basic_block_live_at_start): Kill.
|
||||
(flow_int_list_blocks, basic_block_succ, basic_block_pred): Kill.
|
||||
(basic_block_loop_depth): Kill.
|
||||
(basic_block_for_insn): New.
|
||||
(find_basic_blocks): Split out initial block counting into
|
||||
count_basic_blocks. Call functions split out of find_basic_blocks_1.
|
||||
(count_basic_blocks): New.
|
||||
(find_basic_blocks_1): Split out edge recognition, unreachable
|
||||
block deletion.
|
||||
(create_basic_block): New.
|
||||
(compute_bb_for_insn): New.
|
||||
(clear_edges): New.
|
||||
(free_bb_memory): Kill.
|
||||
(add_edge, add_edge_to_label): Kill.
|
||||
(mark_label_ref): Kill.
|
||||
(make_edges): Rewrite to use edge lists.
|
||||
(make_edge, make_label_edge): New.
|
||||
(mark_critical_edges): New.
|
||||
(split_edge, insert_insn_on_edge): New.
|
||||
(commit_one_edge_insertion, commit_edge_insertions): New.
|
||||
(delete_unreachable_blocks): Rewrite to use edge lists.
|
||||
Split out EH region manipulation into delete_eh_regions.
|
||||
Call tidy_fallthru_edge and merge_blocks.
|
||||
(delete_eh_regions): New.
|
||||
(delete_note_p): New.
|
||||
(delete_insn_chain): New.
|
||||
(delete_block): Split out code into delete_insn_chain and
|
||||
tidy_fallthru_edge. Update edge lists.
|
||||
(expunge_block): New.
|
||||
(flow_delete_insn): New?
|
||||
(can_delete_label_p): New?
|
||||
(merge_blocks_nomove, merge_blocks): New.
|
||||
(tidy_fallthru_edge): New.
|
||||
(calculate_loop_depth): New.
|
||||
(life_analysis): Allocate and free uid_volatile.
|
||||
(free_basic_block_vars): Update for new structures.
|
||||
(record_volatile_insns): Use SET_INSN_VOLATILE.
|
||||
(mark_regs_live_at_end): Tidy EXIT_IGNORE_STACK usage.
|
||||
(mark_used_regs): Likewise.
|
||||
(life_analysis_1): Use bb global_live_at_start, global_live_at_end,
|
||||
local_set regsets. Use bb->aux to store new_live_at_end. Begin
|
||||
life propagation from EXIT_BLOCK rather than last block. Clear
|
||||
regs_ever_live after mark_regs_live_at_end.
|
||||
(allocate_for_life_analysis): Update for new structures.
|
||||
(propagate_block): Split out loop depth calculation to
|
||||
calculate_loop_depth.
|
||||
(regno_uninitialized): Use bb->global_live_at_start.
|
||||
(regno_clobbered_at_setjmp): Likewise.
|
||||
(dump_bb_data): Likewise.
|
||||
(find_auto_inc): Use BLOCK_FOR_INSN instead of BLOCK_NUM.
|
||||
(dump_flow_info): Update for new structures.
|
||||
(dump_edge_info): New.
|
||||
(print_rtl_with_bb): Update for new structues.
|
||||
(compute_preds_succs): Do no work -- convert edge lists.
|
||||
(set_block_for_insn): From corpse of old set_block_num.
|
||||
(set_block_num): Call it.
|
||||
|
||||
* rtl.c (note_insn_name): Add NOTE_INSN_BASIC_BLOCK.
|
||||
* rtl.h (rtunion_def): Add bb entry.
|
||||
(NOTE_BASIC_BLOCK): New.
|
||||
(NOTE_INSN_BASIC_BLOCK): New.
|
||||
|
||||
* varray.h (varray_data_tag): Add bb entry.
|
||||
(VARRAY_BB_INIT, VARRAY_BB): New.
|
||||
|
||||
* emit-rtl.c (emit_label_before): New.
|
||||
|
||||
* except.c (expand_rethrow): Delete insns following the call to
|
||||
rethrow. Put the REG_EH_RETHROW on the call.
|
||||
|
||||
* jump.c (returnjump_p, returnjump_p_1): New.
|
||||
|
||||
* expr.h (nonlocal_goto_handler_labels): New declaration.
|
||||
* function.c (nonlocal_goto_handler_labels): Define it.
|
||||
(push_function_context_to): Save it.
|
||||
(pop_function_context_from): Restore it.
|
||||
(init_function_start): Clear it.
|
||||
(nonlocal_label_rtx_list): Kill.
|
||||
* function.h (struct function): Add storage space for it.
|
||||
* stmt.c (expand_nl_handler_label): Return the new label.
|
||||
(expand_nl_goto_receivers): Collect a list of them in
|
||||
nonlocal_goto_handler_labels.
|
||||
|
||||
* Makefile.in (print-rtl.o): Depend on basic-block.h.
|
||||
(flow.o): Depend on tree.h and insn-flags.h.
|
||||
(sched.o): Depend on tree.h and expr.h.
|
||||
|
||||
* function.c (thread_prologue_and_epilogue_insns): Do not
|
||||
half-heartedly update bb structures.
|
||||
|
||||
* toplev.c: Add flow2 dump as -dw.
|
||||
(rest_of_compilation): Finish .greg before flow2.
|
||||
|
||||
* graph.c (draw_edge): Handle class 3.
|
||||
(print_rtl_graph_with_bb): Make abnormal edges red class 2,
|
||||
change non-fall-thru but adjacent to green class 3. Update
|
||||
to use new structures.
|
||||
|
||||
* print-rtl.c (print_rtx): Handle NOTE_INSN_BASIC_BLOCK.
|
||||
|
||||
* reg-stack.c (BLOCK_NUM): Convert to function. Abort if
|
||||
block_number is -1.
|
||||
(reg_to_stack): Initialize block_num to -1.
|
||||
|
||||
* combine.c (set_nonzero_bits_and_sign_copies): Update reference
|
||||
to basic_block_live_at_start to bb->global_live_at_start.
|
||||
(try_combine): Likewise.
|
||||
(reg_dead_at_p): Likewise.
|
||||
* global.c (global_conflicts): Likewise.
|
||||
Handle stack regs on all abnormal edges, not just computed jumps.
|
||||
(mark_elimination): Update reference to basic_block_live_at_start.
|
||||
(build_insn_chain): Likewise.
|
||||
* haifa-sched.c (haifa_edge): Rename from edge for conflict.
|
||||
(is_cfg_nonregular): Look at nonlocal_goto_handler_labels instead
|
||||
of nonlocal_label_rtx_list.
|
||||
(check_live_1): Update reference to basic_block_live_at_start.
|
||||
(update_live_1): Likewise.
|
||||
(find_pre_sched_live): Likewise.
|
||||
(find_post_sched_live): Likewise.
|
||||
* local-alloc.c (update_equiv_regs): Likewise.
|
||||
(block_alloc): Likewise.
|
||||
* reload1.c (reload, reload_combine): Likewise.
|
||||
* regmove.c (mark_flags_life_zones): Likewise.
|
||||
* resource.c (mark_target_live_regs): Likewise.
|
||||
* sched.c (schedule_block): Likewise.
|
||||
|
||||
* regclass.c (regset_release_memory): Don't free
|
||||
basic_block_live_at_start.
|
||||
|
||||
* unroll.c (copy_loop_body): Don't duplicate NOTE_INSN_BASIC_BLOCK.
|
||||
|
||||
Thu Feb 25 21:32:34 1999 Jason Merrill <jason@yorick.cygnus.com>
|
||||
|
||||
* fixinc.wrap: Also handle struct queue in sys/stream.h.
|
||||
|
@ -21,6 +21,7 @@ Boston, MA 02111-1307, USA. */
|
||||
|
||||
#include "bitmap.h"
|
||||
#include "sbitmap.h"
|
||||
#include "varray.h"
|
||||
|
||||
typedef bitmap regset; /* Head of register set linked list. */
|
||||
|
||||
@ -95,29 +96,65 @@ do { \
|
||||
/* Grow any tables needed when the number of registers is calculated
|
||||
or extended. For the linked list allocation, nothing needs to
|
||||
be done, other than zero the statistics on the first allocation. */
|
||||
#define MAX_REGNO_REG_SET(NUM_REGS, NEW_P, RENUMBER_P)
|
||||
#define MAX_REGNO_REG_SET(NUM_REGS, NEW_P, RENUMBER_P)
|
||||
|
||||
/* Control flow edge information. */
|
||||
typedef struct edge_def {
|
||||
/* Links through the predecessor and successor lists. */
|
||||
struct edge_def *pred_next, *succ_next;
|
||||
|
||||
/* The two blocks at the ends of the edge. */
|
||||
struct basic_block_def *src, *dest;
|
||||
|
||||
/* Instructions queued on the edge. */
|
||||
rtx insns;
|
||||
|
||||
/* Auxiliary info specific to a pass. */
|
||||
void *aux;
|
||||
|
||||
int flags; /* see EDGE_* below */
|
||||
int probability; /* biased by REG_BR_PROB_BASE */
|
||||
} *edge;
|
||||
|
||||
#define EDGE_FALLTHRU 1
|
||||
#define EDGE_CRITICAL 2
|
||||
#define EDGE_ABNORMAL 4
|
||||
#define EDGE_ABNORMAL_CALL 8
|
||||
#define EDGE_EH 16
|
||||
#define EDGE_FAKE 32
|
||||
|
||||
|
||||
/* Basic block information indexed by block number. */
|
||||
typedef struct basic_block_def {
|
||||
/* The first and last insns of the block. */
|
||||
rtx head, end;
|
||||
|
||||
/* The edges into and out of the block. */
|
||||
edge pred, succ;
|
||||
|
||||
/* Liveness info. */
|
||||
regset local_set;
|
||||
regset global_live_at_start;
|
||||
regset global_live_at_end;
|
||||
|
||||
/* Auxiliary info specific to a pass. */
|
||||
void *aux;
|
||||
|
||||
/* The index of this block. */
|
||||
int index;
|
||||
/* The loop depth of this block plus one. */
|
||||
int loop_depth;
|
||||
} *basic_block;
|
||||
|
||||
/* Number of basic blocks in the current function. */
|
||||
|
||||
extern int n_basic_blocks;
|
||||
|
||||
/* Index by basic block number, get first insn in the block. */
|
||||
/* Index by basic block number, get basic block struct info. */
|
||||
|
||||
extern rtx *x_basic_block_head;
|
||||
extern varray_type basic_block_info;
|
||||
|
||||
/* Index by basic block number, get last insn in the block. */
|
||||
|
||||
extern rtx *x_basic_block_end;
|
||||
|
||||
/* Index by basic block number, determine whether the block can be reached
|
||||
through a computed jump. */
|
||||
|
||||
extern char *basic_block_computed_jump_target;
|
||||
|
||||
/* Index by basic block number, get address of regset
|
||||
describing the registers live at the start of that block. */
|
||||
|
||||
extern regset *basic_block_live_at_start;
|
||||
#define BASIC_BLOCK(N) (VARRAY_BB (basic_block_info, (N)))
|
||||
|
||||
/* What registers are live at the setjmp call. */
|
||||
|
||||
@ -177,24 +214,38 @@ extern void free_int_list PROTO ((int_list_block **));
|
||||
|
||||
/* Stuff for recording basic block info. */
|
||||
|
||||
#define BLOCK_HEAD(B) x_basic_block_head[(B)]
|
||||
#define BLOCK_END(B) x_basic_block_end[(B)]
|
||||
#define BLOCK_HEAD(B) (BASIC_BLOCK (B)->head)
|
||||
#define BLOCK_END(B) (BASIC_BLOCK (B)->end)
|
||||
|
||||
/* Special block numbers [markers] for entry and exit. */
|
||||
#define ENTRY_BLOCK (-1)
|
||||
#define EXIT_BLOCK (-2)
|
||||
|
||||
/* from flow.c */
|
||||
extern void free_regset_vector PROTO ((regset *, int nelts));
|
||||
extern int *uid_block_number;
|
||||
#define BLOCK_NUM(INSN) uid_block_number[INSN_UID (INSN)]
|
||||
/* Similarly, block pointers for the edge list. */
|
||||
extern struct basic_block_def entry_exit_blocks[2];
|
||||
#define ENTRY_BLOCK_PTR (&entry_exit_blocks[0])
|
||||
#define EXIT_BLOCK_PTR (&entry_exit_blocks[1])
|
||||
|
||||
extern void dump_bb_data PROTO ((FILE *, int_list_ptr *, int_list_ptr *,
|
||||
int));
|
||||
extern void free_bb_mem PROTO ((void));
|
||||
/* from flow.c */
|
||||
extern void free_regset_vector PROTO ((regset *, int nelts));
|
||||
|
||||
extern varray_type basic_block_for_insn;
|
||||
#define BLOCK_FOR_INSN(INSN) VARRAY_BB (basic_block_for_insn, INSN_UID (INSN))
|
||||
#define BLOCK_NUM(INSN) (BLOCK_FOR_INSN (INSN)->index + 0)
|
||||
|
||||
extern void set_block_for_insn PROTO ((rtx, basic_block));
|
||||
|
||||
extern void dump_bb_data PROTO ((FILE *, int_list_ptr *,
|
||||
int_list_ptr *, int));
|
||||
extern void free_bb_mem PROTO ((void));
|
||||
extern void free_basic_block_vars PROTO ((int));
|
||||
|
||||
extern void compute_preds_succs PROTO ((int_list_ptr *, int_list_ptr *,
|
||||
int *, int *));
|
||||
extern void compute_dominators PROTO ((sbitmap *, sbitmap *,
|
||||
int_list_ptr *, int_list_ptr *));
|
||||
extern basic_block split_edge PROTO ((edge));
|
||||
extern void insert_insn_on_edge PROTO ((rtx, edge));
|
||||
extern void commit_edge_insertions PROTO ((void));
|
||||
|
||||
extern void compute_preds_succs PROTO ((int_list_ptr *, int_list_ptr *,
|
||||
int *, int *));
|
||||
extern void compute_dominators PROTO ((sbitmap *, sbitmap *,
|
||||
int_list_ptr *,
|
||||
int_list_ptr *));
|
||||
|
@ -744,7 +744,7 @@ set_nonzero_bits_and_sign_copies (x, set)
|
||||
&& REGNO (x) >= FIRST_PSEUDO_REGISTER
|
||||
/* If this register is undefined at the start of the file, we can't
|
||||
say what its contents were. */
|
||||
&& ! REGNO_REG_SET_P (basic_block_live_at_start[0], REGNO (x))
|
||||
&& ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start, REGNO (x))
|
||||
&& GET_MODE_BITSIZE (GET_MODE (x)) <= HOST_BITS_PER_WIDE_INT)
|
||||
{
|
||||
if (set == 0 || GET_CODE (set) == CLOBBER)
|
||||
@ -2490,7 +2490,8 @@ try_combine (i3, i2, i1)
|
||||
regno = REGNO (i2dest);
|
||||
REG_N_SETS (regno)--;
|
||||
if (REG_N_SETS (regno) == 0
|
||||
&& ! REGNO_REG_SET_P (basic_block_live_at_start[0], regno))
|
||||
&& ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
|
||||
regno))
|
||||
REG_N_REFS (regno) = 0;
|
||||
}
|
||||
}
|
||||
@ -2512,7 +2513,8 @@ try_combine (i3, i2, i1)
|
||||
{
|
||||
REG_N_SETS (regno)--;
|
||||
if (REG_N_SETS (regno) == 0
|
||||
&& ! REGNO_REG_SET_P (basic_block_live_at_start[0], regno))
|
||||
&& ! REGNO_REG_SET_P (BASIC_BLOCK (0)->global_live_at_start,
|
||||
regno))
|
||||
REG_N_REFS (regno) = 0;
|
||||
}
|
||||
}
|
||||
@ -11038,7 +11040,7 @@ reg_dead_at_p (reg, insn)
|
||||
}
|
||||
|
||||
for (i = reg_dead_regno; i < reg_dead_endregno; i++)
|
||||
if (REGNO_REG_SET_P (basic_block_live_at_start[block], i))
|
||||
if (REGNO_REG_SET_P (BASIC_BLOCK (block)->global_live_at_start, i))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
|
@ -2710,7 +2710,7 @@ emit_call_insn_before (pattern, before)
|
||||
}
|
||||
|
||||
/* Make an insn of code BARRIER
|
||||
and output it before the insn AFTER. */
|
||||
and output it before the insn BEFORE. */
|
||||
|
||||
rtx
|
||||
emit_barrier_before (before)
|
||||
@ -2724,6 +2724,23 @@ emit_barrier_before (before)
|
||||
return insn;
|
||||
}
|
||||
|
||||
/* Emit the label LABEL before the insn BEFORE. */
|
||||
|
||||
rtx
|
||||
emit_label_before (label, before)
|
||||
rtx label, before;
|
||||
{
|
||||
/* This can be called twice for the same label as a result of the
|
||||
confusion that follows a syntax error! So make it harmless. */
|
||||
if (INSN_UID (label) == 0)
|
||||
{
|
||||
INSN_UID (label) = cur_insn_uid++;
|
||||
add_insn_before (label, before);
|
||||
}
|
||||
|
||||
return label;
|
||||
}
|
||||
|
||||
/* Emit a note of subtype SUBTYPE before the insn BEFORE. */
|
||||
|
||||
rtx
|
||||
|
10
gcc/except.c
10
gcc/except.c
@ -1967,11 +1967,17 @@ expand_rethrow (label)
|
||||
label = last_rethrow_symbol;
|
||||
emit_library_call (rethrow_libfunc, 0, VOIDmode, 1, label, Pmode);
|
||||
SYMBOL_REF_USED (label) = 1;
|
||||
|
||||
/* Search backwards for the actual call insn. */
|
||||
insn = get_last_insn ();
|
||||
val = GEN_INT (eh_region_from_symbol (label));
|
||||
while (GET_CODE (insn) != CALL_INSN)
|
||||
insn = PREV_INSN (insn);
|
||||
delete_insns_since (insn);
|
||||
|
||||
/* Mark the label/symbol on the call. */
|
||||
val = GEN_INT (eh_region_from_symbol (label));
|
||||
REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EH_RETHROW, val,
|
||||
REG_NOTES (insn));
|
||||
REG_NOTES (insn));
|
||||
emit_barrier ();
|
||||
}
|
||||
else
|
||||
|
2887
gcc/flow.c
2887
gcc/flow.c
File diff suppressed because it is too large
Load Diff
231
gcc/function.c
231
gcc/function.c
@ -262,6 +262,11 @@ tree nonlocal_labels;
|
||||
|
||||
rtx nonlocal_goto_handler_slots;
|
||||
|
||||
/* List (chain of EXPR_LIST) of labels heading the current handlers for
|
||||
nonlocal gotos. */
|
||||
|
||||
rtx nonlocal_goto_handler_labels;
|
||||
|
||||
/* RTX for stack slot that holds the stack pointer value to restore
|
||||
for a nonlocal goto.
|
||||
Zero when function does not have nonlocal labels. */
|
||||
@ -559,6 +564,7 @@ push_function_context_to (context)
|
||||
p->outgoing_args_size = current_function_outgoing_args_size;
|
||||
p->return_rtx = current_function_return_rtx;
|
||||
p->nonlocal_goto_handler_slots = nonlocal_goto_handler_slots;
|
||||
p->nonlocal_goto_handler_labels = nonlocal_goto_handler_labels;
|
||||
p->nonlocal_goto_stack_level = nonlocal_goto_stack_level;
|
||||
p->nonlocal_labels = nonlocal_labels;
|
||||
p->cleanup_label = cleanup_label;
|
||||
@ -644,6 +650,7 @@ pop_function_context_from (context)
|
||||
current_function_outgoing_args_size = p->outgoing_args_size;
|
||||
current_function_return_rtx = p->return_rtx;
|
||||
nonlocal_goto_handler_slots = p->nonlocal_goto_handler_slots;
|
||||
nonlocal_goto_handler_labels = p->nonlocal_goto_handler_labels;
|
||||
nonlocal_goto_stack_level = p->nonlocal_goto_stack_level;
|
||||
nonlocal_labels = p->nonlocal_labels;
|
||||
cleanup_label = p->cleanup_label;
|
||||
@ -3852,21 +3859,6 @@ delete_handlers ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a list (chain of EXPR_LIST nodes) for the nonlocal labels
|
||||
of the current function. */
|
||||
|
||||
rtx
|
||||
nonlocal_label_rtx_list ()
|
||||
{
|
||||
tree t;
|
||||
rtx x = 0;
|
||||
|
||||
for (t = nonlocal_labels; t; t = TREE_CHAIN (t))
|
||||
x = gen_rtx_EXPR_LIST (VOIDmode, label_rtx (TREE_VALUE (t)), x);
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/* Output a USE for any register use in RTL.
|
||||
This is used with -noreg to mark the extent of lifespan
|
||||
@ -5644,6 +5636,7 @@ init_function_start (subr, filename, line)
|
||||
|
||||
/* No labels have been declared for nonlocal use. */
|
||||
nonlocal_labels = 0;
|
||||
nonlocal_goto_handler_labels = 0;
|
||||
|
||||
/* No function calls so far in this function. */
|
||||
function_call_count = 0;
|
||||
@ -6438,100 +6431,172 @@ contains (insn, vec)
|
||||
|
||||
void
|
||||
thread_prologue_and_epilogue_insns (f)
|
||||
rtx f ATTRIBUTE_UNUSED;
|
||||
rtx f;
|
||||
{
|
||||
int insertted = 0;
|
||||
|
||||
prologue = 0;
|
||||
#ifdef HAVE_prologue
|
||||
if (HAVE_prologue)
|
||||
{
|
||||
rtx head, seq;
|
||||
rtx seq;
|
||||
|
||||
/* The first insn (a NOTE_INSN_DELETED) is followed by zero or more
|
||||
prologue insns and a NOTE_INSN_PROLOGUE_END. */
|
||||
emit_note_after (NOTE_INSN_PROLOGUE_END, f);
|
||||
seq = gen_prologue ();
|
||||
head = emit_insn_after (seq, f);
|
||||
|
||||
/* Include the new prologue insns in the first block. Ignore them
|
||||
if they form a basic block unto themselves. */
|
||||
if (x_basic_block_head && n_basic_blocks
|
||||
&& GET_CODE (BLOCK_HEAD (0)) != CODE_LABEL)
|
||||
BLOCK_HEAD (0) = NEXT_INSN (f);
|
||||
start_sequence ();
|
||||
seq = gen_prologue();
|
||||
emit_insn (seq);
|
||||
|
||||
/* Retain a map of the prologue insns. */
|
||||
prologue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : head);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
prologue = 0;
|
||||
if (GET_CODE (seq) != SEQUENCE)
|
||||
seq = get_insns ();
|
||||
prologue = record_insns (seq);
|
||||
|
||||
emit_note (NULL, NOTE_INSN_PROLOGUE_END);
|
||||
seq = gen_sequence ();
|
||||
end_sequence ();
|
||||
|
||||
/* If optimization is off, and perhaps in an empty function,
|
||||
the entry block will have no successors. */
|
||||
if (ENTRY_BLOCK_PTR->succ)
|
||||
{
|
||||
/* Can't deal with multiple successsors of the entry block. */
|
||||
if (ENTRY_BLOCK_PTR->succ->succ_next)
|
||||
abort ();
|
||||
|
||||
insert_insn_on_edge (seq, ENTRY_BLOCK_PTR->succ);
|
||||
insertted = 1;
|
||||
}
|
||||
else
|
||||
emit_insn_after (seq, f);
|
||||
}
|
||||
#endif
|
||||
|
||||
epilogue = 0;
|
||||
#ifdef HAVE_epilogue
|
||||
if (HAVE_epilogue)
|
||||
{
|
||||
rtx insn = get_last_insn ();
|
||||
rtx prev = prev_nonnote_insn (insn);
|
||||
edge e;
|
||||
basic_block bb = 0;
|
||||
rtx tail = get_last_insn ();
|
||||
|
||||
/* If we end with a BARRIER, we don't need an epilogue. */
|
||||
if (! (prev && GET_CODE (prev) == BARRIER))
|
||||
/* ??? This is gastly. If function returns were not done via uses,
|
||||
but via mark_regs_live_at_end, we could use insert_insn_on_edge
|
||||
and all of this uglyness would go away. */
|
||||
|
||||
switch (optimize)
|
||||
{
|
||||
rtx tail, seq, tem;
|
||||
rtx first_use = 0;
|
||||
rtx last_use = 0;
|
||||
default:
|
||||
/* If the exit block has no non-fake predecessors, we don't
|
||||
need an epilogue. Furthermore, only pay attention to the
|
||||
fallthru predecessors; if (conditional) return insns were
|
||||
generated, by definition we do not need to emit epilogue
|
||||
insns. */
|
||||
|
||||
/* The last basic block ends with a NOTE_INSN_EPILOGUE_BEG, the
|
||||
epilogue insns, the USE insns at the end of a function,
|
||||
the jump insn that returns, and then a BARRIER. */
|
||||
for (e = EXIT_BLOCK_PTR->pred; e ; e = e->pred_next)
|
||||
if ((e->flags & EDGE_FAKE) == 0
|
||||
&& (e->flags & EDGE_FALLTHRU) != 0)
|
||||
break;
|
||||
if (e == NULL)
|
||||
break;
|
||||
|
||||
/* Move the USE insns at the end of a function onto a list. */
|
||||
while (prev
|
||||
&& GET_CODE (prev) == INSN
|
||||
&& GET_CODE (PATTERN (prev)) == USE)
|
||||
{
|
||||
tem = prev;
|
||||
/* We can't handle multiple epilogues -- if one is needed,
|
||||
we won't be able to place it multiple times.
|
||||
|
||||
??? Fix epilogue expanders to not assume they are the
|
||||
last thing done compiling the function. Either that
|
||||
or copy_rtx each insn.
|
||||
|
||||
??? Blah, it's not a simple expression to assert that
|
||||
we've exactly one fallthru exit edge. */
|
||||
|
||||
bb = e->src;
|
||||
tail = bb->end;
|
||||
|
||||
/* ??? If the last insn of the basic block is a jump, then we
|
||||
are creating a new basic block. Wimp out and leave these
|
||||
insns outside any block. */
|
||||
if (GET_CODE (tail) == JUMP_INSN)
|
||||
bb = 0;
|
||||
|
||||
/* FALLTHRU */
|
||||
case 0:
|
||||
{
|
||||
rtx prev, seq, first_use;
|
||||
|
||||
/* Move the USE insns at the end of a function onto a list. */
|
||||
prev = tail;
|
||||
if (GET_CODE (prev) == BARRIER
|
||||
|| GET_CODE (prev) == NOTE)
|
||||
prev = prev_nonnote_insn (prev);
|
||||
|
||||
NEXT_INSN (PREV_INSN (tem)) = NEXT_INSN (tem);
|
||||
PREV_INSN (NEXT_INSN (tem)) = PREV_INSN (tem);
|
||||
if (first_use)
|
||||
{
|
||||
NEXT_INSN (tem) = first_use;
|
||||
PREV_INSN (first_use) = tem;
|
||||
}
|
||||
first_use = tem;
|
||||
if (!last_use)
|
||||
last_use = tem;
|
||||
}
|
||||
first_use = 0;
|
||||
if (prev
|
||||
&& GET_CODE (prev) == INSN
|
||||
&& GET_CODE (PATTERN (prev)) == USE)
|
||||
{
|
||||
/* If the end of the block is the use, grab hold of something
|
||||
else so that we emit barriers etc in the right place. */
|
||||
if (prev == tail)
|
||||
{
|
||||
do
|
||||
tail = PREV_INSN (tail);
|
||||
while (GET_CODE (tail) == INSN
|
||||
&& GET_CODE (PATTERN (tail)) == USE);
|
||||
}
|
||||
|
||||
emit_barrier_after (insn);
|
||||
do
|
||||
{
|
||||
rtx use = prev;
|
||||
prev = prev_nonnote_insn (prev);
|
||||
|
||||
seq = gen_epilogue ();
|
||||
tail = emit_jump_insn_after (seq, insn);
|
||||
remove_insn (use);
|
||||
if (first_use)
|
||||
{
|
||||
NEXT_INSN (use) = first_use;
|
||||
PREV_INSN (first_use) = use;
|
||||
}
|
||||
else
|
||||
NEXT_INSN (use) = NULL_RTX;
|
||||
first_use = use;
|
||||
}
|
||||
while (prev
|
||||
&& GET_CODE (prev) == INSN
|
||||
&& GET_CODE (PATTERN (prev)) == USE);
|
||||
}
|
||||
|
||||
/* Insert the USE insns immediately before the return insn, which
|
||||
must be the first instruction before the final barrier. */
|
||||
if (first_use)
|
||||
{
|
||||
tem = prev_nonnote_insn (get_last_insn ());
|
||||
NEXT_INSN (PREV_INSN (tem)) = first_use;
|
||||
PREV_INSN (first_use) = PREV_INSN (tem);
|
||||
PREV_INSN (tem) = last_use;
|
||||
NEXT_INSN (last_use) = tem;
|
||||
}
|
||||
/* The last basic block ends with a NOTE_INSN_EPILOGUE_BEG, the
|
||||
epilogue insns, the USE insns at the end of a function,
|
||||
the jump insn that returns, and then a BARRIER. */
|
||||
|
||||
emit_note_after (NOTE_INSN_EPILOGUE_BEG, insn);
|
||||
if (GET_CODE (tail) != BARRIER)
|
||||
{
|
||||
prev = next_nonnote_insn (tail);
|
||||
if (!prev || GET_CODE (prev) != BARRIER)
|
||||
emit_barrier_after (tail);
|
||||
}
|
||||
|
||||
/* Include the new epilogue insns in the last block. Ignore
|
||||
them if they form a basic block unto themselves. */
|
||||
if (x_basic_block_end && n_basic_blocks
|
||||
&& GET_CODE (BLOCK_END (n_basic_blocks - 1)) != JUMP_INSN)
|
||||
BLOCK_END (n_basic_blocks - 1) = tail;
|
||||
seq = gen_epilogue ();
|
||||
prev = tail;
|
||||
tail = emit_jump_insn_after (seq, tail);
|
||||
|
||||
/* Retain a map of the epilogue insns. */
|
||||
epilogue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : tail);
|
||||
return;
|
||||
/* Insert the USE insns immediately before the return insn, which
|
||||
must be the last instruction emitted in the sequence. */
|
||||
if (first_use)
|
||||
emit_insns_before (first_use, tail);
|
||||
emit_note_after (NOTE_INSN_EPILOGUE_BEG, prev);
|
||||
|
||||
/* Update the tail of the basic block. */
|
||||
if (bb)
|
||||
bb->end = tail;
|
||||
|
||||
/* Retain a map of the epilogue insns. */
|
||||
epilogue = record_insns (GET_CODE (seq) == SEQUENCE ? seq : tail);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
epilogue = 0;
|
||||
|
||||
if (insertted)
|
||||
commit_edge_insertions ();
|
||||
}
|
||||
|
||||
/* Reposition the prologue-end and epilogue-begin notes after instruction
|
||||
|
@ -83,6 +83,7 @@ struct function
|
||||
int has_computed_jump;
|
||||
int is_thunk;
|
||||
rtx nonlocal_goto_handler_slots;
|
||||
rtx nonlocal_goto_handler_labels;
|
||||
rtx nonlocal_goto_stack_level;
|
||||
tree nonlocal_labels;
|
||||
int args_size;
|
||||
|
41
gcc/global.c
41
gcc/global.c
@ -648,7 +648,7 @@ global_conflicts ()
|
||||
are explicitly marked in basic_block_live_at_start. */
|
||||
|
||||
{
|
||||
register regset old = basic_block_live_at_start[b];
|
||||
register regset old = BASIC_BLOCK (b)->global_live_at_start;
|
||||
int ax = 0;
|
||||
|
||||
REG_SET_TO_HARD_REG_SET (hard_regs_live, old);
|
||||
@ -671,12 +671,22 @@ global_conflicts ()
|
||||
record_conflicts (block_start_allocnos, ax);
|
||||
|
||||
#ifdef STACK_REGS
|
||||
/* Pseudos can't go in stack regs at the start of a basic block
|
||||
that can be reached through a computed goto, since reg-stack
|
||||
can't handle computed gotos. */
|
||||
if (basic_block_computed_jump_target[b])
|
||||
for (ax = FIRST_STACK_REG; ax <= LAST_STACK_REG; ax++)
|
||||
record_one_conflict (ax);
|
||||
{
|
||||
/* Pseudos can't go in stack regs at the start of a basic block
|
||||
that can be reached through a computed goto, since reg-stack
|
||||
can't handle computed gotos. */
|
||||
/* ??? Seems more likely that reg-stack can't handle any abnormal
|
||||
edges, critical or not, computed goto or otherwise. */
|
||||
|
||||
edge e;
|
||||
for (e = BASIC_BLOCK (b)->pred; e ; e = e->pred_next)
|
||||
if (e->flags & EDGE_ABNORMAL)
|
||||
break;
|
||||
|
||||
if (e != NULL)
|
||||
for (ax = FIRST_STACK_REG; ax <= LAST_STACK_REG; ax++)
|
||||
record_one_conflict (ax);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1598,11 +1608,14 @@ mark_elimination (from, to)
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n_basic_blocks; i++)
|
||||
if (REGNO_REG_SET_P (basic_block_live_at_start[i], from))
|
||||
{
|
||||
CLEAR_REGNO_REG_SET (basic_block_live_at_start[i], from);
|
||||
SET_REGNO_REG_SET (basic_block_live_at_start[i], to);
|
||||
}
|
||||
{
|
||||
register regset r = BASIC_BLOCK (i)->global_live_at_start;
|
||||
if (REGNO_REG_SET_P (r, from))
|
||||
{
|
||||
CLEAR_REGNO_REG_SET (r, from);
|
||||
SET_REGNO_REG_SET (r, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Used for communication between the following functions. Holds the
|
||||
@ -1672,13 +1685,13 @@ build_insn_chain (first)
|
||||
int i;
|
||||
CLEAR_REG_SET (live_relevant_regs);
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
if (REGNO_REG_SET_P (basic_block_live_at_start[b], i)
|
||||
if (REGNO_REG_SET_P (BASIC_BLOCK (b)->global_live_at_start, i)
|
||||
&& ! TEST_HARD_REG_BIT (eliminable_regset, i))
|
||||
SET_REGNO_REG_SET (live_relevant_regs, i);
|
||||
|
||||
for (; i < max_regno; i++)
|
||||
if (reg_renumber[i] >= 0
|
||||
&& REGNO_REG_SET_P (basic_block_live_at_start[b], i))
|
||||
&& REGNO_REG_SET_P (BASIC_BLOCK (b)->global_live_at_start, i))
|
||||
SET_REGNO_REG_SET (live_relevant_regs, i);
|
||||
}
|
||||
|
||||
|
85
gcc/graph.c
85
gcc/graph.c
@ -160,7 +160,8 @@ darkgrey\n shape: ellipse" : "white",
|
||||
"repeated_line_number",
|
||||
"range_start",
|
||||
"range_end",
|
||||
"live"
|
||||
"live",
|
||||
"basic_block"
|
||||
};
|
||||
|
||||
fprintf (fp, " %s",
|
||||
@ -191,14 +192,21 @@ draw_edge (fp, from, to, bb_edge, class)
|
||||
int bb_edge;
|
||||
int class;
|
||||
{
|
||||
char * color;
|
||||
switch (graph_dump_format)
|
||||
{
|
||||
case vcg:
|
||||
color = "";
|
||||
if (class == 2)
|
||||
color = "color: red ";
|
||||
else if (bb_edge)
|
||||
color = "color: blue ";
|
||||
else if (class == 3)
|
||||
color = "color: green ";
|
||||
fprintf (fp,
|
||||
"edge: { sourcename: \"%s.%d\" targetname: \"%s.%d\" %s",
|
||||
current_function_name, from,
|
||||
current_function_name, to,
|
||||
bb_edge ? "color: blue " : class ? "color: red " : "");
|
||||
current_function_name, to, color);
|
||||
if (class)
|
||||
fprintf (fp, "class: %d ", class);
|
||||
fputs ("}\n", fp);
|
||||
@ -253,8 +261,8 @@ print_rtl_graph_with_bb (base, suffix, rtx_first)
|
||||
char *buf = (char *) alloca (namelen + suffixlen + extlen);
|
||||
FILE *fp;
|
||||
|
||||
/* Regenerate the basic block information. */
|
||||
find_basic_blocks (rtx_first, max_reg_num (), NULL);
|
||||
if (basic_block_info == NULL)
|
||||
return;
|
||||
|
||||
memcpy (buf, base, namelen);
|
||||
memcpy (buf + namelen, suffix, suffixlen);
|
||||
@ -268,20 +276,14 @@ print_rtl_graph_with_bb (base, suffix, rtx_first)
|
||||
fprintf (fp, "(nil)\n");
|
||||
else
|
||||
{
|
||||
int i, bb;
|
||||
int i;
|
||||
enum bb_state { NOT_IN_BB, IN_ONE_BB, IN_MULTIPLE_BB };
|
||||
int max_uid = get_max_uid ();
|
||||
int *start = (int *) alloca (max_uid * sizeof (int));
|
||||
int *end = (int *) alloca (max_uid * sizeof (int));
|
||||
enum bb_state *in_bb_p = (enum bb_state *)
|
||||
alloca (max_uid * sizeof (enum bb_state));
|
||||
/* Element I is a list of I's predecessors/successors. */
|
||||
int_list_ptr *s_preds;
|
||||
int_list_ptr *s_succs;
|
||||
/* Element I is the number of predecessors/successors of basic
|
||||
block I. */
|
||||
int *num_preds;
|
||||
int *num_succs;
|
||||
basic_block bb;
|
||||
|
||||
for (i = 0; i < max_uid; ++i)
|
||||
{
|
||||
@ -292,28 +294,19 @@ print_rtl_graph_with_bb (base, suffix, rtx_first)
|
||||
for (i = n_basic_blocks - 1; i >= 0; --i)
|
||||
{
|
||||
rtx x;
|
||||
start[INSN_UID (BLOCK_HEAD (i))] = i;
|
||||
end[INSN_UID (BLOCK_END (i))] = i;
|
||||
for (x = BLOCK_HEAD (i); x != NULL_RTX; x = NEXT_INSN (x))
|
||||
bb = BASIC_BLOCK (i);
|
||||
start[INSN_UID (bb->head)] = i;
|
||||
end[INSN_UID (bb->end)] = i;
|
||||
for (x = bb->head; x != NULL_RTX; x = NEXT_INSN (x))
|
||||
{
|
||||
in_bb_p[INSN_UID (x)]
|
||||
= (in_bb_p[INSN_UID (x)] == NOT_IN_BB)
|
||||
? IN_ONE_BB : IN_MULTIPLE_BB;
|
||||
if (x == BLOCK_END (i))
|
||||
if (x == bb->end)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the information about the basic blocks predecessors and
|
||||
successors. */
|
||||
s_preds = (int_list_ptr *) alloca (n_basic_blocks
|
||||
* sizeof (int_list_ptr));
|
||||
s_succs = (int_list_ptr *) alloca (n_basic_blocks
|
||||
* sizeof (int_list_ptr));
|
||||
num_preds = (int *) alloca (n_basic_blocks * sizeof (int));
|
||||
num_succs = (int *) alloca (n_basic_blocks * sizeof (int));
|
||||
compute_preds_succs (s_preds, s_succs, num_preds, num_succs);
|
||||
|
||||
/* Tell print-rtl that we want graph output. */
|
||||
dump_for_graph = 1;
|
||||
|
||||
@ -336,12 +329,12 @@ print_rtl_graph_with_bb (base, suffix, rtx_first)
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((bb = start[INSN_UID (tmp_rtx)]) >= 0)
|
||||
if ((i = start[INSN_UID (tmp_rtx)]) >= 0)
|
||||
{
|
||||
/* We start a subgraph for each basic block. */
|
||||
start_bb (fp, bb);
|
||||
start_bb (fp, i);
|
||||
|
||||
if (bb == 0)
|
||||
if (i == 0)
|
||||
draw_edge (fp, 0, INSN_UID (tmp_rtx), 1, 0);
|
||||
}
|
||||
|
||||
@ -349,40 +342,40 @@ print_rtl_graph_with_bb (base, suffix, rtx_first)
|
||||
did_output = node_data (fp, tmp_rtx);
|
||||
next_insn = next_nonnote_insn (tmp_rtx);
|
||||
|
||||
if ((bb = end[INSN_UID (tmp_rtx)]) >= 0)
|
||||
if ((i = end[INSN_UID (tmp_rtx)]) >= 0)
|
||||
{
|
||||
int_list_ptr p;
|
||||
edge e;
|
||||
|
||||
bb = BASIC_BLOCK (i);
|
||||
|
||||
/* End of the basic block. */
|
||||
end_bb (fp, bb);
|
||||
|
||||
/* Now specify the edges to all the successors of this
|
||||
basic block. */
|
||||
for (p = s_succs[bb]; p != NULL; p = p->next)
|
||||
for (e = bb->succ; e ; e = e->succ_next)
|
||||
{
|
||||
int bb_succ = INT_LIST_VAL (p);
|
||||
|
||||
if (bb_succ >= 0)
|
||||
if (e->dest != EXIT_BLOCK_PTR)
|
||||
{
|
||||
rtx block_head = BLOCK_HEAD (bb_succ);
|
||||
rtx block_head = e->dest->head;
|
||||
|
||||
draw_edge (fp, INSN_UID (tmp_rtx),
|
||||
INSN_UID (block_head),
|
||||
next_insn != block_head, 0);
|
||||
next_insn != block_head,
|
||||
(e->flags & EDGE_ABNORMAL ? 2 : 0));
|
||||
|
||||
if (BLOCK_HEAD (bb_succ) == next_insn)
|
||||
if (block_head == next_insn)
|
||||
edge_printed = 1;
|
||||
}
|
||||
else if (bb_succ == EXIT_BLOCK)
|
||||
else
|
||||
{
|
||||
draw_edge (fp, INSN_UID (tmp_rtx), 999999,
|
||||
next_insn != 0, 0);
|
||||
next_insn != 0,
|
||||
(e->flags & EDGE_ABNORMAL ? 2 : 0));
|
||||
|
||||
if (next_insn == 0)
|
||||
edge_printed = 1;
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
}
|
||||
}
|
||||
|
||||
@ -395,8 +388,8 @@ print_rtl_graph_with_bb (base, suffix, rtx_first)
|
||||
next_insn ? INSN_UID (next_insn) : 999999, 0, 0);
|
||||
else
|
||||
{
|
||||
/* We draw the remaining edges in class 2. We have
|
||||
to skip oevr the barrier since these nodes are
|
||||
/* We draw the remaining edges in class 3. We have
|
||||
to skip over the barrier since these nodes are
|
||||
not printed at all. */
|
||||
do
|
||||
next_insn = NEXT_INSN (next_insn);
|
||||
@ -405,7 +398,7 @@ print_rtl_graph_with_bb (base, suffix, rtx_first)
|
||||
|| GET_CODE (next_insn) == BARRIER));
|
||||
|
||||
draw_edge (fp, XINT (tmp_rtx, 0),
|
||||
next_insn ? INSN_UID (next_insn) : 999999, 0, 2);
|
||||
next_insn ? INSN_UID (next_insn) : 999999, 0, 3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -472,8 +472,8 @@ typedef struct
|
||||
int next_in;
|
||||
int next_out;
|
||||
}
|
||||
edge;
|
||||
static edge *edge_table;
|
||||
haifa_edge;
|
||||
static haifa_edge *edge_table;
|
||||
|
||||
#define NEXT_IN(edge) (edge_table[edge].next_in)
|
||||
#define NEXT_OUT(edge) (edge_table[edge].next_out)
|
||||
@ -1082,7 +1082,7 @@ is_cfg_nonregular ()
|
||||
|
||||
/* If we have a label that could be the target of a nonlocal goto, then
|
||||
the cfg is not well structured. */
|
||||
if (nonlocal_label_rtx_list () != NULL)
|
||||
if (nonlocal_goto_handler_labels)
|
||||
return 1;
|
||||
|
||||
/* If we have any forced labels, then the cfg is not well structured. */
|
||||
@ -1169,8 +1169,8 @@ build_control_flow (s_preds, s_succs, num_preds, num_succs)
|
||||
bzero ((char *) in_edges, n_basic_blocks * sizeof (int));
|
||||
bzero ((char *) out_edges, n_basic_blocks * sizeof (int));
|
||||
|
||||
edge_table = (edge *) xmalloc ((nr_edges) * sizeof (edge));
|
||||
bzero ((char *) edge_table, ((nr_edges) * sizeof (edge)));
|
||||
edge_table = (haifa_edge *) xmalloc ((nr_edges) * sizeof (haifa_edge));
|
||||
bzero ((char *) edge_table, ((nr_edges) * sizeof (haifa_edge)));
|
||||
|
||||
nr_edges = 0;
|
||||
for (i = 0; i < n_basic_blocks; i++)
|
||||
@ -2153,7 +2153,8 @@ check_live_1 (src, x)
|
||||
{
|
||||
int b = candidate_table[src].split_bbs.first_member[i];
|
||||
|
||||
if (REGNO_REG_SET_P (basic_block_live_at_start[b], regno + j))
|
||||
if (REGNO_REG_SET_P (BASIC_BLOCK (b)->global_live_at_start,
|
||||
regno + j))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -2167,7 +2168,7 @@ check_live_1 (src, x)
|
||||
{
|
||||
int b = candidate_table[src].split_bbs.first_member[i];
|
||||
|
||||
if (REGNO_REG_SET_P (basic_block_live_at_start[b], regno))
|
||||
if (REGNO_REG_SET_P (BASIC_BLOCK (b)->global_live_at_start, regno))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@ -2227,7 +2228,8 @@ update_live_1 (src, x)
|
||||
{
|
||||
int b = candidate_table[src].update_bbs.first_member[i];
|
||||
|
||||
SET_REGNO_REG_SET (basic_block_live_at_start[b], regno + j);
|
||||
SET_REGNO_REG_SET (BASIC_BLOCK (b)->global_live_at_start,
|
||||
regno + j);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2237,7 +2239,7 @@ update_live_1 (src, x)
|
||||
{
|
||||
int b = candidate_table[src].update_bbs.first_member[i];
|
||||
|
||||
SET_REGNO_REG_SET (basic_block_live_at_start[b], regno);
|
||||
SET_REGNO_REG_SET (BASIC_BLOCK (b)->global_live_at_start, regno);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -5135,7 +5137,7 @@ finish_sometimes_live (regs_sometimes_live, sometimes_max)
|
||||
|
||||
/* functions for computation of registers live/usage info */
|
||||
|
||||
/* It is assumed that prior to scheduling basic_block_live_at_start (b)
|
||||
/* It is assumed that prior to scheduling BASIC_BLOCK (b)->global_live_at_start
|
||||
contains the registers that are alive at the entry to b.
|
||||
|
||||
Two passes follow: The first pass is performed before the scheduling
|
||||
@ -5165,7 +5167,7 @@ find_pre_sched_live (bb)
|
||||
int b = BB_TO_BLOCK (bb);
|
||||
|
||||
get_block_head_tail (bb, &head, &tail);
|
||||
COPY_REG_SET (bb_live_regs, basic_block_live_at_start[b]);
|
||||
COPY_REG_SET (bb_live_regs, BASIC_BLOCK (b)->global_live_at_start);
|
||||
next_tail = NEXT_INSN (tail);
|
||||
|
||||
for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
|
||||
@ -5303,7 +5305,8 @@ find_post_sched_live (bb)
|
||||
int b_succ;
|
||||
|
||||
b_succ = TO_BLOCK (e);
|
||||
IOR_REG_SET (bb_live_regs, basic_block_live_at_start[b_succ]);
|
||||
IOR_REG_SET (bb_live_regs,
|
||||
BASIC_BLOCK (b_succ)->global_live_at_start);
|
||||
e = NEXT_OUT (e);
|
||||
}
|
||||
while (e != first_edge);
|
||||
@ -5325,7 +5328,7 @@ find_post_sched_live (bb)
|
||||
&& (GET_RTX_CLASS (GET_CODE (tail)) != 'i'))
|
||||
{
|
||||
if (current_nr_blocks > 1)
|
||||
COPY_REG_SET (basic_block_live_at_start[b], bb_live_regs);
|
||||
COPY_REG_SET (BASIC_BLOCK (b)->global_live_at_start, bb_live_regs);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -5448,9 +5451,9 @@ find_post_sched_live (bb)
|
||||
|
||||
finish_sometimes_live (regs_sometimes_live, sometimes_max);
|
||||
|
||||
/* In interblock scheduling, basic_block_live_at_start may have changed. */
|
||||
/* In interblock scheduling, global_live_at_start may have changed. */
|
||||
if (current_nr_blocks > 1)
|
||||
COPY_REG_SET (basic_block_live_at_start[b], bb_live_regs);
|
||||
COPY_REG_SET (BASIC_BLOCK (b)->global_live_at_start, bb_live_regs);
|
||||
|
||||
|
||||
FREE_REG_SET (old_live_regs);
|
||||
@ -5522,7 +5525,7 @@ update_reg_usage ()
|
||||
pseudos which are live in more than one block.
|
||||
|
||||
This is because combine might have made an optimization which
|
||||
invalidated basic_block_live_at_start and reg_n_calls_crossed,
|
||||
invalidated global_live_at_start and reg_n_calls_crossed,
|
||||
but it does not update them. If we update reg_n_calls_crossed
|
||||
here, the two variables are now inconsistent, and this might
|
||||
confuse the caller-save code into saving a register that doesn't
|
||||
@ -8530,7 +8533,7 @@ schedule_insns (dump_file)
|
||||
|
||||
/* The scheduler runs after flow; therefore, we can't blindly call
|
||||
back into find_basic_blocks since doing so could invalidate the
|
||||
info in basic_block_live_at_start.
|
||||
info in global_live_at_start.
|
||||
|
||||
Consider a block consisting entirely of dead stores; after life
|
||||
analysis it would be a block of NOTE_INSN_DELETED notes. If
|
||||
|
18
gcc/jump.c
18
gcc/jump.c
@ -3429,6 +3429,24 @@ condjump_label (insn)
|
||||
return NULL_RTX;
|
||||
}
|
||||
|
||||
/* Return true if INSN is a (possibly conditional) return insn. */
|
||||
|
||||
static int
|
||||
returnjump_p_1 (loc, data)
|
||||
rtx *loc;
|
||||
void *data ATTRIBUTE_UNUSED;
|
||||
{
|
||||
rtx x = *loc;
|
||||
return GET_CODE (x) == RETURN;
|
||||
}
|
||||
|
||||
int
|
||||
returnjump_p (insn)
|
||||
rtx insn;
|
||||
{
|
||||
return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
|
||||
}
|
||||
|
||||
#ifdef HAVE_cc0
|
||||
|
||||
/* Return 1 if X is an RTX that does nothing but set the condition codes
|
||||
|
@ -966,7 +966,8 @@ update_equiv_regs ()
|
||||
BLOCK_HEAD (block) = PREV_INSN (insn);
|
||||
|
||||
for (l = 0; l < n_basic_blocks; l++)
|
||||
CLEAR_REGNO_REG_SET (basic_block_live_at_start[l], regno);
|
||||
CLEAR_REGNO_REG_SET (BASIC_BLOCK (l)->global_live_at_start,
|
||||
regno);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1039,7 +1040,7 @@ block_alloc (b)
|
||||
|
||||
/* Initialize table of hardware registers currently live. */
|
||||
|
||||
REG_SET_TO_HARD_REG_SET (regs_live, basic_block_live_at_start[b]);
|
||||
REG_SET_TO_HARD_REG_SET (regs_live, BASIC_BLOCK (b)->global_live_at_start);
|
||||
|
||||
/* This loop scans the instructions of the basic block
|
||||
and assigns quantities to registers.
|
||||
|
@ -22,9 +22,9 @@ Boston, MA 02111-1307, USA. */
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "rtl.h"
|
||||
#include "bitmap.h"
|
||||
#include "real.h"
|
||||
#include "flags.h"
|
||||
#include "basic-block.h"
|
||||
|
||||
|
||||
/* How to print out a register name.
|
||||
@ -170,6 +170,14 @@ print_rtx (in_rtx)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == 3 && GET_CODE (in_rtx) == NOTE
|
||||
&& NOTE_LINE_NUMBER (in_rtx) == NOTE_INSN_BASIC_BLOCK)
|
||||
{
|
||||
basic_block bb = NOTE_BASIC_BLOCK (in_rtx);
|
||||
fprintf (outfile, " [bb %d]", bb->index);
|
||||
break;
|
||||
}
|
||||
|
||||
if (XSTR (in_rtx, i) == 0)
|
||||
fputs (dump_for_graph ? " \\\"\\\"" : " \"\"", outfile);
|
||||
else
|
||||
|
@ -229,9 +229,23 @@ static rtx
|
||||
/* Get the basic block number of an insn. See note at block_number
|
||||
definition are validity of this information. */
|
||||
|
||||
#define BLOCK_NUM(INSN) \
|
||||
((INSN_UID (INSN) > max_uid) \
|
||||
? (abort() , -1) : block_number[INSN_UID (INSN)])
|
||||
static int BLOCK_NUM PROTO((rtx));
|
||||
|
||||
#ifdef __GNUC__
|
||||
__inline__
|
||||
#endif
|
||||
static int
|
||||
BLOCK_NUM(insn)
|
||||
rtx insn;
|
||||
{
|
||||
int tmp = INSN_UID (insn);
|
||||
if (tmp > max_uid)
|
||||
abort ();
|
||||
tmp = block_number[tmp];
|
||||
if (tmp < 0)
|
||||
abort ();
|
||||
return tmp;
|
||||
}
|
||||
|
||||
extern rtx forced_labels;
|
||||
|
||||
@ -502,6 +516,7 @@ reg_to_stack (first, file)
|
||||
bzero ((char *) block_out_reg_set, blocks * sizeof (HARD_REG_SET));
|
||||
|
||||
block_number = (int *) alloca ((max_uid + 1) * sizeof (int));
|
||||
memset (block_number, -1, (max_uid + 1) * sizeof (int));
|
||||
|
||||
find_blocks (first);
|
||||
stack_reg_life_analysis (first, &stackentry);
|
||||
|
@ -2208,12 +2208,5 @@ reg_classes_intersect_p (c1, c2)
|
||||
void
|
||||
regset_release_memory ()
|
||||
{
|
||||
if (basic_block_live_at_start)
|
||||
{
|
||||
free_regset_vector (basic_block_live_at_start, n_basic_blocks);
|
||||
basic_block_live_at_start = 0;
|
||||
}
|
||||
|
||||
FREE_REG_SET (regs_live_at_setjmp);
|
||||
bitmap_release_memory ();
|
||||
}
|
||||
|
@ -267,7 +267,7 @@ mark_flags_life_zones (flags)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < flags_nregs; ++i)
|
||||
live |= REGNO_REG_SET_P (basic_block_live_at_start[block],
|
||||
live |= REGNO_REG_SET_P (BASIC_BLOCK (block)->global_live_at_start,
|
||||
flags_regno + i);
|
||||
}
|
||||
#endif
|
||||
|
@ -538,9 +538,9 @@ compute_use_by_pseudos (to, from)
|
||||
if (r < 0)
|
||||
{
|
||||
/* reload_combine uses the information from
|
||||
basic_block_live_at_start, which might still contain registers
|
||||
that have not actually been allocated since they have an
|
||||
equivalence. */
|
||||
BASIC_BLOCK->global_live_at_start, which might still
|
||||
contain registers that have not actually been allocated
|
||||
since they have an equivalence. */
|
||||
if (! reload_completed)
|
||||
abort ();
|
||||
}
|
||||
@ -1060,7 +1060,7 @@ reload (first, global, dumpfile)
|
||||
|
||||
if (! frame_pointer_needed)
|
||||
for (i = 0; i < n_basic_blocks; i++)
|
||||
CLEAR_REGNO_REG_SET (basic_block_live_at_start[i],
|
||||
CLEAR_REGNO_REG_SET (BASIC_BLOCK (i)->global_live_at_start,
|
||||
HARD_FRAME_POINTER_REGNUM);
|
||||
|
||||
/* Come here (with failure set nonzero) if we can't get enough spill regs
|
||||
@ -9494,8 +9494,8 @@ reload_combine ()
|
||||
{
|
||||
HARD_REG_SET live;
|
||||
|
||||
REG_SET_TO_HARD_REG_SET (live, basic_block_live_at_start[i]);
|
||||
compute_use_by_pseudos (&live, basic_block_live_at_start[i]);
|
||||
REG_SET_TO_HARD_REG_SET (live, BASIC_BLOCK (i)->global_live_at_start);
|
||||
compute_use_by_pseudos (&live, BASIC_BLOCK (i)->global_live_at_start);
|
||||
COPY_HARD_REG_SET (LABEL_LIVE (insn), live);
|
||||
IOR_HARD_REG_SET (ever_live_at_start, live);
|
||||
}
|
||||
|
@ -875,7 +875,7 @@ mark_target_live_regs (insns, target, res)
|
||||
TARGET. Otherwise, we must assume everything is live. */
|
||||
if (b != -1)
|
||||
{
|
||||
regset regs_live = basic_block_live_at_start[b];
|
||||
regset regs_live = BASIC_BLOCK (b)->global_live_at_start;
|
||||
int j;
|
||||
int regno;
|
||||
rtx start_insn, stop_insn;
|
||||
|
@ -184,7 +184,8 @@ char *note_insn_name[] = { 0 , "NOTE_INSN_DELETED",
|
||||
"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_INSN_RANGE_END", "NOTE_INSN_LIVE",
|
||||
"NOTE_INSN_BASIC_BLOCK" };
|
||||
|
||||
char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
|
||||
"REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
|
||||
|
11
gcc/rtl.h
11
gcc/rtl.h
@ -91,6 +91,7 @@ typedef union rtunion_def
|
||||
addr_diff_vec_flags rt_addr_diff_vec_flags;
|
||||
struct bitmap_head_def *rtbit;
|
||||
union tree_node *rttree;
|
||||
struct basic_block_def *bb;
|
||||
} rtunion;
|
||||
|
||||
/* RTL expression ("rtx"). */
|
||||
@ -404,6 +405,7 @@ extern char *reg_note_name[];
|
||||
#define NOTE_BLOCK_NUMBER(INSN) ((INSN)->fld[3].rtint)
|
||||
#define NOTE_RANGE_INFO(INSN) ((INSN)->fld[3].rtx)
|
||||
#define NOTE_LIVE_INFO(INSN) ((INSN)->fld[3].rtx)
|
||||
#define NOTE_BASIC_BLOCK(INSN) ((INSN)->fld[3].bb)
|
||||
|
||||
/* If the NOTE_BLOCK_NUMBER field gets a -1, it means create a new
|
||||
block node for a live range block. */
|
||||
@ -469,6 +471,8 @@ extern char *reg_note_name[];
|
||||
#define NOTE_INSN_RANGE_END -18
|
||||
/* Record which registers are currently live. */
|
||||
#define NOTE_INSN_LIVE -19
|
||||
/* Record the struct for the following basic block. */
|
||||
#define NOTE_INSN_BASIC_BLOCK -20
|
||||
|
||||
#if 0 /* These are not used, and I don't know what they were for. --rms. */
|
||||
#define NOTE_DECL_NAME(INSN) ((INSN)->fld[3].rtstr)
|
||||
@ -932,6 +936,7 @@ extern rtx emit_insn_before PROTO((rtx, rtx));
|
||||
extern rtx emit_jump_insn_before PROTO((rtx, rtx));
|
||||
extern rtx emit_call_insn_before PROTO((rtx, rtx));
|
||||
extern rtx emit_barrier_before PROTO((rtx));
|
||||
extern rtx emit_label_before PROTO((rtx, rtx));
|
||||
extern rtx emit_note_before PROTO((int, rtx));
|
||||
extern rtx emit_insn_after PROTO((rtx, rtx));
|
||||
extern rtx emit_jump_insn_after PROTO((rtx, rtx));
|
||||
@ -982,7 +987,6 @@ extern rtx simplify_unary_operation PROTO((enum rtx_code, enum machine_mode, rtx
|
||||
extern rtx simplify_binary_operation PROTO((enum rtx_code, enum machine_mode, rtx, rtx));
|
||||
extern rtx simplify_ternary_operation PROTO((enum rtx_code, enum machine_mode, enum machine_mode, rtx, rtx, rtx));
|
||||
extern rtx simplify_relational_operation PROTO((enum rtx_code, enum machine_mode, rtx, rtx));
|
||||
extern rtx nonlocal_label_rtx_list PROTO((void));
|
||||
extern rtx gen_move_insn PROTO((rtx, rtx));
|
||||
extern rtx gen_jump PROTO((rtx));
|
||||
extern rtx gen_beq PROTO((rtx));
|
||||
@ -1300,6 +1304,7 @@ extern int comparison_dominates_p PROTO ((enum rtx_code, enum rtx_code));
|
||||
extern int condjump_p PROTO ((rtx));
|
||||
extern rtx condjump_label PROTO ((rtx));
|
||||
extern int simplejump_p PROTO ((rtx));
|
||||
extern int returnjump_p PROTO ((rtx));
|
||||
extern int sets_cc0_p PROTO ((rtx));
|
||||
extern int invert_jump PROTO ((rtx, rtx));
|
||||
extern int rtx_renumbered_equal_p PROTO ((rtx, rtx));
|
||||
@ -1415,6 +1420,10 @@ extern void expand_null_return PROTO((void));
|
||||
extern void emit_jump PROTO ((rtx));
|
||||
extern int preserve_subexpressions_p PROTO ((void));
|
||||
|
||||
/* List (chain of EXPR_LIST) of labels heading the current handlers for
|
||||
nonlocal gotos. */
|
||||
extern rtx nonlocal_goto_handler_labels;
|
||||
|
||||
/* In expr.c */
|
||||
extern void init_expr_once PROTO ((void));
|
||||
extern void move_by_pieces PROTO ((rtx, rtx, int, int));
|
||||
|
@ -2879,7 +2879,7 @@ schedule_block (b, file)
|
||||
|
||||
if (reload_completed == 0)
|
||||
{
|
||||
COPY_REG_SET (bb_live_regs, basic_block_live_at_start[b]);
|
||||
COPY_REG_SET (bb_live_regs, BASIC_BLOCK (b)->global_live_at_start);
|
||||
CLEAR_REG_SET (bb_dead_regs);
|
||||
|
||||
if (b == 0)
|
||||
|
22
gcc/stmt.c
22
gcc/stmt.c
@ -428,7 +428,7 @@ static int using_eh_for_cleanups_p = 0;
|
||||
static int n_occurrences PROTO((int, char *));
|
||||
static void expand_goto_internal PROTO((tree, rtx, rtx));
|
||||
static int expand_fixup PROTO((tree, rtx, rtx));
|
||||
static void expand_nl_handler_label PROTO((rtx, rtx));
|
||||
static rtx expand_nl_handler_label PROTO((rtx, rtx));
|
||||
static void expand_nl_goto_receiver PROTO((void));
|
||||
static void expand_nl_goto_receivers PROTO((struct nesting *));
|
||||
static void fixup_gotos PROTO((struct nesting *, rtx, tree,
|
||||
@ -3169,7 +3169,7 @@ remember_end_note (block)
|
||||
/* Emit a handler label for a nonlocal goto handler.
|
||||
Also emit code to store the handler label in SLOT before BEFORE_INSN. */
|
||||
|
||||
static void
|
||||
static rtx
|
||||
expand_nl_handler_label (slot, before_insn)
|
||||
rtx slot, before_insn;
|
||||
{
|
||||
@ -3186,6 +3186,8 @@ expand_nl_handler_label (slot, before_insn)
|
||||
emit_insns_before (insns, before_insn);
|
||||
|
||||
emit_label (handler_label);
|
||||
|
||||
return handler_label;
|
||||
}
|
||||
|
||||
/* Emit code to restore vital registers at the beginning of a nonlocal goto
|
||||
@ -3260,6 +3262,7 @@ expand_nl_goto_receivers (thisblock)
|
||||
tree link;
|
||||
rtx afterward = gen_label_rtx ();
|
||||
rtx insns, slot;
|
||||
rtx label_list;
|
||||
int any_invalid;
|
||||
|
||||
/* Record the handler address in the stack slot for that purpose,
|
||||
@ -3283,14 +3286,18 @@ expand_nl_goto_receivers (thisblock)
|
||||
/* Make a separate handler for each label. */
|
||||
link = nonlocal_labels;
|
||||
slot = nonlocal_goto_handler_slots;
|
||||
label_list = NULL_RTX;
|
||||
for (; link; link = TREE_CHAIN (link), slot = XEXP (slot, 1))
|
||||
/* Skip any labels we shouldn't be able to jump to from here,
|
||||
we generate one special handler for all of them below which just calls
|
||||
abort. */
|
||||
if (! DECL_TOO_LATE (TREE_VALUE (link)))
|
||||
{
|
||||
expand_nl_handler_label (XEXP (slot, 0),
|
||||
thisblock->data.block.first_insn);
|
||||
rtx lab;
|
||||
lab = expand_nl_handler_label (XEXP (slot, 0),
|
||||
thisblock->data.block.first_insn);
|
||||
label_list = gen_rtx_EXPR_LIST (VOIDmode, lab, label_list);
|
||||
|
||||
expand_nl_goto_receiver ();
|
||||
|
||||
/* Jump to the "real" nonlocal label. */
|
||||
@ -3305,8 +3312,10 @@ expand_nl_goto_receivers (thisblock)
|
||||
for (; link; link = TREE_CHAIN (link), slot = XEXP (slot, 1))
|
||||
if (DECL_TOO_LATE (TREE_VALUE (link)))
|
||||
{
|
||||
expand_nl_handler_label (XEXP (slot, 0),
|
||||
thisblock->data.block.first_insn);
|
||||
rtx lab;
|
||||
lab = expand_nl_handler_label (XEXP (slot, 0),
|
||||
thisblock->data.block.first_insn);
|
||||
label_list = gen_rtx_EXPR_LIST (VOIDmode, lab, label_list);
|
||||
any_invalid = 1;
|
||||
}
|
||||
|
||||
@ -3318,6 +3327,7 @@ expand_nl_goto_receivers (thisblock)
|
||||
emit_barrier ();
|
||||
}
|
||||
|
||||
nonlocal_goto_handler_labels = label_list;
|
||||
emit_label (afterward);
|
||||
}
|
||||
|
||||
|
52
gcc/toplev.c
52
gcc/toplev.c
@ -292,6 +292,7 @@ int regmove_dump = 0;
|
||||
int sched_dump = 0;
|
||||
int local_reg_dump = 0;
|
||||
int global_reg_dump = 0;
|
||||
int flow2_dump = 0;
|
||||
int sched2_dump = 0;
|
||||
int jump2_opt_dump = 0;
|
||||
#ifdef DELAY_SLOTS
|
||||
@ -1286,6 +1287,7 @@ int regmove_time;
|
||||
int sched_time;
|
||||
int local_alloc_time;
|
||||
int global_alloc_time;
|
||||
int flow2_time;
|
||||
int sched2_time;
|
||||
#ifdef DELAY_SLOTS
|
||||
int dbr_sched_time;
|
||||
@ -2642,6 +2644,7 @@ compile_file (name)
|
||||
sched_time = 0;
|
||||
local_alloc_time = 0;
|
||||
global_alloc_time = 0;
|
||||
flow2_time = 0;
|
||||
sched2_time = 0;
|
||||
#ifdef DELAY_SLOTS
|
||||
dbr_sched_time = 0;
|
||||
@ -2759,6 +2762,12 @@ compile_file (name)
|
||||
if (graph_dump_format != no_graph)
|
||||
clean_graph_dump_file (dump_base_name, ".greg");
|
||||
}
|
||||
if (flow2_dump)
|
||||
{
|
||||
clean_dump_file (".flow2");
|
||||
if (graph_dump_format != no_graph)
|
||||
clean_graph_dump_file (dump_base_name, ".flow2");
|
||||
}
|
||||
if (sched2_dump)
|
||||
{
|
||||
clean_dump_file (".sched2");
|
||||
@ -3303,6 +3312,8 @@ compile_file (name)
|
||||
finish_graph_dump_file (dump_base_name, ".lreg");
|
||||
if (global_reg_dump)
|
||||
finish_graph_dump_file (dump_base_name, ".greg");
|
||||
if (flow_dump)
|
||||
finish_graph_dump_file (dump_base_name, ".flow2");
|
||||
if (sched2_dump)
|
||||
finish_graph_dump_file (dump_base_name, ".sched2");
|
||||
if (jump2_opt_dump)
|
||||
@ -3346,6 +3357,7 @@ compile_file (name)
|
||||
print_time ("sched", sched_time);
|
||||
print_time ("local-alloc", local_alloc_time);
|
||||
print_time ("global-alloc", global_alloc_time);
|
||||
print_time ("flow2", flow2_time);
|
||||
print_time ("sched2", sched2_time);
|
||||
#ifdef DELAY_SLOTS
|
||||
print_time ("dbranch", dbr_sched_time);
|
||||
@ -4079,14 +4091,27 @@ rest_of_compilation (decl)
|
||||
}
|
||||
}
|
||||
|
||||
if (global_reg_dump)
|
||||
{
|
||||
TIMEVAR (dump_time, dump_global_regs (rtl_dump_file));
|
||||
close_dump_file (print_rtl_with_bb, insns);
|
||||
if (graph_dump_format != no_graph)
|
||||
print_rtl_graph_with_bb (dump_base_name, ".greg", insns);
|
||||
}
|
||||
|
||||
/* Re-create the death notes which were deleted during reload. */
|
||||
if (flow2_dump)
|
||||
open_dump_file (".flow2", decl_printable_name (decl, 2));
|
||||
|
||||
if (optimize)
|
||||
TIMEVAR
|
||||
(flow_time,
|
||||
{
|
||||
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
|
||||
life_analysis (insns, max_reg_num (), rtl_dump_file);
|
||||
});
|
||||
{
|
||||
TIMEVAR
|
||||
(flow2_time,
|
||||
{
|
||||
find_basic_blocks (insns, max_reg_num (), rtl_dump_file);
|
||||
life_analysis (insns, max_reg_num (), rtl_dump_file);
|
||||
});
|
||||
}
|
||||
|
||||
flow2_completed = 1;
|
||||
|
||||
@ -4097,13 +4122,13 @@ rest_of_compilation (decl)
|
||||
|
||||
thread_prologue_and_epilogue_insns (insns);
|
||||
|
||||
if (global_reg_dump)
|
||||
if (flow2_dump)
|
||||
{
|
||||
TIMEVAR (dump_time, dump_global_regs (rtl_dump_file));
|
||||
close_dump_file (print_rtl_with_bb, insns);
|
||||
if (graph_dump_format != no_graph)
|
||||
print_rtl_graph_with_bb (dump_base_name, ".greg", insns);
|
||||
print_rtl_graph_with_bb (dump_base_name, ".flow2", insns);
|
||||
}
|
||||
|
||||
if (optimize > 0 && flag_schedule_insns_after_reload)
|
||||
{
|
||||
if (sched2_dump)
|
||||
@ -4227,6 +4252,9 @@ rest_of_compilation (decl)
|
||||
if (! quiet_flag)
|
||||
fflush (asm_out_file);
|
||||
|
||||
/* Release all memory allocated by flow. */
|
||||
free_basic_block_vars (0);
|
||||
|
||||
/* Release all memory held by regsets now */
|
||||
regset_release_memory ();
|
||||
});
|
||||
@ -4258,7 +4286,7 @@ rest_of_compilation (decl)
|
||||
|
||||
exit_rest_of_compilation:
|
||||
|
||||
free_bb_memory ();
|
||||
free_bb_mem ();
|
||||
|
||||
/* In case the function was not output,
|
||||
don't leave any temporary anonymous types
|
||||
@ -4770,6 +4798,7 @@ main (argc, argv)
|
||||
dbr_sched_dump = 1;
|
||||
#endif
|
||||
flow_dump = 1;
|
||||
flow2_dump = 1;
|
||||
global_reg_dump = 1;
|
||||
jump_opt_dump = 1;
|
||||
addressof_dump = 1;
|
||||
@ -4864,6 +4893,9 @@ main (argc, argv)
|
||||
case 'v':
|
||||
graph_dump_format = vcg;
|
||||
break;
|
||||
case 'w':
|
||||
flow2_dump = 1;
|
||||
break;
|
||||
case 'y':
|
||||
set_yydebug (1);
|
||||
break;
|
||||
|
@ -2129,8 +2129,12 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
|
||||
case NOTE:
|
||||
/* VTOP notes are valid only before the loop exit test. If placed
|
||||
anywhere else, loop may generate bad code. */
|
||||
/* BASIC_BLOCK notes exist to stabilize basic block structures with
|
||||
the associated rtl. We do not want to share the structure in
|
||||
this new block. */
|
||||
|
||||
if (NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
|
||||
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK
|
||||
&& (NOTE_LINE_NUMBER (insn) != NOTE_INSN_LOOP_VTOP
|
||||
|| (last_iteration && unroll_type != UNROLL_COMPLETELY)))
|
||||
copy = emit_note (NOTE_SOURCE_FILE (insn),
|
||||
@ -2175,7 +2179,8 @@ copy_loop_body (copy_start, copy_end, map, exit_label, last_iteration,
|
||||
for (insn = copy_notes_from; insn != loop_end; insn = NEXT_INSN (insn))
|
||||
{
|
||||
if (GET_CODE (insn) == NOTE
|
||||
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED)
|
||||
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_DELETED
|
||||
&& NOTE_LINE_NUMBER (insn) != NOTE_INSN_BASIC_BLOCK)
|
||||
emit_note (NOTE_SOURCE_FILE (insn), NOTE_LINE_NUMBER (insn));
|
||||
}
|
||||
}
|
||||
|
@ -75,6 +75,7 @@ typedef union varray_data_tag {
|
||||
struct sched_info_tag *sched[1];
|
||||
struct reg_info_def *reg[1];
|
||||
struct const_equiv_data const_equiv[1];
|
||||
struct basic_block_def *bb[1];
|
||||
} varray_data;
|
||||
|
||||
/* Virtual array of pointers header. */
|
||||
@ -146,6 +147,9 @@ extern varray_type varray_init PROTO ((size_t, size_t, const char *));
|
||||
#define VARRAY_CONST_EQUIV_INIT(va, num, name) \
|
||||
va = varray_init (num, sizeof (struct const_equiv_data), name)
|
||||
|
||||
#define VARRAY_BB_INIT(va, num, name) \
|
||||
va = varray_init (num, sizeof (struct basic_block_def *), name)
|
||||
|
||||
/* Free up memory allocated by the virtual array, but do not free any of the
|
||||
elements involved. */
|
||||
#define VARRAY_FREE(vp) \
|
||||
@ -189,6 +193,7 @@ extern varray_type varray_grow PROTO((varray_type, size_t));
|
||||
#define VARRAY_BITMAP(VA, N) ((VA)->data.bitmap[ VARRAY_CHECK (VA, N) ])
|
||||
#define VARRAY_SCHED(VA, N) ((VA)->data.sched[ VARRAY_CHECK (VA, N) ])
|
||||
#define VARRAY_REG(VA, N) ((VA)->data.reg[ VARRAY_CHECK (VA, N) ])
|
||||
#define VARRAY_CONST_EQUIV(VA, N) ((VA)->data.const_equiv[ VARRAY_CHECK (VA, N) ])
|
||||
#define VARRAY_CONST_EQUIV(VA, N) ((VA)->data.const_equiv[VARRAY_CHECK (VA, N)])
|
||||
#define VARRAY_BB(VA, N) ((VA)->data.bb[ VARRAY_CHECK (VA, N) ])
|
||||
|
||||
#endif /* _VARRAY_H_ */
|
||||
|
Loading…
x
Reference in New Issue
Block a user