From 6af8eb5714109ffd15a57023ae7e2679d567e792 Mon Sep 17 00:00:00 2001 From: Steven Bosscher Date: Wed, 19 May 2004 06:26:21 +0000 Subject: [PATCH] Expanders cleanups after tree-ssa merge, part 1. 2004-05-19 Steven Bosscher 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 --- gcc/ChangeLog | 17 +++ gcc/expr.c | 44 +++--- gcc/stmt.c | 401 +------------------------------------------------- gcc/tree.h | 11 -- 4 files changed, 46 insertions(+), 427 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index cff555cea4a..5627bcc62a7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2004-05-19 Steven Bosscher + + * 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 Devang Patel diff --git a/gcc/expr.c b/gcc/expr.c index 1f8c3ef70d4..dd0725811ed 100644 --- a/gcc/expr.c +++ b/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); diff --git a/gcc/stmt.c b/gcc/stmt.c index 0baeb8ce272..330ae5f2b53 100644 --- a/gcc/stmt.c +++ b/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.) */ diff --git a/gcc/tree.h b/gcc/tree.h index da881a298eb..feebe7351e8 100644 --- a/gcc/tree.h +++ b/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); -- 2.30.2