gimple-ssa-split-paths.cc revision 1.1 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