Expanders cleanups after tree-ssa merge, part 1.
2004-05-19 Steven Bosscher <stevenb@suse.de> Expanders cleanups after tree-ssa merge, part 1. * expr.c (store_constructor): Build loop start and end by hand instead of via loop functions from stmt.c. (expand_expr_real_1): Abort if we see an EXIT_EXPR or a LOOP_EXPR. Remove the code to expand them. * stmt.c (loop_stack): Remove this and everything related. (struct nesting, enum nesting_desc): Update. (expand_fixup): Likewise. (expand_loop_start, expand_start_loop_continue_elsewhere, expand_start_null_loop, expand_loop_continue_here, expand_end_loop, expand_end_null_loop, expand_continue_loop, expand_exit_loop, expand_exit_loop_if_false, expand_exit_loop_top_cond, expand_exit_something): Remove. * tree.h: Remove prototypes. From-SVN: r82018
This commit is contained in:
parent
cc52902d97
commit
6af8eb5714
|
@ -1,3 +1,20 @@
|
|||
2004-05-19 Steven Bosscher <stevenb@suse.de>
|
||||
|
||||
* expr.c (store_constructor): Build loop start and end by hand
|
||||
instead of via loop functions from stmt.c.
|
||||
(expand_expr_real_1): Abort if we see an EXIT_EXPR or a LOOP_EXPR.
|
||||
Remove the code to expand them.
|
||||
|
||||
* stmt.c (loop_stack): Remove this and everything related.
|
||||
(struct nesting, enum nesting_desc): Update.
|
||||
(expand_fixup): Likewise.
|
||||
(expand_loop_start, expand_start_loop_continue_elsewhere,
|
||||
expand_start_null_loop, expand_loop_continue_here, expand_end_loop,
|
||||
expand_end_null_loop, expand_continue_loop, expand_exit_loop,
|
||||
expand_exit_loop_if_false, expand_exit_loop_top_cond,
|
||||
expand_exit_something): Remove.
|
||||
* tree.h: Remove prototypes.
|
||||
|
||||
2004-05-18 Mike Stump <mrs@apple.com>
|
||||
Devang Patel <dpatel@apple.com>
|
||||
|
||||
|
|
44
gcc/expr.c
44
gcc/expr.c
|
@ -4963,8 +4963,7 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
|
|||
{
|
||||
tree lo_index = TREE_OPERAND (index, 0);
|
||||
tree hi_index = TREE_OPERAND (index, 1);
|
||||
rtx index_r, pos_rtx, loop_end;
|
||||
struct nesting *loop;
|
||||
rtx index_r, pos_rtx;
|
||||
HOST_WIDE_INT lo, hi, count;
|
||||
tree position;
|
||||
|
||||
|
@ -5005,9 +5004,11 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
|
|||
}
|
||||
else
|
||||
{
|
||||
expand_expr (hi_index, NULL_RTX, VOIDmode, 0);
|
||||
loop_end = gen_label_rtx ();
|
||||
rtx loop_start = gen_label_rtx ();
|
||||
rtx loop_end = gen_label_rtx ();
|
||||
tree exit_cond;
|
||||
|
||||
expand_expr (hi_index, NULL_RTX, VOIDmode, 0);
|
||||
unsignedp = TYPE_UNSIGNED (domain);
|
||||
|
||||
index = build_decl (VAR_DECL, NULL_TREE, domain);
|
||||
|
@ -5025,7 +5026,11 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
|
|||
emit_queue ();
|
||||
}
|
||||
store_expr (lo_index, index_r, 0);
|
||||
loop = expand_start_loop (0);
|
||||
|
||||
/* Build the head of the loop. */
|
||||
do_pending_stack_adjust ();
|
||||
emit_queue ();
|
||||
emit_label (loop_start);
|
||||
|
||||
/* Assign value to element index. */
|
||||
position
|
||||
|
@ -5046,14 +5051,19 @@ store_constructor (tree exp, rtx target, int cleared, HOST_WIDE_INT size)
|
|||
else
|
||||
store_expr (value, xtarget, 0);
|
||||
|
||||
expand_exit_loop_if_false (loop,
|
||||
build (LT_EXPR, integer_type_node,
|
||||
index, hi_index));
|
||||
/* Generate a conditional jump to exit the loop. */
|
||||
exit_cond = build (LT_EXPR, integer_type_node,
|
||||
index, hi_index);
|
||||
jumpif (exit_cond, loop_end);
|
||||
|
||||
/* Update the loop counter, and jump to the head of
|
||||
the loop. */
|
||||
expand_increment (build (PREINCREMENT_EXPR,
|
||||
TREE_TYPE (index),
|
||||
index, integer_one_node), 0, 0);
|
||||
expand_end_loop ();
|
||||
emit_jump (loop_start);
|
||||
|
||||
/* Build the end of the loop. */
|
||||
emit_label (loop_end);
|
||||
}
|
||||
}
|
||||
|
@ -6804,10 +6814,11 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
|||
expand_computed_goto (TREE_OPERAND (exp, 0));
|
||||
return const0_rtx;
|
||||
|
||||
/* These are lowered during gimplification, so we should never ever
|
||||
see them here. */
|
||||
case LOOP_EXPR:
|
||||
case EXIT_EXPR:
|
||||
expand_exit_loop_if_false (NULL,
|
||||
invert_truthvalue (TREE_OPERAND (exp, 0)));
|
||||
return const0_rtx;
|
||||
abort ();
|
||||
|
||||
case LABELED_BLOCK_EXPR:
|
||||
if (LABELED_BLOCK_BODY (exp))
|
||||
|
@ -6823,15 +6834,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
|
|||
expand_goto (LABELED_BLOCK_LABEL (EXIT_BLOCK_LABELED_BLOCK (exp)));
|
||||
return const0_rtx;
|
||||
|
||||
case LOOP_EXPR:
|
||||
push_temp_slots ();
|
||||
expand_start_loop (1);
|
||||
expand_expr_stmt_value (TREE_OPERAND (exp, 0), 0, 1);
|
||||
expand_end_loop ();
|
||||
pop_temp_slots ();
|
||||
|
||||
return const0_rtx;
|
||||
|
||||
case BIND_EXPR:
|
||||
{
|
||||
tree block = BIND_EXPR_BLOCK (exp);
|
||||
|
|
401
gcc/stmt.c
401
gcc/stmt.c
|
@ -124,7 +124,7 @@ static int cost_table_initialized;
|
|||
The position of an entry on `nesting_stack' is in its `depth' field.
|
||||
|
||||
Each type of construct has its own individual stack.
|
||||
For example, loops have `loop_stack'. Each object points to the
|
||||
For example, loops have `cond_stack'. Each object points to the
|
||||
next object of the same type through the `next' field.
|
||||
|
||||
Some constructs are visible to `break' exit-statements and others
|
||||
|
@ -142,7 +142,6 @@ struct nesting GTY(())
|
|||
rtx exit_label;
|
||||
enum nesting_desc {
|
||||
COND_NESTING,
|
||||
LOOP_NESTING,
|
||||
BLOCK_NESTING,
|
||||
CASE_NESTING
|
||||
} desc;
|
||||
|
@ -159,17 +158,6 @@ struct nesting GTY(())
|
|||
This may be the end of the if or the next else/elseif. */
|
||||
rtx next_label;
|
||||
} GTY ((tag ("COND_NESTING"))) cond;
|
||||
/* For loops. */
|
||||
struct nesting_loop
|
||||
{
|
||||
/* Label at the top of the loop; place to loop back to. */
|
||||
rtx start_label;
|
||||
/* Label at the end of the whole construct. */
|
||||
rtx end_label;
|
||||
/* Label for `continue' statement to jump to;
|
||||
this is in front of the stepper of the loop. */
|
||||
rtx continue_label;
|
||||
} GTY ((tag ("LOOP_NESTING"))) loop;
|
||||
/* For variable binding contours. */
|
||||
struct nesting_block
|
||||
{
|
||||
|
@ -259,8 +247,6 @@ struct nesting GTY(())
|
|||
do { struct nesting *target = STACK; \
|
||||
struct nesting *this; \
|
||||
do { this = nesting_stack; \
|
||||
if (loop_stack == this) \
|
||||
loop_stack = loop_stack->next; \
|
||||
if (cond_stack == this) \
|
||||
cond_stack = cond_stack->next; \
|
||||
if (block_stack == this) \
|
||||
|
@ -336,9 +322,6 @@ struct stmt_status GTY(())
|
|||
/* Chain of all pending conditional statements. */
|
||||
struct nesting * x_cond_stack;
|
||||
|
||||
/* Chain of all pending loops. */
|
||||
struct nesting * x_loop_stack;
|
||||
|
||||
/* Chain of all pending case or switch statements. */
|
||||
struct nesting * x_case_stack;
|
||||
|
||||
|
@ -372,7 +355,6 @@ struct stmt_status GTY(())
|
|||
#define block_stack (cfun->stmt->x_block_stack)
|
||||
#define stack_block_stack (cfun->stmt->x_stack_block_stack)
|
||||
#define cond_stack (cfun->stmt->x_cond_stack)
|
||||
#define loop_stack (cfun->stmt->x_loop_stack)
|
||||
#define case_stack (cfun->stmt->x_case_stack)
|
||||
#define nesting_stack (cfun->stmt->x_nesting_stack)
|
||||
#define nesting_depth (cfun->stmt->x_nesting_depth)
|
||||
|
@ -708,14 +690,6 @@ expand_fixup (tree tree_label, rtx rtl_label, rtx last_insn)
|
|||
&& (rtl_label == cond_stack->data.cond.endif_label
|
||||
|| rtl_label == cond_stack->data.cond.next_label))
|
||||
end_block = cond_stack;
|
||||
/* If we are in a loop, recognize certain labels which
|
||||
are likely targets. This reduces the number of fixups
|
||||
we need to create. */
|
||||
else if (loop_stack
|
||||
&& (rtl_label == loop_stack->data.loop.start_label
|
||||
|| rtl_label == loop_stack->data.loop.end_label
|
||||
|| rtl_label == loop_stack->data.loop.continue_label))
|
||||
end_block = loop_stack;
|
||||
else
|
||||
end_block = 0;
|
||||
|
||||
|
@ -774,9 +748,8 @@ expand_fixup (tree tree_label, rtx rtl_label, rtx last_insn)
|
|||
`SUPERBLOCK') of any other BLOCK nodes which we might create
|
||||
later on when we are expanding the fixup code.
|
||||
|
||||
Note that optimization passes (including expand_end_loop)
|
||||
might move the *_BLOCK notes away, so we use a NOTE_INSN_DELETED
|
||||
as a placeholder. */
|
||||
Note that optimization passes might move the *_BLOCK notes away,
|
||||
so we use a NOTE_INSN_DELETED as a placeholder. */
|
||||
|
||||
{
|
||||
rtx original_before_jump
|
||||
|
@ -2472,384 +2445,22 @@ expand_end_cond (void)
|
|||
clear_last_expr ();
|
||||
}
|
||||
|
||||
/* Generate RTL for the start of a loop. EXIT_FLAG is nonzero if this
|
||||
loop should be exited by `exit_something'. This is a loop for which
|
||||
`expand_continue' will jump to the top of the loop.
|
||||
|
||||
Make an entry on loop_stack to record the labels associated with
|
||||
this loop. */
|
||||
|
||||
struct nesting *
|
||||
expand_start_loop (int exit_flag)
|
||||
{
|
||||
struct nesting *thisloop = ALLOC_NESTING ();
|
||||
|
||||
/* Make an entry on loop_stack for the loop we are entering. */
|
||||
|
||||
thisloop->desc = LOOP_NESTING;
|
||||
thisloop->next = loop_stack;
|
||||
thisloop->all = nesting_stack;
|
||||
thisloop->depth = ++nesting_depth;
|
||||
thisloop->data.loop.start_label = gen_label_rtx ();
|
||||
thisloop->data.loop.end_label = gen_label_rtx ();
|
||||
thisloop->data.loop.continue_label = thisloop->data.loop.start_label;
|
||||
thisloop->exit_label = exit_flag ? thisloop->data.loop.end_label : 0;
|
||||
loop_stack = thisloop;
|
||||
nesting_stack = thisloop;
|
||||
|
||||
do_pending_stack_adjust ();
|
||||
emit_queue ();
|
||||
emit_label (thisloop->data.loop.start_label);
|
||||
|
||||
return thisloop;
|
||||
}
|
||||
|
||||
/* Like expand_start_loop but for a loop where the continuation point
|
||||
(for expand_continue_loop) will be specified explicitly. */
|
||||
|
||||
struct nesting *
|
||||
expand_start_loop_continue_elsewhere (int exit_flag)
|
||||
{
|
||||
struct nesting *thisloop = expand_start_loop (exit_flag);
|
||||
loop_stack->data.loop.continue_label = gen_label_rtx ();
|
||||
return thisloop;
|
||||
}
|
||||
|
||||
/* Begin a null, aka do { } while (0) "loop". But since the contents
|
||||
of said loop can still contain a break, we must frob the loop nest. */
|
||||
|
||||
struct nesting *
|
||||
expand_start_null_loop (void)
|
||||
{
|
||||
struct nesting *thisloop = ALLOC_NESTING ();
|
||||
|
||||
/* Make an entry on loop_stack for the loop we are entering. */
|
||||
|
||||
thisloop->desc = LOOP_NESTING;
|
||||
thisloop->next = loop_stack;
|
||||
thisloop->all = nesting_stack;
|
||||
thisloop->depth = ++nesting_depth;
|
||||
thisloop->data.loop.start_label = emit_note (NOTE_INSN_DELETED);
|
||||
thisloop->data.loop.end_label = gen_label_rtx ();
|
||||
thisloop->data.loop.continue_label = thisloop->data.loop.end_label;
|
||||
thisloop->exit_label = thisloop->data.loop.end_label;
|
||||
loop_stack = thisloop;
|
||||
nesting_stack = thisloop;
|
||||
|
||||
return thisloop;
|
||||
}
|
||||
|
||||
/* Specify the continuation point for a loop started with
|
||||
expand_start_loop_continue_elsewhere.
|
||||
Use this at the point in the code to which a continue statement
|
||||
should jump. */
|
||||
|
||||
void
|
||||
expand_loop_continue_here (void)
|
||||
{
|
||||
do_pending_stack_adjust ();
|
||||
emit_label (loop_stack->data.loop.continue_label);
|
||||
}
|
||||
|
||||
/* Finish a loop. Generate a jump back to the top and the loop-exit label.
|
||||
Pop the block off of loop_stack. */
|
||||
|
||||
void
|
||||
expand_end_loop (void)
|
||||
{
|
||||
rtx start_label = loop_stack->data.loop.start_label;
|
||||
rtx etc_note;
|
||||
int eh_regions, debug_blocks;
|
||||
bool empty_test;
|
||||
|
||||
do_pending_stack_adjust ();
|
||||
|
||||
/* If the loop starts with a loop exit, roll that to the end where
|
||||
it will optimize together with the jump back.
|
||||
|
||||
If the loop presently looks like this (in pseudo-C):
|
||||
|
||||
start_label:
|
||||
if (test) goto end_label;
|
||||
LOOP_END_TOP_COND
|
||||
body;
|
||||
goto start_label;
|
||||
end_label:
|
||||
|
||||
transform it to look like:
|
||||
|
||||
goto start_label;
|
||||
top_label:
|
||||
body;
|
||||
start_label:
|
||||
if (test) goto end_label;
|
||||
goto top_label;
|
||||
end_label:
|
||||
|
||||
We rely on the presence of NOTE_INSN_LOOP_END_TOP_COND to mark
|
||||
the end of the entry conditional. Without this, our lexical scan
|
||||
can't tell the difference between an entry conditional and a
|
||||
body conditional that exits the loop. Mistaking the two means
|
||||
that we can misplace the NOTE_INSN_LOOP_CONT note, which can
|
||||
screw up loop unrolling.
|
||||
|
||||
Things will be oh so much better when loop optimization is done
|
||||
off of a proper control flow graph... */
|
||||
|
||||
/* Scan insns from the top of the loop looking for the END_TOP_COND note. */
|
||||
|
||||
empty_test = true;
|
||||
eh_regions = debug_blocks = 0;
|
||||
for (etc_note = start_label; etc_note ; etc_note = NEXT_INSN (etc_note))
|
||||
if (GET_CODE (etc_note) == NOTE)
|
||||
{
|
||||
if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_LOOP_END_TOP_COND)
|
||||
break;
|
||||
|
||||
if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_LOOP_BEG)
|
||||
abort ();
|
||||
|
||||
/* At the same time, scan for EH region notes, as we don't want
|
||||
to scrog region nesting. This shouldn't happen, but... */
|
||||
if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_EH_REGION_BEG)
|
||||
eh_regions++;
|
||||
else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_EH_REGION_END)
|
||||
{
|
||||
if (--eh_regions < 0)
|
||||
/* We've come to the end of an EH region, but never saw the
|
||||
beginning of that region. That means that an EH region
|
||||
begins before the top of the loop, and ends in the middle
|
||||
of it. The existence of such a situation violates a basic
|
||||
assumption in this code, since that would imply that even
|
||||
when EH_REGIONS is zero, we might move code out of an
|
||||
exception region. */
|
||||
abort ();
|
||||
}
|
||||
|
||||
/* Likewise for debug scopes. In this case we'll either (1) move
|
||||
all of the notes if they are properly nested or (2) leave the
|
||||
notes alone and only rotate the loop at high optimization
|
||||
levels when we expect to scrog debug info. */
|
||||
else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_BLOCK_BEG)
|
||||
debug_blocks++;
|
||||
else if (NOTE_LINE_NUMBER (etc_note) == NOTE_INSN_BLOCK_END)
|
||||
debug_blocks--;
|
||||
}
|
||||
else if (INSN_P (etc_note))
|
||||
empty_test = false;
|
||||
|
||||
if (etc_note
|
||||
&& optimize
|
||||
&& ! empty_test
|
||||
&& eh_regions == 0
|
||||
&& (debug_blocks == 0 || optimize >= 2)
|
||||
&& NEXT_INSN (etc_note) != NULL_RTX
|
||||
&& ! any_condjump_p (get_last_insn ()))
|
||||
{
|
||||
/* We found one. Move everything from START to ETC to the end
|
||||
of the loop, and add a jump from the top of the loop. */
|
||||
rtx top_label = gen_label_rtx ();
|
||||
rtx start_move = start_label;
|
||||
|
||||
emit_label_before (top_label, start_move);
|
||||
|
||||
/* Actually move the insns. If the debug scopes are nested, we
|
||||
can move everything at once. Otherwise we have to move them
|
||||
one by one and squeeze out the block notes. */
|
||||
if (debug_blocks == 0)
|
||||
reorder_insns (start_move, etc_note, get_last_insn ());
|
||||
else
|
||||
{
|
||||
rtx insn, next_insn;
|
||||
for (insn = start_move; insn; insn = next_insn)
|
||||
{
|
||||
/* Figure out which insn comes after this one. We have
|
||||
to do this before we move INSN. */
|
||||
next_insn = (insn == etc_note ? NULL : NEXT_INSN (insn));
|
||||
|
||||
if (GET_CODE (insn) == NOTE
|
||||
&& (NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_BEG
|
||||
|| NOTE_LINE_NUMBER (insn) == NOTE_INSN_BLOCK_END))
|
||||
continue;
|
||||
|
||||
reorder_insns (insn, insn, get_last_insn ());
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the jump from the top of the loop. */
|
||||
emit_jump_insn_before (gen_jump (start_label), top_label);
|
||||
emit_barrier_before (top_label);
|
||||
start_label = top_label;
|
||||
}
|
||||
|
||||
if (etc_note)
|
||||
delete_insn (etc_note);
|
||||
|
||||
emit_jump (start_label);
|
||||
emit_label (loop_stack->data.loop.end_label);
|
||||
|
||||
POPSTACK (loop_stack);
|
||||
|
||||
clear_last_expr ();
|
||||
}
|
||||
|
||||
/* Finish a null loop, aka do { } while (0). */
|
||||
|
||||
void
|
||||
expand_end_null_loop (void)
|
||||
{
|
||||
do_pending_stack_adjust ();
|
||||
emit_label (loop_stack->data.loop.end_label);
|
||||
|
||||
POPSTACK (loop_stack);
|
||||
|
||||
clear_last_expr ();
|
||||
}
|
||||
|
||||
/* Generate a jump to the current loop's continue-point.
|
||||
This is usually the top of the loop, but may be specified
|
||||
explicitly elsewhere. If not currently inside a loop,
|
||||
return 0 and do nothing; caller will print an error message. */
|
||||
|
||||
int
|
||||
expand_continue_loop (struct nesting *whichloop)
|
||||
{
|
||||
/* Emit information for branch prediction. */
|
||||
rtx note;
|
||||
|
||||
if (flag_guess_branch_prob)
|
||||
{
|
||||
note = emit_note (NOTE_INSN_PREDICTION);
|
||||
NOTE_PREDICTION (note) = NOTE_PREDICT (PRED_CONTINUE, IS_TAKEN);
|
||||
}
|
||||
clear_last_expr ();
|
||||
if (whichloop == 0)
|
||||
whichloop = loop_stack;
|
||||
if (whichloop == 0)
|
||||
return 0;
|
||||
expand_goto_internal (NULL_TREE, whichloop->data.loop.continue_label,
|
||||
NULL_RTX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Generate a jump to exit the current loop. If not currently inside a loop,
|
||||
return 0 and do nothing; caller will print an error message. */
|
||||
|
||||
int
|
||||
expand_exit_loop (struct nesting *whichloop)
|
||||
{
|
||||
clear_last_expr ();
|
||||
if (whichloop == 0)
|
||||
whichloop = loop_stack;
|
||||
if (whichloop == 0)
|
||||
return 0;
|
||||
expand_goto_internal (NULL_TREE, whichloop->data.loop.end_label, NULL_RTX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Generate a conditional jump to exit the current loop if COND
|
||||
evaluates to zero. If not currently inside a loop,
|
||||
return 0 and do nothing; caller will print an error message. */
|
||||
|
||||
int
|
||||
expand_exit_loop_if_false (struct nesting *whichloop, tree cond)
|
||||
{
|
||||
rtx label;
|
||||
clear_last_expr ();
|
||||
|
||||
if (whichloop == 0)
|
||||
whichloop = loop_stack;
|
||||
if (whichloop == 0)
|
||||
return 0;
|
||||
|
||||
if (integer_nonzerop (cond))
|
||||
return 1;
|
||||
if (integer_zerop (cond))
|
||||
return expand_exit_loop (whichloop);
|
||||
|
||||
/* Check if we definitely won't need a fixup. */
|
||||
if (whichloop == nesting_stack)
|
||||
{
|
||||
jumpifnot (cond, whichloop->data.loop.end_label);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* In order to handle fixups, we actually create a conditional jump
|
||||
around an unconditional branch to exit the loop. If fixups are
|
||||
necessary, they go before the unconditional branch. */
|
||||
|
||||
label = gen_label_rtx ();
|
||||
jumpif (cond, label);
|
||||
expand_goto_internal (NULL_TREE, whichloop->data.loop.end_label,
|
||||
NULL_RTX);
|
||||
emit_label (label);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Like expand_exit_loop_if_false except also emit a note marking
|
||||
the end of the conditional. Should only be used immediately
|
||||
after expand_loop_start. */
|
||||
|
||||
int
|
||||
expand_exit_loop_top_cond (struct nesting *whichloop, tree cond)
|
||||
{
|
||||
if (! expand_exit_loop_if_false (whichloop, cond))
|
||||
return 0;
|
||||
|
||||
emit_note (NOTE_INSN_LOOP_END_TOP_COND);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Return nonzero if we should preserve sub-expressions as separate
|
||||
pseudos. We never do so if we aren't optimizing. We always do so
|
||||
if -fexpensive-optimizations.
|
||||
|
||||
Otherwise, we only do so if we are in the "early" part of a loop. I.e.,
|
||||
the loop may still be a small one. */
|
||||
if -fexpensive-optimizations. */
|
||||
|
||||
int
|
||||
preserve_subexpressions_p (void)
|
||||
{
|
||||
rtx insn;
|
||||
|
||||
if (flag_expensive_optimizations)
|
||||
return 1;
|
||||
|
||||
if (optimize == 0 || cfun == 0 || cfun->stmt == 0 || loop_stack == 0)
|
||||
if (optimize == 0 || cfun == 0 || cfun->stmt == 0)
|
||||
return 0;
|
||||
|
||||
insn = get_last_insn_anywhere ();
|
||||
|
||||
return (insn
|
||||
&& (INSN_UID (insn) - INSN_UID (loop_stack->data.loop.start_label)
|
||||
< n_non_fixed_regs * 3));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Generate a jump to exit the current loop, conditional, binding contour
|
||||
or case statement. Not all such constructs are visible to this function,
|
||||
only those started with EXIT_FLAG nonzero. Individual languages use
|
||||
the EXIT_FLAG parameter to control which kinds of constructs you can
|
||||
exit this way.
|
||||
|
||||
If not currently inside anything that can be exited,
|
||||
return 0 and do nothing; caller will print an error message. */
|
||||
|
||||
int
|
||||
expand_exit_something (void)
|
||||
{
|
||||
struct nesting *n;
|
||||
clear_last_expr ();
|
||||
for (n = nesting_stack; n; n = n->all)
|
||||
if (n->exit_label != 0)
|
||||
{
|
||||
expand_goto_internal (NULL_TREE, n->exit_label, NULL_RTX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Generate RTL to return from the current function, with no value.
|
||||
(That is, we do not do anything about returning any value.) */
|
||||
|
|
11
gcc/tree.h
11
gcc/tree.h
|
@ -3392,17 +3392,6 @@ extern void expand_start_cond (tree, int);
|
|||
extern void expand_end_cond (void);
|
||||
extern void expand_start_else (void);
|
||||
extern void expand_start_elseif (tree);
|
||||
extern struct nesting *expand_start_loop (int);
|
||||
extern struct nesting *expand_start_loop_continue_elsewhere (int);
|
||||
extern struct nesting *expand_start_null_loop (void);
|
||||
extern void expand_loop_continue_here (void);
|
||||
extern void expand_end_loop (void);
|
||||
extern void expand_end_null_loop (void);
|
||||
extern int expand_continue_loop (struct nesting *);
|
||||
extern int expand_exit_loop (struct nesting *);
|
||||
extern int expand_exit_loop_if_false (struct nesting *,tree);
|
||||
extern int expand_exit_loop_top_cond (struct nesting *, tree);
|
||||
extern int expand_exit_something (void);
|
||||
|
||||
extern void expand_stack_alloc (tree, tree);
|
||||
extern rtx expand_stack_save (void);
|
||||
|
|
Loading…
Reference in New Issue