[tree-ssa]: Loop normalization pass

Daniel Berlin dberlin@dberlin.org
Tue Jan 14 15:40:00 GMT 2003


Normalizes loops to start at 1 (or would we rather 0), and have a stride
of 1.

This is the first step in high level loop optimizations i'm working on.

It currently doesn't create the new statements in GIMPLE form, mainly
because it's pointless at the moment, since the SSA needs to be rebuilt
anyway.  Once we have an SSA form we can update easily, i'll create GIMPLE
statements and update it.

Bootstrapped with -O2 -fno-tree-ccp -ftree-loop on powerpc-apple-darwin6.3.

Since it wants loops to start at 1, rather than 0, it normalizes a *ton*
of loops, and thus, is pretty well tested in that respect.

--Dan

Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.43
diff -u -3 -p -r1.1.4.43 tree-flow.h
--- tree-flow.h	31 Dec 2002 14:23:05 -0000	1.1.4.43
+++ tree-flow.h	14 Jan 2003 15:33:39 -0000
@@ -722,9 +722,11 @@ extern void tree_perform_ssapre PARAMS (
 /* In tree-ssa-ccp.c  */
 void tree_ssa_ccp PARAMS ((tree));

-
 /* In tree-ssa-dce.c  */
 void tree_ssa_eliminate_dead_code PARAMS ((tree));
+
+/* In tree-loop.c  */
+void tree_normalize_loops PARAMS ((tree));

 #include "tree-flow-inline.h"

Index: tree-loop.c
===================================================================
RCS file: tree-loop.c
diff -N tree-loop.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ tree-loop.c	14 Jan 2003 15:33:39 -0000
@@ -0,0 +1,570 @@
+/* Loop optimizations for trees
+   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+   Contributed by Daniel Berlin <dan@dberlin.org>
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+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, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "errors.h"
+#include "ggc.h"
+#include "tree.h"
+
+/* These RTL headers are needed for basic-block.h.  */
+#include "rtl.h"
+#include "tm_p.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+
+#include "diagnostic.h"
+#include "tree-flow.h"
+#include "tree-simple.h"
+#include "timevar.h"
+#include "hashtab.h"
+
+/* Debugging dumps. */
+static FILE *dump_file;
+static int dump_flags;
+
+static tree_ref find_lc_init_in_phi PARAMS ((tree_ref, tree_ref, basic_block));
+static tree_ref find_lc_stride_in_phi PARAMS ((tree_ref, tree_ref, basic_block));
+static bool normalize_loop_counter PARAMS ((tree_ref, tree_ref, basic_block));
+static int count_lc_increments PARAMS ((tree_ref, basic_block));
+static tree get_constant PARAMS ((tree_ref, tree));
+static void normalize_loop PARAMS ((tree, tree));
+static void normalize_loops PARAMS ((tree));
+
+/* Kludge to get constants through copies until copy propagation is
+   working. */
+static tree
+get_constant (constref, init)
+     tree_ref constref;
+     tree init;
+{
+  tree curr;
+
+  STRIP_WFL (init);
+  if (!is_simple_modify_expr (init))
+    return NULL_TREE;
+
+  curr = TREE_OPERAND (init, 1);
+
+  if (TREE_CODE (curr) == INTEGER_CST)
+    return curr;
+
+  if (DECL_P (curr))
+    {
+      ref_list_iterator rli;
+      rli = rli_start (tree_refs (curr));
+      for (; !rli_after_end (rli); rli_step (&rli))
+	{
+	  tree_ref ref = rli_ref (rli);
+	  if (ref_stmt (ref) == ref_stmt (constref)
+	      && ref_var (ref) == curr
+	      && ref_type (ref) == V_USE
+	      && imm_reaching_def (ref))
+	    {
+	      return get_constant (imm_reaching_def (ref),
+				   ref_stmt (imm_reaching_def (ref)));
+	    }
+	}
+    }
+
+  return NULL_TREE;
+}
+
+/* Count number of times lc is incremented. */
+static int
+count_lc_increments (lc, loop_start_bb)
+     tree_ref lc;
+     basic_block loop_start_bb;
+{
+  int defs = 0;
+  basic_block bb;
+  FOR_BB_BETWEEN (bb, loop_start_bb, latch_block (loop_start_bb), next_bb)
+  {
+    ref_list_iterator rli;
+    rli = rli_start (bb_refs (bb));
+    for (; !rli_after_end (rli); rli_step (&rli))
+      {
+	if (ref_type (rli_ref (rli)) == V_DEF)
+	  if (ref_var (rli_ref (rli)) == ref_var (lc))
+	    {
+	      defs++;
+	      if (defs > 1)
+		return defs;
+	    }
+      }
+  }
+  return defs;
+}
+
+
+
+/**
+   @brief Find the loop counter initialization statement.
+   @param lc Loop counter.
+   @param lc_rphi Phi reached from conditional used to exit loop  (i.e. in i >
+   49, the reaching def of i).
+   @param loop_start_bb Basic block which contains the LOOP_EXPR.
+
+   @note TEMPORARY Will be merged with find_lc_stride_in_phi.
+*/
+static tree_ref
+find_lc_init_in_phi (lc, lc_rphi, loop_start_bb)
+     tree_ref lc ATTRIBUTE_UNUSED;
+     tree_ref lc_rphi;
+     basic_block loop_start_bb;
+{
+  /* The initialization statement, after GIMPLEification, comes
+     immediately before the loop.  So it must be in one of the
+     immediate predecessors of the loop_expr's basic block*/
+  /* FIXME: Search for predecessor that dominates the entire loop,
+     rather than knowing how tree-cfg creates these.
+     Or just create loop info and use the pre header.  */
+  size_t i;
+  if (num_phi_args (lc_rphi) > 2)
+    return NULL;
+  for (i = 0; i < num_phi_args (lc_rphi); i++)
+    if (phi_arg_edge (phi_arg (lc_rphi, i))->src->index == loop_start_bb->index - 1)
+      return phi_arg_def (phi_arg (lc_rphi, i));
+  return NULL;
+}
+
+/**
+   @brief Find the loop counter stride amount.
+   @param lc Loop counter.
+   @param lc_rphi Phi reached from conditional used to exit loop
+   (i.e. in i > 49, the reaching def of i).
+   @param loop_start_bb Basic block which contains the LOOP_EXPR.
+
+   @note TEMPORARY: Will be merged with find_lc_init_in_phi. */
+static tree_ref
+find_lc_stride_in_phi (lc, lc_rphi, loop_start_bb)
+     tree_ref lc ATTRIBUTE_UNUSED;
+     tree_ref lc_rphi;
+     basic_block loop_start_bb;
+{
+  /* Stride increments are moved to the end of the loop (we're
+     assuming copy prop is done before loop normalization).
+     If we really have the loop counter, the phi will have arity of
+     2, one arg being the init statement, the other, the stride
+     statement.
+     So we just grab the arg that *isn't* the init statement. */
+
+  size_t i;
+  if (num_phi_args (lc_rphi) > 2)
+    return NULL;
+  for (i = 0; i < num_phi_args (lc_rphi); i++)
+    if (phi_arg_edge (phi_arg (lc_rphi, i))->src->index != loop_start_bb->index - 1)
+      return phi_arg_def (phi_arg (lc_rphi, i));
+  return NULL;
+}
+
+/**
+    @brief Normalize a loop counter
+    @param lc Loop counter.
+    @param lc_rphi Phi reached from conditional used to exit loop
+    (i.e. in i > 49, the reaching def of i).
+    @param loop_start_bb Basic block which contains the LOOP_EXPR.
+    @return true if we normalized the loop counter, false if we
+    couldn't.
+
+    Transform a loop counter that has a constant stride, into a
+    normalized loop counter.
+
+    Normalized loop counters start from 1, and have a stride of 1.
+
+    In C speak, given a loop like:
+    i = 5;
+    while (1)
+     {
+        if (i > 499)
+          goto endofloop;
+       ...
+        i = i + 5;
+     }
+
+We transform it into:
+    nlc = 1;
+    while (1)
+      {
+         i = nlc * 5;
+         if (nlc > 99)
+          goto endofloop;
+       ...
+        nlc = nlc + 1;
+      }
+    i = 500;
+
+*/
+
+static bool
+normalize_loop_counter (lc, lc_rphi, loop_start_bb)
+     tree_ref lc;
+     tree_ref lc_rphi;
+     basic_block loop_start_bb;
+{
+  tree lc_start, lc_end, lc_stride;
+  tree_ref lc_startref, lc_strideref;
+  tree lc_new_indexval, lc_new_end, lc_new_endval;
+  tree lc_cond_stmt;
+  tree nlc;
+  tree lc_type = TREE_TYPE (ref_var (lc));
+
+  lc_start = lc_end = lc_stride = NULL_TREE;
+  lc_new_indexval = lc_new_end = lc_new_endval = NULL_TREE;
+  nlc = create_tmp_var (lc_type, "nlc");
+
+  if (dump_file)
+    {
+      fprintf (dump_file, "Normalizing loop counter named %s\n",
+	       get_name (ref_var (lc)));
+      fprintf (dump_file, "Ref:\n");
+      dump_ref (dump_file, "", lc, 0, 1);
+      fprintf (dump_file, "Phi:\n");
+      dump_ref (dump_file, "", lc_rphi, 0, 1);
+    }
+  lc_cond_stmt = ref_stmt (lc);
+  STRIP_WFL (lc_cond_stmt);
+  if (TREE_CODE (lc_cond_stmt) != COND_EXPR)
+    {
+      return false;
+    }
+
+  if (TREE_CODE_CLASS (TREE_CODE (COND_EXPR_COND (lc_cond_stmt))) != '<')
+    {
+      if (dump_file)
+	fprintf (dump_file, "Can't normalize, exit condition not comparison\n");
+
+      return false;
+    }
+  switch (TREE_CODE (COND_EXPR_COND (lc_cond_stmt)))
+    {
+    case LT_EXPR:
+    case GT_EXPR:
+    case GE_EXPR:
+    case LE_EXPR:
+      break;
+    default:
+      if (dump_file)
+	fprintf (dump_file, "Can't normalize, unhandled conditional op\n");
+      return false;
+    }
+  lc_startref = find_lc_init_in_phi (lc, lc_rphi, loop_start_bb);
+  if (lc_startref)
+    lc_start = ref_stmt (lc_startref);
+  if (lc_start == NULL_TREE)
+    {
+      if (dump_file)
+	{
+	  fprintf (dump_file, "Can't normalize loop counter:");
+	  fprintf (dump_file, "Can't find init right before this loop.");
+	  fprintf (dump_file, "Likely not a loop counter.\n");
+	}
+      return false;
+    }
+  STRIP_WFL (lc_start);
+
+  if (!is_simple_modify_expr (lc_start))
+    {
+      if (dump_file)
+	fprintf (dump_file, "Can't normalize, can't find start.\n");
+      return false;
+    }
+  lc_start = get_constant (lc_startref, lc_start);
+
+  if (lc_start == NULL_TREE)
+    return false;
+
+  if (dump_file)
+    {
+      fprintf (dump_file, "Loop start is:");
+      print_generic_expr (dump_file, lc_start, 1);
+      fprintf (dump_file, "\n");
+    }
+
+  if (TREE_CODE (lc_start) != INTEGER_CST)
+    {
+      if (dump_file)
+	fprintf (dump_file, "Can't normalize, lower bound not constant.\n");
+      return false;
+    }
+
+  lc_end = TREE_OPERAND (COND_EXPR_COND (lc_cond_stmt), 1);
+  if (lc_end == NULL_TREE)
+    return false;
+
+  /* If the condition is GE_EXPR, then the upper is really 1 less than
+     we think.
+     If condition is LE_EXPR, it's one more than we think. */
+  if (TREE_CODE (COND_EXPR_COND (lc_cond_stmt)) == GE_EXPR)
+    lc_end = fold (build (MINUS_EXPR, lc_type, lc_end, integer_one_node));
+  else if (TREE_CODE (COND_EXPR_COND (lc_cond_stmt)) == LE_EXPR)
+    lc_end = fold (build (PLUS_EXPR, lc_type, lc_end, integer_one_node));
+
+  if (dump_file)
+    {
+      fprintf (dump_file, "Loop end is:");
+      print_generic_expr (dump_file, lc_end, 1);
+      fprintf (dump_file, "\n");
+    }
+
+
+  lc_strideref = find_lc_stride_in_phi (lc, lc_rphi, loop_start_bb);
+  if (lc_strideref)
+    lc_stride = ref_stmt (lc_strideref);
+
+  if (lc_stride == NULL_TREE)
+    {
+      if (dump_file)
+	{
+	  fprintf (dump_file, "Can't normalize loop counter:");
+	  fprintf (dump_file, "Can't find stride inside loop.");
+	  fprintf (dump_file, "Likely not a loop counter.\n");
+	}
+      return false;
+    }
+
+  STRIP_WFL (lc_stride);
+  if (!is_simple_modify_expr (lc_stride))
+    {
+      if (dump_file)
+	fprintf (dump_file, "Can't normalize, can't find stride\n");
+      return false;
+    }
+  lc_stride = TREE_OPERAND (lc_stride, 1);
+  STRIP_WFL (lc_stride);
+
+  if (TREE_CODE (lc_stride) != PLUS_EXPR
+      && TREE_CODE (lc_stride) != MINUS_EXPR)
+    {
+      if (dump_file)
+	fprintf (dump_file, "Can't normalize, non-simple stride op.\n");
+      return false;
+    }
+  if (TREE_CODE (lc_stride) == MINUS_EXPR)
+    lc_stride = fold (build1 (NEGATE_EXPR,
+			      TREE_TYPE (lc_stride),
+			      TREE_OPERAND (lc_stride, 1)));
+  else
+    lc_stride = TREE_OPERAND (lc_stride, 1);
+
+  if (TREE_CODE (lc_stride) != INTEGER_CST)
+    {
+      if (dump_file)
+	fprintf (dump_file, "Can't normalize, stride not constant.\n");
+      return false;
+    }
+  else if (dump_file)
+    {
+      fprintf (dump_file, "Loop stride is:");
+      print_generic_expr (dump_file, lc_stride, 1);
+      fprintf (dump_file, "\n");
+    }
+
+  /* FIXME If we have more than one loop counter increment in the
+     loop, we can't do normalization yet , since it would require updating
+     the SSA. */
+  if (count_lc_increments (lc, loop_start_bb)  > 1)
+    {
+      if (dump_file)
+	fprintf (dump_file, "Can't normalize, multiple loop counter increments\n");
+      return false;
+    }
+
+
+  if (integer_onep (lc_start) && integer_onep (lc_stride))
+    return true;
+
+  /* New end = (end - start + stride) / stride */
+  lc_new_end = fold (build (MINUS_EXPR,
+			    lc_type,
+			    lc_end,
+			    lc_start));
+  lc_new_end = fold (build (PLUS_EXPR,
+			    lc_type,
+			    lc_new_end,
+			    lc_stride));
+  lc_new_end = fold (build (TRUNC_DIV_EXPR,
+			    lc_type,
+			    lc_new_end,
+			    lc_stride));
+  if (dump_file)
+    {
+      fprintf (dump_file, "New upper bound is:");
+      print_generic_expr (dump_file, lc_new_end, 1);
+      fprintf (dump_file, "\n");
+    }
+  /* New index value is start + ((new loop counter - 1) * stride)
+     lower */
+  lc_new_indexval = fold (build (PLUS_EXPR,
+				 lc_type,
+				 lc_start,
+				 fold (build (MULT_EXPR,
+					      lc_type,
+					      fold (build (MINUS_EXPR,
+							   lc_type,
+							   nlc,
+							   integer_one_node)),
+					      lc_stride))));
+  lc_new_indexval = build (MODIFY_EXPR,
+			   lc_type,
+			   ref_var (lc),
+			   lc_new_indexval);
+  if (dump_file)
+    {
+      fprintf (dump_file, "New index value is:");
+      print_generic_expr (dump_file, lc_new_indexval, 1);
+      fprintf (dump_file, "\n");
+    }
+  /* New ending value is start + ((new loop counter * stride) -
+     stride)) */
+  lc_new_endval = fold (build (PLUS_EXPR,
+			       lc_type,
+			       fold (build (MINUS_EXPR,
+					    lc_type,
+					    fold (build (MULT_EXPR,
+							 lc_type,
+							 nlc,
+							 lc_stride)),
+					    lc_stride)),
+			       lc_start));
+  lc_new_endval = build (MODIFY_EXPR,
+			 lc_type,
+			 ref_var (lc),
+			 lc_new_endval);
+  if (dump_file)
+    {
+      fprintf (dump_file, "New ending value is:");
+
+      print_generic_stmt (dump_file, lc_new_endval, 1);
+      fprintf (dump_file, "\n");
+    }
+
+  replace_ref_stmt_with (lc_startref, build (MODIFY_EXPR,
+					     lc_type,
+					     nlc,
+					     integer_one_node));
+  replace_ref_stmt_with (lc, build (COMPOUND_EXPR,
+				    lc_type,
+				    lc_new_indexval,
+				    ref_stmt (lc)));
+
+
+  replace_ref_stmt_with (lc_strideref,
+			 build (MODIFY_EXPR,
+				lc_type,
+				nlc,
+				build (PLUS_EXPR,
+				       lc_type,
+				       nlc,
+				       integer_one_node)));
+
+  COND_EXPR_COND (lc_cond_stmt) = build (GT_EXPR,
+					 TREE_TYPE (COND_EXPR_COND (lc_cond_stmt)),
+					 nlc,
+					 lc_new_end);
+  COND_EXPR_THEN (lc_cond_stmt) = build (COMPOUND_EXPR,
+					 TREE_TYPE (COND_EXPR_THEN (lc_cond_stmt)),
+					 lc_new_endval,
+					 COND_EXPR_THEN (lc_cond_stmt));
+
+  return true;
+}
+
+static void
+normalize_loop (loop_stmt, exit_stmt)
+     tree loop_stmt;
+     tree exit_stmt;
+{
+  htab_t cant_do;
+  ref_list_iterator lc_rli;
+
+  cant_do = htab_create (7, htab_hash_pointer, htab_eq_pointer, NULL);
+
+  lc_rli = rli_start (tree_refs (exit_stmt));
+  for (; !rli_after_end (lc_rli); rli_step (&lc_rli))
+    {
+      tree_ref lc_ref;
+      lc_ref = rli_ref (lc_rli);
+      if (ref_type (lc_ref) != V_USE
+	  || !imm_reaching_def (lc_ref))
+	continue;
+      if (ref_type (imm_reaching_def (lc_ref)) != V_PHI
+	  || ref_var (imm_reaching_def (lc_ref)) != ref_var (lc_ref))
+	continue;
+      if (htab_find (cant_do, ref_var (lc_ref)))
+	continue;
+
+      if (!normalize_loop_counter (lc_ref, imm_reaching_def (lc_ref),
+				   bb_for_stmt (loop_stmt)))
+	*(htab_find_slot (cant_do, ref_var (lc_ref), INSERT)) = ref_var (lc_ref);
+
+    }
+  htab_delete (cant_do);
+
+}
+static void
+normalize_loops  (fn)
+     tree fn ATTRIBUTE_UNUSED;
+{
+  basic_block bb;
+
+  FOR_EACH_BB (bb)
+  {
+    if (bb->flags &  BB_LOOP_CONTROL_EXPR)
+      {
+	gimple_stmt_iterator gsi;
+	gsi = gsi_start_bb (bb);
+	for (; !gsi_end_bb (gsi); gsi_step_bb (&gsi))
+	  {
+	    tree stmt = gsi_stmt (gsi);
+	    if (TREE_CODE (stmt) == LOOP_EXPR)
+	      {
+		gimple_stmt_iterator gsi2;
+		gsi2 = gsi_start (&LOOP_EXPR_BODY (stmt));
+		for (; !gsi_end (gsi2); gsi_step (&gsi2))
+		  {
+		    tree stmt2 = gsi_stmt (gsi2);
+		    if (stmt2 && TREE_CODE (stmt2) == COND_EXPR)
+		      if (TREE_CODE (COND_EXPR_THEN (stmt2)) == GOTO_EXPR)
+			{
+			  normalize_loop (stmt, stmt2);
+			}
+		  }
+	      }
+	  }
+      }
+  }
+}
+
+void
+tree_normalize_loops (fn)
+     tree fn;
+{
+  dump_function (TDI_loop, fn);
+  dump_file = dump_begin (TDI_loop, &dump_flags);
+  normalize_loops (fn);
+
+  if (dump_file)
+    dump_end (TDI_loop, dump_file);
+  dump_function (TDI_loop, fn);
+
+}
Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.63
diff -u -3 -p -r1.903.2.63 Makefile.in
--- Makefile.in	13 Jan 2003 23:14:43 -0000	1.903.2.63
+++ Makefile.in	14 Jan 2003 15:33:39 -0000
@@ -67,7 +67,7 @@ XCFLAGS =
 TCFLAGS =
 CFLAGS = -g
 STAGE1_CFLAGS = -g @stage1_cflags@
-BOOT_CFLAGS = -g -O2
+BOOT_CFLAGS = -g -O2

 # Flags to determine code coverage. When coverage is disabled, this will
 # contain the optimization flags, as you normally want code coverage
@@ -767,7 +767,7 @@ OBJS = alias.o bb-reorder.o bitmap.o bui
  tree-optimize.o tree-simple.o simple-break-elim.o simple-goto-elim.o      \
  tree-ssa-pre.o tree-alias-type.o gimplify.o  				   \
  tree-alias-ecr.o tree-alias-common.o tree-alias-steen.o disjoint-set.o    \
- tree-ssa-ccp.o tree-ssa-dce.o tree-browser.o @ANDER@ 			   \
+ tree-ssa-ccp.o tree-ssa-dce.o tree-loop.o tree-browser.o @ANDER@ 	   \
  alloc-pool.o et-forest.o $(GGC) $(out_object_file) $(EXTRA_OBJS)

 BACKEND = main.o libbackend.a
@@ -1434,6 +1434,9 @@ tree-dfa.o : tree-dfa.c $(TREE_FLOW_H) $
    $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h diagnostic.h \
    errors.h tree-inline.h $(HASHTAB_H) flags.h function.h $(TIMEVAR_H) \
    tree-alias-common.h convert.h $(TM_H) coretypes.h
+tree-loop.o : tree-loop.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
+   $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) flags.h output.h \
+   diagnostic.h errors.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h
 tree-optimize.o : tree-optimize.c $(TREE_FLOW_H) $(CONFIG_H) \
    $(SYSTEM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) \
    $(GGC_H) output.h diagnostic.h ssa.h errors.h flags.h tree-alias-common.h \
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-optimize.c,v
retrieving revision 1.1.4.29
diff -u -3 -p -r1.1.4.29 tree-optimize.c
--- tree-optimize.c	8 Jan 2003 03:01:06 -0000	1.1.4.29
+++ tree-optimize.c	14 Jan 2003 15:33:39 -0000
@@ -85,7 +85,10 @@ optimize_function_tree (fndecl)
   if (n_basic_blocks > 0 && ! (errorcount || sorrycount))
     {
       build_tree_ssa (fndecl);
-
+
+      if (flag_tree_loop)
+	tree_normalize_loops  (fndecl);
+
       if (flag_tree_pre)
 	tree_perform_ssapre (fndecl);

Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.654.2.37
diff -u -3 -p -r1.654.2.37 toplev.c
--- toplev.c	29 Dec 2002 22:04:58 -0000	1.654.2.37
+++ toplev.c	14 Jan 2003 15:33:39 -0000
@@ -903,6 +903,9 @@ int flag_tree_cp = 0;
 /* Enable SSA-DCE on trees.  */
 int flag_tree_dce = 0;

+/* Enable loop optimizations on trees.  */
+int flag_tree_loop = 0;
+
 /* Enable interprocedural analysis.  */
 int flag_ip = 0;

@@ -1226,6 +1229,8 @@ static const lang_independent_options f_
    N_("Enable SSA-CP optimization on trees") },
   { "tree-dce", &flag_tree_dce, 1,
    N_("Enable SSA dead code elimination optimization on trees") },
+  { "tree-loop", &flag_tree_loop, 1,
+   N_("Enable loop optimizations on trees") },
   { "ip", &flag_ip, 1,
    N_("Enable interprocedural analysis") },
 };
Index: tree-dump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-dump.c,v
retrieving revision 1.6.2.20
diff -u -3 -p -r1.6.2.20 tree-dump.c
--- tree-dump.c	8 Jan 2003 03:01:06 -0000	1.6.2.20
+++ tree-dump.c	14 Jan 2003 15:33:39 -0000
@@ -674,6 +674,7 @@ static struct dump_file_info dump_files[
   {".dce", "dump-tree-dce", 0, 0},
   {".optimized", "dump-tree-optimized", 0, 0},
   {".xml", "dump-call-graph", 0, 0},
+  {".loop", "dump-tree-loop", 0, 0},
   {NULL, "dump-tree-all", 0, 0},
 };

Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.342.2.37
diff -u -3 -p -r1.342.2.37 tree.h
--- tree.h	8 Jan 2003 03:01:06 -0000	1.342.2.37
+++ tree.h	14 Jan 2003 15:33:39 -0000
@@ -3264,6 +3264,7 @@ enum tree_dump_index
 				   function.  */
   TDI_optimized,		/* dump each function after optimizing it.  */
   TDI_xml,                      /* dump function call graph.   */
+  TDI_loop,
   TDI_all,			/* enable all the dumps above.  */
   TDI_end
 };



More information about the Gcc-patches mailing list