OSDN Git Service

* config/sparc/sparc.md (save_register_windowdi): Add missing mode.
[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
142 /* Return TRUE if block BB has no executable statements, otherwise return
143    FALSE.  */
144 bool
145 empty_block_p (basic_block bb)
146 {
147   block_stmt_iterator bsi;
148
149   /* BB must have no executable statements.  */
150   bsi = bsi_start (bb);
151   while (!bsi_end_p (bsi)
152           && (TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR
153               || IS_EMPTY_STMT (bsi_stmt (bsi))))
154     bsi_next (&bsi);
155   
156   if (!bsi_end_p (bsi))
157     return false;
158
159   return true;
160 }
161
162 /* BB is a basic block which has only one PHI node with precisely two
163    arguments.
164
165    Examine both of BB's predecessors to see if one ends with a 
166    COND_EXPR and the other is a successor of the COND_EXPR.  If so, then
167    we may be able to optimize PHI nodes at the start of BB. 
168
169    If so, mark store the block with the COND_EXPR into COND_BLOCK_P
170    and the other block into OTHER_BLOCK_P and return true, otherwise
171    return false.  */
172
173 static bool
174 candidate_bb_for_phi_optimization (basic_block bb,
175                                    basic_block *cond_block_p,
176                                    basic_block *other_block_p)
177 {
178   tree last0, last1;
179   basic_block cond_block, other_block;
180
181   /* One of the alternatives must come from a block ending with
182      a COND_EXPR.  */
183   last0 = last_stmt (EDGE_PRED (bb, 0)->src);
184   last1 = last_stmt (EDGE_PRED (bb, 1)->src);
185   if (last0 && TREE_CODE (last0) == COND_EXPR)
186     {
187       cond_block = EDGE_PRED (bb, 0)->src;
188       other_block = EDGE_PRED (bb, 1)->src;
189     }
190   else if (last1 && TREE_CODE (last1) == COND_EXPR)
191     {
192       other_block = EDGE_PRED (bb, 0)->src;
193       cond_block = EDGE_PRED (bb, 1)->src;
194     }
195   else
196     return false;
197   
198   /* COND_BLOCK must have precisely two successors.  We indirectly
199      verify that those successors are BB and OTHER_BLOCK.  */
200   if (EDGE_COUNT (cond_block->succs) != 2
201       || (EDGE_SUCC (cond_block, 0)->flags & EDGE_ABNORMAL) != 0
202       || (EDGE_SUCC (cond_block, 1)->flags & EDGE_ABNORMAL) != 0)
203     return false;
204   
205   /* OTHER_BLOCK must have a single predecessor which is COND_BLOCK,
206      OTHER_BLOCK must have a single successor which is BB and
207      OTHER_BLOCK must have no PHI nodes.  */
208   if (EDGE_COUNT (other_block->preds) != 1
209       || EDGE_PRED (other_block, 0)->src != cond_block
210       || EDGE_COUNT (other_block->succs) != 1
211       || EDGE_SUCC (other_block, 0)->dest != bb
212       || phi_nodes (other_block))
213     return false;
214   
215   *cond_block_p = cond_block;
216   *other_block_p = other_block;
217   /* Everything looks OK.  */
218   return true;
219 }
220
221 /* Replace PHI in block BB with statement NEW.  NEW is inserted after
222    BSI.  Remove the edge from COND_BLOCK which does not lead to BB (COND_BLOCK
223    is known to have two edges, one of which must reach BB).  */
224
225 static void
226 replace_phi_with_stmt (block_stmt_iterator bsi, basic_block bb,
227                        basic_block cond_block, tree phi, tree new)
228 {
229   basic_block block_to_remove;
230
231   /* Insert our new statement at the head of our block.  */
232   bsi_insert_after (&bsi, new, BSI_NEW_STMT);
233   
234   /* Register our new statement as the defining statement for
235      the result.  */
236   SSA_NAME_DEF_STMT (PHI_RESULT (phi)) = new;
237   
238   /* Remove the now useless PHI node. 
239   
240      We do not want to use remove_phi_node since that releases the
241      SSA_NAME as well and the SSA_NAME is still being used.  */
242   release_phi_node (phi);
243   bb_ann (bb)->phi_nodes = NULL;
244   
245   /* Remove the empty basic block.  */
246   if (EDGE_SUCC (cond_block, 0)->dest == bb)
247     {
248       EDGE_SUCC (cond_block, 0)->flags |= EDGE_FALLTHRU;
249       EDGE_SUCC (cond_block, 0)->flags &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
250
251       block_to_remove = EDGE_SUCC (cond_block, 1)->dest;
252     }
253   else
254     {
255       EDGE_SUCC (cond_block, 1)->flags |= EDGE_FALLTHRU;
256       EDGE_SUCC (cond_block, 1)->flags
257         &= ~(EDGE_TRUE_VALUE | EDGE_FALSE_VALUE);
258
259       block_to_remove = EDGE_SUCC (cond_block, 0)->dest;
260     }
261   delete_basic_block (block_to_remove);
262   
263   /* Eliminate the COND_EXPR at the end of COND_BLOCK.  */
264   bsi = bsi_last (cond_block);
265   bsi_remove (&bsi);
266   
267   if (dump_file && (dump_flags & TDF_DETAILS))
268     fprintf (dump_file,
269               "COND_EXPR in block %d and PHI in block %d converted to straightline code.\n",
270               cond_block->index,
271               bb->index);
272 }
273
274 /*  The function conditional_replacement does the main work of doing the
275     conditional replacement.  Return true if the replacement is done.
276     Otherwise return false.
277     BB is the basic block where the replacement is going to be done on.  ARG0
278     is argument 0 from PHI.  Likewise for ARG1.  */
279
280 static bool
281 conditional_replacement (basic_block bb, tree phi, tree arg0, tree arg1)
282 {
283   tree result;
284   tree old_result = NULL;
285   basic_block other_block = NULL;
286   basic_block cond_block = NULL;
287   tree new, cond;
288   block_stmt_iterator bsi;
289   edge true_edge, false_edge;
290   tree new_var = NULL;
291
292   /* The PHI arguments have the constants 0 and 1, then convert
293      it to the conditional.  */
294   if ((integer_zerop (arg0) && integer_onep (arg1))
295       || (integer_zerop (arg1) && integer_onep (arg0)))
296     ;
297   else
298     return false;
299   
300   if (!candidate_bb_for_phi_optimization (bb, &cond_block, &other_block)
301       || !empty_block_p (other_block))
302     return false;
303                                                                                 
304   /* If the condition is not a naked SSA_NAME and its type does not
305      match the type of the result, then we have to create a new
306      variable to optimize this case as it would likely create
307      non-gimple code when the condition was converted to the
308      result's type.  */
309   cond = COND_EXPR_COND (last_stmt (cond_block));
310   result = PHI_RESULT (phi);
311   if (TREE_CODE (cond) != SSA_NAME
312       && !lang_hooks.types_compatible_p (TREE_TYPE (cond), TREE_TYPE (result)))
313     {
314       new_var = make_rename_temp (TREE_TYPE (cond), NULL);
315       old_result = cond;
316       cond = new_var;
317     }
318   
319   /* If the condition was a naked SSA_NAME and the type is not the
320      same as the type of the result, then convert the type of the
321      condition.  */
322   if (!lang_hooks.types_compatible_p (TREE_TYPE (cond), TREE_TYPE (result)))
323     cond = fold_convert (TREE_TYPE (result), cond);
324   
325   /* We need to know which is the true edge and which is the false
326      edge so that we know when to invert the condition below.  */
327   extract_true_false_edges_from_block (cond_block, &true_edge, &false_edge);
328       
329   /* Insert our new statement at the head of our block.  */
330   bsi = bsi_after_labels (bb);
331   
332   if (old_result)
333     {
334       tree new1;
335       if (!COMPARISON_CLASS_P (old_result))
336         return false;
337       
338       new1 = build (TREE_CODE (old_result), TREE_TYPE (old_result),
339                     TREE_OPERAND (old_result, 0),
340                     TREE_OPERAND (old_result, 1));
341       
342       new1 = build (MODIFY_EXPR, TREE_TYPE (old_result), new_var, new1);
343       bsi_insert_after (&bsi, new1, BSI_NEW_STMT);
344     }
345   
346   /* At this point we know we have a COND_EXPR with two successors.
347      One successor is BB, the other successor is an empty block which
348      falls through into BB.
349   
350      There is a single PHI node at the join point (BB) and its arguments
351      are constants (0, 1).
352   
353      So, given the condition COND, and the two PHI arguments, we can
354      rewrite this PHI into non-branching code: 
355   
356        dest = (COND) or dest = COND'
357   
358      We use the condition as-is if the argument associated with the
359      true edge has the value one or the argument associated with the
360      false edge as the value zero.  Note that those conditions are not
361      the same since only one of the outgoing edges from the COND_EXPR
362      will directly reach BB and thus be associated with an argument.  */
363   if ((PHI_ARG_EDGE (phi, 0) == true_edge && integer_onep (arg0))
364       || (PHI_ARG_EDGE (phi, 0) == false_edge && integer_zerop (arg0))
365       || (PHI_ARG_EDGE (phi, 1) == true_edge && integer_onep (arg1))
366       || (PHI_ARG_EDGE (phi, 1) == false_edge && integer_zerop (arg1)))
367     {
368       new = build (MODIFY_EXPR, TREE_TYPE (PHI_RESULT (phi)),
369                     PHI_RESULT (phi), cond);
370     }
371   else
372     {
373       tree cond1 = invert_truthvalue (cond);
374       
375       cond = cond1;
376       /* If what we get back is a conditional expression, there is no
377           way that it can be gimple.  */
378       if (TREE_CODE (cond) == COND_EXPR)
379         return false; 
380
381       /* If what we get back is not gimple try to create it as gimple by
382          using a temporary variable.  */
383       if (is_gimple_cast (cond)
384           && !is_gimple_val (TREE_OPERAND (cond, 0)))
385         {
386           tree temp = TREE_OPERAND (cond, 0);
387           tree new_var_1 = make_rename_temp (TREE_TYPE (temp), NULL);
388           new = build (MODIFY_EXPR, TREE_TYPE (new_var_1), new_var_1, temp);
389           bsi_insert_after (&bsi, new, BSI_NEW_STMT);
390           cond = fold_convert (TREE_TYPE (result), new_var_1);
391         }
392       
393       if (TREE_CODE (cond) == TRUTH_NOT_EXPR
394           &&  !is_gimple_val (TREE_OPERAND (cond, 0)))
395         return false;
396
397       new = build (MODIFY_EXPR, TREE_TYPE (PHI_RESULT (phi)),
398                     PHI_RESULT (phi), cond);
399     }
400   
401   replace_phi_with_stmt (bsi, bb, cond_block, phi, new);
402
403   /* Note that we optimized this PHI.  */
404   return true;
405 }
406
407 /*  The function value_replacement does the main work of doing the value
408     replacement.  Return true if the replacement is done.  Otherwise return
409     false.
410     BB is the basic block where the replacement is going to be done on.  ARG0
411     is argument 0 from the PHI.  Likewise for ARG1.  */
412
413 static bool
414 value_replacement (basic_block bb, tree phi, tree arg0, tree arg1)
415 {
416   tree result;
417   basic_block other_block = NULL;
418   basic_block cond_block = NULL;
419   tree new, cond;
420   edge true_edge, false_edge;
421
422   /* If the type says honor signed zeros we cannot do this
423      optimization.  */
424   if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
425     return false;
426
427   if (!candidate_bb_for_phi_optimization (bb, &cond_block, &other_block)
428       || !empty_block_p (other_block))
429     return false;
430
431   cond = COND_EXPR_COND (last_stmt (cond_block));
432   result = PHI_RESULT (phi);
433
434   /* This transformation is only valid for equality comparisons.  */
435   if (TREE_CODE (cond) != NE_EXPR && TREE_CODE (cond) != EQ_EXPR)
436     return false;
437
438   /* We need to know which is the true edge and which is the false
439       edge so that we know if have abs or negative abs.  */
440   extract_true_false_edges_from_block (cond_block, &true_edge, &false_edge);
441
442   /* At this point we know we have a COND_EXPR with two successors.
443      One successor is BB, the other successor is an empty block which
444      falls through into BB.
445
446      The condition for the COND_EXPR is known to be NE_EXPR or EQ_EXPR.
447
448      There is a single PHI node at the join point (BB) with two arguments.
449
450      We now need to verify that the two arguments in the PHI node match
451      the two arguments to the equality comparison.  */
452   
453   if ((operand_equal_for_phi_arg_p (arg0, TREE_OPERAND (cond, 0))
454        && operand_equal_for_phi_arg_p (arg1, TREE_OPERAND (cond, 1)))
455       || (operand_equal_for_phi_arg_p (arg1, TREE_OPERAND (cond, 0))
456           && operand_equal_for_phi_arg_p (arg0, TREE_OPERAND (cond, 1))))
457     {
458       edge e;
459       tree arg;
460
461       /* For NE_EXPR, we want to build an assignment result = arg where
462          arg is the PHI argument associated with the true edge.  For
463          EQ_EXPR we want the PHI argument associated with the false edge.  */
464       e = (TREE_CODE (cond) == NE_EXPR ? true_edge : false_edge);
465
466       /* Unfortunately, E may not reach BB (it may instead have gone to
467          OTHER_BLOCK).  If that is the case, then we want the single outgoing
468          edge from OTHER_BLOCK which reaches BB and represents the desired
469          path from COND_BLOCK.  */
470       if (e->dest == other_block)
471         e = EDGE_SUCC (e->dest, 0);
472
473       /* Now we know the incoming edge to BB that has the argument for the
474          RHS of our new assignment statement.  */
475       if (PHI_ARG_EDGE (phi, 0) == e)
476         arg = arg0;
477       else
478         arg = arg1;
479
480       /* Build the new assignment.  */
481       new = build (MODIFY_EXPR, TREE_TYPE (result), result, arg);
482
483       replace_phi_with_stmt (bsi_after_labels (bb), bb, cond_block, phi, new);
484
485       /* Note that we optimized this PHI.  */
486       return true;
487     }
488   return false;
489 }
490
491 /*  The function absolute_replacement does the main work of doing the absolute
492     replacement.  Return true if the replacement is done.  Otherwise return
493     false.
494     bb is the basic block where the replacement is going to be done on.  arg0
495     is argument 0 from the phi.  Likewise for arg1.  */
496 static bool
497 abs_replacement (basic_block bb, tree phi, tree arg0, tree arg1)
498 {
499   tree result;
500   basic_block other_block = NULL;
501   basic_block cond_block = NULL;
502   tree new, cond;
503   block_stmt_iterator bsi;
504   edge true_edge, false_edge;
505   tree assign = NULL;
506   edge e;
507   tree rhs = NULL, lhs = NULL;
508   bool negate;
509   enum tree_code cond_code;
510
511   /* If the type says honor signed zeros we cannot do this
512      optimization.  */
513   if (HONOR_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (arg1))))
514     return false;
515
516   if (!candidate_bb_for_phi_optimization (bb, &cond_block, &other_block))
517     return false;
518
519   /* OTHER_BLOCK must have only one executable statement which must have the
520      form arg0 = -arg1 or arg1 = -arg0.  */
521   bsi = bsi_start (other_block);
522   while (!bsi_end_p (bsi))
523     {
524       tree stmt = bsi_stmt (bsi);
525
526       /* Empty statements and labels are uninteresting.  */
527       if (TREE_CODE (stmt) == LABEL_EXPR
528           || IS_EMPTY_STMT (stmt))
529         {
530           bsi_next (&bsi);
531           continue;
532         }
533
534       /* If we found the assignment, but it was not the only executable
535          statement in OTHER_BLOCK, then we can not optimize.  */
536       if (assign)
537         return false;
538
539       /* If we got here, then we have found the first executable statement
540          in OTHER_BLOCK.  If it is anything other than arg = -arg1 or
541          arg1 = -arg0, then we can not optimize.  */
542       if (TREE_CODE (stmt) == MODIFY_EXPR)
543         {
544           lhs = TREE_OPERAND (stmt, 0);
545           rhs = TREE_OPERAND (stmt, 1);
546
547           if (TREE_CODE (rhs) == NEGATE_EXPR)
548             {
549               rhs = TREE_OPERAND (rhs, 0);
550
551               /* The assignment has to be arg0 = -arg1 or arg1 = -arg0.  */
552               if ((lhs == arg0 && rhs == arg1)
553                   || (lhs == arg1 && rhs == arg0))
554                 {
555                   assign = stmt;
556                   bsi_next (&bsi);
557                 }
558               else
559                 return false;
560             }
561           else
562             return false;
563         }
564       else
565         return false;
566     }
567
568   /* If we did not find the proper negation assignment, then we can not
569      optimize.  */
570   if (assign == NULL)
571     return false;
572
573   cond = COND_EXPR_COND (last_stmt (cond_block));
574   result = PHI_RESULT (phi);
575
576   /* Only relationals comparing arg[01] against zero are interesting.  */
577   cond_code = TREE_CODE (cond);
578   if (cond_code != GT_EXPR && cond_code != GE_EXPR
579       && cond_code != LT_EXPR && cond_code != LE_EXPR)
580     return false;
581
582   /* Make sure the conditional is arg[01] OP y.  */
583   if (TREE_OPERAND (cond, 0) != rhs)
584     return false;
585
586   if (FLOAT_TYPE_P (TREE_TYPE (TREE_OPERAND (cond, 1)))
587                ? real_zerop (TREE_OPERAND (cond, 1))
588                : integer_zerop (TREE_OPERAND (cond, 1)))
589     ;
590   else
591     return false;
592
593   /* We need to know which is the true edge and which is the false
594      edge so that we know if have abs or negative abs.  */
595   extract_true_false_edges_from_block (cond_block, &true_edge, &false_edge);
596
597   /* For GT_EXPR/GE_EXPR, if the true edge goes to OTHER_BLOCK, then we
598      will need to negate the result.  Similarly for LT_EXPR/LE_EXPR if
599      the false edge goes to OTHER_BLOCK.  */
600   if (cond_code == GT_EXPR || cond_code == GE_EXPR)
601     e = true_edge;
602   else
603     e = false_edge;
604   
605   if (e->dest == other_block)
606     negate = true;
607   else
608     negate = false;
609   
610   if (negate)
611     lhs = make_rename_temp (TREE_TYPE (result), NULL);
612   else
613     lhs = result;
614
615   /* Build the modify expression with abs expression.  */
616   new = build (MODIFY_EXPR, TREE_TYPE (lhs),
617                lhs, build1 (ABS_EXPR, TREE_TYPE (lhs), rhs));
618
619   replace_phi_with_stmt (bsi_after_labels (bb), bb, cond_block, phi, new);
620
621   if (negate)
622     {
623
624       /* Get the right BSI.  We want to insert after the recently 
625          added ABS_EXPR statement (which we know is the first statement
626          in the block.  */
627       bsi = bsi_start (bb);
628       bsi_next (&bsi);
629       new = build (MODIFY_EXPR, TREE_TYPE (result),
630                    result, build1 (NEGATE_EXPR, TREE_TYPE (lhs), lhs));
631
632       bsi_insert_after (&bsi, new, BSI_NEW_STMT);
633
634       /* Register the new statement as defining the temporary -- this is
635          normally done by replace_phi_with_stmt, but the link will be wrong
636          if we had to negate the resulting value.  */
637       SSA_NAME_DEF_STMT (result) = new;
638     }
639
640   /* Note that we optimized this PHI.  */
641   return true;
642 }
643
644
645 /* Always do these optimizations if we have SSA
646    trees to work on.  */                                                
647 static bool
648 gate_phiopt (void)
649 {
650   return 1;
651 }
652                                                                                                 
653 struct tree_opt_pass pass_phiopt =
654 {
655   "phiopt",                             /* name */
656   gate_phiopt,                          /* gate */
657   tree_ssa_phiopt,                      /* execute */
658   NULL,                                 /* sub */
659   NULL,                                 /* next */
660   0,                                    /* static_pass_number */
661   TV_TREE_PHIOPT,                       /* tv_id */
662   PROP_cfg | PROP_ssa | PROP_alias,     /* properties_required */
663   0,                                    /* properties_provided */
664   0,                                    /* properties_destroyed */
665   0,                                    /* todo_flags_start */
666   TODO_cleanup_cfg | TODO_dump_func | TODO_ggc_collect  /* todo_flags_finish */
667     | TODO_verify_ssa | TODO_rename_vars
668     | TODO_verify_flow,
669   0                                     /* letter */
670 };
671                                                                                                 
672