1 1.1 mrg /* Support routines for Splitting Paths to loop backedges 2 1.1 mrg Copyright (C) 2015-2022 Free Software Foundation, Inc. 3 1.1 mrg Contributed by Ajit Kumar Agarwal <ajitkum (at) xilinx.com>. 4 1.1 mrg 5 1.1 mrg This file is part of GCC. 6 1.1 mrg 7 1.1 mrg GCC is free software; you can redistribute it and/or modify 8 1.1 mrg it under the terms of the GNU General Public License as published by 9 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 10 1.1 mrg any later version. 11 1.1 mrg 12 1.1 mrg GCC is distributed in the hope that it will be useful, 13 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 mrg GNU General Public License for more details. 16 1.1 mrg 17 1.1 mrg You should have received a copy of the GNU General Public License 18 1.1 mrg along with GCC; see the file COPYING3. If not see 19 1.1 mrg <http://www.gnu.org/licenses/>. */ 20 1.1 mrg 21 1.1 mrg #include "config.h" 22 1.1 mrg #include "system.h" 23 1.1 mrg #include "coretypes.h" 24 1.1 mrg #include "backend.h" 25 1.1 mrg #include "tree.h" 26 1.1 mrg #include "gimple.h" 27 1.1 mrg #include "tree-pass.h" 28 1.1 mrg #include "tree-cfg.h" 29 1.1 mrg #include "cfganal.h" 30 1.1 mrg #include "cfgloop.h" 31 1.1 mrg #include "gimple-iterator.h" 32 1.1 mrg #include "tracer.h" 33 1.1 mrg #include "predict.h" 34 1.1 mrg #include "gimple-ssa.h" 35 1.1 mrg #include "tree-phinodes.h" 36 1.1 mrg #include "ssa-iterators.h" 37 1.1 mrg #include "fold-const.h" 38 1.1 mrg 39 1.1 mrg /* Given LATCH, the latch block in a loop, see if the shape of the 40 1.1 mrg path reaching LATCH is suitable for being split by duplication. 41 1.1 mrg If so, return the block that will be duplicated into its predecessor 42 1.1 mrg paths. Else return NULL. */ 43 1.1 mrg 44 1.1 mrg static basic_block 45 1.1 mrg find_block_to_duplicate_for_splitting_paths (basic_block latch) 46 1.1 mrg { 47 1.1 mrg /* We should have simple latches at this point. So the latch should 48 1.1 mrg have a single successor. This implies the predecessor of the latch 49 1.1 mrg likely has the loop exit. And it's that predecessor we're most 50 1.1 mrg interested in. To keep things simple, we're going to require that 51 1.1 mrg the latch have a single predecessor too. */ 52 1.1 mrg if (single_succ_p (latch) && single_pred_p (latch)) 53 1.1 mrg { 54 1.1 mrg basic_block bb = get_immediate_dominator (CDI_DOMINATORS, latch); 55 1.1 mrg gcc_assert (single_pred_edge (latch)->src == bb); 56 1.1 mrg 57 1.1 mrg /* If BB has been marked as not to be duplicated, then honor that 58 1.1 mrg request. */ 59 1.1 mrg if (ignore_bb_p (bb)) 60 1.1 mrg return NULL; 61 1.1 mrg 62 1.1 mrg gimple *last = gsi_stmt (gsi_last_nondebug_bb (bb)); 63 1.1 mrg /* The immediate dominator of the latch must end in a conditional. */ 64 1.1 mrg if (!last || gimple_code (last) != GIMPLE_COND) 65 1.1 mrg return NULL; 66 1.1 mrg 67 1.1 mrg /* We're hoping that BB is a join point for an IF-THEN-ELSE diamond 68 1.1 mrg region. Verify that it is. 69 1.1 mrg 70 1.1 mrg First, verify that BB has two predecessors (each arm of the 71 1.1 mrg IF-THEN-ELSE) and two successors (the latch and exit) and that 72 1.1 mrg all edges are normal. */ 73 1.1 mrg if (EDGE_COUNT (bb->preds) == 2 74 1.1 mrg && !(EDGE_PRED (bb, 0)->flags & EDGE_COMPLEX) 75 1.1 mrg && !(EDGE_PRED (bb, 1)->flags & EDGE_COMPLEX) 76 1.1 mrg && EDGE_COUNT (bb->succs) == 2 77 1.1 mrg && !(EDGE_SUCC (bb, 0)->flags & EDGE_COMPLEX) 78 1.1 mrg && !(EDGE_SUCC (bb, 1)->flags & EDGE_COMPLEX)) 79 1.1 mrg { 80 1.1 mrg /* Now verify that BB's immediate dominator ends in a 81 1.1 mrg conditional as well. */ 82 1.1 mrg basic_block bb_idom = get_immediate_dominator (CDI_DOMINATORS, bb); 83 1.1 mrg gimple *last = gsi_stmt (gsi_last_nondebug_bb (bb_idom)); 84 1.1 mrg if (!last || gimple_code (last) != GIMPLE_COND) 85 1.1 mrg return NULL; 86 1.1 mrg 87 1.1 mrg /* And that BB's immediate dominator's successors are the 88 1.1 mrg predecessors of BB or BB itself. */ 89 1.1 mrg if (!(EDGE_PRED (bb, 0)->src == bb_idom 90 1.1 mrg || find_edge (bb_idom, EDGE_PRED (bb, 0)->src)) 91 1.1 mrg || !(EDGE_PRED (bb, 1)->src == bb_idom 92 1.1 mrg || find_edge (bb_idom, EDGE_PRED (bb, 1)->src))) 93 1.1 mrg return NULL; 94 1.1 mrg 95 1.1 mrg /* And that the predecessors of BB each have a single successor 96 1.1 mrg or are BB's immediate domiator itself. */ 97 1.1 mrg if (!(EDGE_PRED (bb, 0)->src == bb_idom 98 1.1 mrg || single_succ_p (EDGE_PRED (bb, 0)->src)) 99 1.1 mrg || !(EDGE_PRED (bb, 1)->src == bb_idom 100 1.1 mrg || single_succ_p (EDGE_PRED (bb, 1)->src))) 101 1.1 mrg return NULL; 102 1.1 mrg 103 1.1 mrg /* So at this point we have a simple diamond for an IF-THEN-ELSE 104 1.1 mrg construct starting at BB_IDOM, with a join point at BB. BB 105 1.1 mrg pass control outside the loop or to the loop latch. 106 1.1 mrg 107 1.1 mrg We're going to want to create two duplicates of BB, one for 108 1.1 mrg each successor of BB_IDOM. */ 109 1.1 mrg return bb; 110 1.1 mrg } 111 1.1 mrg } 112 1.1 mrg return NULL; 113 1.1 mrg } 114 1.1 mrg 115 1.1 mrg /* Return the number of non-debug statements in a block. */ 116 1.1 mrg static unsigned int 117 1.1 mrg count_stmts_in_block (basic_block bb) 118 1.1 mrg { 119 1.1 mrg gimple_stmt_iterator gsi; 120 1.1 mrg unsigned int num_stmts = 0; 121 1.1 mrg 122 1.1 mrg for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 123 1.1 mrg { 124 1.1 mrg gimple *stmt = gsi_stmt (gsi); 125 1.1 mrg if (!is_gimple_debug (stmt)) 126 1.1 mrg num_stmts++; 127 1.1 mrg } 128 1.1 mrg return num_stmts; 129 1.1 mrg } 130 1.1 mrg 131 1.1 mrg /* Return TRUE if CODE represents a tree code that is not likely to 132 1.1 mrg be easily if-convertable because it likely expands into multiple 133 1.1 mrg insns, FALSE otherwise. */ 134 1.1 mrg static bool 135 1.1 mrg poor_ifcvt_candidate_code (enum tree_code code) 136 1.1 mrg { 137 1.1 mrg return (code == MIN_EXPR 138 1.1 mrg || code == MAX_EXPR 139 1.1 mrg || code == ABS_EXPR 140 1.1 mrg || code == COND_EXPR 141 1.1 mrg || code == CALL_EXPR); 142 1.1 mrg } 143 1.1 mrg 144 1.1 mrg /* Return TRUE if BB is a reasonable block to duplicate by examining 145 1.1 mrg its size, false otherwise. BB will always be a loop latch block. 146 1.1 mrg 147 1.1 mrg Things to consider: 148 1.1 mrg 149 1.1 mrg We do not want to spoil if-conversion if at all possible. 150 1.1 mrg 151 1.1 mrg Most of the benefit seems to be from eliminating the unconditional 152 1.1 mrg jump rather than CSE/DCE opportunities. So favor duplicating 153 1.1 mrg small latches. A latch with just a conditional branch is ideal. 154 1.1 mrg 155 1.1 mrg CSE/DCE opportunties crop up when statements from the predecessors 156 1.1 mrg feed statements in the latch and allow statements in the latch to 157 1.1 mrg simplify. */ 158 1.1 mrg 159 1.1 mrg static bool 160 1.1 mrg is_feasible_trace (basic_block bb) 161 1.1 mrg { 162 1.1 mrg basic_block pred1 = EDGE_PRED (bb, 0)->src; 163 1.1 mrg basic_block pred2 = EDGE_PRED (bb, 1)->src; 164 1.1 mrg int num_stmts_in_join = count_stmts_in_block (bb); 165 1.1 mrg int num_stmts_in_pred1 166 1.1 mrg = EDGE_COUNT (pred1->succs) == 1 ? count_stmts_in_block (pred1) : 0; 167 1.1 mrg int num_stmts_in_pred2 168 1.1 mrg = EDGE_COUNT (pred2->succs) == 1 ? count_stmts_in_block (pred2) : 0; 169 1.1 mrg 170 1.1 mrg /* This is meant to catch cases that are likely opportunities for 171 1.1 mrg if-conversion. Essentially we look for the case where 172 1.1 mrg BB's predecessors are both single statement blocks where 173 1.1 mrg the output of that statement feed the same PHI in BB. */ 174 1.1 mrg if (num_stmts_in_pred1 == 1 && num_stmts_in_pred2 == 1) 175 1.1 mrg { 176 1.1 mrg gimple *stmt1 = last_and_only_stmt (pred1); 177 1.1 mrg gimple *stmt2 = last_and_only_stmt (pred2); 178 1.1 mrg 179 1.1 mrg if (stmt1 && stmt2 180 1.1 mrg && gimple_code (stmt1) == GIMPLE_ASSIGN 181 1.1 mrg && gimple_code (stmt2) == GIMPLE_ASSIGN) 182 1.1 mrg { 183 1.1 mrg enum tree_code code1 = gimple_assign_rhs_code (stmt1); 184 1.1 mrg enum tree_code code2 = gimple_assign_rhs_code (stmt2); 185 1.1 mrg 186 1.1 mrg if (!poor_ifcvt_candidate_code (code1) 187 1.1 mrg && !poor_ifcvt_candidate_code (code2)) 188 1.1 mrg { 189 1.1 mrg tree lhs1 = gimple_assign_lhs (stmt1); 190 1.1 mrg tree lhs2 = gimple_assign_lhs (stmt2); 191 1.1 mrg gimple_stmt_iterator gsi; 192 1.1 mrg for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 193 1.1 mrg { 194 1.1 mrg gimple *phi = gsi_stmt (gsi); 195 1.1 mrg if ((gimple_phi_arg_def (phi, 0) == lhs1 196 1.1 mrg && gimple_phi_arg_def (phi, 1) == lhs2) 197 1.1 mrg || (gimple_phi_arg_def (phi, 1) == lhs1 198 1.1 mrg && gimple_phi_arg_def (phi, 0) == lhs2)) 199 1.1 mrg { 200 1.1 mrg if (dump_file && (dump_flags & TDF_DETAILS)) 201 1.1 mrg fprintf (dump_file, 202 1.1 mrg "Block %d appears to be a join point for " 203 1.1 mrg "if-convertable diamond.\n", 204 1.1 mrg bb->index); 205 1.1 mrg return false; 206 1.1 mrg } 207 1.1 mrg } 208 1.1 mrg } 209 1.1 mrg } 210 1.1 mrg } 211 1.1 mrg 212 1.1 mrg /* Canonicalize the form. */ 213 1.1 mrg if (num_stmts_in_pred1 == 0 && num_stmts_in_pred2 == 1) 214 1.1 mrg { 215 1.1 mrg std::swap (pred1, pred2); 216 1.1 mrg std::swap (num_stmts_in_pred1, num_stmts_in_pred2); 217 1.1 mrg } 218 1.1 mrg 219 1.1 mrg /* Another variant. This one is half-diamond. */ 220 1.1 mrg if (num_stmts_in_pred1 == 1 && num_stmts_in_pred2 == 0 221 1.1 mrg && dominated_by_p (CDI_DOMINATORS, pred1, pred2)) 222 1.1 mrg { 223 1.1 mrg gimple *stmt1 = last_and_only_stmt (pred1); 224 1.1 mrg 225 1.1 mrg /* The only statement in PRED1 must be an assignment that is 226 1.1 mrg not a good candidate for if-conversion. This may need some 227 1.1 mrg generalization. */ 228 1.1 mrg if (stmt1 && gimple_code (stmt1) == GIMPLE_ASSIGN) 229 1.1 mrg { 230 1.1 mrg enum tree_code code1 = gimple_assign_rhs_code (stmt1); 231 1.1 mrg 232 1.1 mrg if (!poor_ifcvt_candidate_code (code1)) 233 1.1 mrg { 234 1.1 mrg tree lhs1 = gimple_assign_lhs (stmt1); 235 1.1 mrg tree rhs1 = gimple_assign_rhs1 (stmt1); 236 1.1 mrg 237 1.1 mrg gimple_stmt_iterator gsi; 238 1.1 mrg for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 239 1.1 mrg { 240 1.1 mrg gimple *phi = gsi_stmt (gsi); 241 1.1 mrg if ((gimple_phi_arg_def (phi, 0) == lhs1 242 1.1 mrg && gimple_phi_arg_def (phi, 1) == rhs1) 243 1.1 mrg || (gimple_phi_arg_def (phi, 1) == lhs1 244 1.1 mrg && gimple_phi_arg_def (phi, 0) == rhs1)) 245 1.1 mrg { 246 1.1 mrg if (dump_file && (dump_flags & TDF_DETAILS)) 247 1.1 mrg fprintf (dump_file, 248 1.1 mrg "Block %d appears to be a join point for " 249 1.1 mrg "if-convertable half-diamond.\n", 250 1.1 mrg bb->index); 251 1.1 mrg return false; 252 1.1 mrg } 253 1.1 mrg } 254 1.1 mrg } 255 1.1 mrg } 256 1.1 mrg } 257 1.1 mrg 258 1.1 mrg /* Canonicalize the form. */ 259 1.1 mrg if (single_pred_p (pred1) && single_pred (pred1) == pred2 260 1.1 mrg && num_stmts_in_pred1 == 0) 261 1.1 mrg std::swap (pred1, pred2); 262 1.1 mrg 263 1.1 mrg /* This is meant to catch another kind of cases that are likely opportunities 264 1.1 mrg for if-conversion. After canonicalizing, PRED2 must be an empty block and 265 1.1 mrg PRED1 must be the only predecessor of PRED2. Moreover, PRED1 is supposed 266 1.1 mrg to end with a cond_stmt which has the same args with the PHI in BB. */ 267 1.1 mrg if (single_pred_p (pred2) && single_pred (pred2) == pred1 268 1.1 mrg && num_stmts_in_pred2 == 0) 269 1.1 mrg { 270 1.1 mrg gimple *cond_stmt = last_stmt (pred1); 271 1.1 mrg if (cond_stmt && gimple_code (cond_stmt) == GIMPLE_COND) 272 1.1 mrg { 273 1.1 mrg tree lhs = gimple_cond_lhs (cond_stmt); 274 1.1 mrg tree rhs = gimple_cond_rhs (cond_stmt); 275 1.1 mrg 276 1.1 mrg gimple_stmt_iterator gsi; 277 1.1 mrg for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi)) 278 1.1 mrg { 279 1.1 mrg gimple *phi = gsi_stmt (gsi); 280 1.1 mrg if ((operand_equal_p (gimple_phi_arg_def (phi, 0), lhs) 281 1.1 mrg && operand_equal_p (gimple_phi_arg_def (phi, 1), rhs)) 282 1.1 mrg || (operand_equal_p (gimple_phi_arg_def (phi, 0), rhs) 283 1.1 mrg && (operand_equal_p (gimple_phi_arg_def (phi, 1), lhs)))) 284 1.1 mrg { 285 1.1 mrg if (dump_file && (dump_flags & TDF_DETAILS)) 286 1.1 mrg fprintf (dump_file, 287 1.1 mrg "Block %d appears to be optimized to a join " 288 1.1 mrg "point for if-convertable half-diamond.\n", 289 1.1 mrg bb->index); 290 1.1 mrg return false; 291 1.1 mrg } 292 1.1 mrg } 293 1.1 mrg } 294 1.1 mrg } 295 1.1 mrg 296 1.1 mrg /* If the joiner has no PHIs with useful uses there is zero chance 297 1.1 mrg of CSE/DCE/jump-threading possibilities exposed by duplicating it. */ 298 1.1 mrg bool found_useful_phi = false; 299 1.1 mrg for (gphi_iterator si = gsi_start_phis (bb); ! gsi_end_p (si); 300 1.1 mrg gsi_next (&si)) 301 1.1 mrg { 302 1.1 mrg gphi *phi = si.phi (); 303 1.1 mrg use_operand_p use_p; 304 1.1 mrg imm_use_iterator iter; 305 1.1 mrg FOR_EACH_IMM_USE_FAST (use_p, iter, gimple_phi_result (phi)) 306 1.1 mrg { 307 1.1 mrg gimple *stmt = USE_STMT (use_p); 308 1.1 mrg if (is_gimple_debug (stmt)) 309 1.1 mrg continue; 310 1.1 mrg /* If there's a use in the joiner this might be a CSE/DCE 311 1.1 mrg opportunity, but not if the use is in a conditional 312 1.1 mrg which makes this a likely if-conversion candidate. */ 313 1.1 mrg if (gimple_bb (stmt) == bb 314 1.1 mrg && (!is_gimple_assign (stmt) 315 1.1 mrg || (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) 316 1.1 mrg != tcc_comparison))) 317 1.1 mrg { 318 1.1 mrg found_useful_phi = true; 319 1.1 mrg break; 320 1.1 mrg } 321 1.1 mrg /* If the use is on a loop header PHI and on one path the 322 1.1 mrg value is unchanged this might expose a jump threading 323 1.1 mrg opportunity. */ 324 1.1 mrg if (gimple_code (stmt) == GIMPLE_PHI 325 1.1 mrg && gimple_bb (stmt) == bb->loop_father->header 326 1.1 mrg /* But for memory the PHI alone isn't good enough. */ 327 1.1 mrg && ! virtual_operand_p (gimple_phi_result (stmt))) 328 1.1 mrg { 329 1.1 mrg bool found_unchanged_path = false; 330 1.1 mrg for (unsigned i = 0; i < gimple_phi_num_args (phi); ++i) 331 1.1 mrg if (gimple_phi_arg_def (phi, i) == gimple_phi_result (stmt)) 332 1.1 mrg { 333 1.1 mrg found_unchanged_path = true; 334 1.1 mrg break; 335 1.1 mrg } 336 1.1 mrg /* If we found an unchanged path this can only be a threading 337 1.1 mrg opportunity if we have uses of the loop header PHI result 338 1.1 mrg in a stmt dominating the merge block. Otherwise the 339 1.1 mrg splitting may prevent if-conversion. */ 340 1.1 mrg if (found_unchanged_path) 341 1.1 mrg { 342 1.1 mrg use_operand_p use2_p; 343 1.1 mrg imm_use_iterator iter2; 344 1.1 mrg FOR_EACH_IMM_USE_FAST (use2_p, iter2, gimple_phi_result (stmt)) 345 1.1 mrg { 346 1.1 mrg gimple *use_stmt = USE_STMT (use2_p); 347 1.1 mrg if (is_gimple_debug (use_stmt)) 348 1.1 mrg continue; 349 1.1 mrg basic_block use_bb = gimple_bb (use_stmt); 350 1.1 mrg if (use_bb != bb 351 1.1 mrg && dominated_by_p (CDI_DOMINATORS, bb, use_bb)) 352 1.1 mrg { 353 1.1 mrg if (gcond *cond = dyn_cast <gcond *> (use_stmt)) 354 1.1 mrg if (gimple_cond_code (cond) == EQ_EXPR 355 1.1 mrg || gimple_cond_code (cond) == NE_EXPR) 356 1.1 mrg found_useful_phi = true; 357 1.1 mrg break; 358 1.1 mrg } 359 1.1 mrg } 360 1.1 mrg } 361 1.1 mrg if (found_useful_phi) 362 1.1 mrg break; 363 1.1 mrg } 364 1.1 mrg } 365 1.1 mrg if (found_useful_phi) 366 1.1 mrg break; 367 1.1 mrg } 368 1.1 mrg /* There is one exception namely a controlling condition we can propagate 369 1.1 mrg an equivalence from to the joiner. */ 370 1.1 mrg bool found_cprop_opportunity = false; 371 1.1 mrg basic_block dom = get_immediate_dominator (CDI_DOMINATORS, bb); 372 1.1 mrg gcond *cond = as_a <gcond *> (last_stmt (dom)); 373 1.1 mrg if (gimple_cond_code (cond) == EQ_EXPR 374 1.1 mrg || gimple_cond_code (cond) == NE_EXPR) 375 1.1 mrg for (unsigned i = 0; i < 2; ++i) 376 1.1 mrg { 377 1.1 mrg tree op = gimple_op (cond, i); 378 1.1 mrg if (TREE_CODE (op) == SSA_NAME) 379 1.1 mrg { 380 1.1 mrg use_operand_p use_p; 381 1.1 mrg imm_use_iterator iter; 382 1.1 mrg FOR_EACH_IMM_USE_FAST (use_p, iter, op) 383 1.1 mrg { 384 1.1 mrg if (is_gimple_debug (USE_STMT (use_p))) 385 1.1 mrg continue; 386 1.1 mrg if (gimple_bb (USE_STMT (use_p)) == bb) 387 1.1 mrg { 388 1.1 mrg found_cprop_opportunity = true; 389 1.1 mrg break; 390 1.1 mrg } 391 1.1 mrg } 392 1.1 mrg } 393 1.1 mrg if (found_cprop_opportunity) 394 1.1 mrg break; 395 1.1 mrg } 396 1.1 mrg 397 1.1 mrg if (! found_useful_phi && ! found_cprop_opportunity) 398 1.1 mrg { 399 1.1 mrg if (dump_file && (dump_flags & TDF_DETAILS)) 400 1.1 mrg fprintf (dump_file, 401 1.1 mrg "Block %d is a join that does not expose CSE/DCE/jump-thread " 402 1.1 mrg "opportunities when duplicated.\n", 403 1.1 mrg bb->index); 404 1.1 mrg return false; 405 1.1 mrg } 406 1.1 mrg 407 1.1 mrg /* We may want something here which looks at dataflow and tries 408 1.1 mrg to guess if duplication of BB is likely to result in simplification 409 1.1 mrg of instructions in BB in either the original or the duplicate. */ 410 1.1 mrg 411 1.1 mrg /* Upper Hard limit on the number statements to copy. */ 412 1.1 mrg if (num_stmts_in_join 413 1.1 mrg >= param_max_jump_thread_duplication_stmts) 414 1.1 mrg return false; 415 1.1 mrg 416 1.1 mrg return true; 417 1.1 mrg } 418 1.1 mrg 419 1.1 mrg /* If the immediate dominator of the latch of the loop is 420 1.1 mrg block with conditional branch, then the loop latch is 421 1.1 mrg duplicated to its predecessors path preserving the SSA 422 1.1 mrg semantics. 423 1.1 mrg 424 1.1 mrg CFG before transformation. 425 1.1 mrg 426 1.1 mrg 2 427 1.1 mrg | 428 1.1 mrg | 429 1.1 mrg +---->3 430 1.1 mrg | / \ 431 1.1 mrg | / \ 432 1.1 mrg | 4 5 433 1.1 mrg | \ / 434 1.1 mrg | \ / 435 1.1 mrg | 6 436 1.1 mrg | / \ 437 1.1 mrg | / \ 438 1.1 mrg | 8 7 439 1.1 mrg | | | 440 1.1 mrg ---+ E 441 1.1 mrg 442 1.1 mrg 443 1.1 mrg 444 1.1 mrg Block 8 is the latch. We're going to make copies of block 6 (9 & 10) 445 1.1 mrg and wire things up so they look like this: 446 1.1 mrg 447 1.1 mrg 2 448 1.1 mrg | 449 1.1 mrg | 450 1.1 mrg +---->3 451 1.1 mrg | / \ 452 1.1 mrg | / \ 453 1.1 mrg | 4 5 454 1.1 mrg | | | 455 1.1 mrg | | | 456 1.1 mrg | 9 10 457 1.1 mrg | |\ /| 458 1.1 mrg | | \ / | 459 1.1 mrg | | 7 | 460 1.1 mrg | | | | 461 1.1 mrg | | E | 462 1.1 mrg | | | 463 1.1 mrg | \ / 464 1.1 mrg | \ / 465 1.1 mrg +-----8 466 1.1 mrg 467 1.1 mrg 468 1.1 mrg Blocks 9 and 10 will get merged into blocks 4 & 5 respectively which 469 1.1 mrg enables CSE, DCE and other optimizations to occur on a larger block 470 1.1 mrg of code. */ 471 1.1 mrg 472 1.1 mrg static bool 473 1.1 mrg split_paths () 474 1.1 mrg { 475 1.1 mrg bool changed = false; 476 1.1 mrg 477 1.1 mrg loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS); 478 1.1 mrg initialize_original_copy_tables (); 479 1.1 mrg calculate_dominance_info (CDI_DOMINATORS); 480 1.1 mrg 481 1.1 mrg for (auto loop : loops_list (cfun, LI_FROM_INNERMOST)) 482 1.1 mrg { 483 1.1 mrg /* Only split paths if we are optimizing this loop for speed. */ 484 1.1 mrg if (!optimize_loop_for_speed_p (loop)) 485 1.1 mrg continue; 486 1.1 mrg 487 1.1 mrg /* See if there is a block that we can duplicate to split the 488 1.1 mrg path to the loop latch. */ 489 1.1 mrg basic_block bb 490 1.1 mrg = find_block_to_duplicate_for_splitting_paths (loop->latch); 491 1.1 mrg 492 1.1 mrg /* BB is the merge point for an IF-THEN-ELSE we want to transform. 493 1.1 mrg 494 1.1 mrg Essentially we want to create a duplicate of bb and redirect the 495 1.1 mrg first predecessor of BB to the duplicate (leaving the second 496 1.1 mrg predecessor as is. This will split the path leading to the latch 497 1.1 mrg re-using BB to avoid useless copying. */ 498 1.1 mrg if (bb && is_feasible_trace (bb)) 499 1.1 mrg { 500 1.1 mrg if (dump_file && (dump_flags & TDF_DETAILS)) 501 1.1 mrg fprintf (dump_file, 502 1.1 mrg "Duplicating join block %d into predecessor paths\n", 503 1.1 mrg bb->index); 504 1.1 mrg basic_block pred0 = EDGE_PRED (bb, 0)->src; 505 1.1 mrg if (EDGE_COUNT (pred0->succs) != 1) 506 1.1 mrg pred0 = EDGE_PRED (bb, 1)->src; 507 1.1 mrg transform_duplicate (pred0, bb); 508 1.1 mrg changed = true; 509 1.1 mrg 510 1.1 mrg /* If BB has an outgoing edge marked as IRREDUCIBLE, then 511 1.1 mrg duplicating BB may result in an irreducible region turning 512 1.1 mrg into a natural loop. 513 1.1 mrg 514 1.1 mrg Long term we might want to hook this into the block 515 1.1 mrg duplication code, but as we've seen with similar changes 516 1.1 mrg for edge removal, that can be somewhat risky. */ 517 1.1 mrg if (EDGE_SUCC (bb, 0)->flags & EDGE_IRREDUCIBLE_LOOP 518 1.1 mrg || EDGE_SUCC (bb, 1)->flags & EDGE_IRREDUCIBLE_LOOP) 519 1.1 mrg { 520 1.1 mrg if (dump_file && (dump_flags & TDF_DETAILS)) 521 1.1 mrg fprintf (dump_file, 522 1.1 mrg "Join block %d has EDGE_IRREDUCIBLE_LOOP set. " 523 1.1 mrg "Scheduling loop fixups.\n", 524 1.1 mrg bb->index); 525 1.1 mrg loops_state_set (LOOPS_NEED_FIXUP); 526 1.1 mrg } 527 1.1 mrg } 528 1.1 mrg } 529 1.1 mrg 530 1.1 mrg loop_optimizer_finalize (); 531 1.1 mrg free_original_copy_tables (); 532 1.1 mrg return changed; 533 1.1 mrg } 534 1.1 mrg 535 1.1 mrg /* Main entry point for splitting paths. Returns TODO_cleanup_cfg if any 536 1.1 mrg paths where split, otherwise return zero. */ 537 1.1 mrg 538 1.1 mrg static unsigned int 539 1.1 mrg execute_split_paths () 540 1.1 mrg { 541 1.1 mrg /* If we don't have at least 2 real blocks and backedges in the 542 1.1 mrg CFG, then there's no point in trying to perform path splitting. */ 543 1.1 mrg if (n_basic_blocks_for_fn (cfun) <= NUM_FIXED_BLOCKS + 1 544 1.1 mrg || !mark_dfs_back_edges ()) 545 1.1 mrg return 0; 546 1.1 mrg 547 1.1 mrg bool changed = split_paths(); 548 1.1 mrg if (changed) 549 1.1 mrg free_dominance_info (CDI_DOMINATORS); 550 1.1 mrg 551 1.1 mrg return changed ? TODO_cleanup_cfg : 0; 552 1.1 mrg } 553 1.1 mrg 554 1.1 mrg static bool 555 1.1 mrg gate_split_paths () 556 1.1 mrg { 557 1.1 mrg return flag_split_paths; 558 1.1 mrg } 559 1.1 mrg 560 1.1 mrg namespace { 561 1.1 mrg 562 1.1 mrg const pass_data pass_data_split_paths = 563 1.1 mrg { 564 1.1 mrg GIMPLE_PASS, /* type */ 565 1.1 mrg "split-paths", /* name */ 566 1.1 mrg OPTGROUP_NONE, /* optinfo_flags */ 567 1.1 mrg TV_SPLIT_PATHS, /* tv_id */ 568 1.1 mrg PROP_ssa, /* properties_required */ 569 1.1 mrg 0, /* properties_provided */ 570 1.1 mrg 0, /* properties_destroyed */ 571 1.1 mrg 0, /* todo_flags_start */ 572 1.1 mrg TODO_update_ssa, /* todo_flags_finish */ 573 1.1 mrg }; 574 1.1 mrg 575 1.1 mrg class pass_split_paths : public gimple_opt_pass 576 1.1 mrg { 577 1.1 mrg public: 578 1.1 mrg pass_split_paths (gcc::context *ctxt) 579 1.1 mrg : gimple_opt_pass (pass_data_split_paths, ctxt) 580 1.1 mrg {} 581 1.1 mrg /* opt_pass methods: */ 582 1.1 mrg opt_pass * clone () { return new pass_split_paths (m_ctxt); } 583 1.1 mrg virtual bool gate (function *) { return gate_split_paths (); } 584 1.1 mrg virtual unsigned int execute (function *) { return execute_split_paths (); } 585 1.1 mrg 586 1.1 mrg }; // class pass_split_paths 587 1.1 mrg 588 1.1 mrg } // anon namespace 589 1.1 mrg 590 1.1 mrg gimple_opt_pass * 591 1.1 mrg make_pass_split_paths (gcc::context *ctxt) 592 1.1 mrg { 593 1.1 mrg return new pass_split_paths (ctxt); 594 1.1 mrg } 595