This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[tree-ssa] Linearize trivial COND_EXPR+PHI node sequences



This patch linearizes sequences like:


bb0:
  if (cond) goto bb2; else goto bb1;
bb1:
bb2:
  x = PHI (0 (bb1), 1 (bb0)
                                                                               



Into:

bb0:
  x = cond;
                                                                               


[ bb1 becomes unreachable and bb0 & bb2 get merged into a single block. ]

These kinds of sequences are quite common with gimplified conditionals and
often represent branches which are static predictor is particularly lame
at predicting.

To put some kind of numbers behind that statement, for perl::eval this patch
reduces the number of dynamic branches by just over 1.6% -- and as it turns
out the vast majority of those dynamic branches were ones we ones that we
could not make a static prediction for.

It appears to a small positive bias from a benchmarking standpoint, certainly
nothing to get terribly excited about.

[ I'll be checking in a relatively simple testcase for this optimization
  shortly as well. ]

	* Makefile.in (OBJS-common): Add tree-ssa-phiopt.o
	(tree-ssa-phiopt.o): Add dependencies.
	* timevar.def (TV_TREE_PHIOPT): New timevar.
	* tree-cfg.c (extract_true_false_edges_from_block): Moved here from
	tree-ssa-dom.c.
	(tree_verify_flow_info): Use extract_true_false_edges_from_block.
	* tree-flow.h (extract_true_false_edges_from_block): Declare.
	* tree-ssa-dom.c (extract_true_false_edges_from_block): Moved into
	tree-cfg.c.
	(get_eq_expr_value): Improve type check.
	* tree-optimize.c (init_tree_optimization_passes): Link in
	phiopt pass.
	* tree-pass.h (pass_phiopt): Declare.
	* tree-ssa-phiopt.c: New file with PHI node optimization pass.
	* doc/invoke.texi: Document dump for PHI node optimization.

Index: Makefile.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Makefile.in,v
retrieving revision 1.903.2.175
diff -c -p -r1.903.2.175 Makefile.in
*** Makefile.in	10 Feb 2004 18:24:14 -0000	1.903.2.175
--- Makefile.in	10 Feb 2004 22:13:40 -0000
*************** OBJS-common = \
*** 870,875 ****
--- 870,876 ----
   tree-alias-type.o gimplify.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-live.o tree-ssa-operands.o tree-ssa-alias.o       \
+  tree-ssa-phiopt.o							   \
   tree-ssa-dom.o domwalk.o tree-tailcall.o gimple-low.o tree-iterator.o	   \
   tree-phinodes.o tree-ssanames.o tree-sra.o tree-complex.o tree-ssa-loop.o \
   alias.o bb-reorder.o bitmap.o builtins.o caller-save.o calls.o	  	   \
*************** tree-ssa.o : tree-ssa.c $(TREE_FLOW_H) $
*** 1536,1541 ****
--- 1537,1545 ----
     errors.h toplev.h function.h $(TIMEVAR_H) tree-alias-common.h \
     $(TM_H) coretypes.h $(TREE_DUMP_H) tree-ssa-live.h langhooks.h \
     cfgloop.h domwalk.h tree-pass.h
+ tree-ssa-phiopt.o : tree-ssa-phiopt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+    $(TM_H) errors.h $(GGC_H) $(TREE_H) $(RTL_H) $(TM_P_H) $(BASIC_BLOCK_H) \
+    $(TREE_FLOW_H) tree-pass.h $(TREE_DUMP_H)
  tree-ssa-dom.o : tree-ssa-dom.c $(TREE_FLOW_H) $(CONFIG_H) $(SYSTEM_H) \
     $(RTL_H) $(TREE_H) $(TM_P_H) $(EXPR_H) $(GGC_H) output.h diagnostic.h \
     errors.h function.h $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) \
Index: timevar.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/timevar.def,v
retrieving revision 1.14.2.32
diff -c -p -r1.14.2.32 timevar.def
*** timevar.def	10 Feb 2004 18:24:15 -0000	1.14.2.32
--- timevar.def	10 Feb 2004 22:13:41 -0000
*************** DEFTIMEVAR (TV_TREE_SRA              , "
*** 74,79 ****
--- 74,80 ----
  DEFTIMEVAR (TV_TREE_CCP		     , "tree CCP")
  DEFTIMEVAR (TV_TREE_SPLIT_EDGES      , "tree split crit edges")
  DEFTIMEVAR (TV_TREE_PRE		     , "tree PRE")
+ DEFTIMEVAR (TV_TREE_PHIOPT	     , "tree optimize phi nodes ")
  DEFTIMEVAR (TV_TREE_DCE		     , "tree conservative DCE")
  DEFTIMEVAR (TV_TREE_CD_DCE	     , "tree aggressive DCE")
  DEFTIMEVAR (TV_TREE_LOOP	     , "tree loop optimization")
Index: tree-cfg.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-cfg.c,v
retrieving revision 1.1.4.265
diff -c -p -r1.1.4.265 tree-cfg.c
*** tree-cfg.c	10 Feb 2004 00:53:22 -0000	1.1.4.265
--- tree-cfg.c	10 Feb 2004 22:13:47 -0000
*************** tree_verify_flow_info (void)
*** 3086,3095 ****
  		error ("Structured COND_EXPR at end of bb %d\n", bb->index);
  		err = 1;
  	      }
! 	    if (bb->succ->flags & EDGE_TRUE_VALUE)
! 	      true_edge = bb->succ, false_edge = bb->succ->succ_next;
! 	    else
! 	      false_edge = bb->succ, true_edge = bb->succ->succ_next;
  	    if (!true_edge || !false_edge
  		|| !(true_edge->flags & EDGE_TRUE_VALUE)
  		|| !(false_edge->flags & EDGE_FALSE_VALUE)
--- 3086,3094 ----
  		error ("Structured COND_EXPR at end of bb %d\n", bb->index);
  		err = 1;
  	      }
! 
! 	    extract_true_false_edges_from_block (bb, &true_edge, &false_edge);
! 
  	    if (!true_edge || !false_edge
  		|| !(true_edge->flags & EDGE_TRUE_VALUE)
  		|| !(false_edge->flags & EDGE_FALSE_VALUE)
*************** execute_warn_function_return (void)
*** 4026,4031 ****
--- 4025,4054 ----
  	      break;
  	    }
  	}
+     }
+ }
+ 
+ /* Given a basic block which ends with a conditional and has precisely
+    two successors, determine which of the edges is taken if the conditional
+    is true and which is taken if the conditional is false.  Set TRUE_EDGE
+    and FALSE_EDGE appropriately.  */
+ 
+ void
+ extract_true_false_edges_from_block (basic_block b,
+ 				     edge *true_edge,
+ 				     edge *false_edge)
+ {
+   edge e = b->succ;
+ 
+   if (e->flags & EDGE_TRUE_VALUE)
+     {
+       *true_edge = e;
+       *false_edge = e->succ_next;
+     }
+   else
+     {
+       *false_edge = e;
+       *true_edge = e->succ_next;
      }
  }
  
Index: tree-flow.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-flow.h,v
retrieving revision 1.1.4.185
diff -c -p -r1.1.4.185 tree-flow.h
*** tree-flow.h	10 Feb 2004 18:24:16 -0000	1.1.4.185
--- tree-flow.h	10 Feb 2004 22:13:48 -0000
*************** extern void compute_dominance_frontiers 
*** 480,485 ****
--- 480,487 ----
  extern bool verify_stmt (tree);
  extern void verify_stmts (void);
  extern basic_block tree_duplicate_bb (basic_block, edge);
+ extern void extract_true_false_edges_from_block (basic_block, edge *, edge 
*);
+ 
  
  /* In tree-pretty-print.c.  */
  extern void dump_generic_bb (FILE *, basic_block, int, int);
Index: tree-optimize.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v
retrieving revision 1.1.4.117
diff -c -p -r1.1.4.117 tree-optimize.c
*** tree-optimize.c	10 Feb 2004 00:53:24 -0000	1.1.4.117
--- tree-optimize.c	10 Feb 2004 22:13:50 -0000
*************** init_tree_optimization_passes (void)
*** 283,288 ****
--- 283,289 ----
    NEXT_PASS (pass_dce);
    NEXT_PASS (pass_dominator);
    NEXT_PASS (DUP_PASS (pass_dce));
+   NEXT_PASS (pass_phiopt);
    NEXT_PASS (pass_may_alias);
    NEXT_PASS (pass_del_pta);
    NEXT_PASS (pass_profile);
*************** init_tree_optimization_passes (void)
*** 290,295 ****
--- 291,297 ----
    NEXT_PASS (pass_sra);
    NEXT_PASS (DUP_PASS (pass_dominator));
    NEXT_PASS (DUP_PASS (pass_dce));
+   NEXT_PASS (DUP_PASS (pass_phiopt));
    NEXT_PASS (pass_tail_recursion);
    NEXT_PASS (pass_loop);
    NEXT_PASS (pass_ccp);
*************** init_tree_optimization_passes (void)
*** 298,303 ****
--- 300,306 ----
    NEXT_PASS (pass_pre);
    NEXT_PASS (DUP_PASS (pass_dominator));
    NEXT_PASS (pass_cd_dce);
+   NEXT_PASS (DUP_PASS (pass_phiopt));
    NEXT_PASS (pass_tail_calls);
    NEXT_PASS (pass_late_warn_uninitialized);
    NEXT_PASS (pass_warn_function_return);
Index: tree-pass.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-pass.h,v
retrieving revision 1.1.2.8
diff -c -p -r1.1.2.8 tree-pass.h
*** tree-pass.h	10 Feb 2004 00:53:25 -0000	1.1.2.8
--- tree-pass.h	10 Feb 2004 22:13:50 -0000
*************** extern struct tree_opt_pass pass_fold_bu
*** 117,122 ****
--- 117,123 ----
  extern struct tree_opt_pass pass_early_warn_uninitialized;
  extern struct tree_opt_pass pass_late_warn_uninitialized;
  extern struct tree_opt_pass pass_warn_function_return;
+ extern struct tree_opt_pass pass_phiopt;
  
  
  #endif /* GCC_TREE_PASS_H */
Index: tree-ssa-dom.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/Attic/tree-ssa-dom.c,v
retrieving revision 1.1.2.132
diff -c -p -r1.1.2.132 tree-ssa-dom.c
*** tree-ssa-dom.c	10 Feb 2004 18:24:16 -0000	1.1.2.132
--- tree-ssa-dom.c	10 Feb 2004 22:13:57 -0000
*************** static void remove_local_expressions_fro
*** 256,262 ****
  static void restore_vars_to_original_value (varray_type locals,
  					    unsigned limit, 
  					    varray_type table);
- static void extract_true_false_edges_from_block (basic_block, edge *, edge 
*);
  static void register_definitions_for_stmt (tree, varray_type *);
  static void redirect_edges_and_update_ssa_graph (varray_type);
  
--- 256,261 ----
*************** restore_vars_to_original_value (varray_t
*** 1077,1107 ****
      }
  }
  
- /* Given a basic block which ends with a conditional and has precisely
-    two successors, determine which of the edges is taken if the conditional
-    is true and which is taken if the conditional is false.  Set TRUE_EDGE
-    and FALSE_EDGE appropriately.  */
- 
- static void
- extract_true_false_edges_from_block (basic_block b,
- 				     edge *true_edge,
- 				     edge *false_edge)
- {
-   edge e = b->succ;
- 
-   if (e->flags & EDGE_TRUE_VALUE)
-     {
-       *true_edge = e;
-       *false_edge = e->succ_next;
-     }
-   else
-     {
-       *false_edge = e;
-       *true_edge = e->succ_next;
-     }
- }
- 
- 
  /* We have finished processing the dominator children of BB, perform
     any finalization actions in preparation for leaving this node in
     the dominator tree.  */
--- 1076,1081 ----
*************** get_eq_expr_value (tree if_stmt,
*** 3151,3157 ****
  	 the value of op0 on both arms of the branch.  */
        if ((TREE_CODE (cond) == EQ_EXPR || TREE_CODE (cond) == NE_EXPR)
  	  && TREE_CODE (op0) == SSA_NAME
! 	  && TREE_TYPE (op0) == boolean_type_node
  	  && is_gimple_min_invariant (op1))
  	{
  	  if ((TREE_CODE (cond) == EQ_EXPR && true_arm)
--- 3125,3131 ----
  	 the value of op0 on both arms of the branch.  */
        if ((TREE_CODE (cond) == EQ_EXPR || TREE_CODE (cond) == NE_EXPR)
  	  && TREE_CODE (op0) == SSA_NAME
! 	  && TREE_CODE (TREE_TYPE (op0)) == BOOLEAN_TYPE
  	  && is_gimple_min_invariant (op1))
  	{
  	  if ((TREE_CODE (cond) == EQ_EXPR && true_arm)
Index: tree-ssa-phiopt.c
===================================================================
RCS file: tree-ssa-phiopt.c
diff -N tree-ssa-phiopt.c
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- tree-ssa-phiopt.c	10 Feb 2004 22:13:58 -0000
***************
*** 0 ****
--- 1,274 ----
+ /* Optimization of PHI nodes by converting them into straightline code.
+    Copyright (C) 2004 Free Software Foundation, Inc.
+ 
+ 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 "errors.h"
+ #include "ggc.h"
+ #include "tree.h"
+ #include "rtl.h"
+ #include "tm_p.h"
+ #include "basic-block.h"
+ #include "timevar.h"
+ #include "diagnostic.h"
+ #include "tree-flow.h"
+ #include "tree-pass.h"
+ #include "tree-dump.h"
+ 
+ static void tree_ssa_phiopt (void);
+ 
+ /* This pass eliminates PHI nodes which can be trivially implemented as
+    an assignment from a conditional expression.  ie if we have something
+    like:
+ 
+      bb0:
+       if (cond) goto bb2; else goto bb1;
+      bb1:
+      bb2:
+       x = PHI (0 (bb1), 1 (bb0)
+ 
+     We can rewrite that as:
+     
+     bb0:
+     bb1:
+     bb2:
+       x = cond;
+ 
+     bb1 will become unreachable and bb0 and bb2 will almost always
+     be merged into a single block.  This occurs often due to gimplification
+     of conditionals.  */
+    
+ static void
+ tree_ssa_phiopt (void)
+ {
+   basic_block bb;
+   bool removed_phis = false;
+ 
+   /* Search every basic block for PHI nodes we may be able to optimize.  */
+   FOR_EACH_BB (bb)
+     {
+       tree arg0, arg1, result, phi;
+       basic_block other_block = NULL;
+       basic_block cond_block = NULL;
+       tree last0, last1, new, cond;
+       block_stmt_iterator bsi;
+       edge true_edge, false_edge;
+ 
+ 
+       /* We're searching for blocks with one PHI node which has two
+ 	 arguments.  */
+       phi = phi_nodes (bb);
+       if (!phi
+ 	  || TREE_CHAIN (phi) != NULL
+ 	  || PHI_NUM_ARGS (phi) != 2)
+ 	continue;
+ 
+       /* The PHI arguments must be the constants 0 and 1.  */
+       arg0 = PHI_ARG_DEF (phi, 0);
+       arg1 = PHI_ARG_DEF (phi, 1);
+       if ((integer_zerop (arg0) && integer_onep (arg1))
+ 	  || (integer_zerop (arg1) && integer_onep (arg0)))
+ 	;
+       else
+ 	continue;
+ 
+       /* One of the alternatives must come from a block ending with
+ 	 a COND_EXPR.  The other block must be entirely empty, except
+ 	 for labels.  */
+       last0 = last_stmt (bb->pred->src);
+       last1 = last_stmt (bb->pred->pred_next->src);
+       if (last0 && TREE_CODE (last0) == COND_EXPR)
+ 	{
+ 	  cond_block = bb->pred->src;
+ 	  other_block = bb->pred->pred_next->src;
+ 	}
+       else if (last1 && TREE_CODE (last1) == COND_EXPR)
+ 	{
+ 	  other_block = bb->pred->src;
+ 	  cond_block = bb->pred->pred_next->src;
+ 	}
+       else
+ 	continue;
+ 
+       /* COND_BLOCK must have precisely two successors.  We indirectly
+ 	 verify that those successors are BB and OTHER_BLOCK.  */
+       if (!cond_block->succ
+ 	  || !cond_block->succ->succ_next
+ 	  || cond_block->succ->succ_next->succ_next
+ 	  || (cond_block->succ->flags & EDGE_ABNORMAL) != 0
+ 	  || (cond_block->succ->succ_next->flags & EDGE_ABNORMAL) != 0)
+ 	continue;
+ 
+       /* OTHER_BLOCK must have a single predecessor which is COND_BLOCK,
+ 	 OTHER_BLOCK must have a single successor which is BB and
+ 	 OTHER_BLOCK must have no PHI nodes.  */
+       if (!other_block->pred
+ 	  || other_block->pred->src != cond_block
+ 	  || other_block->pred->pred_next
+ 	  || !other_block->succ
+ 	  || other_block->succ->dest != bb
+ 	  || other_block->succ->succ_next
+ 	  || phi_nodes (other_block))
+ 	continue;
+ 
+       /* OTHER_BLOCK must have no executable statements.  */
+       bsi = bsi_start (other_block);
+       while (!bsi_end_p (bsi)
+ 	     && (TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR
+ 		 || IS_EMPTY_STMT (bsi_stmt (bsi))))
+ 	bsi_next (&bsi);
+       if (!bsi_end_p (bsi))
+ 	continue;
+ 
+       /* If the condition is not a naked SSA_NAME and its type does not
+ 	 match the type of the result, then we can not optimize this case
+ 	 as it would likely create non-gimple code when the condition
+ 	 was converted to the result's type.  */
+       cond = COND_EXPR_COND (last_stmt (cond_block));
+       result = PHI_RESULT (phi);
+       if (TREE_CODE (cond) != SSA_NAME
+ 	  && (TYPE_MAIN_VARIANT (TREE_TYPE (cond))
+ 	      != TYPE_MAIN_VARIANT (TREE_TYPE (result))))
+ 	continue;
+ 
+       /* If the condition was a naked SSA_NAME and the type is not the
+ 	 same as the type of the result, then convert the type of the
+ 	 condition.  */
+       if (TYPE_MAIN_VARIANT (TREE_TYPE (cond))
+ 	  != TYPE_MAIN_VARIANT (TREE_TYPE (result)))
+ 	cond = convert (TREE_TYPE (result), cond);
+ 
+       /* We need to know which is the true edge and which is the false
+ 	 edge so that we know when to invert the condition below.  */
+       extract_true_false_edges_from_block (cond_block, &true_edge, 
&false_edge);
+ 
+       /* At this point we know we have a COND_EXPR with two successors.
+ 	 One successor is BB, the other successor is an empty block which
+ 	 falls through into BB.
+ 
+ 	 There is a single PHI node at the join point (BB) and its arguments
+ 	 are constants (0, 1).
+ 
+ 	 So, given the condition COND, and the two PHI arguments, we can
+ 	 rewrite this PHI into non-branching code: 
+ 
+ 	    dest = (COND) or dest = COND'
+ 
+ 	 We use the condition as-is if the argument associated with the
+ 	 true edge has the value one or the argument associated with the
+ 	 false edge as the value zero.  Note that those conditions are not
+ 	 the same since only one of the outgoing edges from the COND_EXPR
+ 	 will directly reach BB and thus be associated with an argument.  */
+       if ((PHI_ARG_EDGE (phi, 0) == true_edge && integer_onep (arg0))
+ 	  || (PHI_ARG_EDGE (phi, 0) == false_edge && integer_zerop (arg0))
+ 	  || (PHI_ARG_EDGE (phi, 1) == true_edge && integer_onep (arg1))
+ 	  || (PHI_ARG_EDGE (phi, 1) == false_edge && integer_zerop (arg1)))
+ 	{
+ 	  new = build (MODIFY_EXPR, TREE_TYPE (PHI_RESULT (phi)),
+ 		       PHI_RESULT (phi), cond);
+ 	}
+       else
+ 	{
+ 	  cond = invert_truthvalue (cond);
+ 
+ 	  /* Inversion of the condition may result in non-gimple code,
+ 	     if so, then we can not optimize this PHI.  */
+ 	  if (TREE_CODE (cond) == TRUTH_NOT_EXPR)
+ 	    continue;
+ 
+ 	  new = build (MODIFY_EXPR, TREE_TYPE (PHI_RESULT (phi)),
+ 		       PHI_RESULT (phi), cond);
+ 	}
+ 
+       /* Insert our new statement at the head of our block.  */
+       bsi = bsi_start (bb);
+       bsi_insert_after (&bsi, new, BSI_SAME_STMT);
+ 
+       /* Register our new statement as the defining statement for
+ 	 the result.  */
+       SSA_NAME_DEF_STMT (PHI_RESULT (phi)) = new;
+ 
+       /* Remove the now useless PHI node. 
+ 
+ 	 We do not want to use remove_phi_node since that releases the
+ 	 SSA_NAME as well and the SSA_NAME is still being used.  */
+       release_phi_node (phi);
+       bb_ann (bb)->phi_nodes = NULL;
+ 
+       /* Disconnect the edge leading into the empty block.  That will
+ 	 make the empty block unreachable and it will be removed later.  */
+       if (cond_block->succ->dest == bb)
+ 	{
+ 	  cond_block->succ->flags |= EDGE_FALLTHRU;
+ 	  ssa_remove_edge (cond_block->succ->succ_next);
+ 	}
+       else
+ 	{
+ 	  cond_block->succ->succ_next->flags |= EDGE_FALLTHRU;
+ 	  ssa_remove_edge (cond_block->succ);
+ 	}
+ 
+       /* Eliminate the COND_EXPR at the end of COND_BLOCK.  */
+       bsi = bsi_last (cond_block);
+       bsi_remove (&bsi);
+ 
+       if (tree_dump_file && (tree_dump_flags & TDF_DETAILS))
+ 	fprintf (tree_dump_file,
+ 		 "COND_EXPR in block %d and PHI in block %d converted to straightline 
code.\n",
+ 		 cond_block->index,
+ 		 bb->index);
+ 		
+       /* Note that we optimized this PHI.  */
+       removed_phis = true;
+     }
+ 
+   /* If we removed any PHIs, then we have unreachable blocks and blocks
+      which need to be merged in the CFG.  */
+   if (removed_phis)
+     cleanup_tree_cfg ();
+ }
+ 
+ 												
+ static bool
+ gate_phiopt (void)
+ {
+   return 1;
+ }
+ 												
+ struct tree_opt_pass pass_phiopt =
+ {
+   "phiopt",				/* name */
+   gate_phiopt,				/* gate */
+   tree_ssa_phiopt,			/* execute */
+   NULL,					/* sub */
+   NULL,					/* next */
+   0,					/* static_pass_number */
+   TV_TREE_PHIOPT,			/* tv_id */
+   PROP_cfg | PROP_ssa,			/* properties_required */
+   0,					/* properties_provided */
+   0,					/* properties_destroyed */
+   0,					/* todo_flags_start */
+   TODO_dump_func | TODO_ggc_collect	/* todo_flags_finish */
+     | TODO_verify_ssa
+ };
+ 												
+ 
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.152.2.69
diff -c -p -r1.152.2.69 invoke.texi
*** doc/invoke.texi	6 Feb 2004 23:20:07 -0000	1.152.2.69
--- doc/invoke.texi	10 Feb 2004 22:14:40 -0000
*************** in the following sections.
*** 254,259 ****
--- 254,260 ----
  -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-dom@r{[}-@var{n}@r{]} @gol
+ -fdump-tree-phiopt@r{[}-@var{n}@r{]} @gol
  -fdump-tree-loop@r{[}-@var{n}@r{]} -fdump-tree-sra@r{[}-@var{n}@r{]} @gol
  -feliminate-dwarf2-dups -feliminate-unused-debug-types @gol
  -feliminate-unused-debug-symbols -fmem-report -fprofile-arcs @gol
*************** file name is made by appending @file{.sr
*** 3520,3525 ****
--- 3521,3531 ----
  @opindex fdump-tree-dom
  Dump each function after applying dominator tree optimizations.  The file
  name is made by appending @file{.dom} to the source file name.
+ 
+ @item phiopt
+ @opindex fdump-tree-phiopt
+ Dump each function after optimizing PHI nodes into straightline code.  The 
file
+ name is made by appending @file{.phiopt} to the source file name.
  
  @item loop
  @opindex fdump-tree-loop














Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]