OSDN Git Service

2004-10-27 Andrew Pinski <pinskia@physics.uc.edu>
[pf3gnuchains/gcc-fork.git] / gcc / tree-ssa-phiopt.c
1 /* Optimization of PHI nodes by converting them into straightline code.
2    Copyright (C) 2004 Free Software Foundation, Inc.
3
4 This file is part of GCC.
5    
6 GCC is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10    
11 GCC is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15    
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING.  If not, write to the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "errors.h"
26 #include "ggc.h"
27 #include "tree.h"
28 #include "rtl.h"
29 #include "flags.h"
30 #include "tm_p.h"
31 #include "basic-block.h"
32 #include "timevar.h"
33 #include "diagnostic.h"
34 #include "tree-flow.h"
35 #include "tree-pass.h"
36 #include "tree-dump.h"
37 #include "langhooks.h"
38
39 static void tree_ssa_phiopt (void);
40 static bool conditional_replacement (basic_block, tree, tree, tree);
41 static bool value_replacement (basic_block, tree, tree, tree);
42 static bool abs_replacement (basic_block, tree, tree, tree);
43 static void replace_phi_with_stmt (block_stmt_iterator, basic_block,
44                                    basic_block, tree, tree);
45 static bool candidate_bb_for_phi_optimization (basic_block,
46                                                basic_block *,
47                                                basic_block *);
48
49 /* This pass eliminates PHI nodes which can be trivially implemented as
50    an assignment from a conditional expression.  i.e. if we have something
51    like:
52
53      bb0:
54       if (cond) goto bb2; else goto bb1;
55      bb1:
56      bb2:
57       x = PHI (0 (bb1), 1 (bb0)
58
59    We can rewrite that as:
60     
61      bb0:
62      bb1:
63      bb2:
64       x = cond;
65
66    bb1 will become unreachable and bb0 and bb2 will almost always
67    be merged into a single block.  This occurs often due to gimplification
68     of conditionals. 
69    
70    Also done is the following optimization:
71
72      bb0:
73       if (a != b) goto bb2; else goto bb1;
74      bb1:
75      bb2:
76       x = PHI (a (bb1), b (bb0))
77
78    We can rewrite that as:
79
80      bb0:
81      bb1:
82      bb2:
83       x = b;
84
85    This can sometimes occur as a result of other optimizations.  A
86    similar transformation is done by the ifcvt RTL optimizer. 
87
88    This pass also eliminates PHI nodes which are really absolute 
89    values.  i.e. if we have something like:
90
91      bb0:
92       if (a >= 0) goto bb2; else goto bb1;
93      bb1:
94       x = -a;
95      bb2:
96       x = PHI (x (bb1), a (bb0));
97
98    We can rewrite that as:
99
100      bb0:
101      bb1:
102      bb2:
103       x = ABS_EXPR< a >;
104
105    bb1 will become unreachable and bb0 and bb2 will almost always be merged
106    into a single block.  Similar transformations are done by the ifcvt
107    RTL optimizer.  */ 
108
109 static void
110 tree_ssa_phiopt (void)
111 {
112   basic_block bb;
113   bool removed_phis = false;
114
115   /* Search every basic block for PHI nodes we may be able to optimize.  */
116   FOR_EACH_BB (bb)
117     {
118       tree arg0, arg1, phi;
119
120       /* We're searching for blocks with one PHI node which has two
121          arguments.  */
122       phi = phi_nodes (bb);
123       if (phi && PHI_CHAIN (phi) == NULL
124           && PHI_NUM_ARGS (phi) == 2)
125         {
126           arg0 = PHI_ARG_DEF (phi, 0);
127           arg1 = PHI_ARG_DEF (phi, 1);
128             
129           /* Do the replacement of conditional if it can be done.  */
130             if (conditional_replacement (bb, phi, arg0, arg1)
131                 || value_replacement (bb, phi, arg0, arg1)
132                 || abs_replacement (bb, phi, arg0, arg1))
133               {
134                 /* We have done the replacement so we need to rebuild the
135                    cfg when this pass is complete.  */
136                 removed_phis = true;
137               }
138         }
139     }
140
141   /* If we removed any PHIs, then we have unreachable blocks and blocks
142      which need to be merged in the CFG.  */
143   if (removed_phis)
144     cleanup_tree_cfg ();
145 }
146
147 /* Return TRUE if block BB has no executable statements, otherwise return
148    FALSE.  */
149 bool
150 empty_block_p (basic_block bb)
151 {
152   block_stmt_iterator bsi;
153
154   /* BB must have no executable statements.  */
155   bsi = bsi_start (bb);
156   while (!bsi_end_p (bsi)
157           && (TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR
158               || IS_EMPTY_STMT (bsi_stmt (bsi))))
159     bsi_next (&bsi);
160   
161   if (!bsi_end_p (bsi))
162     return false;
163
164   return true;
165 }
166
167 /* BB is a basic block which has only one PHI node with precisely two
168    arguments.
169
170    Examine both of BB's predecessors to see if one ends with a 
171    COND_EXPR and the other is a successor of the COND_EXPR.  If so, then
172    we may be able to optimize PHI nodes at the start of BB. 
173
174    If so, mark store the block with the COND_EXPR into COND_BLOCK_P
175    and the other block into OTHER_BLOCK_P and return true, otherwise
176    return false.  */
177
178 static bool
179 candidate_bb_for_phi_optimization (basic_block bb,
180                                    basic_block *cond_block_p,
181                                    basic_block *other_block_p)
182 {
183   tree last0, last1;
184   basic_block cond_block, other_block;
185
186   /* One of the alternatives must come from a block ending with
187      a COND_EXPR.  */
188   last0 = last_stmt (EDGE_PRED (bb, 0)->src);
189   last1 = last_stmt (EDGE_PRED (bb, 1)->src);
190   if (last0 && TREE_CODE (last0) == COND_EXPR)
191     {
192       cond_block = EDGE_PRED (bb, 0)->src;
193       other_block = EDGE_PRED (bb, 1)->src;
194     }
195   else if (last1 && TREE_CODE (last1) == COND_EXPR)
196     {
197       other_block = EDGE_PRED (bb, 0)->src;
198       cond_block = EDGE_PRED (bb, 1)->src;
199     }
200   else
201     return false;
202   
203   /* COND_BLOCK must have precisely two successors.  We indirectly
204      verify that those successors are BB and OTHER_BLOCK.  */
205   if (EDGE_COUNT (cond_block->succs) != 2
206       || (EDGE_SUCC (cond_block, 0)->flags & EDGE_ABNORMAL) != 0
207       || (EDGE_SUCC (cond_block, 1)->flags & EDGE_ABNORMAL) != 0)
208     return false;
209   
210   /* OTHER_BLOCK must have a single predecessor which is COND_BLOCK,
211      OTHER_BLOCK must have a single successor which is BB and
212      OTHER_BLOCK must have no PHI nodes.  */
213   if (EDGE_COUNT (other_block->preds) != 1
214       || EDGE_PRED (other_block, 0)->src != cond_block
215       || EDGE_COUNT (other_block->succs) != 1
216       || EDGE_SUCC (other_block, 0)->dest != bb
217       || phi_nodes (other_block))
218     return false;
219   
220   *cond_block_p = cond_block;
221   *other_block_p = other_block;
222   /* Everything looks OK.  */
223   return true;
224 }
225
226 /* Replace PHI in block BB with statement NEW.  NEW is inserted after
227    BSI.  Remove the edge from COND_BLOCK which does not lead to BB (COND_BLOCK
228    is known to have two edges, one of which must reach BB).  */
229
230 static void
231 replace_phi_with_stmt (block_stmt_iterator bsi, basic_block bb,
232                        basic_block cond_block, tree phi, tree new)
233 {
234   basic_block block_to_remove;
235
236   /* Insert our new statement at the head of our block.  */
237   bsi_insert_after (&bsi, new, BSI_NEW_STMT);
238   
239   /* Register our new statement as the defining statement for
240      the result.  */
241   SSA_NAME_DEF_STMT (PHI_RESULT (phi)) = new;
242   
243   /* Remove the now useless PHI node. 
244   
245      We do not want to use remove_phi_node since that releases the
246      SSA_NAME as well and the SSA_NAME is still being used.  */
247   release_phi_node (phi);
248   bb_ann (bb)->phi_nodes = NULL;
249   
250   /* Remove the empty basic block.  */
251   if (EDGE_SUCC (cond_block, 0)->dest == bb)
252     {
253       EDGE_SUCC (cond_block, 0)->flags |= EDGE_FALLTHRU;
254       EDGE_SUCC (cond_block, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
255
256       block_to_remove = EDGE_SUCC (cond_block, 1)->dest;
257     }
258   else
259     {
260       EDGE_SUCC (cond_block, 1)->flags |= EDGE_FALLTHRU;
261       EDGE_SUCC (cond_block, 1)->flags
262         &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
263
264       block_to_remove = EDGE_SUCC (cond_block, 0)->dest;
265     }
266   delete_basic_block (block_to_remove);
267   
268   /* Eliminate the COND_EXPR at the end of COND_BLOCK.  */
269   bsi = bsi_last (cond_block);
270   bsi_remove (&bsi);
271   
272   if (dump_file && (dump_flags & TDF_DETAILS))
273     fprintf (dump_file,
274               "COND_EXPR in block %d and PHI in block %d converted to straightline code.\n",
275               cond_block->index,
276               bb->index);
277 }
278
279 /*  The function conditional_replacement does the main work of doing the
280     conditional replacement.  Return true if the replacement is done.
281     Otherwise return false.
282     BB is the basic block where the replacement is going to be done on.  ARG0
283     is argument 0 from PHI.  Likewise for ARG1.  */
284
285 static bool
286 conditional_replacement (basic_block bb, tree phi, tree arg0, tree arg1)
287 {
288   tree result;
289   tree old_result = NULL;
290   basic_block other_block = NULL;
291   basic_block cond_block = NULL;
292   tree new, cond;
293   block_stmt_iterator bsi;
294   edge true_edge, false_edge;
295   tree new_var = NULL;
296
297   /* The PHI arguments have the constants 0 and 1, then convert
298      it to the conditional.  */
299   if ((integer_zerop (arg0) && integer_onep (arg1))
300       || (integer_zerop (arg1) && integer_onep (arg0)))
301     ;
302   else
303     return false;
304   
305   if (!candidate_bb_for_phi_optimization (bb, &cond_block, &other_block)
306       || !empty_block_p (other_block))
307     return false;
308                                                                                 
309   /* If the condition is not a naked SSA_NAME and its type does not
310      match the type of the result, then we have to create a new
311      variable to optimize this case as it would likely create
312      non-gimple code when the condition was converted to the
313      result's type.  */
314   cond = COND_EXPR_COND (last_stmt (cond_block));
315   result = PHI_RESULT (phi);
316   if (TREE_CODE (cond) != SSA_NAME
317       && !lang_hooks.types_compatible_p (TREE_TYPE (cond), TREE_TYPE (result)))
318     {
319       new_var = make_rename_temp (TREE_TYPE (cond), NULL);
320       old_result = cond;
321       cond = new_var;
322     }
323   
324   /* If the condition was a naked SSA_NAME and the type is not the
325      same as the type of the result, then convert the type of the
326      condition.  */
327   if (!lang_hooks.types_compatible_p (TREE_TYPE (cond), TREE_TYPE (result)))
328     cond = fold_convert (TREE_TYPE (result), cond);
329   
330   /* We need to know which is the true edge and which is the false
331      edge so that we know when to invert the condition below.  */
332   extract_true_false_edges_from_block (cond_block, &true_edge, &false_edge);
333       
334   /* Insert our new statement at the head of our block.  */
335   bsi = bsi_after_labels (bb);
336   
337   if (old_result)
338     {
339       tree new1;
340       if (!COMPARISON_CLASS_P (old_result))
341         return false;
342       
343       new1 = build (TREE_CODE (old_result), TREE_TYPE (old_result),
344                     TREE_OPERAND (old_result, 0),
345                     TREE_OPERAND (old_result, 1));
346       
347       new1 = build (MODIFY_EXPR, TREE_TYPE (old_result), new_var, new1);
348       bsi_insert_after (&bsi, new1, BSI_NEW_STMT);
349     }
350   
351   /* At this point we know we have a COND_EXPR with two successors.
352      One successor is BB, the other successor is an empty block which
353      falls through into BB.
354   
355      There is a single PHI node at the join point (BB) and its arguments
356      are constants (0, 1).
357   
358      So, given the condition COND, and the two PHI arguments, we can
359      rewrite this PHI into non-branching code: 
360   
361        dest = (COND) or dest = COND'
362   
363      We use the condition as-is if the argument associated with the
364      true edge has the value one or the argument associated with the
365      false edge as the value zero.  Note that those conditions are not
366      the same since only one of the outgoing edges from the COND_EXPR
367      will directly reach BB and thus be associated with an argument.  */
368   if ((PHI_ARG_EDGE (phi, 0) == true_edge && integer_onep (arg0))
369       || (PHI_ARG_EDGE (phi, 0) == false_edge && integer_zerop (arg0))
370       || (PHI_ARG_EDGE (phi, 1) == true_edge && integer_onep (arg1))
371       || (PHI_ARG_EDGE (phi, 1) == false_edge && integer_zerop (arg1)))
372     {
373       new = build (MODIFY_EXPR, TREE_TYPE (PHI_RESULT (phi)),
374                     PHI_RESULT (phi), cond);
375     }
376   else
377     {
378       tree cond1 = invert_truthvalue (cond);
379       
380       cond = cond1;
381       /* If what we get back is a conditional expression, there is no
382           way that it can be gimple.  */
383       if (TREE_CODE (cond) == COND_EXPR)
384         return false; 
385
386       /* If what we get back is not gimple try to create it as gimple by
387          using a temporary variable.  */
388       if (is_gimple_cast (cond)
389           && !is_gimple_val (TREE_OPERAND (cond, 0)))
390         {
391           tree temp = TREE_OPERAND (cond, 0);
392           tree new_var_1 = make_rename_temp (TREE_TYPE (temp), NULL);
393           new = build (MODIFY_EXPR, TREE_TYPE (new_var_1), new_var_1, temp);
394           bsi_insert_after (&bsi, new, BSI_NEW_STMT);
395           cond = fold_convert (TREE_TYPE (result), new_var_1);
396         }
397       
398       if (TREE_CODE (cond) == TRUTH_NOT_EXPR
399           &&  !is_gimple_val (TREE_OPERAND (cond, 0)))
400         return false;
401
402       new = build (MODIFY_EXPR, TREE_TYPE (PHI_RESULT (phi)),
403                     PHI_RESULT (phi), cond);
404     }
405   
406   replace_phi_with_stmt (bsi, bb, cond_block, phi, new);
407
408   /* Note that we optimized this PHI.  */
409   return true;
410 }
411
412 /*  The function value_replacement does the main work of doing the value
413     replacement.  Return true if the replacement is done.  Otherwise return
414     false.
415     BB is the basic block where the replacement is going to be done on.  ARG0
416     is argument 0 from the PHI.  Likewise for ARG1.  */
417
418 static bool
419 value_replacement (basic_block bb, tree phi, tree arg0, tree arg1)
420 {
421   tree result;
422   basic_block other_block = NULL;
423   basic_block cond_block = NULL;
424   tree new, cond;
425   edge true_edge, false_edge;
426
427   /* If the type says honor signed zeros we cannot do this
428      optimization.  */
429   if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
430     return false;
431
432   if (!candidate_bb_for_phi_optimization (bb, &cond_block, &other_block)
433       || !empty_block_p (other_block))
434     return false;
435
436   cond = COND_EXPR_COND (last_stmt (cond_block));
437   result = PHI_RESULT (phi);
438
439   /* This transformation is only valid for equality comparisons.  */
440   if (TREE_CODE (cond) != NE_EXPR && TREE_CODE (cond) != EQ_EXPR)
441     return false;
442
443   /* We need to know which is the true edge and which is the false
444       edge so that we know if have abs or negative abs.  */
445   extract_true_false_edges_from_block (cond_block, &true_edge, &false_edge);
446
447   /* At this point we know we have a COND_EXPR with two successors.
448      One successor is BB, the other successor is an empty block which
449      falls through into BB.
450
451      The condition for the COND_EXPR is known to be NE_EXPR or EQ_EXPR.
452
453      There is a single PHI node at the join point (BB) with two arguments.
454
455      We now need to verify that the two arguments in the PHI node match
456      the two arguments to the equality comparison.  */
457   
458   if ((operand_equal_p (arg0, TREE_OPERAND (cond, 0), 0)
459        && operand_equal_p (arg1, TREE_OPERAND (cond, 1), 0))
460       || (operand_equal_p (arg1, TREE_OPERAND (cond, 0), 0)
461           && operand_equal_p (arg0, TREE_OPERAND (cond, 1), 0)))
462     {
463       edge e;
464       tree arg;
465
466       /* For NE_EXPR, we want to build an assignment result = arg where
467          arg is the PHI argument associated with the true edge.  For
468          EQ_EXPR we want the PHI argument associated with the false edge.  */
469       e = (TREE_CODE (cond) == NE_EXPR ? true_edge : false_edge);
470
471       /* Unfortunately, E may not reach BB (it may instead have gone to
472          OTHER_BLOCK).  If that is the case, then we want the single outgoing
473          edge from OTHER_BLOCK which reaches BB and represents the desired
474          path from COND_BLOCK.  */
475       if (e->dest == other_block)
476         e = EDGE_SUCC (e->dest, 0);
477
478       /* Now we know the incoming edge to BB that has the argument for the
479          RHS of our new assignment statement.  */
480       if (PHI_ARG_EDGE (phi, 0) == e)
481         arg = arg0;
482       else
483         arg = arg1;
484
485       /* Build the new assignment.  */
486       new = build (MODIFY_EXPR, TREE_TYPE (result), result, arg);
487
488       replace_phi_with_stmt (bsi_after_labels (bb), bb, cond_block, phi, new);
489
490       /* Note that we optimized this PHI.  */
491       return true;
492     }
493   return false;
494 }
495
496 /*  The function absolute_replacement does the main work of doing the absolute
497     replacement.  Return true if the replacement is done.  Otherwise return
498     false.
499     bb is the basic block where the replacement is going to be done on.  arg0
500     is argument 0 from the phi.  Likewise for arg1.  */
501 static bool
502 abs_replacement (basic_block bb, tree phi, tree arg0, tree arg1)
503 {
504   tree result;
505   basic_block other_block = NULL;
506   basic_block cond_block = NULL;
507   tree new, cond;
508   block_stmt_iterator bsi;
509   edge true_edge, false_edge;
510   tree assign = NULL;
511   edge e;
512   tree rhs = NULL, lhs = NULL;
513   bool negate;
514   enum tree_code cond_code;
515
516   /* If the type says honor signed zeros we cannot do this
517      optimization.  */
518   if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
519     return false;
520
521   if (!candidate_bb_for_phi_optimization (bb, &cond_block, &other_block))
522     return false;
523
524   /* OTHER_BLOCK must have only one executable statement which must have the
525      form arg0 = -arg1 or arg1 = -arg0.  */
526   bsi = bsi_start (other_block);
527   while (!bsi_end_p (bsi))
528     {
529       tree stmt = bsi_stmt (bsi);
530
531       /* Empty statements and labels are uninteresting.  */
532       if (TREE_CODE (stmt) == LABEL_EXPR
533           || IS_EMPTY_STMT (stmt))
534         {
535           bsi_next (&bsi);
536           continue;
537         }
538
539       /* If we found the assignment, but it was not the only executable
540          statement in OTHER_BLOCK, then we can not optimize.  */
541       if (assign)
542         return false;
543
544       /* If we got here, then we have found the first executable statement
545          in OTHER_BLOCK.  If it is anything other than arg = -arg1 or
546          arg1 = -arg0, then we can not optimize.  */
547       if (TREE_CODE (stmt) == MODIFY_EXPR)
548         {
549           lhs = TREE_OPERAND (stmt, 0);
550           rhs = TREE_OPERAND (stmt, 1);
551
552           if (TREE_CODE (rhs) == NEGATE_EXPR)
553             {
554               rhs = TREE_OPERAND (rhs, 0);
555
556               /* The assignment has to be arg0 = -arg1 or arg1 = -arg0.  */
557               if ((lhs == arg0 && rhs == arg1)
558                   || (lhs == arg1 && rhs == arg0))
559                 {
560                   assign = stmt;
561                   bsi_next (&bsi);
562                 }
563               else
564                 return false;
565             }
566           else
567             return false;
568         }
569       else
570         return false;
571     }
572
573   /* If we did not find the proper negation assignment, then we can not
574      optimize.  */
575   if (assign == NULL)
576     return false;
577
578   cond = COND_EXPR_COND (last_stmt (cond_block));
579   result = PHI_RESULT (phi);
580
581   /* Only relationals comparing arg[01] against zero are interesting.  */
582   cond_code = TREE_CODE (cond);
583   if (cond_code != GT_EXPR && cond_code != GE_EXPR
584       && cond_code != LT_EXPR && cond_code != LE_EXPR)
585     return false;
586
587   /* Make sure the conditional is arg[01] OP y.  */
588   if (TREE_OPERAND (cond, 0) != rhs)
589     return false;
590
591   if (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (cond, 1)))
592                ? real_zerop (TREE_OPERAND (cond, 1))
593                : integer_zerop (TREE_OPERAND (cond, 1)))
594     ;
595   else
596     return false;
597
598   /* We need to know which is the true edge and which is the false
599      edge so that we know if have abs or negative abs.  */
600   extract_true_false_edges_from_block (cond_block, &true_edge, &false_edge);
601
602   /* For GT_EXPR/GE_EXPR, if the true edge goes to OTHER_BLOCK, then we
603      will need to negate the result.  Similarly for LT_EXPR/LE_EXPR if
604      the false edge goes to OTHER_BLOCK.  */
605   if (cond_code == GT_EXPR || cond_code == GE_EXPR)
606     e = true_edge;
607   else
608     e = false_edge;
609   
610   if (e->dest == other_block)
611     negate = true;
612   else
613     negate = false;
614   
615   if (negate)
616     lhs = make_rename_temp (TREE_TYPE (result), NULL);
617   else
618     lhs = result;
619
620   /* Build the modify expression with abs expression.  */
621   new = build (MODIFY_EXPR, TREE_TYPE (lhs),
622                lhs, build1 (ABS_EXPR, TREE_TYPE (lhs), rhs));
623
624   replace_phi_with_stmt (bsi_after_labels (bb), bb, cond_block, phi, new);
625
626   if (negate)
627     {
628
629       /* Get the right BSI.  We want to insert after the recently 
630          added ABS_EXPR statement (which we know is the first statement
631          in the block.  */
632       bsi = bsi_start (bb);
633       bsi_next (&bsi);
634       new = build (MODIFY_EXPR, TREE_TYPE (result),
635                    result, build1 (NEGATE_EXPR, TREE_TYPE (lhs), lhs));
636
637       bsi_insert_after (&bsi, new, BSI_NEW_STMT);
638
639       /* Register the new statement as defining the temporary -- this is
640          normally done by replace_phi_with_stmt, but the link will be wrong
641          if we had to negate the resulting value.  */
642       SSA_NAME_DEF_STMT (result) = new;
643     }
644
645   /* Note that we optimized this PHI.  */
646   return true;
647 }
648
649
650 /* Always do these optimizations if we have SSA
651    trees to work on.  */                                                
652 static bool
653 gate_phiopt (void)
654 {
655   return 1;
656 }
657                                                                                                 
658 struct tree_opt_pass pass_phiopt =
659 {
660   "phiopt",                             /* name */
661   gate_phiopt,                          /* gate */
662   tree_ssa_phiopt,                      /* execute */
663   NULL,                                 /* sub */
664   NULL,                                 /* next */
665   0,                                    /* static_pass_number */
666   TV_TREE_PHIOPT,                       /* tv_id */
667   PROP_cfg | PROP_ssa | PROP_alias,     /* properties_required */
668   0,                                    /* properties_provided */
669   0,                                    /* properties_destroyed */
670   0,                                    /* todo_flags_start */
671   TODO_dump_func | TODO_ggc_collect     /* todo_flags_finish */
672     | TODO_verify_ssa | TODO_rename_vars
673     | TODO_verify_flow,
674   0                                     /* letter */
675 };
676                                                                                                 
677