1*e4b17023SJohn Marino /* Loop unswitching. 2*e4b17023SJohn Marino Copyright (C) 2004, 2005, 2007, 2008, 2010 Free Software Foundation, Inc. 3*e4b17023SJohn Marino 4*e4b17023SJohn Marino This file is part of GCC. 5*e4b17023SJohn Marino 6*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it 7*e4b17023SJohn Marino under the terms of the GNU General Public License as published by the 8*e4b17023SJohn Marino Free Software Foundation; either version 3, or (at your option) any 9*e4b17023SJohn Marino later version. 10*e4b17023SJohn Marino 11*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT 12*e4b17023SJohn Marino ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14*e4b17023SJohn Marino for more details. 15*e4b17023SJohn Marino 16*e4b17023SJohn Marino You should have received a copy of the GNU General Public License 17*e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see 18*e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */ 19*e4b17023SJohn Marino 20*e4b17023SJohn Marino #include "config.h" 21*e4b17023SJohn Marino #include "system.h" 22*e4b17023SJohn Marino #include "coretypes.h" 23*e4b17023SJohn Marino #include "tm.h" 24*e4b17023SJohn Marino #include "tree.h" 25*e4b17023SJohn Marino #include "tm_p.h" 26*e4b17023SJohn Marino #include "basic-block.h" 27*e4b17023SJohn Marino #include "output.h" 28*e4b17023SJohn Marino #include "tree-flow.h" 29*e4b17023SJohn Marino #include "tree-dump.h" 30*e4b17023SJohn Marino #include "timevar.h" 31*e4b17023SJohn Marino #include "cfgloop.h" 32*e4b17023SJohn Marino #include "params.h" 33*e4b17023SJohn Marino #include "tree-pass.h" 34*e4b17023SJohn Marino #include "tree-inline.h" 35*e4b17023SJohn Marino 36*e4b17023SJohn Marino /* This file implements the loop unswitching, i.e. transformation of loops like 37*e4b17023SJohn Marino 38*e4b17023SJohn Marino while (A) 39*e4b17023SJohn Marino { 40*e4b17023SJohn Marino if (inv) 41*e4b17023SJohn Marino B; 42*e4b17023SJohn Marino 43*e4b17023SJohn Marino X; 44*e4b17023SJohn Marino 45*e4b17023SJohn Marino if (!inv) 46*e4b17023SJohn Marino C; 47*e4b17023SJohn Marino } 48*e4b17023SJohn Marino 49*e4b17023SJohn Marino where inv is the loop invariant, into 50*e4b17023SJohn Marino 51*e4b17023SJohn Marino if (inv) 52*e4b17023SJohn Marino { 53*e4b17023SJohn Marino while (A) 54*e4b17023SJohn Marino { 55*e4b17023SJohn Marino B; 56*e4b17023SJohn Marino X; 57*e4b17023SJohn Marino } 58*e4b17023SJohn Marino } 59*e4b17023SJohn Marino else 60*e4b17023SJohn Marino { 61*e4b17023SJohn Marino while (A) 62*e4b17023SJohn Marino { 63*e4b17023SJohn Marino X; 64*e4b17023SJohn Marino C; 65*e4b17023SJohn Marino } 66*e4b17023SJohn Marino } 67*e4b17023SJohn Marino 68*e4b17023SJohn Marino Inv is considered invariant iff the values it compares are both invariant; 69*e4b17023SJohn Marino tree-ssa-loop-im.c ensures that all the suitable conditions are in this 70*e4b17023SJohn Marino shape. */ 71*e4b17023SJohn Marino 72*e4b17023SJohn Marino static struct loop *tree_unswitch_loop (struct loop *, basic_block, tree); 73*e4b17023SJohn Marino static bool tree_unswitch_single_loop (struct loop *, int); 74*e4b17023SJohn Marino static tree tree_may_unswitch_on (basic_block, struct loop *); 75*e4b17023SJohn Marino 76*e4b17023SJohn Marino /* Main entry point. Perform loop unswitching on all suitable loops. */ 77*e4b17023SJohn Marino 78*e4b17023SJohn Marino unsigned int 79*e4b17023SJohn Marino tree_ssa_unswitch_loops (void) 80*e4b17023SJohn Marino { 81*e4b17023SJohn Marino loop_iterator li; 82*e4b17023SJohn Marino struct loop *loop; 83*e4b17023SJohn Marino bool changed = false; 84*e4b17023SJohn Marino 85*e4b17023SJohn Marino /* Go through inner loops (only original ones). */ 86*e4b17023SJohn Marino FOR_EACH_LOOP (li, loop, LI_ONLY_INNERMOST) 87*e4b17023SJohn Marino { 88*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 89*e4b17023SJohn Marino fprintf (dump_file, ";; Considering loop %d\n", loop->num); 90*e4b17023SJohn Marino 91*e4b17023SJohn Marino /* Do not unswitch in cold regions. */ 92*e4b17023SJohn Marino if (optimize_loop_for_size_p (loop)) 93*e4b17023SJohn Marino { 94*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 95*e4b17023SJohn Marino fprintf (dump_file, ";; Not unswitching cold loops\n"); 96*e4b17023SJohn Marino continue; 97*e4b17023SJohn Marino } 98*e4b17023SJohn Marino 99*e4b17023SJohn Marino /* The loop should not be too large, to limit code growth. */ 100*e4b17023SJohn Marino if (tree_num_loop_insns (loop, &eni_size_weights) 101*e4b17023SJohn Marino > (unsigned) PARAM_VALUE (PARAM_MAX_UNSWITCH_INSNS)) 102*e4b17023SJohn Marino { 103*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 104*e4b17023SJohn Marino fprintf (dump_file, ";; Not unswitching, loop too big\n"); 105*e4b17023SJohn Marino continue; 106*e4b17023SJohn Marino } 107*e4b17023SJohn Marino 108*e4b17023SJohn Marino changed |= tree_unswitch_single_loop (loop, 0); 109*e4b17023SJohn Marino } 110*e4b17023SJohn Marino 111*e4b17023SJohn Marino if (changed) 112*e4b17023SJohn Marino return TODO_cleanup_cfg; 113*e4b17023SJohn Marino return 0; 114*e4b17023SJohn Marino } 115*e4b17023SJohn Marino 116*e4b17023SJohn Marino /* Checks whether we can unswitch LOOP on condition at end of BB -- one of its 117*e4b17023SJohn Marino basic blocks (for what it means see comments below). */ 118*e4b17023SJohn Marino 119*e4b17023SJohn Marino static tree 120*e4b17023SJohn Marino tree_may_unswitch_on (basic_block bb, struct loop *loop) 121*e4b17023SJohn Marino { 122*e4b17023SJohn Marino gimple stmt, def; 123*e4b17023SJohn Marino tree cond, use; 124*e4b17023SJohn Marino basic_block def_bb; 125*e4b17023SJohn Marino ssa_op_iter iter; 126*e4b17023SJohn Marino 127*e4b17023SJohn Marino /* BB must end in a simple conditional jump. */ 128*e4b17023SJohn Marino stmt = last_stmt (bb); 129*e4b17023SJohn Marino if (!stmt || gimple_code (stmt) != GIMPLE_COND) 130*e4b17023SJohn Marino return NULL_TREE; 131*e4b17023SJohn Marino 132*e4b17023SJohn Marino /* To keep the things simple, we do not directly remove the conditions, 133*e4b17023SJohn Marino but just replace tests with 0 != 0 resp. 1 != 0. Prevent the infinite 134*e4b17023SJohn Marino loop where we would unswitch again on such a condition. */ 135*e4b17023SJohn Marino if (gimple_cond_true_p (stmt) || gimple_cond_false_p (stmt)) 136*e4b17023SJohn Marino return NULL_TREE; 137*e4b17023SJohn Marino 138*e4b17023SJohn Marino /* Condition must be invariant. */ 139*e4b17023SJohn Marino FOR_EACH_SSA_TREE_OPERAND (use, stmt, iter, SSA_OP_USE) 140*e4b17023SJohn Marino { 141*e4b17023SJohn Marino def = SSA_NAME_DEF_STMT (use); 142*e4b17023SJohn Marino def_bb = gimple_bb (def); 143*e4b17023SJohn Marino if (def_bb 144*e4b17023SJohn Marino && flow_bb_inside_loop_p (loop, def_bb)) 145*e4b17023SJohn Marino return NULL_TREE; 146*e4b17023SJohn Marino } 147*e4b17023SJohn Marino 148*e4b17023SJohn Marino cond = build2 (gimple_cond_code (stmt), boolean_type_node, 149*e4b17023SJohn Marino gimple_cond_lhs (stmt), gimple_cond_rhs (stmt)); 150*e4b17023SJohn Marino 151*e4b17023SJohn Marino return cond; 152*e4b17023SJohn Marino } 153*e4b17023SJohn Marino 154*e4b17023SJohn Marino /* Simplifies COND using checks in front of the entry of the LOOP. Just very 155*e4b17023SJohn Marino simplish (sufficient to prevent us from duplicating loop in unswitching 156*e4b17023SJohn Marino unnecessarily). */ 157*e4b17023SJohn Marino 158*e4b17023SJohn Marino static tree 159*e4b17023SJohn Marino simplify_using_entry_checks (struct loop *loop, tree cond) 160*e4b17023SJohn Marino { 161*e4b17023SJohn Marino edge e = loop_preheader_edge (loop); 162*e4b17023SJohn Marino gimple stmt; 163*e4b17023SJohn Marino 164*e4b17023SJohn Marino while (1) 165*e4b17023SJohn Marino { 166*e4b17023SJohn Marino stmt = last_stmt (e->src); 167*e4b17023SJohn Marino if (stmt 168*e4b17023SJohn Marino && gimple_code (stmt) == GIMPLE_COND 169*e4b17023SJohn Marino && gimple_cond_code (stmt) == TREE_CODE (cond) 170*e4b17023SJohn Marino && operand_equal_p (gimple_cond_lhs (stmt), 171*e4b17023SJohn Marino TREE_OPERAND (cond, 0), 0) 172*e4b17023SJohn Marino && operand_equal_p (gimple_cond_rhs (stmt), 173*e4b17023SJohn Marino TREE_OPERAND (cond, 1), 0)) 174*e4b17023SJohn Marino return (e->flags & EDGE_TRUE_VALUE 175*e4b17023SJohn Marino ? boolean_true_node 176*e4b17023SJohn Marino : boolean_false_node); 177*e4b17023SJohn Marino 178*e4b17023SJohn Marino if (!single_pred_p (e->src)) 179*e4b17023SJohn Marino return cond; 180*e4b17023SJohn Marino 181*e4b17023SJohn Marino e = single_pred_edge (e->src); 182*e4b17023SJohn Marino if (e->src == ENTRY_BLOCK_PTR) 183*e4b17023SJohn Marino return cond; 184*e4b17023SJohn Marino } 185*e4b17023SJohn Marino } 186*e4b17023SJohn Marino 187*e4b17023SJohn Marino /* Unswitch single LOOP. NUM is number of unswitchings done; we do not allow 188*e4b17023SJohn Marino it to grow too much, it is too easy to create example on that the code would 189*e4b17023SJohn Marino grow exponentially. */ 190*e4b17023SJohn Marino 191*e4b17023SJohn Marino static bool 192*e4b17023SJohn Marino tree_unswitch_single_loop (struct loop *loop, int num) 193*e4b17023SJohn Marino { 194*e4b17023SJohn Marino basic_block *bbs; 195*e4b17023SJohn Marino struct loop *nloop; 196*e4b17023SJohn Marino unsigned i, found; 197*e4b17023SJohn Marino tree cond = NULL_TREE; 198*e4b17023SJohn Marino gimple stmt; 199*e4b17023SJohn Marino bool changed = false; 200*e4b17023SJohn Marino 201*e4b17023SJohn Marino i = 0; 202*e4b17023SJohn Marino bbs = get_loop_body (loop); 203*e4b17023SJohn Marino found = loop->num_nodes; 204*e4b17023SJohn Marino 205*e4b17023SJohn Marino while (1) 206*e4b17023SJohn Marino { 207*e4b17023SJohn Marino /* Find a bb to unswitch on. */ 208*e4b17023SJohn Marino for (; i < loop->num_nodes; i++) 209*e4b17023SJohn Marino if ((cond = tree_may_unswitch_on (bbs[i], loop))) 210*e4b17023SJohn Marino break; 211*e4b17023SJohn Marino 212*e4b17023SJohn Marino if (i == loop->num_nodes) 213*e4b17023SJohn Marino { 214*e4b17023SJohn Marino if (dump_file 215*e4b17023SJohn Marino && num > PARAM_VALUE (PARAM_MAX_UNSWITCH_LEVEL) 216*e4b17023SJohn Marino && (dump_flags & TDF_DETAILS)) 217*e4b17023SJohn Marino fprintf (dump_file, ";; Not unswitching anymore, hit max level\n"); 218*e4b17023SJohn Marino 219*e4b17023SJohn Marino if (found == loop->num_nodes) 220*e4b17023SJohn Marino { 221*e4b17023SJohn Marino free (bbs); 222*e4b17023SJohn Marino return changed; 223*e4b17023SJohn Marino } 224*e4b17023SJohn Marino break; 225*e4b17023SJohn Marino } 226*e4b17023SJohn Marino 227*e4b17023SJohn Marino cond = simplify_using_entry_checks (loop, cond); 228*e4b17023SJohn Marino stmt = last_stmt (bbs[i]); 229*e4b17023SJohn Marino if (integer_nonzerop (cond)) 230*e4b17023SJohn Marino { 231*e4b17023SJohn Marino /* Remove false path. */ 232*e4b17023SJohn Marino gimple_cond_set_condition_from_tree (stmt, boolean_true_node); 233*e4b17023SJohn Marino changed = true; 234*e4b17023SJohn Marino } 235*e4b17023SJohn Marino else if (integer_zerop (cond)) 236*e4b17023SJohn Marino { 237*e4b17023SJohn Marino /* Remove true path. */ 238*e4b17023SJohn Marino gimple_cond_set_condition_from_tree (stmt, boolean_false_node); 239*e4b17023SJohn Marino changed = true; 240*e4b17023SJohn Marino } 241*e4b17023SJohn Marino /* Do not unswitch too much. */ 242*e4b17023SJohn Marino else if (num > PARAM_VALUE (PARAM_MAX_UNSWITCH_LEVEL)) 243*e4b17023SJohn Marino { 244*e4b17023SJohn Marino i++; 245*e4b17023SJohn Marino continue; 246*e4b17023SJohn Marino } 247*e4b17023SJohn Marino /* In nested tree_unswitch_single_loop first optimize all conditions 248*e4b17023SJohn Marino using entry checks, then discover still reachable blocks in the 249*e4b17023SJohn Marino loop and find the condition only among those still reachable bbs. */ 250*e4b17023SJohn Marino else if (num != 0) 251*e4b17023SJohn Marino { 252*e4b17023SJohn Marino if (found == loop->num_nodes) 253*e4b17023SJohn Marino found = i; 254*e4b17023SJohn Marino i++; 255*e4b17023SJohn Marino continue; 256*e4b17023SJohn Marino } 257*e4b17023SJohn Marino else 258*e4b17023SJohn Marino { 259*e4b17023SJohn Marino found = i; 260*e4b17023SJohn Marino break; 261*e4b17023SJohn Marino } 262*e4b17023SJohn Marino 263*e4b17023SJohn Marino update_stmt (stmt); 264*e4b17023SJohn Marino i++; 265*e4b17023SJohn Marino } 266*e4b17023SJohn Marino 267*e4b17023SJohn Marino if (num != 0) 268*e4b17023SJohn Marino { 269*e4b17023SJohn Marino basic_block *tos, *worklist; 270*e4b17023SJohn Marino 271*e4b17023SJohn Marino /* When called recursively, first do a quick discovery 272*e4b17023SJohn Marino of reachable bbs after the above changes and only 273*e4b17023SJohn Marino consider conditions in still reachable bbs. */ 274*e4b17023SJohn Marino tos = worklist = XNEWVEC (basic_block, loop->num_nodes); 275*e4b17023SJohn Marino 276*e4b17023SJohn Marino for (i = 0; i < loop->num_nodes; i++) 277*e4b17023SJohn Marino bbs[i]->flags &= ~BB_REACHABLE; 278*e4b17023SJohn Marino 279*e4b17023SJohn Marino /* Start with marking header. */ 280*e4b17023SJohn Marino *tos++ = bbs[0]; 281*e4b17023SJohn Marino bbs[0]->flags |= BB_REACHABLE; 282*e4b17023SJohn Marino 283*e4b17023SJohn Marino /* Iterate: find everything reachable from what we've already seen 284*e4b17023SJohn Marino within the same innermost loop. Don't look through false edges 285*e4b17023SJohn Marino if condition is always true or true edges if condition is 286*e4b17023SJohn Marino always false. */ 287*e4b17023SJohn Marino while (tos != worklist) 288*e4b17023SJohn Marino { 289*e4b17023SJohn Marino basic_block b = *--tos; 290*e4b17023SJohn Marino edge e; 291*e4b17023SJohn Marino edge_iterator ei; 292*e4b17023SJohn Marino int flags = 0; 293*e4b17023SJohn Marino 294*e4b17023SJohn Marino if (EDGE_COUNT (b->succs) == 2) 295*e4b17023SJohn Marino { 296*e4b17023SJohn Marino gimple stmt = last_stmt (b); 297*e4b17023SJohn Marino if (stmt 298*e4b17023SJohn Marino && gimple_code (stmt) == GIMPLE_COND) 299*e4b17023SJohn Marino { 300*e4b17023SJohn Marino if (gimple_cond_true_p (stmt)) 301*e4b17023SJohn Marino flags = EDGE_FALSE_VALUE; 302*e4b17023SJohn Marino else if (gimple_cond_false_p (stmt)) 303*e4b17023SJohn Marino flags = EDGE_TRUE_VALUE; 304*e4b17023SJohn Marino } 305*e4b17023SJohn Marino } 306*e4b17023SJohn Marino 307*e4b17023SJohn Marino FOR_EACH_EDGE (e, ei, b->succs) 308*e4b17023SJohn Marino { 309*e4b17023SJohn Marino basic_block dest = e->dest; 310*e4b17023SJohn Marino 311*e4b17023SJohn Marino if (dest->loop_father == loop 312*e4b17023SJohn Marino && !(dest->flags & BB_REACHABLE) 313*e4b17023SJohn Marino && !(e->flags & flags)) 314*e4b17023SJohn Marino { 315*e4b17023SJohn Marino *tos++ = dest; 316*e4b17023SJohn Marino dest->flags |= BB_REACHABLE; 317*e4b17023SJohn Marino } 318*e4b17023SJohn Marino } 319*e4b17023SJohn Marino } 320*e4b17023SJohn Marino 321*e4b17023SJohn Marino free (worklist); 322*e4b17023SJohn Marino 323*e4b17023SJohn Marino /* Find a bb to unswitch on. */ 324*e4b17023SJohn Marino for (; found < loop->num_nodes; found++) 325*e4b17023SJohn Marino if ((bbs[found]->flags & BB_REACHABLE) 326*e4b17023SJohn Marino && (cond = tree_may_unswitch_on (bbs[found], loop))) 327*e4b17023SJohn Marino break; 328*e4b17023SJohn Marino 329*e4b17023SJohn Marino if (found == loop->num_nodes) 330*e4b17023SJohn Marino { 331*e4b17023SJohn Marino free (bbs); 332*e4b17023SJohn Marino return changed; 333*e4b17023SJohn Marino } 334*e4b17023SJohn Marino } 335*e4b17023SJohn Marino 336*e4b17023SJohn Marino if (dump_file && (dump_flags & TDF_DETAILS)) 337*e4b17023SJohn Marino fprintf (dump_file, ";; Unswitching loop\n"); 338*e4b17023SJohn Marino 339*e4b17023SJohn Marino initialize_original_copy_tables (); 340*e4b17023SJohn Marino /* Unswitch the loop on this condition. */ 341*e4b17023SJohn Marino nloop = tree_unswitch_loop (loop, bbs[found], cond); 342*e4b17023SJohn Marino if (!nloop) 343*e4b17023SJohn Marino { 344*e4b17023SJohn Marino free_original_copy_tables (); 345*e4b17023SJohn Marino free (bbs); 346*e4b17023SJohn Marino return changed; 347*e4b17023SJohn Marino } 348*e4b17023SJohn Marino 349*e4b17023SJohn Marino /* Update the SSA form after unswitching. */ 350*e4b17023SJohn Marino update_ssa (TODO_update_ssa); 351*e4b17023SJohn Marino free_original_copy_tables (); 352*e4b17023SJohn Marino 353*e4b17023SJohn Marino /* Invoke itself on modified loops. */ 354*e4b17023SJohn Marino tree_unswitch_single_loop (nloop, num + 1); 355*e4b17023SJohn Marino tree_unswitch_single_loop (loop, num + 1); 356*e4b17023SJohn Marino free (bbs); 357*e4b17023SJohn Marino return true; 358*e4b17023SJohn Marino } 359*e4b17023SJohn Marino 360*e4b17023SJohn Marino /* Unswitch a LOOP w.r. to given basic block UNSWITCH_ON. We only support 361*e4b17023SJohn Marino unswitching of innermost loops. COND is the condition determining which 362*e4b17023SJohn Marino loop is entered -- the new loop is entered if COND is true. Returns NULL 363*e4b17023SJohn Marino if impossible, new loop otherwise. */ 364*e4b17023SJohn Marino 365*e4b17023SJohn Marino static struct loop * 366*e4b17023SJohn Marino tree_unswitch_loop (struct loop *loop, 367*e4b17023SJohn Marino basic_block unswitch_on, tree cond) 368*e4b17023SJohn Marino { 369*e4b17023SJohn Marino unsigned prob_true; 370*e4b17023SJohn Marino edge edge_true, edge_false; 371*e4b17023SJohn Marino 372*e4b17023SJohn Marino /* Some sanity checking. */ 373*e4b17023SJohn Marino gcc_assert (flow_bb_inside_loop_p (loop, unswitch_on)); 374*e4b17023SJohn Marino gcc_assert (EDGE_COUNT (unswitch_on->succs) == 2); 375*e4b17023SJohn Marino gcc_assert (loop->inner == NULL); 376*e4b17023SJohn Marino 377*e4b17023SJohn Marino extract_true_false_edges_from_block (unswitch_on, &edge_true, &edge_false); 378*e4b17023SJohn Marino prob_true = edge_true->probability; 379*e4b17023SJohn Marino return loop_version (loop, unshare_expr (cond), 380*e4b17023SJohn Marino NULL, prob_true, prob_true, 381*e4b17023SJohn Marino REG_BR_PROB_BASE - prob_true, false); 382*e4b17023SJohn Marino } 383