tree-if-conv.c

Go to the documentation of this file.
00001 /* If-conversion for vectorizer.
00002    Copyright (C) 2004, 2005 Free Software Foundation, Inc.
00003    Contributed by Devang Patel <dpatel@apple.com>
00004 
00005 This file is part of GCC.
00006 
00007 GCC is free software; you can redistribute it and/or modify it under
00008 the terms of the GNU General Public License as published by the Free
00009 Software Foundation; either version 2, or (at your option) any later
00010 version.
00011 
00012 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
00013 WARRANTY; without even the implied warranty of MERCHANTABILITY or
00014 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00015 for more details.
00016 
00017 You should have received a copy of the GNU General Public License
00018 along with GCC; see the file COPYING.  If not, write to the Free
00019 Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
00020 02110-1301, USA.  */
00021 
00022 /* This pass implements tree level if-conversion transformation of loops.
00023    Initial goal is to help vectorizer vectorize loops with conditions.
00024 
00025    A short description of if-conversion:
00026 
00027      o Decide if a loop is if-convertible or not.
00028      o Walk all loop basic blocks in breadth first order (BFS order).
00029        o Remove conditional statements (at the end of basic block)
00030          and propagate condition into destination basic blocks'
00031          predicate list.
00032        o Replace modify expression with conditional modify expression
00033          using current basic block's condition.
00034      o Merge all basic blocks
00035        o Replace phi nodes with conditional modify expr
00036        o Merge all basic blocks into header
00037 
00038      Sample transformation:
00039 
00040      INPUT
00041      -----
00042 
00043      # i_23 = PHI <0(0), i_18(10)>;
00044      <L0>:;
00045      j_15 = A[i_23];
00046      if (j_15 > 41) goto <L1>; else goto <L17>;
00047 
00048      <L17>:;
00049      goto <bb 3> (<L3>);
00050 
00051      <L1>:;
00052 
00053      # iftmp.2_4 = PHI <0(8), 42(2)>;
00054      <L3>:;
00055      A[i_23] = iftmp.2_4;
00056      i_18 = i_23 + 1;
00057      if (i_18 <= 15) goto <L19>; else goto <L18>;
00058 
00059      <L19>:;
00060      goto <bb 1> (<L0>);
00061 
00062      <L18>:;
00063 
00064      OUTPUT
00065      ------
00066 
00067      # i_23 = PHI <0(0), i_18(10)>;
00068      <L0>:;
00069      j_15 = A[i_23];
00070 
00071      <L3>:;
00072      iftmp.2_4 = j_15 > 41 ? 42 : 0;
00073      A[i_23] = iftmp.2_4;
00074      i_18 = i_23 + 1;
00075      if (i_18 <= 15) goto <L19>; else goto <L18>;
00076 
00077      <L19>:;
00078      goto <bb 1> (<L0>);
00079 
00080      <L18>:;
00081 */
00082 
00083 #include "config.h"
00084 #include "system.h"
00085 #include "coretypes.h"
00086 #include "tm.h"
00087 #include "tree.h"
00088 #include "c-common.h"
00089 #include "flags.h"
00090 #include "timevar.h"
00091 #include "varray.h"
00092 #include "rtl.h"
00093 #include "basic-block.h"
00094 #include "diagnostic.h"
00095 #include "tree-flow.h"
00096 #include "tree-dump.h"
00097 #include "cfgloop.h"
00098 #include "tree-chrec.h"
00099 #include "tree-data-ref.h"
00100 #include "tree-scalar-evolution.h"
00101 #include "tree-pass.h"
00102 #include "target.h"
00103 
00104 /* local function prototypes */
00105 static unsigned int main_tree_if_conversion (void);
00106 static tree tree_if_convert_stmt (struct loop *loop, tree, tree,
00107                                   block_stmt_iterator *);
00108 static void tree_if_convert_cond_expr (struct loop *, tree, tree,
00109                                        block_stmt_iterator *);
00110 static bool if_convertible_phi_p (struct loop *, basic_block, tree);
00111 static bool if_convertible_modify_expr_p (struct loop *, basic_block, tree);
00112 static bool if_convertible_stmt_p (struct loop *, basic_block, tree);
00113 static bool if_convertible_bb_p (struct loop *, basic_block, basic_block);
00114 static bool if_convertible_loop_p (struct loop *, bool);
00115 static void add_to_predicate_list (basic_block, tree);
00116 static tree add_to_dst_predicate_list (struct loop * loop, basic_block, tree, tree,
00117                                        block_stmt_iterator *);
00118 static void clean_predicate_lists (struct loop *loop);
00119 static basic_block find_phi_replacement_condition (struct loop *loop,
00120                                                    basic_block, tree *,
00121                                                    block_stmt_iterator *);
00122 static void replace_phi_with_cond_modify_expr (tree, tree, basic_block,
00123                                                block_stmt_iterator *);
00124 static void process_phi_nodes (struct loop *);
00125 static void combine_blocks (struct loop *);
00126 static tree ifc_temp_var (tree, tree);
00127 static bool pred_blocks_visited_p (basic_block, bitmap *);
00128 static basic_block * get_loop_body_in_if_conv_order (const struct loop *loop);
00129 static bool bb_with_exit_edge_p (struct loop *, basic_block);
00130 
00131 /* List of basic blocks in if-conversion-suitable order.  */
00132 static basic_block *ifc_bbs;
00133 
00134 /* Main entry point.
00135    Apply if-conversion to the LOOP. Return true if successful otherwise return
00136    false. If false is returned then loop remains unchanged.
00137    FOR_VECTORIZER is a boolean flag. It indicates whether if-conversion is used
00138    for vectorizer or not. If it is used for vectorizer, additional checks are
00139    used. (Vectorization checks are not yet implemented).  */
00140 
00141 static bool
00142 tree_if_conversion (struct loop *loop, bool for_vectorizer)
00143 {
00144   basic_block bb;
00145   block_stmt_iterator itr;
00146   tree cond;
00147   unsigned int i;
00148 
00149   ifc_bbs = NULL;
00150 
00151   /* if-conversion is not appropriate for all loops. First, check if loop  is
00152      if-convertible or not.  */
00153   if (!if_convertible_loop_p (loop, for_vectorizer))
00154     {
00155       if (dump_file && (dump_flags & TDF_DETAILS))
00156         fprintf (dump_file,"-------------------------\n");
00157       if (ifc_bbs)
00158         {
00159           free (ifc_bbs);
00160           ifc_bbs = NULL;
00161         }
00162       free_dominance_info (CDI_POST_DOMINATORS);
00163       return false;
00164     }
00165 
00166   cond = NULL_TREE;
00167 
00168   /* Do actual work now.  */
00169   for (i = 0; i < loop->num_nodes; i++)
00170     {
00171       bb = ifc_bbs [i];
00172 
00173       /* Update condition using predicate list.  */
00174       cond = bb->aux;
00175 
00176       /* Process all statements in this basic block.
00177          Remove conditional expression, if any, and annotate
00178          destination basic block(s) appropriately.  */
00179       for (itr = bsi_start (bb); !bsi_end_p (itr); /* empty */)
00180         {
00181           tree t = bsi_stmt (itr);
00182           cond = tree_if_convert_stmt (loop, t, cond, &itr);
00183           if (!bsi_end_p (itr))
00184             bsi_next (&itr);
00185         }
00186 
00187       /* If current bb has only one successor, then consider it as an
00188          unconditional goto.  */
00189       if (single_succ_p (bb))
00190         {
00191           basic_block bb_n = single_succ (bb);
00192           if (cond != NULL_TREE)
00193             add_to_predicate_list (bb_n, cond);
00194           cond = NULL_TREE;
00195         }
00196     }
00197 
00198   /* Now, all statements are if-converted and basic blocks are
00199      annotated appropriately. Combine all basic block into one huge
00200      basic block.  */
00201   combine_blocks (loop);
00202 
00203   /* clean up */
00204   clean_predicate_lists (loop);
00205   free (ifc_bbs);
00206   ifc_bbs = NULL;
00207 
00208   return true;
00209 }
00210 
00211 /* if-convert stmt T which is part of LOOP.
00212    If T is a MODIFY_EXPR than it is converted into conditional modify
00213    expression using COND.  For conditional expressions, add condition in the
00214    destination basic block's predicate list and remove conditional
00215    expression itself. BSI is the iterator used to traverse statements of
00216    loop. It is used here when it is required to delete current statement.  */
00217 
00218 static tree
00219 tree_if_convert_stmt (struct loop *  loop, tree t, tree cond,
00220                       block_stmt_iterator *bsi)
00221 {
00222   if (dump_file && (dump_flags & TDF_DETAILS))
00223     {
00224       fprintf (dump_file, "------if-convert stmt\n");
00225       print_generic_stmt (dump_file, t, TDF_SLIM);
00226       print_generic_stmt (dump_file, cond, TDF_SLIM);
00227     }
00228 
00229   switch (TREE_CODE (t))
00230     {
00231       /* Labels are harmless here.  */
00232     case LABEL_EXPR:
00233       break;
00234 
00235     case MODIFY_EXPR:
00236       /* This modify_expr is killing previous value of LHS. Appropriate value will
00237          be selected by PHI node based on condition. It is possible that before
00238          this transformation, PHI nodes was selecting default value and now it will
00239          use this new value. This is OK because it does not change validity the
00240          program.  */
00241       break;
00242 
00243     case COND_EXPR:
00244       /* Update destination blocks' predicate list and remove this
00245          condition expression.  */
00246       tree_if_convert_cond_expr (loop, t, cond, bsi);
00247       cond = NULL_TREE;
00248       break;
00249 
00250     default:
00251       gcc_unreachable ();
00252     }
00253   return cond;
00254 }
00255 
00256 /* STMT is COND_EXPR. Update two destination's predicate list.
00257    Remove COND_EXPR, if it is not the loop exit condition. Otherwise
00258    update loop exit condition appropriately.  BSI is the iterator
00259    used to traverse statement list. STMT is part of loop LOOP.  */
00260 
00261 static void
00262 tree_if_convert_cond_expr (struct loop *loop, tree stmt, tree cond,
00263                            block_stmt_iterator *bsi)
00264 {
00265   tree c, c2;
00266   edge true_edge, false_edge;
00267 
00268   gcc_assert (TREE_CODE (stmt) == COND_EXPR);
00269 
00270   c = COND_EXPR_COND (stmt);
00271 
00272   extract_true_false_edges_from_block (bb_for_stmt (stmt),
00273                                        &true_edge, &false_edge);
00274 
00275   /* Add new condition into destination's predicate list.  */
00276 
00277   /* If 'c' is true then TRUE_EDGE is taken.  */
00278   add_to_dst_predicate_list (loop, true_edge->dest, cond,
00279                              unshare_expr (c), bsi);
00280 
00281   /* If 'c' is false then FALSE_EDGE is taken.  */
00282   c2 = invert_truthvalue (unshare_expr (c));
00283   add_to_dst_predicate_list (loop, false_edge->dest, cond, c2, bsi);
00284 
00285   /* Now this conditional statement is redundant. Remove it.
00286      But, do not remove exit condition! Update exit condition
00287      using new condition.  */
00288   if (!bb_with_exit_edge_p (loop, bb_for_stmt (stmt)))
00289     {
00290       bsi_remove (bsi, true);
00291       cond = NULL_TREE;
00292     }
00293   return;
00294 }
00295 
00296 /* Return true, iff PHI is if-convertible. PHI is part of loop LOOP
00297    and it belongs to basic block BB.
00298    PHI is not if-convertible
00299    - if it has more than 2 arguments.
00300    - Virtual PHI is immediately used in another PHI node.  */
00301 
00302 static bool
00303 if_convertible_phi_p (struct loop *loop, basic_block bb, tree phi)
00304 {
00305   if (dump_file && (dump_flags & TDF_DETAILS))
00306     {
00307       fprintf (dump_file, "-------------------------\n");
00308       print_generic_stmt (dump_file, phi, TDF_SLIM);
00309     }
00310 
00311   if (bb != loop->header && PHI_NUM_ARGS (phi) != 2)
00312     {
00313       if (dump_file && (dump_flags & TDF_DETAILS))
00314         fprintf (dump_file, "More than two phi node args.\n");
00315       return false;
00316     }
00317 
00318   if (!is_gimple_reg (SSA_NAME_VAR (PHI_RESULT (phi))))
00319     {
00320       imm_use_iterator imm_iter;
00321       use_operand_p use_p;
00322       FOR_EACH_IMM_USE_FAST (use_p, imm_iter, PHI_RESULT (phi))
00323         {
00324           if (TREE_CODE (USE_STMT (use_p)) == PHI_NODE)
00325             {
00326               if (dump_file && (dump_flags & TDF_DETAILS))
00327                 fprintf (dump_file, "Difficult to handle this virtual phi.\n");
00328               return false;
00329             }
00330         }
00331     }
00332 
00333   return true;
00334 }
00335 
00336 /* Return true, if M_EXPR is if-convertible.
00337    MODIFY_EXPR is not if-convertible if,
00338    - It is not movable.
00339    - It could trap.
00340    - LHS is not var decl.
00341   MODIFY_EXPR is part of block BB, which is inside loop LOOP.
00342 */
00343 
00344 static bool
00345 if_convertible_modify_expr_p (struct loop *loop, basic_block bb, tree m_expr)
00346 {
00347   if (dump_file && (dump_flags & TDF_DETAILS))
00348     {
00349       fprintf (dump_file, "-------------------------\n");
00350       print_generic_stmt (dump_file, m_expr, TDF_SLIM);
00351     }
00352 
00353   /* Be conservative and do not handle immovable expressions.  */
00354   if (movement_possibility (m_expr) == MOVE_IMPOSSIBLE)
00355     {
00356       if (dump_file && (dump_flags & TDF_DETAILS))
00357         fprintf (dump_file, "stmt is movable. Don't take risk\n");
00358       return false;
00359     }
00360 
00361   /* See if it needs speculative loading or not.  */
00362   if (bb != loop->header
00363       && tree_could_trap_p (TREE_OPERAND (m_expr, 1)))
00364     {
00365       if (dump_file && (dump_flags & TDF_DETAILS))
00366         fprintf (dump_file, "tree could trap...\n");
00367       return false;
00368     }
00369 
00370   if (TREE_CODE (TREE_OPERAND (m_expr, 1)) == CALL_EXPR)
00371     {
00372       if (dump_file && (dump_flags & TDF_DETAILS))
00373         fprintf (dump_file, "CALL_EXPR \n");
00374       return false;
00375     }
00376 
00377   if (TREE_CODE (TREE_OPERAND (m_expr, 0)) != SSA_NAME
00378       && bb != loop->header
00379       && !bb_with_exit_edge_p (loop, bb))
00380     {
00381       if (dump_file && (dump_flags & TDF_DETAILS))
00382         {
00383           fprintf (dump_file, "LHS is not var\n");
00384           print_generic_stmt (dump_file, m_expr, TDF_SLIM);
00385         }
00386       return false;
00387     }
00388 
00389 
00390   return true;
00391 }
00392 
00393 /* Return true, iff STMT is if-convertible.
00394    Statement is if-convertible if,
00395    - It is if-convertible MODIFY_EXPR
00396    - IT is LABEL_EXPR or COND_EXPR.
00397    STMT is inside block BB, which is inside loop LOOP.  */
00398 
00399 static bool
00400 if_convertible_stmt_p (struct loop *loop, basic_block bb, tree stmt)
00401 {
00402   switch (TREE_CODE (stmt))
00403     {
00404     case LABEL_EXPR:
00405       break;
00406 
00407     case MODIFY_EXPR:
00408 
00409       if (!if_convertible_modify_expr_p (loop, bb, stmt))
00410         return false;
00411       break;
00412 
00413     case COND_EXPR:
00414       break;
00415 
00416     default:
00417       /* Don't know what to do with 'em so don't do anything.  */
00418       if (dump_file && (dump_flags & TDF_DETAILS))
00419         {
00420           fprintf (dump_file, "don't know what to do\n");
00421           print_generic_stmt (dump_file, stmt, TDF_SLIM);
00422         }
00423       return false;
00424       break;
00425     }
00426 
00427   return true;
00428 }
00429 
00430 /* Return true, iff BB is if-convertible.
00431    Note: This routine does _not_ check basic block statements and phis.
00432    Basic block is not if-convertible if,
00433    - Basic block is non-empty and it is after exit block (in BFS order).
00434    - Basic block is after exit block but before latch.
00435    - Basic block edge(s) is not normal.
00436    EXIT_BB_SEEN is true if basic block with exit edge is already seen.
00437    BB is inside loop LOOP.  */
00438 
00439 static bool
00440 if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb)
00441 {
00442   edge e;
00443   edge_iterator ei;
00444 
00445   if (dump_file && (dump_flags & TDF_DETAILS))
00446     fprintf (dump_file, "----------[%d]-------------\n", bb->index);
00447 
00448   if (exit_bb)
00449     {
00450       if (bb != loop->latch)
00451         {
00452           if (dump_file && (dump_flags & TDF_DETAILS))
00453             fprintf (dump_file, "basic block after exit bb but before latch\n");
00454           return false;
00455         }
00456       else if (!empty_block_p (bb))
00457         {
00458           if (dump_file && (dump_flags & TDF_DETAILS))
00459             fprintf (dump_file, "non empty basic block after exit bb\n");
00460           return false;
00461         }
00462       else if (bb == loop->latch 
00463                && bb != exit_bb
00464                && !dominated_by_p (CDI_DOMINATORS, bb, exit_bb))
00465           {
00466             if (dump_file && (dump_flags & TDF_DETAILS))
00467               fprintf (dump_file, "latch is not dominated by exit_block\n");
00468             return false;
00469           }
00470     }
00471 
00472   /* Be less adventurous and handle only normal edges.  */
00473   FOR_EACH_EDGE (e, ei, bb->succs)
00474     if (e->flags &
00475         (EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_ABNORMAL | EDGE_IRREDUCIBLE_LOOP))
00476       {
00477         if (dump_file && (dump_flags & TDF_DETAILS))
00478           fprintf (dump_file,"Difficult to handle edges\n");
00479         return false;
00480       }
00481 
00482   return true;
00483 }
00484 
00485 /* Return true, iff LOOP is if-convertible.
00486    LOOP is if-convertible if,
00487    - It is innermost.
00488    - It has two or more basic blocks.
00489    - It has only one exit.
00490    - Loop header is not the exit edge.
00491    - If its basic blocks and phi nodes are if convertible. See above for
00492      more info.
00493    FOR_VECTORIZER enables vectorizer specific checks. For example, support
00494    for vector conditions, data dependency checks etc.. (Not implemented yet).  */
00495 
00496 static bool
00497 if_convertible_loop_p (struct loop *loop, bool for_vectorizer ATTRIBUTE_UNUSED)
00498 {
00499   tree phi;
00500   basic_block bb;
00501   block_stmt_iterator itr;
00502   unsigned int i;
00503   edge e;
00504   edge_iterator ei;
00505   basic_block exit_bb = NULL;
00506 
00507   /* Handle only inner most loop.  */
00508   if (!loop || loop->inner)
00509     {
00510       if (dump_file && (dump_flags & TDF_DETAILS))
00511         fprintf (dump_file, "not inner most loop\n");
00512       return false;
00513     }
00514 
00515   /* If only one block, no need for if-conversion.  */
00516   if (loop->num_nodes <= 2)
00517     {
00518       if (dump_file && (dump_flags & TDF_DETAILS))
00519         fprintf (dump_file, "less than 2 basic blocks\n");
00520       return false;
00521     }
00522 
00523   /* More than one loop exit is too much to handle.  */
00524   if (!loop->single_exit)
00525     {
00526       if (dump_file && (dump_flags & TDF_DETAILS))
00527         fprintf (dump_file, "multiple exits\n");
00528       return false;
00529     }
00530 
00531   /* ??? Check target's vector conditional operation support for vectorizer.  */
00532 
00533   /* If one of the loop header's edge is exit edge then do not apply
00534      if-conversion.  */
00535   FOR_EACH_EDGE (e, ei, loop->header->succs)
00536     {
00537       if (loop_exit_edge_p (loop, e))
00538         return false;
00539     }
00540 
00541   calculate_dominance_info (CDI_DOMINATORS);
00542   calculate_dominance_info (CDI_POST_DOMINATORS);
00543 
00544   /* Allow statements that can be handled during if-conversion.  */
00545   ifc_bbs = get_loop_body_in_if_conv_order (loop);
00546   if (!ifc_bbs)
00547     {
00548       if (dump_file && (dump_flags & TDF_DETAILS))
00549         fprintf (dump_file,"Irreducible loop\n");
00550       free_dominance_info (CDI_POST_DOMINATORS);
00551       return false;
00552     }
00553 
00554   for (i = 0; i < loop->num_nodes; i++)
00555     {
00556       bb = ifc_bbs[i];
00557 
00558       if (!if_convertible_bb_p (loop, bb, exit_bb))
00559         return false;
00560 
00561       /* Check statements.  */
00562       for (itr = bsi_start (bb); !bsi_end_p (itr); bsi_next (&itr))
00563         if (!if_convertible_stmt_p (loop, bb, bsi_stmt (itr)))
00564           return false;
00565       /* ??? Check data dependency for vectorizer.  */
00566 
00567       /* What about phi nodes ? */
00568       for (phi = phi_nodes (bb); phi; phi = PHI_CHAIN (phi))
00569         if (!if_convertible_phi_p (loop, bb, phi))
00570           return false;
00571 
00572       if (bb_with_exit_edge_p (loop, bb))
00573         exit_bb = bb;
00574     }
00575 
00576   /* OK. Did not find any potential issues so go ahead in if-convert
00577      this loop. Now there is no looking back.  */
00578   if (dump_file)
00579     fprintf (dump_file,"Applying if-conversion\n");
00580 
00581   free_dominance_info (CDI_POST_DOMINATORS);
00582   return true;
00583 }
00584 
00585 /* Add condition COND into predicate list of basic block BB.  */
00586 
00587 static void
00588 add_to_predicate_list (basic_block bb, tree new_cond)
00589 {
00590   tree cond = bb->aux;
00591 
00592   if (cond)
00593     cond = fold_build2 (TRUTH_OR_EXPR, boolean_type_node,
00594                         unshare_expr (cond), new_cond);
00595   else
00596     cond = new_cond;
00597 
00598   bb->aux = cond;
00599 }
00600 
00601 /* Add condition COND into BB's predicate list.  PREV_COND is
00602    existing condition.  */
00603 
00604 static tree
00605 add_to_dst_predicate_list (struct loop * loop, basic_block bb,
00606                            tree prev_cond, tree cond,
00607                            block_stmt_iterator *bsi)
00608 {
00609   tree new_cond = NULL_TREE;
00610 
00611   if (!flow_bb_inside_loop_p (loop, bb))
00612     return NULL_TREE;
00613 
00614   if (prev_cond == boolean_true_node || !prev_cond)
00615     new_cond = unshare_expr (cond);
00616   else
00617     {
00618       tree tmp;
00619       tree tmp_stmt = NULL_TREE;
00620       tree tmp_stmts1 = NULL_TREE;
00621       tree tmp_stmts2 = NULL_TREE;
00622       prev_cond = force_gimple_operand (unshare_expr (prev_cond),
00623                                         &tmp_stmts1, true, NULL);
00624       if (tmp_stmts1)
00625         bsi_insert_before (bsi, tmp_stmts1, BSI_SAME_STMT);
00626 
00627       cond = force_gimple_operand (unshare_expr (cond),
00628                                    &tmp_stmts2, true, NULL);
00629       if (tmp_stmts2)
00630         bsi_insert_before (bsi, tmp_stmts2, BSI_SAME_STMT);
00631 
00632       /* new_cond == prev_cond AND cond */
00633       tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
00634                     unshare_expr (prev_cond), cond);
00635       tmp_stmt = ifc_temp_var (boolean_type_node, tmp);
00636       bsi_insert_before (bsi, tmp_stmt, BSI_SAME_STMT);
00637       new_cond = TREE_OPERAND (tmp_stmt, 0);
00638     }
00639   add_to_predicate_list (bb, new_cond);
00640   return new_cond;
00641 }
00642 
00643 /* During if-conversion aux field from basic block is used to hold predicate
00644    list. Clean each basic block's predicate list for the given LOOP.  */
00645 
00646 static void
00647 clean_predicate_lists (struct loop *loop)
00648 {
00649   basic_block *bb;
00650   unsigned int i;
00651   bb = get_loop_body (loop);
00652   for (i = 0; i < loop->num_nodes; i++)
00653     bb[i]->aux = NULL;
00654 
00655   free (bb);
00656 }
00657 
00658 /* Basic block BB has two predecessors. Using predecessor's aux field, set
00659    appropriate condition COND for the PHI node replacement. Return true block
00660    whose phi arguments are selected when cond is true.  */
00661 
00662 static basic_block
00663 find_phi_replacement_condition (struct loop *loop, 
00664                                 basic_block bb, tree *cond,
00665                                 block_stmt_iterator *bsi)
00666 {
00667   basic_block first_bb = NULL;
00668   basic_block second_bb = NULL;
00669   tree tmp_cond, new_stmts;
00670 
00671   gcc_assert (EDGE_COUNT (bb->preds) == 2);
00672   first_bb = (EDGE_PRED (bb, 0))->src;
00673   second_bb = (EDGE_PRED (bb, 1))->src;
00674 
00675   /* Use condition based on following criteria:
00676      1)
00677        S1: x = !c ? a : b;
00678 
00679        S2: x = c ? b : a;
00680 
00681        S2 is preferred over S1. Make 'b' first_bb and use its condition.
00682        
00683      2) Do not make loop header first_bb.
00684 
00685      3)
00686        S1: x = !(c == d)? a : b;
00687 
00688        S21: t1 = c == d;
00689        S22: x = t1 ? b : a;
00690 
00691        S3: x = (c == d) ? b : a;
00692 
00693        S3 is preferred over S1 and S2*, Make 'b' first_bb and use 
00694        its condition.  
00695 
00696      4) If  pred B is dominated by pred A then use pred B's condition.
00697         See PR23115.  */
00698 
00699   /* Select condition that is not TRUTH_NOT_EXPR.  */
00700   tmp_cond = first_bb->aux;
00701   if (TREE_CODE (tmp_cond) == TRUTH_NOT_EXPR)
00702     {
00703       basic_block tmp_bb;
00704       tmp_bb = first_bb;
00705       first_bb = second_bb;
00706       second_bb = tmp_bb;
00707     }
00708 
00709   /* Check if FIRST_BB is loop header or not and make sure that
00710      FIRST_BB does not dominate SECOND_BB.  */
00711   if (first_bb == loop->header
00712       || dominated_by_p (CDI_DOMINATORS, second_bb, first_bb))
00713     {
00714       tmp_cond = second_bb->aux;
00715       if (TREE_CODE (tmp_cond) == TRUTH_NOT_EXPR)
00716         {
00717           /* Select non loop header condition but do not switch basic blocks.  */
00718           *cond = invert_truthvalue (unshare_expr (tmp_cond));
00719         }
00720       else
00721         {
00722           /* Select non loop header condition.  */
00723           first_bb = second_bb;
00724           *cond = first_bb->aux;
00725         }
00726     }
00727   else
00728     /* FIRST_BB is not loop header */
00729     *cond = first_bb->aux;
00730 
00731   /* Create temp. for the condition. Vectorizer prefers to have gimple
00732      value as condition. Various targets use different means to communicate
00733      condition in vector compare operation. Using gimple value allows compiler
00734      to emit vector compare and select RTL without exposing compare's result.  */
00735   *cond = force_gimple_operand (*cond, &new_stmts, false, NULL_TREE);
00736   if (new_stmts)
00737     bsi_insert_before (bsi, new_stmts, BSI_SAME_STMT);
00738   if (!is_gimple_reg (*cond) && !is_gimple_condexpr (*cond))
00739     {
00740       tree new_stmt;
00741 
00742       new_stmt = ifc_temp_var (TREE_TYPE (*cond), unshare_expr (*cond));
00743       bsi_insert_before (bsi, new_stmt, BSI_SAME_STMT);
00744       *cond = TREE_OPERAND (new_stmt, 0);
00745     }
00746 
00747   gcc_assert (*cond);
00748 
00749   return first_bb;
00750 }
00751 
00752 
00753 /* Replace PHI node with conditional modify expr using COND.
00754    This routine does not handle PHI nodes with more than two arguments.
00755    For example,
00756      S1: A = PHI <x1(1), x2(5)
00757    is converted into,
00758      S2: A = cond ? x1 : x2;
00759    S2 is inserted at the top of basic block's statement list.
00760    When COND is true, phi arg from TRUE_BB is selected.
00761 */
00762 
00763 static void
00764 replace_phi_with_cond_modify_expr (tree phi, tree cond, basic_block true_bb,
00765                                    block_stmt_iterator *bsi)
00766 {
00767   tree new_stmt;
00768   basic_block bb;
00769   tree rhs;
00770   tree arg_0, arg_1;
00771 
00772   gcc_assert (TREE_CODE (phi) == PHI_NODE);
00773   
00774   /* If this is not filtered earlier, then now it is too late.  */
00775   gcc_assert (PHI_NUM_ARGS (phi) == 2);
00776 
00777   /* Find basic block and initialize iterator.  */
00778   bb = bb_for_stmt (phi);
00779 
00780   new_stmt = NULL_TREE;
00781   arg_0 = NULL_TREE;
00782   arg_1 = NULL_TREE;
00783 
00784   /* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr.  */
00785   if (EDGE_PRED (bb, 1)->src == true_bb)
00786     {
00787       arg_0 = PHI_ARG_DEF (phi, 1);
00788       arg_1 = PHI_ARG_DEF (phi, 0);
00789     }
00790   else
00791     {
00792       arg_0 = PHI_ARG_DEF (phi, 0);
00793       arg_1 = PHI_ARG_DEF (phi, 1);
00794     }
00795 
00796   /* Build new RHS using selected condition and arguments.  */
00797   rhs = build3 (COND_EXPR, TREE_TYPE (PHI_RESULT (phi)),
00798                 unshare_expr (cond), unshare_expr (arg_0),
00799                 unshare_expr (arg_1));
00800 
00801   /* Create new MODIFY expression using RHS.  */
00802   new_stmt = build2 (MODIFY_EXPR, TREE_TYPE (PHI_RESULT (phi)),
00803                      unshare_expr (PHI_RESULT (phi)), rhs);
00804 
00805   /* Make new statement definition of the original phi result.  */
00806   SSA_NAME_DEF_STMT (PHI_RESULT (phi)) = new_stmt;
00807 
00808   /* Insert using iterator.  */
00809   bsi_insert_before (bsi, new_stmt, BSI_SAME_STMT);
00810   update_stmt (new_stmt);
00811 
00812   if (dump_file && (dump_flags & TDF_DETAILS))
00813     {
00814       fprintf (dump_file, "new phi replacement stmt\n");
00815       print_generic_stmt (dump_file, new_stmt, TDF_SLIM);
00816     }
00817 }
00818 
00819 /* Process phi nodes for the given  LOOP.  Replace phi nodes with cond
00820    modify expr.  */
00821 
00822 static void
00823 process_phi_nodes (struct loop *loop)
00824 {
00825   basic_block bb;
00826   unsigned int orig_loop_num_nodes = loop->num_nodes;
00827   unsigned int i;
00828 
00829   /* Replace phi nodes with cond. modify expr.  */
00830   for (i = 1; i < orig_loop_num_nodes; i++)
00831     {
00832       tree phi, cond;
00833       block_stmt_iterator bsi;
00834       basic_block true_bb = NULL;
00835       bb = ifc_bbs[i];
00836 
00837       if (bb == loop->header)
00838         continue;
00839 
00840       phi = phi_nodes (bb);
00841       bsi = bsi_after_labels (bb);
00842 
00843       /* BB has two predecessors. Using predecessor's aux field, set
00844          appropriate condition for the PHI node replacement.  */
00845       if (phi)
00846         true_bb = find_phi_replacement_condition (loop, bb, &cond, &bsi);
00847 
00848       while (phi)
00849         {
00850           tree next = PHI_CHAIN (phi);
00851           replace_phi_with_cond_modify_expr (phi, cond, true_bb, &bsi);
00852           release_phi_node (phi);
00853           phi = next;
00854         }
00855       bb->phi_nodes = NULL;
00856     }
00857   return;
00858 }
00859 
00860 /* Combine all basic block from the given LOOP into one or two super
00861    basic block.  Replace PHI nodes with conditional modify expression.  */
00862 
00863 static void
00864 combine_blocks (struct loop *loop)
00865 {
00866   basic_block bb, exit_bb, merge_target_bb;
00867   unsigned int orig_loop_num_nodes = loop->num_nodes;
00868   unsigned int i;
00869   unsigned int n_exits;
00870   edge *exits;
00871 
00872   exits = get_loop_exit_edges (loop, &n_exits);
00873   free (exits);
00874   /* Process phi nodes to prepare blocks for merge.  */
00875   process_phi_nodes (loop);
00876 
00877   exit_bb = NULL;
00878 
00879   /* Merge basic blocks */
00880   merge_target_bb = loop->header;
00881   for (i = 1; i < orig_loop_num_nodes; i++)
00882     {
00883       edge e;
00884       block_stmt_iterator bsi;
00885       tree_stmt_iterator last;
00886 
00887       bb = ifc_bbs[i];
00888 
00889       if (!exit_bb && bb_with_exit_edge_p (loop, bb))
00890           exit_bb = bb;
00891 
00892       if (bb == exit_bb)
00893         {
00894           edge_iterator ei;
00895 
00896           /* Connect this node with loop header.  */
00897           make_edge (ifc_bbs[0], bb, EDGE_FALLTHRU);
00898           set_immediate_dominator (CDI_DOMINATORS, bb, ifc_bbs[0]);
00899 
00900           if (exit_bb != loop->latch)
00901             {
00902               /* Redirect non-exit edge to loop->latch.  */
00903               FOR_EACH_EDGE (e, ei, bb->succs)
00904                 {
00905                   if (!loop_exit_edge_p (loop, e))
00906                     {
00907                       redirect_edge_and_branch (e, loop->latch);
00908                       set_immediate_dominator (CDI_DOMINATORS, loop->latch, bb);
00909                     }
00910                 }
00911             }
00912           continue;
00913         }
00914 
00915       if (bb == loop->latch && empty_block_p (bb))
00916         continue;
00917 
00918       /* It is time to remove this basic block.  First remove edges.  */
00919       while (EDGE_COUNT (bb->preds) > 0)
00920         remove_edge (EDGE_PRED (bb, 0));
00921 
00922       /* This is loop latch and loop does not have exit then do not
00923          delete this basic block. Just remove its PREDS and reconnect 
00924          loop->header and loop->latch blocks.  */
00925       if (bb == loop->latch && n_exits == 0)
00926         {
00927           make_edge (loop->header, loop->latch, EDGE_FALLTHRU);
00928           set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header);
00929           continue;
00930         }
00931 
00932       while (EDGE_COUNT (bb->succs) > 0)
00933         remove_edge (EDGE_SUCC (bb, 0));
00934 
00935       /* Remove labels and make stmts member of loop->header.  */
00936       for (bsi = bsi_start (bb); !bsi_end_p (bsi); )
00937         {
00938           if (TREE_CODE (bsi_stmt (bsi)) == LABEL_EXPR)
00939             bsi_remove (&bsi, true);
00940           else
00941             {
00942               set_bb_for_stmt (bsi_stmt (bsi), merge_target_bb);
00943               bsi_next (&bsi);
00944             }
00945         }
00946 
00947       /* Update stmt list.  */
00948       last = tsi_last (merge_target_bb->stmt_list);
00949       tsi_link_after (&last, bb->stmt_list, TSI_NEW_STMT);
00950       bb->stmt_list = NULL;
00951 
00952       /* Update dominator info.  */
00953       if (dom_computed[CDI_DOMINATORS])
00954         delete_from_dominance_info (CDI_DOMINATORS, bb);
00955       if (dom_computed[CDI_POST_DOMINATORS])
00956         delete_from_dominance_info (CDI_POST_DOMINATORS, bb);
00957 
00958       /* Remove basic block.  */
00959       if (bb == loop->latch)
00960         loop->latch = merge_target_bb;
00961       remove_bb_from_loops (bb);
00962       expunge_block (bb);
00963     }
00964 
00965   /* Now if possible, merge loop header and block with exit edge.
00966      This reduces number of basic blocks to 2. Auto vectorizer addresses
00967      loops with two nodes only.  FIXME: Use cleanup_tree_cfg().  */
00968   if (exit_bb
00969       && loop->header != loop->latch
00970       && exit_bb != loop->latch 
00971       && empty_block_p (loop->latch))
00972     {
00973       if (can_merge_blocks_p (loop->header, exit_bb))
00974         {
00975           remove_bb_from_loops (exit_bb);
00976           merge_blocks (loop->header, exit_bb);
00977         }
00978     }
00979 }
00980 
00981 /* Make new  temp variable of type TYPE. Add MODIFY_EXPR to assign EXP
00982    to the new variable.  */
00983 
00984 static tree
00985 ifc_temp_var (tree type, tree exp)
00986 {
00987   const char *name = "_ifc_";
00988   tree var, stmt, new_name;
00989 
00990   if (is_gimple_reg (exp))
00991     return exp;
00992 
00993   /* Create new temporary variable.  */
00994   var = create_tmp_var (type, name);
00995   add_referenced_var (var);
00996 
00997   /* Build new statement to assign EXP to new variable.  */
00998   stmt = build2 (MODIFY_EXPR, type, var, exp);
00999 
01000   /* Get SSA name for the new variable and set make new statement
01001      its definition statement.  */
01002   new_name = make_ssa_name (var, stmt);
01003   TREE_OPERAND (stmt, 0) = new_name;
01004   SSA_NAME_DEF_STMT (new_name) = stmt;
01005 
01006   return stmt;
01007 }
01008 
01009 
01010 /* Return TRUE iff, all pred blocks of BB are visited.
01011    Bitmap VISITED keeps history of visited blocks.  */
01012 
01013 static bool
01014 pred_blocks_visited_p (basic_block bb, bitmap *visited)
01015 {
01016   edge e;
01017   edge_iterator ei;
01018   FOR_EACH_EDGE (e, ei, bb->preds)
01019     if (!bitmap_bit_p (*visited, e->src->index))
01020       return false;
01021 
01022   return true;
01023 }
01024 
01025 /* Get body of a LOOP in suitable order for if-conversion.
01026    It is caller's responsibility to deallocate basic block
01027    list.  If-conversion suitable order is, BFS order with one
01028    additional constraint. Select block in BFS block, if all
01029    pred are already selected.  */
01030 
01031 static basic_block *
01032 get_loop_body_in_if_conv_order (const struct loop *loop)
01033 {
01034   basic_block *blocks, *blocks_in_bfs_order;
01035   basic_block bb;
01036   bitmap visited;
01037   unsigned int index = 0;
01038   unsigned int visited_count = 0;
01039 
01040   gcc_assert (loop->num_nodes);
01041   gcc_assert (loop->latch != EXIT_BLOCK_PTR);
01042 
01043   blocks = XCNEWVEC (basic_block, loop->num_nodes);
01044   visited = BITMAP_ALLOC (NULL);
01045 
01046   blocks_in_bfs_order = get_loop_body_in_bfs_order (loop);
01047 
01048   index = 0;
01049   while (index < loop->num_nodes)
01050     {
01051       bb = blocks_in_bfs_order [index];
01052 
01053       if (bb->flags & BB_IRREDUCIBLE_LOOP)
01054         {
01055           free (blocks_in_bfs_order);
01056           BITMAP_FREE (visited);
01057           free (blocks);
01058           return NULL;
01059         }
01060       if (!bitmap_bit_p (visited, bb->index))
01061         {
01062           if (pred_blocks_visited_p (bb, &visited)
01063               || bb == loop->header)
01064             {
01065               /* This block is now visited.  */
01066               bitmap_set_bit (visited, bb->index);
01067               blocks[visited_count++] = bb;
01068             }
01069         }
01070       index++;
01071       if (index == loop->num_nodes
01072           && visited_count != loop->num_nodes)
01073         {
01074           /* Not done yet.  */
01075           index = 0;
01076         }
01077     }
01078   free (blocks_in_bfs_order);
01079   BITMAP_FREE (visited);
01080   return blocks;
01081 }
01082 
01083 /* Return true if one of the basic block BB edge is exit of LOOP.  */
01084 
01085 static bool
01086 bb_with_exit_edge_p (struct loop *loop, basic_block bb)
01087 {
01088   edge e;
01089   edge_iterator ei;
01090   bool exit_edge_found = false;
01091 
01092   FOR_EACH_EDGE (e, ei, bb->succs)
01093     if (loop_exit_edge_p (loop, e))
01094       {
01095         exit_edge_found = true;
01096         break;
01097       }
01098 
01099   return exit_edge_found;
01100 }
01101 
01102 /* Tree if-conversion pass management.  */
01103 
01104 static unsigned int
01105 main_tree_if_conversion (void)
01106 {
01107   unsigned i, loop_num;
01108   struct loop *loop;
01109 
01110   if (!current_loops)
01111     return 0;
01112 
01113   loop_num = current_loops->num;
01114   for (i = 0; i < loop_num; i++)
01115     {
01116       loop =  current_loops->parray[i];
01117       if (!loop)
01118       continue;
01119 
01120       tree_if_conversion (loop, true);
01121     }
01122   return 0;
01123 }
01124 
01125 static bool
01126 gate_tree_if_conversion (void)
01127 {
01128   return flag_tree_vectorize != 0;
01129 }
01130 
01131 struct tree_opt_pass pass_if_conversion =
01132 {
01133   "ifcvt",                              /* name */
01134   gate_tree_if_conversion,              /* gate */
01135   main_tree_if_conversion,              /* execute */
01136   NULL,                                 /* sub */
01137   NULL,                                 /* next */
01138   0,                                    /* static_pass_number */
01139   0,                                    /* tv_id */
01140   PROP_cfg | PROP_ssa | PROP_alias,     /* properties_required */
01141   0,                                    /* properties_provided */
01142   0,                                    /* properties_destroyed */
01143   0,                                    /* todo_flags_start */
01144   TODO_dump_func | TODO_verify_loops | TODO_verify_stmts | TODO_verify_flow,    
01145                                         /* todo_flags_finish */
01146   0                                     /* letter */
01147 };

Generated on Sun Sep 17 18:03:29 2006 for Tree SSA by  doxygen 1.4.6