[tree-ssa]: Forward substitution for loops

Daniel Berlin dberlin@dberlin.org
Sat Aug 9 18:37:00 GMT 2003


This patch performs forward substitution in loops.
I won't ask for approval until the loop stuff is sorted out, i'm sending
it in case anyone wants to try it out.

The #if'0 parts in cfgloop.c were necessary for testing purposes due to us
not being able to canonicalize loop headers with the trees right now.

Bootstrapped and regtests on x86, c, c++, java, f77 and objc.

The transformation performed is thus:

int main(int argc)
{
	int i;
	int b = 30;
	for (i = 0; i < 50 ; i++)
	{
		int a;
		int c;
		int j;
		a = b + 5 + argc;
		c = a + 2;
		for (j = 0; j < 30; j++)
		{
			int k;
			k = c + 3;
			printf ("%d\n", k);
		}
	}
}

Becomes

int main(int argc)
{
        for (i = 0; i < 50 ; i++)
        {
		for (j = 0; j < 30; j++)
		{
			int k;
			k = argc + 40;
			printf ("%d\n", k);
		}
	}
}

It also forward substitutes into array accesses, etc.

It doesn't perform code movement, though it could and it knows when the
statement becomes loop invariant.

IVS and loop interchange are next.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.108
diff -u -3 -p -w -B -b -r1.903.2.108 Makefile.in
--- Makefile.in	8 Aug 2003 00:27:09 -0000	1.903.2.108
+++ Makefile.in	9 Aug 2003 18:24:14 -0000
@@ -840,7 +840,7 @@ OBJS-common = \
  tree-alias-type.o gimplify.o tree-nomudflap.o tree-pretty-print.o         \
  tree-alias-common.o tree-ssa-ccp.o tree-browser.o @ANDER@ tree-ssa-dce.o  \
  tree-ssa-pre.o tree-ssa-copyprop.o tree-ssa-live.o tree-must-alias.o	   \
- tree-ssa-dom.o								   \
+ tree-ssa-dom.o	tree-loop.o						   \
  alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o	  	   \
  cfg.o cfganal.o cfgbuild.o cfgcleanup.o cfglayout.o cfgloop.o		   \
  cfgloopanal.o cfgloopmanip.o loop-init.o loop-unswitch.o loop-unroll.o	   \
@@ -1545,6 +1545,10 @@ 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 langhooks.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) output.h diagnostic.h ssa.h errors.h flags.h tree-alias-common.h \
+   $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_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: cfgloop.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cfgloop.c,v
retrieving revision 1.14.2.11
diff -u -3 -p -w -B -b -r1.14.2.11 cfgloop.c
--- cfgloop.c	23 Jul 2003 16:59:32 -0000	1.14.2.11
+++ cfgloop.c	9 Aug 2003 18:24:14 -0000
@@ -696,6 +696,7 @@ flow_loops_find (struct loops *loops, in
   rc_order = NULL;

   /* Join loops with shared headers.  */
+  if (0)
   canonicalize_loop_headers ();

   /* Compute the dominators.  */
@@ -735,9 +736,11 @@ flow_loops_find (struct loops *loops, in
 	     from a latch node.  */
 	  if (latch != ENTRY_BLOCK_PTR && dominated_by_p (dom, latch, header))
 	    {
+#if 0
 	      /* Shared headers should be eliminated by now.  */
 	      if (more_latches)
 		abort ();
+#endif
 	      more_latches = 1;
 	      SET_BIT (headers, header->index);
 	      num_loops++;
Index: common.opt
===================================================================
RCS file: /cvs/gcc/gcc/gcc/common.opt,v
retrieving revision 1.14.2.3
diff -u -3 -p -w -B -b -r1.14.2.3 common.opt
--- common.opt	29 Jul 2003 04:45:58 -0000	1.14.2.3
+++ common.opt	9 Aug 2003 18:24:14 -0000
@@ -703,6 +703,14 @@ ftree-dominator-opts
 Common
 Enable dominator optimizations

+ftree-loop-fwdsubst
+Common
+Enable loop forward substitution
+
+ftree-loop-optimize
+Common
+Enable loop optimizations on trees
+
 ftree-must-alias
 Common
 Detect must-alias relations to remove pointer de-references
Index: flags.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/flags.h,v
retrieving revision 1.86.2.31
diff -u -3 -p -w -B -b -r1.86.2.31 flags.h
--- flags.h	29 Jul 2003 04:45:58 -0000	1.86.2.31
+++ flags.h	9 Aug 2003 18:24:14 -0000
@@ -692,6 +692,12 @@ extern int flag_disable_tree_ssa;
 /* Enable SSA-PRE on trees.  */
 extern int flag_tree_pre;

+/* Enable loop forward substitution on trees.  */
+extern int flag_tree_loop_fwdsubst;
+
+/* Enable loop optimizations on trees.  */
+extern int flag_tree_loop_optimize;
+
 /* Enable SSA-CCP on trees.  */
 extern int flag_tree_ccp;

Index: opts.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/opts.c,v
retrieving revision 1.31.2.6
diff -u -3 -p -w -B -b -r1.31.2.6 opts.c
--- opts.c	29 Jul 2003 04:45:58 -0000	1.31.2.6
+++ opts.c	9 Aug 2003 18:24:15 -0000
@@ -509,6 +509,9 @@ decode_options (unsigned int argc, const
       /* FIXME: Temporary hack to facilitate testing PRE.  */
       if (getenv ("TREE_SSA_DO_PRE"))
 	flag_tree_pre = 1;
+      flag_tree_loop_optimize = 1;
+      flag_tree_loop_fwdsubst = 1;
+
     }

   if (optimize >= 2)
@@ -1370,6 +1373,14 @@ common_handle_option (size_t scode, cons

     case OPT_ftree_dominator_opts:
       flag_tree_dom = value;
+      break;
+
+    case OPT_ftree_loop_fwdsubst:
+      flag_tree_loop_fwdsubst = value;
+      break;
+
+    case OPT_ftree_loop_optimize:
+      flag_tree_loop_optimize = value;
       break;

     case OPT_ftree_must_alias:
Index: toplev.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/toplev.c,v
retrieving revision 1.654.2.61
diff -u -3 -p -w -B -b -r1.654.2.61 toplev.c
--- toplev.c	29 Jul 2003 04:45:58 -0000	1.654.2.61
+++ toplev.c	9 Aug 2003 18:24:16 -0000
@@ -968,6 +968,12 @@ int flag_disable_tree_ssa = 0;
 /* Enable the SSA-PRE tree optimization.  */
 int flag_tree_pre = 0;

+/* Enable forward substitution on trees. */
+int flag_tree_loop_fwdsubst = 0;
+
+/* Enable loop optimization on trees.  */
+int flag_tree_loop_optimize = 0;
+
 /* Enable points-to analysis on trees. */
 enum pta_type flag_tree_points_to = PTA_NONE;

Index: tree-dfa.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-dfa.c,v
retrieving revision 1.1.4.143
diff -u -3 -p -w -B -b -r1.1.4.143 tree-dfa.c
--- tree-dfa.c	8 Aug 2003 00:27:10 -0000	1.1.4.143
+++ tree-dfa.c	9 Aug 2003 18:24:16 -0000
@@ -130,7 +130,6 @@ static void add_def (tree *, tree);
 static void add_use (tree *, tree);
 static void add_vdef (tree, tree, voperands_t);
 static void add_stmt_operand (tree *, tree, int, voperands_t);
-static void add_immediate_use (tree, tree);
 static tree find_vars_r (tree *, int *, void *);
 static void add_referenced_var (tree, struct walk_state *);
 static tree get_memory_tag_for (tree);
@@ -1151,7 +1150,7 @@ compute_reaching_defs (int flags ATTRIBU
 /* Add statement USE_STMT to the list of statements that use definitions
     made by STMT.  */

-static void
+void
 add_immediate_use (tree stmt, tree use_stmt)
 {
   stmt_ann_t ann = get_stmt_ann (stmt);
Index: tree-dump.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-dump.c,v
retrieving revision 1.6.2.35
diff -u -3 -p -w -B -b -r1.6.2.35 tree-dump.c
--- tree-dump.c	31 Jul 2003 00:36:33 -0000	1.6.2.35
+++ tree-dump.c	9 Aug 2003 18:24:16 -0000
@@ -655,6 +655,7 @@ static struct dump_file_info dump_files[
   {".ssa", "tree-ssa", 0, 0},
   {".dom", "tree-dom", 0, 0},
   {".mustalias", "tree-mustalias", 0, 0},
+  {".fwdsubst", "tree-loop-fwdsubst", 0, 0},
   {".predot", "tree-predot", 0, 0},
   {".pre", "tree-pre", 0, 0},
   {".ccp", "tree-ccp", 0, 0},
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.101
diff -u -3 -p -w -B -b -r1.1.4.101 tree-flow.h
--- tree-flow.h	8 Aug 2003 00:27:10 -0000	1.1.4.101
+++ tree-flow.h	9 Aug 2003 18:24:17 -0000
@@ -418,7 +418,8 @@ extern int could_trap_p (tree);
 extern basic_block tree_split_edge (edge);

 /* In tree-dfa.c  */
-void find_referenced_vars (tree);
+extern void add_immediate_use (tree, tree);
+extern void find_referenced_vars (tree);
 extern void get_stmt_operands (tree);
 extern var_ann_t create_var_ann (tree);
 extern stmt_ann_t create_stmt_ann (tree);
@@ -491,6 +492,8 @@ void tree_ssa_dce (tree);
 void tree_ssa_copyprop (tree);
 void propagate_copy (tree *, tree);

+/* In tree-loop.c  */
+extern void tree_loop_optimize (tree);

 /* In tree-flow-inline.h  */
 static inline int phi_arg_from_edge (tree, edge);
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	9 Aug 2003 18:24:17 -0000
@@ -0,0 +1,257 @@
+/* Loop optimization functions for trees.
+   Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.
+   Contributed by Daniel Berlin <dberlin@dberlin.org>
+
+This file is part of GCC.
+
+GCC 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.
+
+GCC 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 GCC; 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 "tree.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "hard-reg-set.h"
+#include "basic-block.h"
+#include "output.h"
+#include "expr.h"
+#include "diagnostic.h"
+#include "basic-block.h"
+#include "flags.h"
+#include "tree-flow.h"
+#include "tree-dump.h"
+#include "timevar.h"
+#include "tree-simple.h"
+#include "cfgloop.h"
+#include "bitmap.h"
+#include "tree-inline.h"
+static FILE *fs_dump_file;
+static int fs_dump_flags;
+static bool forward_subst (tree, bitmap);
+static void forward_subst_in_loops (tree, struct loops *);
+static bool contains_unrenamed_variables (tree);
+
+static void
+forward_subst_in_loops (tree fndecl, struct loops *loops)
+{
+  size_t i;
+  basic_block *bbs;
+  bitmap loop_body = BITMAP_GGC_ALLOC ();
+
+  fs_dump_file = dump_begin (TDI_loop_fwdsubst, &fs_dump_flags);
+
+  /* Compute the immediate uses. */
+  compute_immediate_uses (TDFA_USE_OPS);
+
+  /* Let's do it the O(n*number of loops) way for now. */
+  for (i = 0; i < loops->num; i++)
+    {
+      int j;
+      size_t k;
+      block_stmt_iterator bsi;
+      bitmap_clear (loop_body);
+      bbs = get_loop_body (loops->parray[i]);
+      for (k = 0; k <loops->parray[i]->num_nodes; k++)
+	if (bbs[k]->index >= 0)
+	  bitmap_set_bit (loop_body, bbs[k]->index);
+
+      for (j = 0; j < n_basic_blocks; j++)
+	for (bsi = bsi_start (BASIC_BLOCK (j));
+	     ! bsi_end_p (bsi);
+	     bsi_next (&bsi))
+	  {
+	    tree stmt = bsi_stmt (bsi);
+	    if (TREE_CODE (stmt) == MODIFY_EXPR
+		&& TREE_CODE (TREE_OPERAND (stmt, 0)) == SSA_NAME)
+	      forward_subst (bsi_stmt (bsi), loop_body);
+	  }
+    }
+  if (fs_dump_file)
+    {
+      dump_function_to_file (fndecl, fs_dump_file, fs_dump_flags);
+      dump_end (TDI_loop_fwdsubst, fs_dump_file);
+    }
+}
+
+/* Determine if t contains unrenamed variables.  */
+static bool
+contains_unrenamed_variables (tree t)
+{
+  enum tree_code code;
+  char class;
+  int i;
+
+  if (t == NULL_TREE)
+    return false;
+
+  code = TREE_CODE (t);
+  class = TREE_CODE_CLASS (code);
+
+  if (class == 'd')
+    return true;
+  else if (class == 'c')
+    return false;
+  else if (IS_EXPR_CODE_CLASS (class) || class == 'r')
+    {
+      if (code == NOP_EXPR
+	|| code == CONVERT_EXPR
+	  || code == NON_LVALUE_EXPR)
+	return contains_unrenamed_variables (TREE_OPERAND (t, 0));
+      for (i = first_rtl_op (code) - 1; i >= 0; --i)
+	if (contains_unrenamed_variables (TREE_OPERAND (t, i)))
+	  return true;
+    }
+  else if (code == TREE_LIST)
+    {
+      for (; t; t = TREE_CHAIN (t))
+	if (contains_unrenamed_variables (TREE_VALUE (t)))
+	  return true;
+    }
+  else if (code == SSA_NAME)
+    return false;
+
+  return false;
+}
+
+/* Perform forward substitution of STMT into the BODY of loop.  */
+bool forward_subst (tree stmt, bitmap body)
+{
+  stmt_ann_t ann;
+  size_t i;
+  varray_type in_ssa_edges;
+  varray_type out_ssa_edges;
+  bool all_uses_gone = false;
+  bool all_loop_uses_gone = false;
+  bool changed_imm_uses = false;
+
+  ann = stmt_ann (stmt);
+  if (ann->makes_aliased_loads
+      || ann->makes_aliased_stores
+      || ann->has_volatile_ops)
+    return false;
+  if (contains_unrenamed_variables (stmt))
+    return false;
+
+  get_stmt_operands (stmt);
+
+  /* Determine loop invariance */
+  in_ssa_edges = use_ops (stmt);
+  if (in_ssa_edges)
+    for (i = 0; i < VARRAY_ACTIVE_SIZE (in_ssa_edges); i++)
+      {
+	tree *e = VARRAY_GENERIC_PTR (in_ssa_edges, i);
+	tree source = SSA_NAME_DEF_STMT (*e);
+	if ((bb_for_stmt (source) != NULL
+	     && bitmap_bit_p (body, bb_for_stmt (source)->index)))
+	  /* AND it's not the induction variable for L, once we can do
+	     induction variable recognition.  */
+	  return true;
+      }
+  /* It's invariant, try to propagate into loop. */
+  out_ssa_edges = immediate_uses (stmt);
+  if (out_ssa_edges)
+    {
+      varray_type fixed_immediate_uses = out_ssa_edges;
+      changed_imm_uses = false;
+      all_uses_gone = true;
+      all_loop_uses_gone = true;
+      for (i = 0; i < VARRAY_ACTIVE_SIZE (out_ssa_edges); i++)
+	{
+	  tree target = VARRAY_TREE (out_ssa_edges, i);
+	  if (bitmap_bit_p (body, bb_for_stmt (target)->index))
+	    {
+	      if (TREE_CODE (target) != PHI_NODE
+		  && TREE_CODE (target) == MODIFY_EXPR
+		  /* We aren't smart enough to handle vuses and
+		     copying  into INDIRECT_REFs properly right now.  */
+		  && TREE_CODE (TREE_OPERAND (target, 0)) != INDIRECT_REF)
+		{
+		  size_t j;
+		  tree copy = target;
+		  varray_type copyuses;
+
+		  /* Make a copy of the tree first, the
+		     non-destructive folders only know how to fold
+		     into complete constants. */
+		  walk_tree (&copy, copy_tree_r, NULL, NULL);
+		  create_stmt_ann (copy);
+		  modify_stmt (copy);
+		  get_stmt_operands (copy);
+		  copyuses = use_ops (copy);
+		  for (j = 0; j < VARRAY_ACTIVE_SIZE (copyuses); j++)
+		    {
+		      tree *usep = VARRAY_GENERIC_PTR (copyuses, j);
+		      if (*usep == TREE_OPERAND (stmt, 0))
+			*usep = TREE_OPERAND (stmt, 1);
+		    }
+		  TREE_OPERAND (copy, 1) = fold (TREE_OPERAND (copy, 1));
+		  if (is_gimple_rhs (TREE_OPERAND (copy, 1)))
+		    {
+		      if (fs_dump_file)
+			{
+			  fprintf (fs_dump_file, "Replacing ");
+			  print_generic_stmt (fs_dump_file, target, 0);
+			  fprintf (fs_dump_file, " with ");
+			  print_generic_stmt (fs_dump_file, copy, 0);
+			  fprintf (fs_dump_file, "\n");
+			}
+		      TREE_OPERAND (target, 1) = TREE_OPERAND (copy, 1);
+		      modify_stmt (target);
+		      VARRAY_TREE (fixed_immediate_uses, i) = NULL_TREE;
+		      changed_imm_uses = true;
+		    }
+		  else all_loop_uses_gone = false;
+		}
+	      else all_loop_uses_gone = false;
+	    }
+	  else all_uses_gone = false;
+	}
+      /* Update the immediate uses if they changed.  */
+      if (changed_imm_uses)
+	{
+	  stmt_ann (stmt)->df->immediate_uses = NULL;
+	  for (i = 0; i < VARRAY_ACTIVE_SIZE (fixed_immediate_uses); i++)
+	    if (VARRAY_TREE (fixed_immediate_uses, i) != NULL_TREE)
+	      add_immediate_use (stmt, VARRAY_TREE (fixed_immediate_uses, i));
+	}
+    }
+  if (all_uses_gone && all_loop_uses_gone)
+    {
+      /* We could delete the statement, but DCE will do it for us.  */
+    }
+  else if (all_loop_uses_gone)
+    {
+      /* We could move the statement outside the loop, if it's inside
+	 of one.  */
+    }
+  return false;
+}
+
+
+void tree_loop_optimize (tree fndecl)
+{
+  struct loops *loops;
+  loops = loop_optimizer_init (NULL);
+  if (loops)
+    {
+      if (flag_tree_loop_fwdsubst)
+	forward_subst_in_loops (fndecl, loops);
+    }
+
+  loop_optimizer_finalize (loops, NULL);
+}
+
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-optimize.c,v
retrieving revision 1.1.4.43
diff -u -3 -p -w -B -b -r1.1.4.43 tree-optimize.c
--- tree-optimize.c	8 Aug 2003 00:27:10 -0000	1.1.4.43
+++ tree-optimize.c	9 Aug 2003 18:24:17 -0000
@@ -36,6 +36,7 @@ Boston, MA 02111-1307, USA.  */
 #include "tree-flow.h"
 #include "tree-dump.h"
 #include "timevar.h"
+#include "tree-simple.h"

 /* Rewrite a function tree to the SSA form and perform the SSA-based
    optimizations on it.  */
@@ -90,6 +90,9 @@ optimize_function_tree (tree fndecl)
 	  if (flag_tree_dom && flag_tree_must_alias)
 	    tree_compute_must_alias (fndecl);
 	}
+
+      if (flag_tree_loop_optimize)
+	tree_loop_optimize (fndecl);

       if (flag_tree_pre)
 	tree_perform_ssapre (fndecl);
Index: tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree.h,v
retrieving revision 1.342.2.87
diff -u -3 -p -w -B -b -r1.342.2.87 tree.h
--- tree.h	5 Aug 2003 15:17:59 -0000	1.342.2.87
+++ tree.h	9 Aug 2003 18:24:18 -0000
@@ -3395,6 +3395,8 @@ enum tree_dump_index
 				   for each function.  */
   TDI_mustalias,		/* dump must-alias information for each
 				   function.  */
+  TDI_loop_fwdsubst,            /* dump loop forward substitution information
+				   for each function.  */
   TDI_predot,
   TDI_pre,                      /* dump SSA PRE information for each
 				   function.  */
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.152.2.50
diff -u -3 -p -w -B -b -r1.152.2.50 invoke.texi
--- doc/invoke.texi	26 Jul 2003 16:27:44 -0000	1.152.2.50
+++ doc/invoke.texi	9 Aug 2003 18:24:22 -0000
@@ -249,6 +249,7 @@ in the following sections.
 -fdump-tree-ccp@r{[}-@var{n}@r{]} -fdump-tree-dce@r{[}-@var{n}@r{]} @gol
 -fdump-tree-gimple@r{[}-raw@r{]} -fdump-tree-mudflap@r{[}-@var{n}@r{]} @gol
 -fdump-tree-must-alias@r{[}-@var{n}@r{]} -fdump-tree-dom@r{[}-@var{n}@r{]}@gol
+-fdump-tree-loop-fwdsubst@r{[}-@var{n}@r{]} @gol
 -feliminate-dwarf2-dups -feliminate-unused-debug-types @gol
 -feliminate-unused-debug-symbols -fmem-report -fprofile-arcs @gol
 -frandom-seed=@var{string} -fsched-verbose=@var{n} @gol
@@ -296,6 +297,7 @@ in the following sections.
 -funswitch-loops  -fold-unroll-loops  -fold-unroll-all-loops @gol
 -fdisable-gimple  -ftree-pre  -ftree-ccp  -ftree-dce  -ftree-copyprop  @gol
 -fdisable-tree-ssa -ftree-dominator-opts -ftree-must-alias @gol
+-ftree-loop-optimize -ftree-loop-fwdsubst @gol
 --param @var{name}=@var{value}
 -O  -O0  -O1  -O2  -O3  -Os}

@@ -3396,6 +3398,11 @@ appending @file{.copyprop} to the source
 Dump each function after dead code elimination.  The file name is made by
 appending @file{.dce} to the source file name.

+@item forwardsubst
+@opindex fdump-tree-loop-fwdsubst
+Dump each function after loop forward substitution.  The file name is
+made by appending @file{.fwdsubst} to the source file name.
+
 @item mudflap
 @opindex fdump-tree-mudflap
 Dump each function after adding mudflap instrumentation.  The file name is
@@ -4145,8 +4152,14 @@ Perform dead code elimination (DCE) on t
 default at -O and higher.

 @item -ftree-dominator-opts
-Perform dead code elimination (DCE) on trees.  This flag is enabled by
+Perform dominator optimizations on trees.  This flag is enabled by
 default at -O and higher.
+
+@item -ftree-loop-optimize
+Perform loop optimizations on trees.
+
+@item -ftree-loop-fwdsubst
+Perform forward substitution on statements in loops.

 @item -ftree-must-alias
 Perform must-alias analysis on trees.  This analysis will attempt to



More information about the Gcc-patches mailing list