OSDN Git Service

(find_reloads_address_1, case POST_INC): Don't use
[pf3gnuchains/gcc-fork.git] / gcc / c-iterate.c
index 0325026..f8dec10 100644 (file)
@@ -1,5 +1,5 @@
 /* Build expressions with type checking for C compiler.
-   Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 89, 92, 93, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 /* This file is part of the C front end.
@@ -29,20 +30,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "flags.h"
 #include "obstack.h"
 #include "rtl.h"
-
-static void expand_stmt_with_iterators_1 ();
-static tree collect_iterators();
-static void iterator_loop_prologue ();
-static void iterator_loop_epilogue ();
-static void add_ixpansion ();
-static void delete_ixpansion();
-static int top_level_ixpansion_p ();
-static void istack_sublevel_to_current ();
-
-/* A special obstack, and a pointer to the start of
-   all the data in it (so we can free everything easily).  */
-static struct obstack ixp_obstack;
-static char *ixp_firstobj;
 \f
 /*
                KEEPING TRACK OF EXPANSIONS
@@ -95,8 +82,26 @@ struct iter_stack_node
 };
 
 struct iter_stack_node *iter_stack;
-
 struct iter_stack_node sublevel_ixpansions;
+
+/* A special obstack, and a pointer to the start of
+   all the data in it (so we can free everything easily).  */
+static struct obstack ixp_obstack;
+static char *ixp_firstobj;
+
+/* During collect_iterators, a list of SAVE_EXPRs already scanned.  */
+static tree save_exprs;
+
+static void expand_stmt_with_iterators_1 PROTO((tree, tree));
+static tree collect_iterators          PROTO((tree, tree));
+static void iterator_loop_prologue     PROTO((tree, rtx *, rtx *));
+static void iterator_loop_epilogue     PROTO((tree, rtx *, rtx *));
+static int top_level_ixpansion_p       PROTO((void));
+static void isn_append                 PROTO((struct iter_stack_node *,
+                                              struct iter_stack_node *));
+static void istack_sublevel_to_current PROTO((void));
+static void add_ixpansion              PROTO((tree, rtx, rtx, rtx, rtx));
+static void delete_ixpansion           PROTO((tree));
 \f
 /* Initialize our obstack once per compilation.  */
 
@@ -144,7 +149,9 @@ void
 iterator_expand (stmt)
     tree stmt;
 {
-  tree iter_list = collect_iterators (stmt, NULL_TREE);
+  tree iter_list;
+  save_exprs = NULL_TREE;
+  iter_list = collect_iterators (stmt, NULL_TREE);
   expand_stmt_with_iterators_1 (stmt, iter_list);
   istack_sublevel_to_current ();
 }
@@ -202,6 +209,14 @@ collect_iterators (exp, list)
        return list;
       }
 
+    case SAVE_EXPR:
+      /* In each scan, scan a given save_expr only once.  */
+      if (value_member (exp, save_exprs))
+       return list;
+
+      save_exprs = tree_cons (NULL_TREE, exp, save_exprs);
+      return collect_iterators (TREE_OPERAND (exp, 0), list);
+
       /* we do not automatically iterate blocks -- one must */
       /* use the FOR construct to do that */
 
@@ -229,7 +244,6 @@ collect_iterators (exp, list)
            /* Some tree codes have RTL, not trees, as operands.  */
            switch (TREE_CODE (exp))
              {
-             case SAVE_EXPR:
              case CALL_EXPR:
                num_args = 2;
                break;
@@ -266,19 +280,22 @@ iterator_loop_prologue (idecl, start_note, end_note)
      tree idecl;
      rtx *start_note, *end_note;
 {
+  tree expr;
+
   /* Force the save_expr in DECL_INITIAL to be calculated
      if it hasn't been calculated yet.  */
-  expand_expr (DECL_INITIAL (idecl), 0, VOIDmode, 0);
+  expand_expr (DECL_INITIAL (idecl), const0_rtx, VOIDmode, 0);
 
   if (DECL_RTL (idecl) == 0)
     expand_decl (idecl);
 
   if (start_note)
     *start_note = emit_note (0, NOTE_INSN_DELETED);
+
   /* Initialize counter.  */
-  expand_expr (build (MODIFY_EXPR, TREE_TYPE (idecl),
-                     idecl, integer_zero_node),
-              0, VOIDmode, 0);
+  expr = build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, integer_zero_node);
+  TREE_SIDE_EFFECTS (expr) = 1;
+  expand_expr (expr, const0_rtx, VOIDmode, 0);
 
   expand_start_loop_continue_elsewhere (1);
 
@@ -317,16 +334,19 @@ iterator_loop_epilogue (idecl, start_note, end_note)
     *start_note = emit_note (0, NOTE_INSN_DELETED);
   expand_loop_continue_here ();
   incr = build_binary_op (PLUS_EXPR, idecl, integer_one_node, 0);
-  expand_expr (build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, incr),
-              0, VOIDmode, 0);
+  incr = build (MODIFY_EXPR, TREE_TYPE (idecl), idecl, incr);
+  TREE_SIDE_EFFECTS (incr) = 1;
+  expand_expr (incr, const0_rtx, VOIDmode, 0);
   test = build_binary_op (LT_EXPR, idecl, DECL_INITIAL (idecl), 0);
   expand_exit_loop_if_false (0, test);
   expand_end_loop ();
 
   ITERATOR_BOUND_P (idecl) = 0;
   /* we can reset rtl since there is not chance that this expansion */
-  /* would be superceded by a higher level one */
-  if (top_level_ixpansion_p ())
+  /* would be superseded by a higher level one */
+  /* but don't do this if the decl is static, since we need to share */
+  /* the same decl in that case.  */
+  if (top_level_ixpansion_p () && ! TREE_STATIC (idecl))
     DECL_RTL (idecl) = 0;
   if (end_note)
     *end_note = emit_note (0, NOTE_INSN_DELETED);
@@ -392,7 +412,7 @@ void
 push_iterator_stack ()
 {
   struct iter_stack_node *new_top
-    = (struct iter_stack_node*) 
+    = (struct iter_stack_node *) 
       obstack_alloc (&ixp_obstack, sizeof (struct iter_stack_node));
 
   new_top->first = 0;
@@ -417,7 +437,7 @@ pop_iterator_stack ()
 \f
 
 /* Record an iterator expansion ("ixpansion") for IDECL.
-   The remaining paramters are the notes in the loop entry
+   The remaining parameters are the notes in the loop entry
    and exit rtl.  */
 
 static void
@@ -425,15 +445,15 @@ add_ixpansion (idecl, pro_start, pro_end, epi_start, epi_end)
      tree idecl;
      rtx pro_start, pro_end, epi_start, epi_end;
 {
-  struct ixpansionnewix;
+  struct ixpansion *newix;
     
   /* Do nothing if we are not inside "({...})",
      as in that case this expansion can't need subsequent RTL modification.  */
   if (iter_stack == 0)
     return;
 
-  newix = (struct ixpansion*) obstack_alloc (&ixp_obstack,
-                                            sizeof (struct ixpansion));
+  newix = (struct ixpansion *) obstack_alloc (&ixp_obstack,
+                                             sizeof (struct ixpansion));
   newix->ixdecl = idecl;
   newix->ixprologue_start = pro_start;
   newix->ixprologue_end   = pro_end;
@@ -454,7 +474,7 @@ static void
 delete_ixpansion (idecl)
      tree idecl;
 {
-  struct ixpansionprevix = 0, *ix;
+  struct ixpansion *previx = 0, *ix;
 
   for (ix = sublevel_ixpansions.first; ix; ix = ix->next)
     if (ix->ixdecl == idecl)
@@ -560,7 +580,7 @@ pixl (head)
   return head;
 }
 
-/* Print Iterator Stack*/
+/* Print Iterator Stack.  */
 
 void
 pis ()