1e4b17023SJohn Marino /* If-conversion for vectorizer. 2e4b17023SJohn Marino Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 3e4b17023SJohn Marino Free Software Foundation, Inc. 4e4b17023SJohn Marino Contributed by Devang Patel <dpatel@apple.com> 5e4b17023SJohn Marino 6e4b17023SJohn Marino This file is part of GCC. 7e4b17023SJohn Marino 8e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under 9e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free 10e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later 11e4b17023SJohn Marino version. 12e4b17023SJohn Marino 13e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY 14e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or 15e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 16e4b17023SJohn Marino for more details. 17e4b17023SJohn Marino 18e4b17023SJohn Marino You should have received a copy of the GNU General Public License 19e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see 20e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */ 21e4b17023SJohn Marino 22e4b17023SJohn Marino /* This pass implements a tree level if-conversion of loops. Its 23e4b17023SJohn Marino initial goal is to help the vectorizer to vectorize loops with 24e4b17023SJohn Marino conditions. 25e4b17023SJohn Marino 26e4b17023SJohn Marino A short description of if-conversion: 27e4b17023SJohn Marino 28e4b17023SJohn Marino o Decide if a loop is if-convertible or not. 29e4b17023SJohn Marino o Walk all loop basic blocks in breadth first order (BFS order). 30e4b17023SJohn Marino o Remove conditional statements (at the end of basic block) 31e4b17023SJohn Marino and propagate condition into destination basic blocks' 32e4b17023SJohn Marino predicate list. 33e4b17023SJohn Marino o Replace modify expression with conditional modify expression 34e4b17023SJohn Marino using current basic block's condition. 35e4b17023SJohn Marino o Merge all basic blocks 36e4b17023SJohn Marino o Replace phi nodes with conditional modify expr 37e4b17023SJohn Marino o Merge all basic blocks into header 38e4b17023SJohn Marino 39e4b17023SJohn Marino Sample transformation: 40e4b17023SJohn Marino 41e4b17023SJohn Marino INPUT 42e4b17023SJohn Marino ----- 43e4b17023SJohn Marino 44e4b17023SJohn Marino # i_23 = PHI <0(0), i_18(10)>; 45e4b17023SJohn Marino <L0>:; 46e4b17023SJohn Marino j_15 = A[i_23]; 47e4b17023SJohn Marino if (j_15 > 41) goto <L1>; else goto <L17>; 48e4b17023SJohn Marino 49e4b17023SJohn Marino <L17>:; 50e4b17023SJohn Marino goto <bb 3> (<L3>); 51e4b17023SJohn Marino 52e4b17023SJohn Marino <L1>:; 53e4b17023SJohn Marino 54e4b17023SJohn Marino # iftmp.2_4 = PHI <0(8), 42(2)>; 55e4b17023SJohn Marino <L3>:; 56e4b17023SJohn Marino A[i_23] = iftmp.2_4; 57e4b17023SJohn Marino i_18 = i_23 + 1; 58e4b17023SJohn Marino if (i_18 <= 15) goto <L19>; else goto <L18>; 59e4b17023SJohn Marino 60e4b17023SJohn Marino <L19>:; 61e4b17023SJohn Marino goto <bb 1> (<L0>); 62e4b17023SJohn Marino 63e4b17023SJohn Marino <L18>:; 64e4b17023SJohn Marino 65e4b17023SJohn Marino OUTPUT 66e4b17023SJohn Marino ------ 67e4b17023SJohn Marino 68e4b17023SJohn Marino # i_23 = PHI <0(0), i_18(10)>; 69e4b17023SJohn Marino <L0>:; 70e4b17023SJohn Marino j_15 = A[i_23]; 71e4b17023SJohn Marino 72e4b17023SJohn Marino <L3>:; 73e4b17023SJohn Marino iftmp.2_4 = j_15 > 41 ? 42 : 0; 74e4b17023SJohn Marino A[i_23] = iftmp.2_4; 75e4b17023SJohn Marino i_18 = i_23 + 1; 76e4b17023SJohn Marino if (i_18 <= 15) goto <L19>; else goto <L18>; 77e4b17023SJohn Marino 78e4b17023SJohn Marino <L19>:; 79e4b17023SJohn Marino goto <bb 1> (<L0>); 80e4b17023SJohn Marino 81e4b17023SJohn Marino <L18>:; 82e4b17023SJohn Marino */ 83e4b17023SJohn Marino 84e4b17023SJohn Marino #include "config.h" 85e4b17023SJohn Marino #include "system.h" 86e4b17023SJohn Marino #include "coretypes.h" 87e4b17023SJohn Marino #include "tm.h" 88e4b17023SJohn Marino #include "tree.h" 89e4b17023SJohn Marino #include "flags.h" 90e4b17023SJohn Marino #include "timevar.h" 91e4b17023SJohn Marino #include "basic-block.h" 92e4b17023SJohn Marino #include "tree-pretty-print.h" 93e4b17023SJohn Marino #include "gimple-pretty-print.h" 94e4b17023SJohn Marino #include "tree-flow.h" 95e4b17023SJohn Marino #include "tree-dump.h" 96e4b17023SJohn Marino #include "cfgloop.h" 97e4b17023SJohn Marino #include "tree-chrec.h" 98e4b17023SJohn Marino #include "tree-data-ref.h" 99e4b17023SJohn Marino #include "tree-scalar-evolution.h" 100e4b17023SJohn Marino #include "tree-pass.h" 101e4b17023SJohn Marino #include "dbgcnt.h" 102e4b17023SJohn Marino 103e4b17023SJohn Marino /* List of basic blocks in if-conversion-suitable order. */ 104e4b17023SJohn Marino static basic_block *ifc_bbs; 105e4b17023SJohn Marino 106e4b17023SJohn Marino /* Structure used to predicate basic blocks. This is attached to the 107e4b17023SJohn Marino ->aux field of the BBs in the loop to be if-converted. */ 108e4b17023SJohn Marino typedef struct bb_predicate_s { 109e4b17023SJohn Marino 110e4b17023SJohn Marino /* The condition under which this basic block is executed. */ 111e4b17023SJohn Marino tree predicate; 112e4b17023SJohn Marino 113e4b17023SJohn Marino /* PREDICATE is gimplified, and the sequence of statements is 114e4b17023SJohn Marino recorded here, in order to avoid the duplication of computations 115e4b17023SJohn Marino that occur in previous conditions. See PR44483. */ 116e4b17023SJohn Marino gimple_seq predicate_gimplified_stmts; 117e4b17023SJohn Marino } *bb_predicate_p; 118e4b17023SJohn Marino 119e4b17023SJohn Marino /* Returns true when the basic block BB has a predicate. */ 120e4b17023SJohn Marino 121e4b17023SJohn Marino static inline bool 122e4b17023SJohn Marino bb_has_predicate (basic_block bb) 123e4b17023SJohn Marino { 124e4b17023SJohn Marino return bb->aux != NULL; 125e4b17023SJohn Marino } 126e4b17023SJohn Marino 127e4b17023SJohn Marino /* Returns the gimplified predicate for basic block BB. */ 128e4b17023SJohn Marino 129e4b17023SJohn Marino static inline tree 130e4b17023SJohn Marino bb_predicate (basic_block bb) 131e4b17023SJohn Marino { 132e4b17023SJohn Marino return ((bb_predicate_p) bb->aux)->predicate; 133e4b17023SJohn Marino } 134e4b17023SJohn Marino 135e4b17023SJohn Marino /* Sets the gimplified predicate COND for basic block BB. */ 136e4b17023SJohn Marino 137e4b17023SJohn Marino static inline void 138e4b17023SJohn Marino set_bb_predicate (basic_block bb, tree cond) 139e4b17023SJohn Marino { 140e4b17023SJohn Marino gcc_assert ((TREE_CODE (cond) == TRUTH_NOT_EXPR 141e4b17023SJohn Marino && is_gimple_condexpr (TREE_OPERAND (cond, 0))) 142e4b17023SJohn Marino || is_gimple_condexpr (cond)); 143e4b17023SJohn Marino ((bb_predicate_p) bb->aux)->predicate = cond; 144e4b17023SJohn Marino } 145e4b17023SJohn Marino 146e4b17023SJohn Marino /* Returns the sequence of statements of the gimplification of the 147e4b17023SJohn Marino predicate for basic block BB. */ 148e4b17023SJohn Marino 149e4b17023SJohn Marino static inline gimple_seq 150e4b17023SJohn Marino bb_predicate_gimplified_stmts (basic_block bb) 151e4b17023SJohn Marino { 152e4b17023SJohn Marino return ((bb_predicate_p) bb->aux)->predicate_gimplified_stmts; 153e4b17023SJohn Marino } 154e4b17023SJohn Marino 155e4b17023SJohn Marino /* Sets the sequence of statements STMTS of the gimplification of the 156e4b17023SJohn Marino predicate for basic block BB. */ 157e4b17023SJohn Marino 158e4b17023SJohn Marino static inline void 159e4b17023SJohn Marino set_bb_predicate_gimplified_stmts (basic_block bb, gimple_seq stmts) 160e4b17023SJohn Marino { 161e4b17023SJohn Marino ((bb_predicate_p) bb->aux)->predicate_gimplified_stmts = stmts; 162e4b17023SJohn Marino } 163e4b17023SJohn Marino 164e4b17023SJohn Marino /* Adds the sequence of statements STMTS to the sequence of statements 165e4b17023SJohn Marino of the predicate for basic block BB. */ 166e4b17023SJohn Marino 167e4b17023SJohn Marino static inline void 168e4b17023SJohn Marino add_bb_predicate_gimplified_stmts (basic_block bb, gimple_seq stmts) 169e4b17023SJohn Marino { 170e4b17023SJohn Marino gimple_seq_add_seq 171e4b17023SJohn Marino (&(((bb_predicate_p) bb->aux)->predicate_gimplified_stmts), stmts); 172e4b17023SJohn Marino } 173e4b17023SJohn Marino 174e4b17023SJohn Marino /* Initializes to TRUE the predicate of basic block BB. */ 175e4b17023SJohn Marino 176e4b17023SJohn Marino static inline void 177e4b17023SJohn Marino init_bb_predicate (basic_block bb) 178e4b17023SJohn Marino { 179e4b17023SJohn Marino bb->aux = XNEW (struct bb_predicate_s); 180e4b17023SJohn Marino set_bb_predicate_gimplified_stmts (bb, NULL); 181e4b17023SJohn Marino set_bb_predicate (bb, boolean_true_node); 182e4b17023SJohn Marino } 183e4b17023SJohn Marino 184e4b17023SJohn Marino /* Free the predicate of basic block BB. */ 185e4b17023SJohn Marino 186e4b17023SJohn Marino static inline void 187e4b17023SJohn Marino free_bb_predicate (basic_block bb) 188e4b17023SJohn Marino { 189e4b17023SJohn Marino gimple_seq stmts; 190e4b17023SJohn Marino 191e4b17023SJohn Marino if (!bb_has_predicate (bb)) 192e4b17023SJohn Marino return; 193e4b17023SJohn Marino 194e4b17023SJohn Marino /* Release the SSA_NAMEs created for the gimplification of the 195e4b17023SJohn Marino predicate. */ 196e4b17023SJohn Marino stmts = bb_predicate_gimplified_stmts (bb); 197e4b17023SJohn Marino if (stmts) 198e4b17023SJohn Marino { 199e4b17023SJohn Marino gimple_stmt_iterator i; 200e4b17023SJohn Marino 201e4b17023SJohn Marino for (i = gsi_start (stmts); !gsi_end_p (i); gsi_next (&i)) 202e4b17023SJohn Marino free_stmt_operands (gsi_stmt (i)); 203e4b17023SJohn Marino } 204e4b17023SJohn Marino 205e4b17023SJohn Marino free (bb->aux); 206e4b17023SJohn Marino bb->aux = NULL; 207e4b17023SJohn Marino } 208e4b17023SJohn Marino 209e4b17023SJohn Marino /* Free the predicate of BB and reinitialize it with the true 210e4b17023SJohn Marino predicate. */ 211e4b17023SJohn Marino 212e4b17023SJohn Marino static inline void 213e4b17023SJohn Marino reset_bb_predicate (basic_block bb) 214e4b17023SJohn Marino { 215e4b17023SJohn Marino free_bb_predicate (bb); 216e4b17023SJohn Marino init_bb_predicate (bb); 217e4b17023SJohn Marino } 218e4b17023SJohn Marino 219e4b17023SJohn Marino /* Returns a new SSA_NAME of type TYPE that is assigned the value of 220e4b17023SJohn Marino the expression EXPR. Inserts the statement created for this 221e4b17023SJohn Marino computation before GSI and leaves the iterator GSI at the same 222e4b17023SJohn Marino statement. */ 223e4b17023SJohn Marino 224e4b17023SJohn Marino static tree 225e4b17023SJohn Marino ifc_temp_var (tree type, tree expr, gimple_stmt_iterator *gsi) 226e4b17023SJohn Marino { 227e4b17023SJohn Marino const char *name = "_ifc_"; 228e4b17023SJohn Marino tree var, new_name; 229e4b17023SJohn Marino gimple stmt; 230e4b17023SJohn Marino 231e4b17023SJohn Marino /* Create new temporary variable. */ 232e4b17023SJohn Marino var = create_tmp_var (type, name); 233e4b17023SJohn Marino add_referenced_var (var); 234e4b17023SJohn Marino 235e4b17023SJohn Marino /* Build new statement to assign EXPR to new variable. */ 236e4b17023SJohn Marino stmt = gimple_build_assign (var, expr); 237e4b17023SJohn Marino 238e4b17023SJohn Marino /* Get SSA name for the new variable and set make new statement 239e4b17023SJohn Marino its definition statement. */ 240e4b17023SJohn Marino new_name = make_ssa_name (var, stmt); 241e4b17023SJohn Marino gimple_assign_set_lhs (stmt, new_name); 242e4b17023SJohn Marino SSA_NAME_DEF_STMT (new_name) = stmt; 243e4b17023SJohn Marino update_stmt (stmt); 244e4b17023SJohn Marino 245e4b17023SJohn Marino gsi_insert_before (gsi, stmt, GSI_SAME_STMT); 246e4b17023SJohn Marino return gimple_assign_lhs (stmt); 247e4b17023SJohn Marino } 248e4b17023SJohn Marino 249e4b17023SJohn Marino /* Return true when COND is a true predicate. */ 250e4b17023SJohn Marino 251e4b17023SJohn Marino static inline bool 252e4b17023SJohn Marino is_true_predicate (tree cond) 253e4b17023SJohn Marino { 254e4b17023SJohn Marino return (cond == NULL_TREE 255e4b17023SJohn Marino || cond == boolean_true_node 256e4b17023SJohn Marino || integer_onep (cond)); 257e4b17023SJohn Marino } 258e4b17023SJohn Marino 259e4b17023SJohn Marino /* Returns true when BB has a predicate that is not trivial: true or 260e4b17023SJohn Marino NULL_TREE. */ 261e4b17023SJohn Marino 262e4b17023SJohn Marino static inline bool 263e4b17023SJohn Marino is_predicated (basic_block bb) 264e4b17023SJohn Marino { 265e4b17023SJohn Marino return !is_true_predicate (bb_predicate (bb)); 266e4b17023SJohn Marino } 267e4b17023SJohn Marino 268e4b17023SJohn Marino /* Parses the predicate COND and returns its comparison code and 269e4b17023SJohn Marino operands OP0 and OP1. */ 270e4b17023SJohn Marino 271e4b17023SJohn Marino static enum tree_code 272e4b17023SJohn Marino parse_predicate (tree cond, tree *op0, tree *op1) 273e4b17023SJohn Marino { 274e4b17023SJohn Marino gimple s; 275e4b17023SJohn Marino 276e4b17023SJohn Marino if (TREE_CODE (cond) == SSA_NAME 277e4b17023SJohn Marino && is_gimple_assign (s = SSA_NAME_DEF_STMT (cond))) 278e4b17023SJohn Marino { 279e4b17023SJohn Marino if (TREE_CODE_CLASS (gimple_assign_rhs_code (s)) == tcc_comparison) 280e4b17023SJohn Marino { 281e4b17023SJohn Marino *op0 = gimple_assign_rhs1 (s); 282e4b17023SJohn Marino *op1 = gimple_assign_rhs2 (s); 283e4b17023SJohn Marino return gimple_assign_rhs_code (s); 284e4b17023SJohn Marino } 285e4b17023SJohn Marino 286e4b17023SJohn Marino else if (gimple_assign_rhs_code (s) == TRUTH_NOT_EXPR) 287e4b17023SJohn Marino { 288e4b17023SJohn Marino tree op = gimple_assign_rhs1 (s); 289e4b17023SJohn Marino tree type = TREE_TYPE (op); 290e4b17023SJohn Marino enum tree_code code = parse_predicate (op, op0, op1); 291e4b17023SJohn Marino 292e4b17023SJohn Marino return code == ERROR_MARK ? ERROR_MARK 293e4b17023SJohn Marino : invert_tree_comparison (code, HONOR_NANS (TYPE_MODE (type))); 294e4b17023SJohn Marino } 295e4b17023SJohn Marino 296e4b17023SJohn Marino return ERROR_MARK; 297e4b17023SJohn Marino } 298e4b17023SJohn Marino 299e4b17023SJohn Marino if (TREE_CODE_CLASS (TREE_CODE (cond)) == tcc_comparison) 300e4b17023SJohn Marino { 301e4b17023SJohn Marino *op0 = TREE_OPERAND (cond, 0); 302e4b17023SJohn Marino *op1 = TREE_OPERAND (cond, 1); 303e4b17023SJohn Marino return TREE_CODE (cond); 304e4b17023SJohn Marino } 305e4b17023SJohn Marino 306e4b17023SJohn Marino return ERROR_MARK; 307e4b17023SJohn Marino } 308e4b17023SJohn Marino 309e4b17023SJohn Marino /* Returns the fold of predicate C1 OR C2 at location LOC. */ 310e4b17023SJohn Marino 311e4b17023SJohn Marino static tree 312e4b17023SJohn Marino fold_or_predicates (location_t loc, tree c1, tree c2) 313e4b17023SJohn Marino { 314e4b17023SJohn Marino tree op1a, op1b, op2a, op2b; 315e4b17023SJohn Marino enum tree_code code1 = parse_predicate (c1, &op1a, &op1b); 316e4b17023SJohn Marino enum tree_code code2 = parse_predicate (c2, &op2a, &op2b); 317e4b17023SJohn Marino 318e4b17023SJohn Marino if (code1 != ERROR_MARK && code2 != ERROR_MARK) 319e4b17023SJohn Marino { 320e4b17023SJohn Marino tree t = maybe_fold_or_comparisons (code1, op1a, op1b, 321e4b17023SJohn Marino code2, op2a, op2b); 322e4b17023SJohn Marino if (t) 323e4b17023SJohn Marino return t; 324e4b17023SJohn Marino } 325e4b17023SJohn Marino 326e4b17023SJohn Marino return fold_build2_loc (loc, TRUTH_OR_EXPR, boolean_type_node, c1, c2); 327e4b17023SJohn Marino } 328e4b17023SJohn Marino 329e4b17023SJohn Marino /* Add condition NC to the predicate list of basic block BB. */ 330e4b17023SJohn Marino 331e4b17023SJohn Marino static inline void 332e4b17023SJohn Marino add_to_predicate_list (basic_block bb, tree nc) 333e4b17023SJohn Marino { 334e4b17023SJohn Marino tree bc, *tp; 335e4b17023SJohn Marino 336e4b17023SJohn Marino if (is_true_predicate (nc)) 337e4b17023SJohn Marino return; 338e4b17023SJohn Marino 339e4b17023SJohn Marino if (!is_predicated (bb)) 340e4b17023SJohn Marino bc = nc; 341e4b17023SJohn Marino else 342e4b17023SJohn Marino { 343e4b17023SJohn Marino bc = bb_predicate (bb); 344e4b17023SJohn Marino bc = fold_or_predicates (EXPR_LOCATION (bc), nc, bc); 345e4b17023SJohn Marino if (is_true_predicate (bc)) 346e4b17023SJohn Marino { 347e4b17023SJohn Marino reset_bb_predicate (bb); 348e4b17023SJohn Marino return; 349e4b17023SJohn Marino } 350e4b17023SJohn Marino } 351e4b17023SJohn Marino 352e4b17023SJohn Marino /* Allow a TRUTH_NOT_EXPR around the main predicate. */ 353e4b17023SJohn Marino if (TREE_CODE (bc) == TRUTH_NOT_EXPR) 354e4b17023SJohn Marino tp = &TREE_OPERAND (bc, 0); 355e4b17023SJohn Marino else 356e4b17023SJohn Marino tp = &bc; 357e4b17023SJohn Marino if (!is_gimple_condexpr (*tp)) 358e4b17023SJohn Marino { 359e4b17023SJohn Marino gimple_seq stmts; 360e4b17023SJohn Marino *tp = force_gimple_operand_1 (*tp, &stmts, is_gimple_condexpr, NULL_TREE); 361e4b17023SJohn Marino add_bb_predicate_gimplified_stmts (bb, stmts); 362e4b17023SJohn Marino } 363e4b17023SJohn Marino set_bb_predicate (bb, bc); 364e4b17023SJohn Marino } 365e4b17023SJohn Marino 366e4b17023SJohn Marino /* Add the condition COND to the previous condition PREV_COND, and add 367e4b17023SJohn Marino this to the predicate list of the destination of edge E. LOOP is 368e4b17023SJohn Marino the loop to be if-converted. */ 369e4b17023SJohn Marino 370e4b17023SJohn Marino static void 371e4b17023SJohn Marino add_to_dst_predicate_list (struct loop *loop, edge e, 372e4b17023SJohn Marino tree prev_cond, tree cond) 373e4b17023SJohn Marino { 374e4b17023SJohn Marino if (!flow_bb_inside_loop_p (loop, e->dest)) 375e4b17023SJohn Marino return; 376e4b17023SJohn Marino 377e4b17023SJohn Marino if (!is_true_predicate (prev_cond)) 378e4b17023SJohn Marino cond = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, 379e4b17023SJohn Marino prev_cond, cond); 380e4b17023SJohn Marino 381e4b17023SJohn Marino add_to_predicate_list (e->dest, cond); 382e4b17023SJohn Marino } 383e4b17023SJohn Marino 384e4b17023SJohn Marino /* Return true if one of the successor edges of BB exits LOOP. */ 385e4b17023SJohn Marino 386e4b17023SJohn Marino static bool 387e4b17023SJohn Marino bb_with_exit_edge_p (struct loop *loop, basic_block bb) 388e4b17023SJohn Marino { 389e4b17023SJohn Marino edge e; 390e4b17023SJohn Marino edge_iterator ei; 391e4b17023SJohn Marino 392e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs) 393e4b17023SJohn Marino if (loop_exit_edge_p (loop, e)) 394e4b17023SJohn Marino return true; 395e4b17023SJohn Marino 396e4b17023SJohn Marino return false; 397e4b17023SJohn Marino } 398e4b17023SJohn Marino 399e4b17023SJohn Marino /* Return true when PHI is if-convertible. PHI is part of loop LOOP 400e4b17023SJohn Marino and it belongs to basic block BB. 401e4b17023SJohn Marino 402e4b17023SJohn Marino PHI is not if-convertible if: 403e4b17023SJohn Marino - it has more than 2 arguments. 404e4b17023SJohn Marino 405e4b17023SJohn Marino When the flag_tree_loop_if_convert_stores is not set, PHI is not 406e4b17023SJohn Marino if-convertible if: 407e4b17023SJohn Marino - a virtual PHI is immediately used in another PHI node, 408e4b17023SJohn Marino - there is a virtual PHI in a BB other than the loop->header. */ 409e4b17023SJohn Marino 410e4b17023SJohn Marino static bool 411e4b17023SJohn Marino if_convertible_phi_p (struct loop *loop, basic_block bb, gimple phi) 412e4b17023SJohn Marino { 413e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 414e4b17023SJohn Marino { 415e4b17023SJohn Marino fprintf (dump_file, "-------------------------\n"); 416e4b17023SJohn Marino print_gimple_stmt (dump_file, phi, 0, TDF_SLIM); 417e4b17023SJohn Marino } 418e4b17023SJohn Marino 419e4b17023SJohn Marino if (bb != loop->header && gimple_phi_num_args (phi) != 2) 420e4b17023SJohn Marino { 421e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 422e4b17023SJohn Marino fprintf (dump_file, "More than two phi node args.\n"); 423e4b17023SJohn Marino return false; 424e4b17023SJohn Marino } 425e4b17023SJohn Marino 426e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores) 427e4b17023SJohn Marino return true; 428e4b17023SJohn Marino 429e4b17023SJohn Marino /* When the flag_tree_loop_if_convert_stores is not set, check 430e4b17023SJohn Marino that there are no memory writes in the branches of the loop to be 431e4b17023SJohn Marino if-converted. */ 432e4b17023SJohn Marino if (!is_gimple_reg (SSA_NAME_VAR (gimple_phi_result (phi)))) 433e4b17023SJohn Marino { 434e4b17023SJohn Marino imm_use_iterator imm_iter; 435e4b17023SJohn Marino use_operand_p use_p; 436e4b17023SJohn Marino 437e4b17023SJohn Marino if (bb != loop->header) 438e4b17023SJohn Marino { 439e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 440e4b17023SJohn Marino fprintf (dump_file, "Virtual phi not on loop->header.\n"); 441e4b17023SJohn Marino return false; 442e4b17023SJohn Marino } 443e4b17023SJohn Marino 444e4b17023SJohn Marino FOR_EACH_IMM_USE_FAST (use_p, imm_iter, gimple_phi_result (phi)) 445e4b17023SJohn Marino { 446e4b17023SJohn Marino if (gimple_code (USE_STMT (use_p)) == GIMPLE_PHI) 447e4b17023SJohn Marino { 448e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 449e4b17023SJohn Marino fprintf (dump_file, "Difficult to handle this virtual phi.\n"); 450e4b17023SJohn Marino return false; 451e4b17023SJohn Marino } 452e4b17023SJohn Marino } 453e4b17023SJohn Marino } 454e4b17023SJohn Marino 455e4b17023SJohn Marino return true; 456e4b17023SJohn Marino } 457e4b17023SJohn Marino 458e4b17023SJohn Marino /* Records the status of a data reference. This struct is attached to 459e4b17023SJohn Marino each DR->aux field. */ 460e4b17023SJohn Marino 461e4b17023SJohn Marino struct ifc_dr { 462e4b17023SJohn Marino /* -1 when not initialized, 0 when false, 1 when true. */ 463e4b17023SJohn Marino int written_at_least_once; 464e4b17023SJohn Marino 465e4b17023SJohn Marino /* -1 when not initialized, 0 when false, 1 when true. */ 466e4b17023SJohn Marino int rw_unconditionally; 467e4b17023SJohn Marino }; 468e4b17023SJohn Marino 469e4b17023SJohn Marino #define IFC_DR(DR) ((struct ifc_dr *) (DR)->aux) 470e4b17023SJohn Marino #define DR_WRITTEN_AT_LEAST_ONCE(DR) (IFC_DR (DR)->written_at_least_once) 471e4b17023SJohn Marino #define DR_RW_UNCONDITIONALLY(DR) (IFC_DR (DR)->rw_unconditionally) 472e4b17023SJohn Marino 473e4b17023SJohn Marino /* Returns true when the memory references of STMT are read or written 474e4b17023SJohn Marino unconditionally. In other words, this function returns true when 475e4b17023SJohn Marino for every data reference A in STMT there exist other accesses to 476e4b17023SJohn Marino a data reference with the same base with predicates that add up (OR-up) to 477e4b17023SJohn Marino the true predicate: this ensures that the data reference A is touched 478e4b17023SJohn Marino (read or written) on every iteration of the if-converted loop. */ 479e4b17023SJohn Marino 480e4b17023SJohn Marino static bool 481e4b17023SJohn Marino memrefs_read_or_written_unconditionally (gimple stmt, 482e4b17023SJohn Marino VEC (data_reference_p, heap) *drs) 483e4b17023SJohn Marino { 484e4b17023SJohn Marino int i, j; 485e4b17023SJohn Marino data_reference_p a, b; 486e4b17023SJohn Marino tree ca = bb_predicate (gimple_bb (stmt)); 487e4b17023SJohn Marino 488e4b17023SJohn Marino for (i = 0; VEC_iterate (data_reference_p, drs, i, a); i++) 489e4b17023SJohn Marino if (DR_STMT (a) == stmt) 490e4b17023SJohn Marino { 491e4b17023SJohn Marino bool found = false; 492e4b17023SJohn Marino int x = DR_RW_UNCONDITIONALLY (a); 493e4b17023SJohn Marino 494e4b17023SJohn Marino if (x == 0) 495e4b17023SJohn Marino return false; 496e4b17023SJohn Marino 497e4b17023SJohn Marino if (x == 1) 498e4b17023SJohn Marino continue; 499e4b17023SJohn Marino 500e4b17023SJohn Marino for (j = 0; VEC_iterate (data_reference_p, drs, j, b); j++) 501e4b17023SJohn Marino { 502e4b17023SJohn Marino tree ref_base_a = DR_REF (a); 503e4b17023SJohn Marino tree ref_base_b = DR_REF (b); 504e4b17023SJohn Marino 505e4b17023SJohn Marino if (DR_STMT (b) == stmt) 506e4b17023SJohn Marino continue; 507e4b17023SJohn Marino 508e4b17023SJohn Marino while (TREE_CODE (ref_base_a) == COMPONENT_REF 509e4b17023SJohn Marino || TREE_CODE (ref_base_a) == IMAGPART_EXPR 510e4b17023SJohn Marino || TREE_CODE (ref_base_a) == REALPART_EXPR) 511e4b17023SJohn Marino ref_base_a = TREE_OPERAND (ref_base_a, 0); 512e4b17023SJohn Marino 513e4b17023SJohn Marino while (TREE_CODE (ref_base_b) == COMPONENT_REF 514e4b17023SJohn Marino || TREE_CODE (ref_base_b) == IMAGPART_EXPR 515e4b17023SJohn Marino || TREE_CODE (ref_base_b) == REALPART_EXPR) 516e4b17023SJohn Marino ref_base_b = TREE_OPERAND (ref_base_b, 0); 517e4b17023SJohn Marino 518e4b17023SJohn Marino if (!operand_equal_p (ref_base_a, ref_base_b, 0)) 519e4b17023SJohn Marino { 520e4b17023SJohn Marino tree cb = bb_predicate (gimple_bb (DR_STMT (b))); 521e4b17023SJohn Marino 522e4b17023SJohn Marino if (DR_RW_UNCONDITIONALLY (b) == 1 523e4b17023SJohn Marino || is_true_predicate (cb) 524e4b17023SJohn Marino || is_true_predicate (ca 525e4b17023SJohn Marino = fold_or_predicates (EXPR_LOCATION (cb), ca, cb))) 526e4b17023SJohn Marino { 527e4b17023SJohn Marino DR_RW_UNCONDITIONALLY (a) = 1; 528e4b17023SJohn Marino DR_RW_UNCONDITIONALLY (b) = 1; 529e4b17023SJohn Marino found = true; 530e4b17023SJohn Marino break; 531e4b17023SJohn Marino } 532e4b17023SJohn Marino } 533e4b17023SJohn Marino } 534e4b17023SJohn Marino 535e4b17023SJohn Marino if (!found) 536e4b17023SJohn Marino { 537e4b17023SJohn Marino DR_RW_UNCONDITIONALLY (a) = 0; 538e4b17023SJohn Marino return false; 539e4b17023SJohn Marino } 540e4b17023SJohn Marino } 541e4b17023SJohn Marino 542e4b17023SJohn Marino return true; 543e4b17023SJohn Marino } 544e4b17023SJohn Marino 545e4b17023SJohn Marino /* Returns true when the memory references of STMT are unconditionally 546e4b17023SJohn Marino written. In other words, this function returns true when for every 547e4b17023SJohn Marino data reference A written in STMT, there exist other writes to the 548e4b17023SJohn Marino same data reference with predicates that add up (OR-up) to the true 549e4b17023SJohn Marino predicate: this ensures that the data reference A is written on 550e4b17023SJohn Marino every iteration of the if-converted loop. */ 551e4b17023SJohn Marino 552e4b17023SJohn Marino static bool 553e4b17023SJohn Marino write_memrefs_written_at_least_once (gimple stmt, 554e4b17023SJohn Marino VEC (data_reference_p, heap) *drs) 555e4b17023SJohn Marino { 556e4b17023SJohn Marino int i, j; 557e4b17023SJohn Marino data_reference_p a, b; 558e4b17023SJohn Marino tree ca = bb_predicate (gimple_bb (stmt)); 559e4b17023SJohn Marino 560e4b17023SJohn Marino for (i = 0; VEC_iterate (data_reference_p, drs, i, a); i++) 561e4b17023SJohn Marino if (DR_STMT (a) == stmt 562e4b17023SJohn Marino && DR_IS_WRITE (a)) 563e4b17023SJohn Marino { 564e4b17023SJohn Marino bool found = false; 565e4b17023SJohn Marino int x = DR_WRITTEN_AT_LEAST_ONCE (a); 566e4b17023SJohn Marino 567e4b17023SJohn Marino if (x == 0) 568e4b17023SJohn Marino return false; 569e4b17023SJohn Marino 570e4b17023SJohn Marino if (x == 1) 571e4b17023SJohn Marino continue; 572e4b17023SJohn Marino 573e4b17023SJohn Marino for (j = 0; VEC_iterate (data_reference_p, drs, j, b); j++) 574e4b17023SJohn Marino if (DR_STMT (b) != stmt 575e4b17023SJohn Marino && DR_IS_WRITE (b) 576e4b17023SJohn Marino && same_data_refs_base_objects (a, b)) 577e4b17023SJohn Marino { 578e4b17023SJohn Marino tree cb = bb_predicate (gimple_bb (DR_STMT (b))); 579e4b17023SJohn Marino 580e4b17023SJohn Marino if (DR_WRITTEN_AT_LEAST_ONCE (b) == 1 581e4b17023SJohn Marino || is_true_predicate (cb) 582e4b17023SJohn Marino || is_true_predicate (ca = fold_or_predicates (EXPR_LOCATION (cb), 583e4b17023SJohn Marino ca, cb))) 584e4b17023SJohn Marino { 585e4b17023SJohn Marino DR_WRITTEN_AT_LEAST_ONCE (a) = 1; 586e4b17023SJohn Marino DR_WRITTEN_AT_LEAST_ONCE (b) = 1; 587e4b17023SJohn Marino found = true; 588e4b17023SJohn Marino break; 589e4b17023SJohn Marino } 590e4b17023SJohn Marino } 591e4b17023SJohn Marino 592e4b17023SJohn Marino if (!found) 593e4b17023SJohn Marino { 594e4b17023SJohn Marino DR_WRITTEN_AT_LEAST_ONCE (a) = 0; 595e4b17023SJohn Marino return false; 596e4b17023SJohn Marino } 597e4b17023SJohn Marino } 598e4b17023SJohn Marino 599e4b17023SJohn Marino return true; 600e4b17023SJohn Marino } 601e4b17023SJohn Marino 602e4b17023SJohn Marino /* Return true when the memory references of STMT won't trap in the 603e4b17023SJohn Marino if-converted code. There are two things that we have to check for: 604e4b17023SJohn Marino 605e4b17023SJohn Marino - writes to memory occur to writable memory: if-conversion of 606e4b17023SJohn Marino memory writes transforms the conditional memory writes into 607e4b17023SJohn Marino unconditional writes, i.e. "if (cond) A[i] = foo" is transformed 608e4b17023SJohn Marino into "A[i] = cond ? foo : A[i]", and as the write to memory may not 609e4b17023SJohn Marino be executed at all in the original code, it may be a readonly 610e4b17023SJohn Marino memory. To check that A is not const-qualified, we check that 611e4b17023SJohn Marino there exists at least an unconditional write to A in the current 612e4b17023SJohn Marino function. 613e4b17023SJohn Marino 614e4b17023SJohn Marino - reads or writes to memory are valid memory accesses for every 615e4b17023SJohn Marino iteration. To check that the memory accesses are correctly formed 616e4b17023SJohn Marino and that we are allowed to read and write in these locations, we 617e4b17023SJohn Marino check that the memory accesses to be if-converted occur at every 618e4b17023SJohn Marino iteration unconditionally. */ 619e4b17023SJohn Marino 620e4b17023SJohn Marino static bool 621e4b17023SJohn Marino ifcvt_memrefs_wont_trap (gimple stmt, VEC (data_reference_p, heap) *refs) 622e4b17023SJohn Marino { 623e4b17023SJohn Marino return write_memrefs_written_at_least_once (stmt, refs) 624e4b17023SJohn Marino && memrefs_read_or_written_unconditionally (stmt, refs); 625e4b17023SJohn Marino } 626e4b17023SJohn Marino 627e4b17023SJohn Marino /* Wrapper around gimple_could_trap_p refined for the needs of the 628e4b17023SJohn Marino if-conversion. Try to prove that the memory accesses of STMT could 629e4b17023SJohn Marino not trap in the innermost loop containing STMT. */ 630e4b17023SJohn Marino 631e4b17023SJohn Marino static bool 632e4b17023SJohn Marino ifcvt_could_trap_p (gimple stmt, VEC (data_reference_p, heap) *refs) 633e4b17023SJohn Marino { 634e4b17023SJohn Marino if (gimple_vuse (stmt) 635e4b17023SJohn Marino && !gimple_could_trap_p_1 (stmt, false, false) 636e4b17023SJohn Marino && ifcvt_memrefs_wont_trap (stmt, refs)) 637e4b17023SJohn Marino return false; 638e4b17023SJohn Marino 639e4b17023SJohn Marino return gimple_could_trap_p (stmt); 640e4b17023SJohn Marino } 641e4b17023SJohn Marino 642e4b17023SJohn Marino /* Return true when STMT is if-convertible. 643e4b17023SJohn Marino 644e4b17023SJohn Marino GIMPLE_ASSIGN statement is not if-convertible if, 645e4b17023SJohn Marino - it is not movable, 646e4b17023SJohn Marino - it could trap, 647e4b17023SJohn Marino - LHS is not var decl. */ 648e4b17023SJohn Marino 649e4b17023SJohn Marino static bool 650e4b17023SJohn Marino if_convertible_gimple_assign_stmt_p (gimple stmt, 651e4b17023SJohn Marino VEC (data_reference_p, heap) *refs) 652e4b17023SJohn Marino { 653e4b17023SJohn Marino tree lhs = gimple_assign_lhs (stmt); 654e4b17023SJohn Marino basic_block bb; 655e4b17023SJohn Marino 656e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 657e4b17023SJohn Marino { 658e4b17023SJohn Marino fprintf (dump_file, "-------------------------\n"); 659e4b17023SJohn Marino print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); 660e4b17023SJohn Marino } 661e4b17023SJohn Marino 662e4b17023SJohn Marino if (!is_gimple_reg_type (TREE_TYPE (lhs))) 663e4b17023SJohn Marino return false; 664e4b17023SJohn Marino 665e4b17023SJohn Marino /* Some of these constrains might be too conservative. */ 666e4b17023SJohn Marino if (stmt_ends_bb_p (stmt) 667e4b17023SJohn Marino || gimple_has_volatile_ops (stmt) 668e4b17023SJohn Marino || (TREE_CODE (lhs) == SSA_NAME 669e4b17023SJohn Marino && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)) 670e4b17023SJohn Marino || gimple_has_side_effects (stmt)) 671e4b17023SJohn Marino { 672e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 673e4b17023SJohn Marino fprintf (dump_file, "stmt not suitable for ifcvt\n"); 674e4b17023SJohn Marino return false; 675e4b17023SJohn Marino } 676e4b17023SJohn Marino 677e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores) 678e4b17023SJohn Marino { 679e4b17023SJohn Marino if (ifcvt_could_trap_p (stmt, refs)) 680e4b17023SJohn Marino { 681e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 682e4b17023SJohn Marino fprintf (dump_file, "tree could trap...\n"); 683e4b17023SJohn Marino return false; 684e4b17023SJohn Marino } 685e4b17023SJohn Marino return true; 686e4b17023SJohn Marino } 687e4b17023SJohn Marino 688e4b17023SJohn Marino if (gimple_assign_rhs_could_trap_p (stmt)) 689e4b17023SJohn Marino { 690e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 691e4b17023SJohn Marino fprintf (dump_file, "tree could trap...\n"); 692e4b17023SJohn Marino return false; 693e4b17023SJohn Marino } 694e4b17023SJohn Marino 695e4b17023SJohn Marino bb = gimple_bb (stmt); 696e4b17023SJohn Marino 697e4b17023SJohn Marino if (TREE_CODE (lhs) != SSA_NAME 698e4b17023SJohn Marino && bb != bb->loop_father->header 699e4b17023SJohn Marino && !bb_with_exit_edge_p (bb->loop_father, bb)) 700e4b17023SJohn Marino { 701e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 702e4b17023SJohn Marino { 703e4b17023SJohn Marino fprintf (dump_file, "LHS is not var\n"); 704e4b17023SJohn Marino print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); 705e4b17023SJohn Marino } 706e4b17023SJohn Marino return false; 707e4b17023SJohn Marino } 708e4b17023SJohn Marino 709e4b17023SJohn Marino return true; 710e4b17023SJohn Marino } 711e4b17023SJohn Marino 712e4b17023SJohn Marino /* Return true when STMT is if-convertible. 713e4b17023SJohn Marino 714e4b17023SJohn Marino A statement is if-convertible if: 715e4b17023SJohn Marino - it is an if-convertible GIMPLE_ASSGIN, 716e4b17023SJohn Marino - it is a GIMPLE_LABEL or a GIMPLE_COND. */ 717e4b17023SJohn Marino 718e4b17023SJohn Marino static bool 719e4b17023SJohn Marino if_convertible_stmt_p (gimple stmt, VEC (data_reference_p, heap) *refs) 720e4b17023SJohn Marino { 721e4b17023SJohn Marino switch (gimple_code (stmt)) 722e4b17023SJohn Marino { 723e4b17023SJohn Marino case GIMPLE_LABEL: 724e4b17023SJohn Marino case GIMPLE_DEBUG: 725e4b17023SJohn Marino case GIMPLE_COND: 726e4b17023SJohn Marino return true; 727e4b17023SJohn Marino 728e4b17023SJohn Marino case GIMPLE_ASSIGN: 729e4b17023SJohn Marino return if_convertible_gimple_assign_stmt_p (stmt, refs); 730e4b17023SJohn Marino 731e4b17023SJohn Marino case GIMPLE_CALL: 732e4b17023SJohn Marino { 733e4b17023SJohn Marino tree fndecl = gimple_call_fndecl (stmt); 734e4b17023SJohn Marino if (fndecl) 735e4b17023SJohn Marino { 736e4b17023SJohn Marino int flags = gimple_call_flags (stmt); 737e4b17023SJohn Marino if ((flags & ECF_CONST) 738e4b17023SJohn Marino && !(flags & ECF_LOOPING_CONST_OR_PURE) 739e4b17023SJohn Marino /* We can only vectorize some builtins at the moment, 740e4b17023SJohn Marino so restrict if-conversion to those. */ 741e4b17023SJohn Marino && DECL_BUILT_IN (fndecl)) 742e4b17023SJohn Marino return true; 743e4b17023SJohn Marino } 744e4b17023SJohn Marino return false; 745e4b17023SJohn Marino } 746e4b17023SJohn Marino 747e4b17023SJohn Marino default: 748e4b17023SJohn Marino /* Don't know what to do with 'em so don't do anything. */ 749e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 750e4b17023SJohn Marino { 751e4b17023SJohn Marino fprintf (dump_file, "don't know what to do\n"); 752e4b17023SJohn Marino print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM); 753e4b17023SJohn Marino } 754e4b17023SJohn Marino return false; 755e4b17023SJohn Marino break; 756e4b17023SJohn Marino } 757e4b17023SJohn Marino 758e4b17023SJohn Marino return true; 759e4b17023SJohn Marino } 760e4b17023SJohn Marino 761e4b17023SJohn Marino /* Return true when BB is if-convertible. This routine does not check 762e4b17023SJohn Marino basic block's statements and phis. 763e4b17023SJohn Marino 764e4b17023SJohn Marino A basic block is not if-convertible if: 765e4b17023SJohn Marino - it is non-empty and it is after the exit block (in BFS order), 766e4b17023SJohn Marino - it is after the exit block but before the latch, 767e4b17023SJohn Marino - its edges are not normal. 768e4b17023SJohn Marino 769e4b17023SJohn Marino EXIT_BB is the basic block containing the exit of the LOOP. BB is 770e4b17023SJohn Marino inside LOOP. */ 771e4b17023SJohn Marino 772e4b17023SJohn Marino static bool 773e4b17023SJohn Marino if_convertible_bb_p (struct loop *loop, basic_block bb, basic_block exit_bb) 774e4b17023SJohn Marino { 775e4b17023SJohn Marino edge e; 776e4b17023SJohn Marino edge_iterator ei; 777e4b17023SJohn Marino 778e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 779e4b17023SJohn Marino fprintf (dump_file, "----------[%d]-------------\n", bb->index); 780e4b17023SJohn Marino 781e4b17023SJohn Marino if (EDGE_COUNT (bb->preds) > 2 782e4b17023SJohn Marino || EDGE_COUNT (bb->succs) > 2) 783e4b17023SJohn Marino return false; 784e4b17023SJohn Marino 785e4b17023SJohn Marino if (exit_bb) 786e4b17023SJohn Marino { 787e4b17023SJohn Marino if (bb != loop->latch) 788e4b17023SJohn Marino { 789e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 790e4b17023SJohn Marino fprintf (dump_file, "basic block after exit bb but before latch\n"); 791e4b17023SJohn Marino return false; 792e4b17023SJohn Marino } 793e4b17023SJohn Marino else if (!empty_block_p (bb)) 794e4b17023SJohn Marino { 795e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 796e4b17023SJohn Marino fprintf (dump_file, "non empty basic block after exit bb\n"); 797e4b17023SJohn Marino return false; 798e4b17023SJohn Marino } 799e4b17023SJohn Marino else if (bb == loop->latch 800e4b17023SJohn Marino && bb != exit_bb 801e4b17023SJohn Marino && !dominated_by_p (CDI_DOMINATORS, bb, exit_bb)) 802e4b17023SJohn Marino { 803e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 804e4b17023SJohn Marino fprintf (dump_file, "latch is not dominated by exit_block\n"); 805e4b17023SJohn Marino return false; 806e4b17023SJohn Marino } 807e4b17023SJohn Marino } 808e4b17023SJohn Marino 809e4b17023SJohn Marino /* Be less adventurous and handle only normal edges. */ 810e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->succs) 811e4b17023SJohn Marino if (e->flags & 812e4b17023SJohn Marino (EDGE_ABNORMAL_CALL | EDGE_EH | EDGE_ABNORMAL | EDGE_IRREDUCIBLE_LOOP)) 813e4b17023SJohn Marino { 814e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 815e4b17023SJohn Marino fprintf (dump_file, "Difficult to handle edges\n"); 816e4b17023SJohn Marino return false; 817e4b17023SJohn Marino } 818e4b17023SJohn Marino 819*95d28233SJohn Marino /* At least one incoming edge has to be non-critical as otherwise edge 820*95d28233SJohn Marino predicates are not equal to basic-block predicates of the edge 821*95d28233SJohn Marino source. */ 822*95d28233SJohn Marino if (EDGE_COUNT (bb->preds) > 1 823*95d28233SJohn Marino && bb != loop->header) 824*95d28233SJohn Marino { 825*95d28233SJohn Marino bool found = false; 826*95d28233SJohn Marino FOR_EACH_EDGE (e, ei, bb->preds) 827*95d28233SJohn Marino if (EDGE_COUNT (e->src->succs) == 1) 828*95d28233SJohn Marino found = true; 829*95d28233SJohn Marino if (!found) 830*95d28233SJohn Marino { 831*95d28233SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 832*95d28233SJohn Marino fprintf (dump_file, "only critical predecessors\n"); 833e4b17023SJohn Marino return false; 834*95d28233SJohn Marino } 835*95d28233SJohn Marino } 836e4b17023SJohn Marino 837e4b17023SJohn Marino return true; 838e4b17023SJohn Marino } 839e4b17023SJohn Marino 840e4b17023SJohn Marino /* Return true when all predecessor blocks of BB are visited. The 841e4b17023SJohn Marino VISITED bitmap keeps track of the visited blocks. */ 842e4b17023SJohn Marino 843e4b17023SJohn Marino static bool 844e4b17023SJohn Marino pred_blocks_visited_p (basic_block bb, bitmap *visited) 845e4b17023SJohn Marino { 846e4b17023SJohn Marino edge e; 847e4b17023SJohn Marino edge_iterator ei; 848e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, bb->preds) 849e4b17023SJohn Marino if (!bitmap_bit_p (*visited, e->src->index)) 850e4b17023SJohn Marino return false; 851e4b17023SJohn Marino 852e4b17023SJohn Marino return true; 853e4b17023SJohn Marino } 854e4b17023SJohn Marino 855e4b17023SJohn Marino /* Get body of a LOOP in suitable order for if-conversion. It is 856e4b17023SJohn Marino caller's responsibility to deallocate basic block list. 857e4b17023SJohn Marino If-conversion suitable order is, breadth first sort (BFS) order 858e4b17023SJohn Marino with an additional constraint: select a block only if all its 859e4b17023SJohn Marino predecessors are already selected. */ 860e4b17023SJohn Marino 861e4b17023SJohn Marino static basic_block * 862e4b17023SJohn Marino get_loop_body_in_if_conv_order (const struct loop *loop) 863e4b17023SJohn Marino { 864e4b17023SJohn Marino basic_block *blocks, *blocks_in_bfs_order; 865e4b17023SJohn Marino basic_block bb; 866e4b17023SJohn Marino bitmap visited; 867e4b17023SJohn Marino unsigned int index = 0; 868e4b17023SJohn Marino unsigned int visited_count = 0; 869e4b17023SJohn Marino 870e4b17023SJohn Marino gcc_assert (loop->num_nodes); 871e4b17023SJohn Marino gcc_assert (loop->latch != EXIT_BLOCK_PTR); 872e4b17023SJohn Marino 873e4b17023SJohn Marino blocks = XCNEWVEC (basic_block, loop->num_nodes); 874e4b17023SJohn Marino visited = BITMAP_ALLOC (NULL); 875e4b17023SJohn Marino 876e4b17023SJohn Marino blocks_in_bfs_order = get_loop_body_in_bfs_order (loop); 877e4b17023SJohn Marino 878e4b17023SJohn Marino index = 0; 879e4b17023SJohn Marino while (index < loop->num_nodes) 880e4b17023SJohn Marino { 881e4b17023SJohn Marino bb = blocks_in_bfs_order [index]; 882e4b17023SJohn Marino 883e4b17023SJohn Marino if (bb->flags & BB_IRREDUCIBLE_LOOP) 884e4b17023SJohn Marino { 885e4b17023SJohn Marino free (blocks_in_bfs_order); 886e4b17023SJohn Marino BITMAP_FREE (visited); 887e4b17023SJohn Marino free (blocks); 888e4b17023SJohn Marino return NULL; 889e4b17023SJohn Marino } 890e4b17023SJohn Marino 891e4b17023SJohn Marino if (!bitmap_bit_p (visited, bb->index)) 892e4b17023SJohn Marino { 893e4b17023SJohn Marino if (pred_blocks_visited_p (bb, &visited) 894e4b17023SJohn Marino || bb == loop->header) 895e4b17023SJohn Marino { 896e4b17023SJohn Marino /* This block is now visited. */ 897e4b17023SJohn Marino bitmap_set_bit (visited, bb->index); 898e4b17023SJohn Marino blocks[visited_count++] = bb; 899e4b17023SJohn Marino } 900e4b17023SJohn Marino } 901e4b17023SJohn Marino 902e4b17023SJohn Marino index++; 903e4b17023SJohn Marino 904e4b17023SJohn Marino if (index == loop->num_nodes 905e4b17023SJohn Marino && visited_count != loop->num_nodes) 906e4b17023SJohn Marino /* Not done yet. */ 907e4b17023SJohn Marino index = 0; 908e4b17023SJohn Marino } 909e4b17023SJohn Marino free (blocks_in_bfs_order); 910e4b17023SJohn Marino BITMAP_FREE (visited); 911e4b17023SJohn Marino return blocks; 912e4b17023SJohn Marino } 913e4b17023SJohn Marino 914e4b17023SJohn Marino /* Returns true when the analysis of the predicates for all the basic 915e4b17023SJohn Marino blocks in LOOP succeeded. 916e4b17023SJohn Marino 917e4b17023SJohn Marino predicate_bbs first allocates the predicates of the basic blocks. 918e4b17023SJohn Marino These fields are then initialized with the tree expressions 919e4b17023SJohn Marino representing the predicates under which a basic block is executed 920e4b17023SJohn Marino in the LOOP. As the loop->header is executed at each iteration, it 921e4b17023SJohn Marino has the "true" predicate. Other statements executed under a 922e4b17023SJohn Marino condition are predicated with that condition, for example 923e4b17023SJohn Marino 924e4b17023SJohn Marino | if (x) 925e4b17023SJohn Marino | S1; 926e4b17023SJohn Marino | else 927e4b17023SJohn Marino | S2; 928e4b17023SJohn Marino 929e4b17023SJohn Marino S1 will be predicated with "x", and 930e4b17023SJohn Marino S2 will be predicated with "!x". */ 931e4b17023SJohn Marino 932e4b17023SJohn Marino static bool 933e4b17023SJohn Marino predicate_bbs (loop_p loop) 934e4b17023SJohn Marino { 935e4b17023SJohn Marino unsigned int i; 936e4b17023SJohn Marino 937e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++) 938e4b17023SJohn Marino init_bb_predicate (ifc_bbs[i]); 939e4b17023SJohn Marino 940e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++) 941e4b17023SJohn Marino { 942e4b17023SJohn Marino basic_block bb = ifc_bbs[i]; 943e4b17023SJohn Marino tree cond; 944e4b17023SJohn Marino gimple_stmt_iterator itr; 945e4b17023SJohn Marino 946e4b17023SJohn Marino /* The loop latch is always executed and has no extra conditions 947e4b17023SJohn Marino to be processed: skip it. */ 948e4b17023SJohn Marino if (bb == loop->latch) 949e4b17023SJohn Marino { 950e4b17023SJohn Marino reset_bb_predicate (loop->latch); 951e4b17023SJohn Marino continue; 952e4b17023SJohn Marino } 953e4b17023SJohn Marino 954e4b17023SJohn Marino cond = bb_predicate (bb); 955e4b17023SJohn Marino 956e4b17023SJohn Marino for (itr = gsi_start_bb (bb); !gsi_end_p (itr); gsi_next (&itr)) 957e4b17023SJohn Marino { 958e4b17023SJohn Marino gimple stmt = gsi_stmt (itr); 959e4b17023SJohn Marino 960e4b17023SJohn Marino switch (gimple_code (stmt)) 961e4b17023SJohn Marino { 962e4b17023SJohn Marino case GIMPLE_LABEL: 963e4b17023SJohn Marino case GIMPLE_ASSIGN: 964e4b17023SJohn Marino case GIMPLE_CALL: 965e4b17023SJohn Marino case GIMPLE_DEBUG: 966e4b17023SJohn Marino break; 967e4b17023SJohn Marino 968e4b17023SJohn Marino case GIMPLE_COND: 969e4b17023SJohn Marino { 970e4b17023SJohn Marino tree c2, tem; 971e4b17023SJohn Marino edge true_edge, false_edge; 972e4b17023SJohn Marino location_t loc = gimple_location (stmt); 973e4b17023SJohn Marino tree c = fold_build2_loc (loc, gimple_cond_code (stmt), 974e4b17023SJohn Marino boolean_type_node, 975e4b17023SJohn Marino gimple_cond_lhs (stmt), 976e4b17023SJohn Marino gimple_cond_rhs (stmt)); 977e4b17023SJohn Marino 978e4b17023SJohn Marino /* Add new condition into destination's predicate list. */ 979e4b17023SJohn Marino extract_true_false_edges_from_block (gimple_bb (stmt), 980e4b17023SJohn Marino &true_edge, &false_edge); 981e4b17023SJohn Marino 982e4b17023SJohn Marino /* If C is true, then TRUE_EDGE is taken. */ 983e4b17023SJohn Marino add_to_dst_predicate_list (loop, true_edge, 984e4b17023SJohn Marino unshare_expr (cond), 985e4b17023SJohn Marino unshare_expr (c)); 986e4b17023SJohn Marino 987e4b17023SJohn Marino /* If C is false, then FALSE_EDGE is taken. */ 988e4b17023SJohn Marino c2 = invert_truthvalue_loc (loc, unshare_expr (c)); 989e4b17023SJohn Marino tem = canonicalize_cond_expr_cond (c2); 990e4b17023SJohn Marino if (tem) 991e4b17023SJohn Marino c2 = tem; 992e4b17023SJohn Marino add_to_dst_predicate_list (loop, false_edge, 993e4b17023SJohn Marino unshare_expr (cond), c2); 994e4b17023SJohn Marino 995e4b17023SJohn Marino cond = NULL_TREE; 996e4b17023SJohn Marino break; 997e4b17023SJohn Marino } 998e4b17023SJohn Marino 999e4b17023SJohn Marino default: 1000e4b17023SJohn Marino /* Not handled yet in if-conversion. */ 1001e4b17023SJohn Marino return false; 1002e4b17023SJohn Marino } 1003e4b17023SJohn Marino } 1004e4b17023SJohn Marino 1005e4b17023SJohn Marino /* If current bb has only one successor, then consider it as an 1006e4b17023SJohn Marino unconditional goto. */ 1007e4b17023SJohn Marino if (single_succ_p (bb)) 1008e4b17023SJohn Marino { 1009e4b17023SJohn Marino basic_block bb_n = single_succ (bb); 1010e4b17023SJohn Marino 1011e4b17023SJohn Marino /* The successor bb inherits the predicate of its 1012e4b17023SJohn Marino predecessor. If there is no predicate in the predecessor 1013e4b17023SJohn Marino bb, then consider the successor bb as always executed. */ 1014e4b17023SJohn Marino if (cond == NULL_TREE) 1015e4b17023SJohn Marino cond = boolean_true_node; 1016e4b17023SJohn Marino 1017e4b17023SJohn Marino add_to_predicate_list (bb_n, cond); 1018e4b17023SJohn Marino } 1019e4b17023SJohn Marino } 1020e4b17023SJohn Marino 1021e4b17023SJohn Marino /* The loop header is always executed. */ 1022e4b17023SJohn Marino reset_bb_predicate (loop->header); 1023e4b17023SJohn Marino gcc_assert (bb_predicate_gimplified_stmts (loop->header) == NULL 1024e4b17023SJohn Marino && bb_predicate_gimplified_stmts (loop->latch) == NULL); 1025e4b17023SJohn Marino 1026e4b17023SJohn Marino return true; 1027e4b17023SJohn Marino } 1028e4b17023SJohn Marino 1029e4b17023SJohn Marino /* Return true when LOOP is if-convertible. This is a helper function 1030e4b17023SJohn Marino for if_convertible_loop_p. REFS and DDRS are initialized and freed 1031e4b17023SJohn Marino in if_convertible_loop_p. */ 1032e4b17023SJohn Marino 1033e4b17023SJohn Marino static bool 1034e4b17023SJohn Marino if_convertible_loop_p_1 (struct loop *loop, 1035e4b17023SJohn Marino VEC (loop_p, heap) **loop_nest, 1036e4b17023SJohn Marino VEC (data_reference_p, heap) **refs, 1037e4b17023SJohn Marino VEC (ddr_p, heap) **ddrs) 1038e4b17023SJohn Marino { 1039e4b17023SJohn Marino bool res; 1040e4b17023SJohn Marino unsigned int i; 1041e4b17023SJohn Marino basic_block exit_bb = NULL; 1042e4b17023SJohn Marino 1043e4b17023SJohn Marino /* Don't if-convert the loop when the data dependences cannot be 1044e4b17023SJohn Marino computed: the loop won't be vectorized in that case. */ 1045e4b17023SJohn Marino res = compute_data_dependences_for_loop (loop, true, loop_nest, refs, ddrs); 1046e4b17023SJohn Marino if (!res) 1047e4b17023SJohn Marino return false; 1048e4b17023SJohn Marino 1049e4b17023SJohn Marino calculate_dominance_info (CDI_DOMINATORS); 1050e4b17023SJohn Marino 1051e4b17023SJohn Marino /* Allow statements that can be handled during if-conversion. */ 1052e4b17023SJohn Marino ifc_bbs = get_loop_body_in_if_conv_order (loop); 1053e4b17023SJohn Marino if (!ifc_bbs) 1054e4b17023SJohn Marino { 1055e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 1056e4b17023SJohn Marino fprintf (dump_file, "Irreducible loop\n"); 1057e4b17023SJohn Marino return false; 1058e4b17023SJohn Marino } 1059e4b17023SJohn Marino 1060e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++) 1061e4b17023SJohn Marino { 1062e4b17023SJohn Marino basic_block bb = ifc_bbs[i]; 1063e4b17023SJohn Marino 1064e4b17023SJohn Marino if (!if_convertible_bb_p (loop, bb, exit_bb)) 1065e4b17023SJohn Marino return false; 1066e4b17023SJohn Marino 1067e4b17023SJohn Marino if (bb_with_exit_edge_p (loop, bb)) 1068e4b17023SJohn Marino exit_bb = bb; 1069e4b17023SJohn Marino } 1070e4b17023SJohn Marino 1071e4b17023SJohn Marino res = predicate_bbs (loop); 1072e4b17023SJohn Marino if (!res) 1073e4b17023SJohn Marino return false; 1074e4b17023SJohn Marino 1075e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores) 1076e4b17023SJohn Marino { 1077e4b17023SJohn Marino data_reference_p dr; 1078e4b17023SJohn Marino 1079e4b17023SJohn Marino for (i = 0; VEC_iterate (data_reference_p, *refs, i, dr); i++) 1080e4b17023SJohn Marino { 1081e4b17023SJohn Marino dr->aux = XNEW (struct ifc_dr); 1082e4b17023SJohn Marino DR_WRITTEN_AT_LEAST_ONCE (dr) = -1; 1083e4b17023SJohn Marino DR_RW_UNCONDITIONALLY (dr) = -1; 1084e4b17023SJohn Marino } 1085e4b17023SJohn Marino } 1086e4b17023SJohn Marino 1087e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++) 1088e4b17023SJohn Marino { 1089e4b17023SJohn Marino basic_block bb = ifc_bbs[i]; 1090e4b17023SJohn Marino gimple_stmt_iterator itr; 1091e4b17023SJohn Marino 1092e4b17023SJohn Marino for (itr = gsi_start_phis (bb); !gsi_end_p (itr); gsi_next (&itr)) 1093e4b17023SJohn Marino if (!if_convertible_phi_p (loop, bb, gsi_stmt (itr))) 1094e4b17023SJohn Marino return false; 1095e4b17023SJohn Marino 1096e4b17023SJohn Marino /* Check the if-convertibility of statements in predicated BBs. */ 1097e4b17023SJohn Marino if (is_predicated (bb)) 1098e4b17023SJohn Marino for (itr = gsi_start_bb (bb); !gsi_end_p (itr); gsi_next (&itr)) 1099e4b17023SJohn Marino if (!if_convertible_stmt_p (gsi_stmt (itr), *refs)) 1100e4b17023SJohn Marino return false; 1101e4b17023SJohn Marino } 1102e4b17023SJohn Marino 1103e4b17023SJohn Marino if (dump_file) 1104e4b17023SJohn Marino fprintf (dump_file, "Applying if-conversion\n"); 1105e4b17023SJohn Marino 1106e4b17023SJohn Marino return true; 1107e4b17023SJohn Marino } 1108e4b17023SJohn Marino 1109e4b17023SJohn Marino /* Return true when LOOP is if-convertible. 1110e4b17023SJohn Marino LOOP is if-convertible if: 1111e4b17023SJohn Marino - it is innermost, 1112e4b17023SJohn Marino - it has two or more basic blocks, 1113e4b17023SJohn Marino - it has only one exit, 1114e4b17023SJohn Marino - loop header is not the exit edge, 1115e4b17023SJohn Marino - if its basic blocks and phi nodes are if convertible. */ 1116e4b17023SJohn Marino 1117e4b17023SJohn Marino static bool 1118e4b17023SJohn Marino if_convertible_loop_p (struct loop *loop) 1119e4b17023SJohn Marino { 1120e4b17023SJohn Marino edge e; 1121e4b17023SJohn Marino edge_iterator ei; 1122e4b17023SJohn Marino bool res = false; 1123e4b17023SJohn Marino VEC (data_reference_p, heap) *refs; 1124e4b17023SJohn Marino VEC (ddr_p, heap) *ddrs; 1125e4b17023SJohn Marino VEC (loop_p, heap) *loop_nest; 1126e4b17023SJohn Marino 1127e4b17023SJohn Marino /* Handle only innermost loop. */ 1128e4b17023SJohn Marino if (!loop || loop->inner) 1129e4b17023SJohn Marino { 1130e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 1131e4b17023SJohn Marino fprintf (dump_file, "not innermost loop\n"); 1132e4b17023SJohn Marino return false; 1133e4b17023SJohn Marino } 1134e4b17023SJohn Marino 1135e4b17023SJohn Marino /* If only one block, no need for if-conversion. */ 1136e4b17023SJohn Marino if (loop->num_nodes <= 2) 1137e4b17023SJohn Marino { 1138e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 1139e4b17023SJohn Marino fprintf (dump_file, "less than 2 basic blocks\n"); 1140e4b17023SJohn Marino return false; 1141e4b17023SJohn Marino } 1142e4b17023SJohn Marino 1143e4b17023SJohn Marino /* More than one loop exit is too much to handle. */ 1144e4b17023SJohn Marino if (!single_exit (loop)) 1145e4b17023SJohn Marino { 1146e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 1147e4b17023SJohn Marino fprintf (dump_file, "multiple exits\n"); 1148e4b17023SJohn Marino return false; 1149e4b17023SJohn Marino } 1150e4b17023SJohn Marino 1151e4b17023SJohn Marino /* If one of the loop header's edge is an exit edge then do not 1152e4b17023SJohn Marino apply if-conversion. */ 1153e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, loop->header->succs) 1154e4b17023SJohn Marino if (loop_exit_edge_p (loop, e)) 1155e4b17023SJohn Marino return false; 1156e4b17023SJohn Marino 1157e4b17023SJohn Marino refs = VEC_alloc (data_reference_p, heap, 5); 1158e4b17023SJohn Marino ddrs = VEC_alloc (ddr_p, heap, 25); 1159e4b17023SJohn Marino loop_nest = VEC_alloc (loop_p, heap, 3); 1160e4b17023SJohn Marino res = if_convertible_loop_p_1 (loop, &loop_nest, &refs, &ddrs); 1161e4b17023SJohn Marino 1162e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores) 1163e4b17023SJohn Marino { 1164e4b17023SJohn Marino data_reference_p dr; 1165e4b17023SJohn Marino unsigned int i; 1166e4b17023SJohn Marino 1167e4b17023SJohn Marino for (i = 0; VEC_iterate (data_reference_p, refs, i, dr); i++) 1168e4b17023SJohn Marino free (dr->aux); 1169e4b17023SJohn Marino } 1170e4b17023SJohn Marino 1171e4b17023SJohn Marino VEC_free (loop_p, heap, loop_nest); 1172e4b17023SJohn Marino free_data_refs (refs); 1173e4b17023SJohn Marino free_dependence_relations (ddrs); 1174e4b17023SJohn Marino return res; 1175e4b17023SJohn Marino } 1176e4b17023SJohn Marino 1177e4b17023SJohn Marino /* Basic block BB has two predecessors. Using predecessor's bb 1178e4b17023SJohn Marino predicate, set an appropriate condition COND for the PHI node 1179e4b17023SJohn Marino replacement. Return the true block whose phi arguments are 1180e4b17023SJohn Marino selected when cond is true. LOOP is the loop containing the 1181e4b17023SJohn Marino if-converted region, GSI is the place to insert the code for the 1182e4b17023SJohn Marino if-conversion. */ 1183e4b17023SJohn Marino 1184e4b17023SJohn Marino static basic_block 1185*95d28233SJohn Marino find_phi_replacement_condition (basic_block bb, tree *cond, 1186e4b17023SJohn Marino gimple_stmt_iterator *gsi) 1187e4b17023SJohn Marino { 1188e4b17023SJohn Marino edge first_edge, second_edge; 1189e4b17023SJohn Marino tree tmp_cond; 1190e4b17023SJohn Marino 1191e4b17023SJohn Marino gcc_assert (EDGE_COUNT (bb->preds) == 2); 1192e4b17023SJohn Marino first_edge = EDGE_PRED (bb, 0); 1193e4b17023SJohn Marino second_edge = EDGE_PRED (bb, 1); 1194e4b17023SJohn Marino 1195*95d28233SJohn Marino /* Prefer an edge with a not negated predicate. 1196*95d28233SJohn Marino ??? That's a very weak cost model. */ 1197e4b17023SJohn Marino tmp_cond = bb_predicate (first_edge->src); 1198e4b17023SJohn Marino gcc_assert (tmp_cond); 1199e4b17023SJohn Marino if (TREE_CODE (tmp_cond) == TRUTH_NOT_EXPR) 1200e4b17023SJohn Marino { 1201e4b17023SJohn Marino edge tmp_edge; 1202e4b17023SJohn Marino 1203e4b17023SJohn Marino tmp_edge = first_edge; 1204e4b17023SJohn Marino first_edge = second_edge; 1205e4b17023SJohn Marino second_edge = tmp_edge; 1206e4b17023SJohn Marino } 1207e4b17023SJohn Marino 1208*95d28233SJohn Marino /* Check if the edge we take the condition from is not critical. 1209*95d28233SJohn Marino We know that at least one non-critical edge exists. */ 1210*95d28233SJohn Marino if (EDGE_COUNT (first_edge->src->succs) > 1) 1211e4b17023SJohn Marino { 1212e4b17023SJohn Marino *cond = bb_predicate (second_edge->src); 1213e4b17023SJohn Marino 1214e4b17023SJohn Marino if (TREE_CODE (*cond) == TRUTH_NOT_EXPR) 1215e4b17023SJohn Marino *cond = TREE_OPERAND (*cond, 0); 1216e4b17023SJohn Marino else 1217e4b17023SJohn Marino /* Select non loop header bb. */ 1218e4b17023SJohn Marino first_edge = second_edge; 1219e4b17023SJohn Marino } 1220e4b17023SJohn Marino else 1221e4b17023SJohn Marino *cond = bb_predicate (first_edge->src); 1222e4b17023SJohn Marino 1223e4b17023SJohn Marino /* Gimplify the condition to a valid cond-expr conditonal operand. */ 1224e4b17023SJohn Marino *cond = force_gimple_operand_gsi_1 (gsi, unshare_expr (*cond), 1225e4b17023SJohn Marino is_gimple_condexpr, NULL_TREE, 1226e4b17023SJohn Marino true, GSI_SAME_STMT); 1227e4b17023SJohn Marino 1228e4b17023SJohn Marino return first_edge->src; 1229e4b17023SJohn Marino } 1230e4b17023SJohn Marino 1231e4b17023SJohn Marino /* Replace a scalar PHI node with a COND_EXPR using COND as condition. 1232e4b17023SJohn Marino This routine does not handle PHI nodes with more than two 1233e4b17023SJohn Marino arguments. 1234e4b17023SJohn Marino 1235e4b17023SJohn Marino For example, 1236e4b17023SJohn Marino S1: A = PHI <x1(1), x2(5)> 1237e4b17023SJohn Marino is converted into, 1238e4b17023SJohn Marino S2: A = cond ? x1 : x2; 1239e4b17023SJohn Marino 1240e4b17023SJohn Marino The generated code is inserted at GSI that points to the top of 1241e4b17023SJohn Marino basic block's statement list. When COND is true, phi arg from 1242e4b17023SJohn Marino TRUE_BB is selected. */ 1243e4b17023SJohn Marino 1244e4b17023SJohn Marino static void 1245e4b17023SJohn Marino predicate_scalar_phi (gimple phi, tree cond, 1246e4b17023SJohn Marino basic_block true_bb, 1247e4b17023SJohn Marino gimple_stmt_iterator *gsi) 1248e4b17023SJohn Marino { 1249e4b17023SJohn Marino gimple new_stmt; 1250e4b17023SJohn Marino basic_block bb; 1251e4b17023SJohn Marino tree rhs, res, arg, scev; 1252e4b17023SJohn Marino 1253e4b17023SJohn Marino gcc_assert (gimple_code (phi) == GIMPLE_PHI 1254e4b17023SJohn Marino && gimple_phi_num_args (phi) == 2); 1255e4b17023SJohn Marino 1256e4b17023SJohn Marino res = gimple_phi_result (phi); 1257e4b17023SJohn Marino /* Do not handle virtual phi nodes. */ 1258e4b17023SJohn Marino if (!is_gimple_reg (SSA_NAME_VAR (res))) 1259e4b17023SJohn Marino return; 1260e4b17023SJohn Marino 1261e4b17023SJohn Marino bb = gimple_bb (phi); 1262e4b17023SJohn Marino 1263e4b17023SJohn Marino if ((arg = degenerate_phi_result (phi)) 1264e4b17023SJohn Marino || ((scev = analyze_scalar_evolution (gimple_bb (phi)->loop_father, 1265e4b17023SJohn Marino res)) 1266e4b17023SJohn Marino && !chrec_contains_undetermined (scev) 1267e4b17023SJohn Marino && scev != res 1268e4b17023SJohn Marino && (arg = gimple_phi_arg_def (phi, 0)))) 1269e4b17023SJohn Marino rhs = arg; 1270e4b17023SJohn Marino else 1271e4b17023SJohn Marino { 1272e4b17023SJohn Marino tree arg_0, arg_1; 1273e4b17023SJohn Marino /* Use condition that is not TRUTH_NOT_EXPR in conditional modify expr. */ 1274e4b17023SJohn Marino if (EDGE_PRED (bb, 1)->src == true_bb) 1275e4b17023SJohn Marino { 1276e4b17023SJohn Marino arg_0 = gimple_phi_arg_def (phi, 1); 1277e4b17023SJohn Marino arg_1 = gimple_phi_arg_def (phi, 0); 1278e4b17023SJohn Marino } 1279e4b17023SJohn Marino else 1280e4b17023SJohn Marino { 1281e4b17023SJohn Marino arg_0 = gimple_phi_arg_def (phi, 0); 1282e4b17023SJohn Marino arg_1 = gimple_phi_arg_def (phi, 1); 1283e4b17023SJohn Marino } 1284e4b17023SJohn Marino 1285e4b17023SJohn Marino /* Build new RHS using selected condition and arguments. */ 1286e4b17023SJohn Marino rhs = build3 (COND_EXPR, TREE_TYPE (res), 1287e4b17023SJohn Marino unshare_expr (cond), arg_0, arg_1); 1288e4b17023SJohn Marino } 1289e4b17023SJohn Marino 1290e4b17023SJohn Marino new_stmt = gimple_build_assign (res, rhs); 1291e4b17023SJohn Marino SSA_NAME_DEF_STMT (gimple_phi_result (phi)) = new_stmt; 1292e4b17023SJohn Marino gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT); 1293e4b17023SJohn Marino update_stmt (new_stmt); 1294e4b17023SJohn Marino 1295e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 1296e4b17023SJohn Marino { 1297e4b17023SJohn Marino fprintf (dump_file, "new phi replacement stmt\n"); 1298e4b17023SJohn Marino print_gimple_stmt (dump_file, new_stmt, 0, TDF_SLIM); 1299e4b17023SJohn Marino } 1300e4b17023SJohn Marino } 1301e4b17023SJohn Marino 1302e4b17023SJohn Marino /* Replaces in LOOP all the scalar phi nodes other than those in the 1303e4b17023SJohn Marino LOOP->header block with conditional modify expressions. */ 1304e4b17023SJohn Marino 1305e4b17023SJohn Marino static void 1306e4b17023SJohn Marino predicate_all_scalar_phis (struct loop *loop) 1307e4b17023SJohn Marino { 1308e4b17023SJohn Marino basic_block bb; 1309e4b17023SJohn Marino unsigned int orig_loop_num_nodes = loop->num_nodes; 1310e4b17023SJohn Marino unsigned int i; 1311e4b17023SJohn Marino 1312e4b17023SJohn Marino for (i = 1; i < orig_loop_num_nodes; i++) 1313e4b17023SJohn Marino { 1314e4b17023SJohn Marino gimple phi; 1315e4b17023SJohn Marino tree cond = NULL_TREE; 1316e4b17023SJohn Marino gimple_stmt_iterator gsi, phi_gsi; 1317e4b17023SJohn Marino basic_block true_bb = NULL; 1318e4b17023SJohn Marino bb = ifc_bbs[i]; 1319e4b17023SJohn Marino 1320e4b17023SJohn Marino if (bb == loop->header) 1321e4b17023SJohn Marino continue; 1322e4b17023SJohn Marino 1323e4b17023SJohn Marino phi_gsi = gsi_start_phis (bb); 1324e4b17023SJohn Marino if (gsi_end_p (phi_gsi)) 1325e4b17023SJohn Marino continue; 1326e4b17023SJohn Marino 1327e4b17023SJohn Marino /* BB has two predecessors. Using predecessor's aux field, set 1328e4b17023SJohn Marino appropriate condition for the PHI node replacement. */ 1329e4b17023SJohn Marino gsi = gsi_after_labels (bb); 1330*95d28233SJohn Marino true_bb = find_phi_replacement_condition (bb, &cond, &gsi); 1331e4b17023SJohn Marino 1332e4b17023SJohn Marino while (!gsi_end_p (phi_gsi)) 1333e4b17023SJohn Marino { 1334e4b17023SJohn Marino phi = gsi_stmt (phi_gsi); 1335e4b17023SJohn Marino predicate_scalar_phi (phi, cond, true_bb, &gsi); 1336e4b17023SJohn Marino release_phi_node (phi); 1337e4b17023SJohn Marino gsi_next (&phi_gsi); 1338e4b17023SJohn Marino } 1339e4b17023SJohn Marino 1340e4b17023SJohn Marino set_phi_nodes (bb, NULL); 1341e4b17023SJohn Marino } 1342e4b17023SJohn Marino } 1343e4b17023SJohn Marino 1344e4b17023SJohn Marino /* Insert in each basic block of LOOP the statements produced by the 1345e4b17023SJohn Marino gimplification of the predicates. */ 1346e4b17023SJohn Marino 1347e4b17023SJohn Marino static void 1348e4b17023SJohn Marino insert_gimplified_predicates (loop_p loop) 1349e4b17023SJohn Marino { 1350e4b17023SJohn Marino unsigned int i; 1351e4b17023SJohn Marino 1352e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++) 1353e4b17023SJohn Marino { 1354e4b17023SJohn Marino basic_block bb = ifc_bbs[i]; 1355e4b17023SJohn Marino gimple_seq stmts; 1356e4b17023SJohn Marino 1357e4b17023SJohn Marino if (!is_predicated (bb)) 1358e4b17023SJohn Marino { 1359e4b17023SJohn Marino /* Do not insert statements for a basic block that is not 1360e4b17023SJohn Marino predicated. Also make sure that the predicate of the 1361e4b17023SJohn Marino basic block is set to true. */ 1362e4b17023SJohn Marino reset_bb_predicate (bb); 1363e4b17023SJohn Marino continue; 1364e4b17023SJohn Marino } 1365e4b17023SJohn Marino 1366e4b17023SJohn Marino stmts = bb_predicate_gimplified_stmts (bb); 1367e4b17023SJohn Marino if (stmts) 1368e4b17023SJohn Marino { 1369e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores) 1370e4b17023SJohn Marino { 1371e4b17023SJohn Marino /* Insert the predicate of the BB just after the label, 1372e4b17023SJohn Marino as the if-conversion of memory writes will use this 1373e4b17023SJohn Marino predicate. */ 1374e4b17023SJohn Marino gimple_stmt_iterator gsi = gsi_after_labels (bb); 1375e4b17023SJohn Marino gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT); 1376e4b17023SJohn Marino } 1377e4b17023SJohn Marino else 1378e4b17023SJohn Marino { 1379e4b17023SJohn Marino /* Insert the predicate of the BB at the end of the BB 1380e4b17023SJohn Marino as this would reduce the register pressure: the only 1381e4b17023SJohn Marino use of this predicate will be in successor BBs. */ 1382e4b17023SJohn Marino gimple_stmt_iterator gsi = gsi_last_bb (bb); 1383e4b17023SJohn Marino 1384e4b17023SJohn Marino if (gsi_end_p (gsi) 1385e4b17023SJohn Marino || stmt_ends_bb_p (gsi_stmt (gsi))) 1386e4b17023SJohn Marino gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT); 1387e4b17023SJohn Marino else 1388e4b17023SJohn Marino gsi_insert_seq_after (&gsi, stmts, GSI_SAME_STMT); 1389e4b17023SJohn Marino } 1390e4b17023SJohn Marino 1391e4b17023SJohn Marino /* Once the sequence is code generated, set it to NULL. */ 1392e4b17023SJohn Marino set_bb_predicate_gimplified_stmts (bb, NULL); 1393e4b17023SJohn Marino } 1394e4b17023SJohn Marino } 1395e4b17023SJohn Marino } 1396e4b17023SJohn Marino 1397e4b17023SJohn Marino /* Predicate each write to memory in LOOP. 1398e4b17023SJohn Marino 1399e4b17023SJohn Marino This function transforms control flow constructs containing memory 1400e4b17023SJohn Marino writes of the form: 1401e4b17023SJohn Marino 1402e4b17023SJohn Marino | for (i = 0; i < N; i++) 1403e4b17023SJohn Marino | if (cond) 1404e4b17023SJohn Marino | A[i] = expr; 1405e4b17023SJohn Marino 1406e4b17023SJohn Marino into the following form that does not contain control flow: 1407e4b17023SJohn Marino 1408e4b17023SJohn Marino | for (i = 0; i < N; i++) 1409e4b17023SJohn Marino | A[i] = cond ? expr : A[i]; 1410e4b17023SJohn Marino 1411e4b17023SJohn Marino The original CFG looks like this: 1412e4b17023SJohn Marino 1413e4b17023SJohn Marino | bb_0 1414e4b17023SJohn Marino | i = 0 1415e4b17023SJohn Marino | end_bb_0 1416e4b17023SJohn Marino | 1417e4b17023SJohn Marino | bb_1 1418e4b17023SJohn Marino | if (i < N) goto bb_5 else goto bb_2 1419e4b17023SJohn Marino | end_bb_1 1420e4b17023SJohn Marino | 1421e4b17023SJohn Marino | bb_2 1422e4b17023SJohn Marino | cond = some_computation; 1423e4b17023SJohn Marino | if (cond) goto bb_3 else goto bb_4 1424e4b17023SJohn Marino | end_bb_2 1425e4b17023SJohn Marino | 1426e4b17023SJohn Marino | bb_3 1427e4b17023SJohn Marino | A[i] = expr; 1428e4b17023SJohn Marino | goto bb_4 1429e4b17023SJohn Marino | end_bb_3 1430e4b17023SJohn Marino | 1431e4b17023SJohn Marino | bb_4 1432e4b17023SJohn Marino | goto bb_1 1433e4b17023SJohn Marino | end_bb_4 1434e4b17023SJohn Marino 1435e4b17023SJohn Marino insert_gimplified_predicates inserts the computation of the COND 1436e4b17023SJohn Marino expression at the beginning of the destination basic block: 1437e4b17023SJohn Marino 1438e4b17023SJohn Marino | bb_0 1439e4b17023SJohn Marino | i = 0 1440e4b17023SJohn Marino | end_bb_0 1441e4b17023SJohn Marino | 1442e4b17023SJohn Marino | bb_1 1443e4b17023SJohn Marino | if (i < N) goto bb_5 else goto bb_2 1444e4b17023SJohn Marino | end_bb_1 1445e4b17023SJohn Marino | 1446e4b17023SJohn Marino | bb_2 1447e4b17023SJohn Marino | cond = some_computation; 1448e4b17023SJohn Marino | if (cond) goto bb_3 else goto bb_4 1449e4b17023SJohn Marino | end_bb_2 1450e4b17023SJohn Marino | 1451e4b17023SJohn Marino | bb_3 1452e4b17023SJohn Marino | cond = some_computation; 1453e4b17023SJohn Marino | A[i] = expr; 1454e4b17023SJohn Marino | goto bb_4 1455e4b17023SJohn Marino | end_bb_3 1456e4b17023SJohn Marino | 1457e4b17023SJohn Marino | bb_4 1458e4b17023SJohn Marino | goto bb_1 1459e4b17023SJohn Marino | end_bb_4 1460e4b17023SJohn Marino 1461e4b17023SJohn Marino predicate_mem_writes is then predicating the memory write as follows: 1462e4b17023SJohn Marino 1463e4b17023SJohn Marino | bb_0 1464e4b17023SJohn Marino | i = 0 1465e4b17023SJohn Marino | end_bb_0 1466e4b17023SJohn Marino | 1467e4b17023SJohn Marino | bb_1 1468e4b17023SJohn Marino | if (i < N) goto bb_5 else goto bb_2 1469e4b17023SJohn Marino | end_bb_1 1470e4b17023SJohn Marino | 1471e4b17023SJohn Marino | bb_2 1472e4b17023SJohn Marino | if (cond) goto bb_3 else goto bb_4 1473e4b17023SJohn Marino | end_bb_2 1474e4b17023SJohn Marino | 1475e4b17023SJohn Marino | bb_3 1476e4b17023SJohn Marino | cond = some_computation; 1477e4b17023SJohn Marino | A[i] = cond ? expr : A[i]; 1478e4b17023SJohn Marino | goto bb_4 1479e4b17023SJohn Marino | end_bb_3 1480e4b17023SJohn Marino | 1481e4b17023SJohn Marino | bb_4 1482e4b17023SJohn Marino | goto bb_1 1483e4b17023SJohn Marino | end_bb_4 1484e4b17023SJohn Marino 1485e4b17023SJohn Marino and finally combine_blocks removes the basic block boundaries making 1486e4b17023SJohn Marino the loop vectorizable: 1487e4b17023SJohn Marino 1488e4b17023SJohn Marino | bb_0 1489e4b17023SJohn Marino | i = 0 1490e4b17023SJohn Marino | if (i < N) goto bb_5 else goto bb_1 1491e4b17023SJohn Marino | end_bb_0 1492e4b17023SJohn Marino | 1493e4b17023SJohn Marino | bb_1 1494e4b17023SJohn Marino | cond = some_computation; 1495e4b17023SJohn Marino | A[i] = cond ? expr : A[i]; 1496e4b17023SJohn Marino | if (i < N) goto bb_5 else goto bb_4 1497e4b17023SJohn Marino | end_bb_1 1498e4b17023SJohn Marino | 1499e4b17023SJohn Marino | bb_4 1500e4b17023SJohn Marino | goto bb_1 1501e4b17023SJohn Marino | end_bb_4 1502e4b17023SJohn Marino */ 1503e4b17023SJohn Marino 1504e4b17023SJohn Marino static void 1505e4b17023SJohn Marino predicate_mem_writes (loop_p loop) 1506e4b17023SJohn Marino { 1507e4b17023SJohn Marino unsigned int i, orig_loop_num_nodes = loop->num_nodes; 1508e4b17023SJohn Marino 1509e4b17023SJohn Marino for (i = 1; i < orig_loop_num_nodes; i++) 1510e4b17023SJohn Marino { 1511e4b17023SJohn Marino gimple_stmt_iterator gsi; 1512e4b17023SJohn Marino basic_block bb = ifc_bbs[i]; 1513e4b17023SJohn Marino tree cond = bb_predicate (bb); 1514e4b17023SJohn Marino bool swap; 1515e4b17023SJohn Marino gimple stmt; 1516e4b17023SJohn Marino 1517e4b17023SJohn Marino if (is_true_predicate (cond)) 1518e4b17023SJohn Marino continue; 1519e4b17023SJohn Marino 1520e4b17023SJohn Marino swap = false; 1521e4b17023SJohn Marino if (TREE_CODE (cond) == TRUTH_NOT_EXPR) 1522e4b17023SJohn Marino { 1523e4b17023SJohn Marino swap = true; 1524e4b17023SJohn Marino cond = TREE_OPERAND (cond, 0); 1525e4b17023SJohn Marino } 1526e4b17023SJohn Marino 1527e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 1528e4b17023SJohn Marino if ((stmt = gsi_stmt (gsi)) 1529e4b17023SJohn Marino && gimple_assign_single_p (stmt) 1530e4b17023SJohn Marino && gimple_vdef (stmt)) 1531e4b17023SJohn Marino { 1532e4b17023SJohn Marino tree lhs = gimple_assign_lhs (stmt); 1533e4b17023SJohn Marino tree rhs = gimple_assign_rhs1 (stmt); 1534e4b17023SJohn Marino tree type = TREE_TYPE (lhs); 1535e4b17023SJohn Marino 1536e4b17023SJohn Marino lhs = ifc_temp_var (type, unshare_expr (lhs), &gsi); 1537e4b17023SJohn Marino rhs = ifc_temp_var (type, unshare_expr (rhs), &gsi); 1538e4b17023SJohn Marino if (swap) 1539e4b17023SJohn Marino { 1540e4b17023SJohn Marino tree tem = lhs; 1541e4b17023SJohn Marino lhs = rhs; 1542e4b17023SJohn Marino rhs = tem; 1543e4b17023SJohn Marino } 1544e4b17023SJohn Marino cond = force_gimple_operand_gsi_1 (&gsi, unshare_expr (cond), 1545e4b17023SJohn Marino is_gimple_condexpr, NULL_TREE, 1546e4b17023SJohn Marino true, GSI_SAME_STMT); 1547e4b17023SJohn Marino rhs = build3 (COND_EXPR, type, unshare_expr (cond), rhs, lhs); 1548e4b17023SJohn Marino gimple_assign_set_rhs1 (stmt, ifc_temp_var (type, rhs, &gsi)); 1549e4b17023SJohn Marino update_stmt (stmt); 1550e4b17023SJohn Marino } 1551e4b17023SJohn Marino } 1552e4b17023SJohn Marino } 1553e4b17023SJohn Marino 1554e4b17023SJohn Marino /* Remove all GIMPLE_CONDs and GIMPLE_LABELs of all the basic blocks 1555e4b17023SJohn Marino other than the exit and latch of the LOOP. Also resets the 1556e4b17023SJohn Marino GIMPLE_DEBUG information. */ 1557e4b17023SJohn Marino 1558e4b17023SJohn Marino static void 1559e4b17023SJohn Marino remove_conditions_and_labels (loop_p loop) 1560e4b17023SJohn Marino { 1561e4b17023SJohn Marino gimple_stmt_iterator gsi; 1562e4b17023SJohn Marino unsigned int i; 1563e4b17023SJohn Marino 1564e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++) 1565e4b17023SJohn Marino { 1566e4b17023SJohn Marino basic_block bb = ifc_bbs[i]; 1567e4b17023SJohn Marino 1568e4b17023SJohn Marino if (bb_with_exit_edge_p (loop, bb) 1569e4b17023SJohn Marino || bb == loop->latch) 1570e4b17023SJohn Marino continue; 1571e4b17023SJohn Marino 1572e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); ) 1573e4b17023SJohn Marino switch (gimple_code (gsi_stmt (gsi))) 1574e4b17023SJohn Marino { 1575e4b17023SJohn Marino case GIMPLE_COND: 1576e4b17023SJohn Marino case GIMPLE_LABEL: 1577e4b17023SJohn Marino gsi_remove (&gsi, true); 1578e4b17023SJohn Marino break; 1579e4b17023SJohn Marino 1580e4b17023SJohn Marino case GIMPLE_DEBUG: 1581e4b17023SJohn Marino /* ??? Should there be conditional GIMPLE_DEBUG_BINDs? */ 1582e4b17023SJohn Marino if (gimple_debug_bind_p (gsi_stmt (gsi))) 1583e4b17023SJohn Marino { 1584e4b17023SJohn Marino gimple_debug_bind_reset_value (gsi_stmt (gsi)); 1585e4b17023SJohn Marino update_stmt (gsi_stmt (gsi)); 1586e4b17023SJohn Marino } 1587e4b17023SJohn Marino gsi_next (&gsi); 1588e4b17023SJohn Marino break; 1589e4b17023SJohn Marino 1590e4b17023SJohn Marino default: 1591e4b17023SJohn Marino gsi_next (&gsi); 1592e4b17023SJohn Marino } 1593e4b17023SJohn Marino } 1594e4b17023SJohn Marino } 1595e4b17023SJohn Marino 1596e4b17023SJohn Marino /* Combine all the basic blocks from LOOP into one or two super basic 1597e4b17023SJohn Marino blocks. Replace PHI nodes with conditional modify expressions. */ 1598e4b17023SJohn Marino 1599e4b17023SJohn Marino static void 1600e4b17023SJohn Marino combine_blocks (struct loop *loop) 1601e4b17023SJohn Marino { 1602e4b17023SJohn Marino basic_block bb, exit_bb, merge_target_bb; 1603e4b17023SJohn Marino unsigned int orig_loop_num_nodes = loop->num_nodes; 1604e4b17023SJohn Marino unsigned int i; 1605e4b17023SJohn Marino edge e; 1606e4b17023SJohn Marino edge_iterator ei; 1607e4b17023SJohn Marino 1608e4b17023SJohn Marino remove_conditions_and_labels (loop); 1609e4b17023SJohn Marino insert_gimplified_predicates (loop); 1610e4b17023SJohn Marino predicate_all_scalar_phis (loop); 1611e4b17023SJohn Marino 1612e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores) 1613e4b17023SJohn Marino predicate_mem_writes (loop); 1614e4b17023SJohn Marino 1615e4b17023SJohn Marino /* Merge basic blocks: first remove all the edges in the loop, 1616e4b17023SJohn Marino except for those from the exit block. */ 1617e4b17023SJohn Marino exit_bb = NULL; 1618e4b17023SJohn Marino for (i = 0; i < orig_loop_num_nodes; i++) 1619e4b17023SJohn Marino { 1620e4b17023SJohn Marino bb = ifc_bbs[i]; 1621e4b17023SJohn Marino free_bb_predicate (bb); 1622e4b17023SJohn Marino if (bb_with_exit_edge_p (loop, bb)) 1623e4b17023SJohn Marino { 1624e4b17023SJohn Marino exit_bb = bb; 1625e4b17023SJohn Marino break; 1626e4b17023SJohn Marino } 1627e4b17023SJohn Marino } 1628e4b17023SJohn Marino gcc_assert (exit_bb != loop->latch); 1629e4b17023SJohn Marino 1630e4b17023SJohn Marino for (i = 1; i < orig_loop_num_nodes; i++) 1631e4b17023SJohn Marino { 1632e4b17023SJohn Marino bb = ifc_bbs[i]; 1633e4b17023SJohn Marino 1634e4b17023SJohn Marino for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei));) 1635e4b17023SJohn Marino { 1636e4b17023SJohn Marino if (e->src == exit_bb) 1637e4b17023SJohn Marino ei_next (&ei); 1638e4b17023SJohn Marino else 1639e4b17023SJohn Marino remove_edge (e); 1640e4b17023SJohn Marino } 1641e4b17023SJohn Marino } 1642e4b17023SJohn Marino 1643e4b17023SJohn Marino if (exit_bb != NULL) 1644e4b17023SJohn Marino { 1645e4b17023SJohn Marino if (exit_bb != loop->header) 1646e4b17023SJohn Marino { 1647e4b17023SJohn Marino /* Connect this node to loop header. */ 1648e4b17023SJohn Marino make_edge (loop->header, exit_bb, EDGE_FALLTHRU); 1649e4b17023SJohn Marino set_immediate_dominator (CDI_DOMINATORS, exit_bb, loop->header); 1650e4b17023SJohn Marino } 1651e4b17023SJohn Marino 1652e4b17023SJohn Marino /* Redirect non-exit edges to loop->latch. */ 1653e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, exit_bb->succs) 1654e4b17023SJohn Marino { 1655e4b17023SJohn Marino if (!loop_exit_edge_p (loop, e)) 1656e4b17023SJohn Marino redirect_edge_and_branch (e, loop->latch); 1657e4b17023SJohn Marino } 1658e4b17023SJohn Marino set_immediate_dominator (CDI_DOMINATORS, loop->latch, exit_bb); 1659e4b17023SJohn Marino } 1660e4b17023SJohn Marino else 1661e4b17023SJohn Marino { 1662e4b17023SJohn Marino /* If the loop does not have an exit, reconnect header and latch. */ 1663e4b17023SJohn Marino make_edge (loop->header, loop->latch, EDGE_FALLTHRU); 1664e4b17023SJohn Marino set_immediate_dominator (CDI_DOMINATORS, loop->latch, loop->header); 1665e4b17023SJohn Marino } 1666e4b17023SJohn Marino 1667e4b17023SJohn Marino merge_target_bb = loop->header; 1668e4b17023SJohn Marino for (i = 1; i < orig_loop_num_nodes; i++) 1669e4b17023SJohn Marino { 1670e4b17023SJohn Marino gimple_stmt_iterator gsi; 1671e4b17023SJohn Marino gimple_stmt_iterator last; 1672e4b17023SJohn Marino 1673e4b17023SJohn Marino bb = ifc_bbs[i]; 1674e4b17023SJohn Marino 1675e4b17023SJohn Marino if (bb == exit_bb || bb == loop->latch) 1676e4b17023SJohn Marino continue; 1677e4b17023SJohn Marino 1678e4b17023SJohn Marino /* Make stmts member of loop->header. */ 1679e4b17023SJohn Marino for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 1680e4b17023SJohn Marino gimple_set_bb (gsi_stmt (gsi), merge_target_bb); 1681e4b17023SJohn Marino 1682e4b17023SJohn Marino /* Update stmt list. */ 1683e4b17023SJohn Marino last = gsi_last_bb (merge_target_bb); 1684e4b17023SJohn Marino gsi_insert_seq_after (&last, bb_seq (bb), GSI_NEW_STMT); 1685e4b17023SJohn Marino set_bb_seq (bb, NULL); 1686e4b17023SJohn Marino 1687e4b17023SJohn Marino delete_basic_block (bb); 1688e4b17023SJohn Marino } 1689e4b17023SJohn Marino 1690e4b17023SJohn Marino /* If possible, merge loop header to the block with the exit edge. 1691e4b17023SJohn Marino This reduces the number of basic blocks to two, to please the 1692e4b17023SJohn Marino vectorizer that handles only loops with two nodes. */ 1693e4b17023SJohn Marino if (exit_bb 1694e4b17023SJohn Marino && exit_bb != loop->header 1695e4b17023SJohn Marino && can_merge_blocks_p (loop->header, exit_bb)) 1696e4b17023SJohn Marino merge_blocks (loop->header, exit_bb); 1697e4b17023SJohn Marino 1698e4b17023SJohn Marino free (ifc_bbs); 1699e4b17023SJohn Marino ifc_bbs = NULL; 1700e4b17023SJohn Marino } 1701e4b17023SJohn Marino 1702e4b17023SJohn Marino /* If-convert LOOP when it is legal. For the moment this pass has no 1703e4b17023SJohn Marino profitability analysis. Returns true when something changed. */ 1704e4b17023SJohn Marino 1705e4b17023SJohn Marino static bool 1706e4b17023SJohn Marino tree_if_conversion (struct loop *loop) 1707e4b17023SJohn Marino { 1708e4b17023SJohn Marino bool changed = false; 1709e4b17023SJohn Marino ifc_bbs = NULL; 1710e4b17023SJohn Marino 1711e4b17023SJohn Marino if (!if_convertible_loop_p (loop) 1712e4b17023SJohn Marino || !dbg_cnt (if_conversion_tree)) 1713e4b17023SJohn Marino goto cleanup; 1714e4b17023SJohn Marino 1715e4b17023SJohn Marino /* Now all statements are if-convertible. Combine all the basic 1716e4b17023SJohn Marino blocks into one huge basic block doing the if-conversion 1717e4b17023SJohn Marino on-the-fly. */ 1718e4b17023SJohn Marino combine_blocks (loop); 1719e4b17023SJohn Marino 1720e4b17023SJohn Marino if (flag_tree_loop_if_convert_stores) 1721e4b17023SJohn Marino mark_sym_for_renaming (gimple_vop (cfun)); 1722e4b17023SJohn Marino 1723e4b17023SJohn Marino changed = true; 1724e4b17023SJohn Marino 1725e4b17023SJohn Marino cleanup: 1726e4b17023SJohn Marino if (ifc_bbs) 1727e4b17023SJohn Marino { 1728e4b17023SJohn Marino unsigned int i; 1729e4b17023SJohn Marino 1730e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++) 1731e4b17023SJohn Marino free_bb_predicate (ifc_bbs[i]); 1732e4b17023SJohn Marino 1733e4b17023SJohn Marino free (ifc_bbs); 1734e4b17023SJohn Marino ifc_bbs = NULL; 1735e4b17023SJohn Marino } 1736e4b17023SJohn Marino 1737e4b17023SJohn Marino return changed; 1738e4b17023SJohn Marino } 1739e4b17023SJohn Marino 1740e4b17023SJohn Marino /* Tree if-conversion pass management. */ 1741e4b17023SJohn Marino 1742e4b17023SJohn Marino static unsigned int 1743e4b17023SJohn Marino main_tree_if_conversion (void) 1744e4b17023SJohn Marino { 1745e4b17023SJohn Marino loop_iterator li; 1746e4b17023SJohn Marino struct loop *loop; 1747e4b17023SJohn Marino bool changed = false; 1748e4b17023SJohn Marino unsigned todo = 0; 1749e4b17023SJohn Marino 1750e4b17023SJohn Marino if (number_of_loops () <= 1) 1751e4b17023SJohn Marino return 0; 1752e4b17023SJohn Marino 1753e4b17023SJohn Marino FOR_EACH_LOOP (li, loop, 0) 1754e4b17023SJohn Marino changed |= tree_if_conversion (loop); 1755e4b17023SJohn Marino 1756e4b17023SJohn Marino if (changed) 1757e4b17023SJohn Marino todo |= TODO_cleanup_cfg; 1758e4b17023SJohn Marino 1759e4b17023SJohn Marino if (changed && flag_tree_loop_if_convert_stores) 1760e4b17023SJohn Marino todo |= TODO_update_ssa_only_virtuals; 1761e4b17023SJohn Marino 1762e4b17023SJohn Marino return todo; 1763e4b17023SJohn Marino } 1764e4b17023SJohn Marino 1765e4b17023SJohn Marino /* Returns true when the if-conversion pass is enabled. */ 1766e4b17023SJohn Marino 1767e4b17023SJohn Marino static bool 1768e4b17023SJohn Marino gate_tree_if_conversion (void) 1769e4b17023SJohn Marino { 1770e4b17023SJohn Marino return ((flag_tree_vectorize && flag_tree_loop_if_convert != 0) 1771e4b17023SJohn Marino || flag_tree_loop_if_convert == 1 1772e4b17023SJohn Marino || flag_tree_loop_if_convert_stores == 1); 1773e4b17023SJohn Marino } 1774e4b17023SJohn Marino 1775e4b17023SJohn Marino struct gimple_opt_pass pass_if_conversion = 1776e4b17023SJohn Marino { 1777e4b17023SJohn Marino { 1778e4b17023SJohn Marino GIMPLE_PASS, 1779e4b17023SJohn Marino "ifcvt", /* name */ 1780e4b17023SJohn Marino gate_tree_if_conversion, /* gate */ 1781e4b17023SJohn Marino main_tree_if_conversion, /* execute */ 1782e4b17023SJohn Marino NULL, /* sub */ 1783e4b17023SJohn Marino NULL, /* next */ 1784e4b17023SJohn Marino 0, /* static_pass_number */ 1785e4b17023SJohn Marino TV_NONE, /* tv_id */ 1786e4b17023SJohn Marino PROP_cfg | PROP_ssa, /* properties_required */ 1787e4b17023SJohn Marino 0, /* properties_provided */ 1788e4b17023SJohn Marino 0, /* properties_destroyed */ 1789e4b17023SJohn Marino 0, /* todo_flags_start */ 1790e4b17023SJohn Marino TODO_verify_stmts | TODO_verify_flow 1791e4b17023SJohn Marino /* todo_flags_finish */ 1792e4b17023SJohn Marino } 1793e4b17023SJohn Marino }; 1794