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