Expanders cleanups after tree-ssa merge, part 1.
authorSteven Bosscher <stevenb@suse.de>
Wed, 19 May 2004 06:26:21 +0000 (06:26 +0000)
committerSteven Bosscher <steven@gcc.gnu.org>
Wed, 19 May 2004 06:26:21 +0000 (06:26 +0000)
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

gcc/ChangeLog
gcc/expr.c
gcc/stmt.c
gcc/tree.h

index cff555cea4aa712fc9b8022fa60f2532f6c52355..5627bcc62a74f390223899b7c164ee49aca56f56 100644 (file)
@@ -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>
 
index 1f8c3ef70d489c3588f452eab916b09f6cf05f7e..dd0725811edd4931ba952c9fad27d206ec9d7db5 100644 (file)
@@ -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);
index 0baeb8ce27281183aabf57a3b2a95654c663a65e..330ae5f2b539709ab8dfce262d1799f76d4c56f7 100644 (file)
@@ -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 ();
 }
 \f
-/* 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;
-}
 \f
 /* Generate RTL to return from the current function, with no value.
    (That is, we do not do anything about returning any value.)  */
index da881a298ebc79f07740267c0b662c5626529132..feebe7351e8a0810201c916e4cd1d343470e1609 100644 (file)
@@ -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);