]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/tree-ssa-threadbackward.cc
Daily bump.
[thirdparty/gcc.git] / gcc / tree-ssa-threadbackward.cc
CommitLineData
0732f75f 1/* SSA Jump Threading
7adcbafe 2 Copyright (C) 2005-2022 Free Software Foundation, Inc.
0732f75f
JL
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 3, or (at your option)
9any later version.
10
11GCC is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
19
20#include "config.h"
21#include "system.h"
22#include "coretypes.h"
23#include "backend.h"
24#include "predict.h"
25#include "tree.h"
26#include "gimple.h"
27#include "fold-const.h"
28#include "cfgloop.h"
29#include "gimple-iterator.h"
30#include "tree-cfg.h"
31#include "tree-ssa-threadupdate.h"
0732f75f
JL
32#include "tree-ssa-loop.h"
33#include "cfganal.h"
34#include "tree-pass.h"
8b2ef235
JL
35#include "gimple-ssa.h"
36#include "tree-phinodes.h"
27bddc4a 37#include "tree-inline.h"
0a4e5cf3 38#include "tree-vectorizer.h"
2e96b5f1
AH
39#include "value-range.h"
40#include "gimple-range.h"
41#include "tree-ssa-threadedge.h"
42#include "gimple-range-path.h"
43#include "ssa.h"
44#include "tree-cfgcleanup.h"
779275c0 45#include "tree-pretty-print.h"
01b50387 46#include "cfghooks.h"
bc5baac5 47#include "dbgcnt.h"
0732f75f 48
69e55442
AH
49// Path registry for the backwards threader. After all paths have been
50// registered with register_path(), thread_through_all_blocks() is called
51// to modify the CFG.
52
7f6c2258 53class back_threader_registry : public back_jt_path_registry
69e55442
AH
54{
55public:
69e55442 56 bool register_path (const vec<basic_block> &, edge taken);
69e55442
AH
57};
58
59// Class to abstract the profitability code for the backwards threader.
60
61class back_threader_profitability
62{
63public:
64 back_threader_profitability (bool speed_p)
65 : m_speed_p (speed_p)
66 { }
67 bool profitable_path_p (const vec<basic_block> &, tree name, edge taken,
68 bool *irreducible_loop = NULL);
69e55442
AH
69private:
70 const bool m_speed_p;
71};
72
4e0f56d7
AH
73// Back threader flags.
74#define BT_NONE 0
75// Generate fast code at the expense of code size.
76#define BT_SPEED 1
77// Resolve unknown SSAs on entry to a threading path. If set, use the
78// ranger. If not, assume all ranges on entry to a path are VARYING.
79#define BT_RESOLVE 2
80
2e96b5f1
AH
81class back_threader
82{
2e96b5f1 83public:
bc5baac5 84 back_threader (function *fun, unsigned flags, bool first);
4e0f56d7
AH
85 ~back_threader ();
86 unsigned thread_blocks ();
2e96b5f1 87private:
4e0f56d7 88 void maybe_thread_block (basic_block bb);
34cd97ff 89 void find_paths (basic_block bb, tree name);
bc5baac5 90 bool debug_counter ();
cbeeadff 91 edge maybe_register_path ();
53080c5b 92 void maybe_register_path_dump (edge taken_edge);
98b212c1 93 void find_paths_to_names (basic_block bb, bitmap imports);
8a04a5fb 94 void resolve_phi (gphi *phi, bitmap imports);
2e96b5f1
AH
95 edge find_taken_edge (const vec<basic_block> &path);
96 edge find_taken_edge_cond (const vec<basic_block> &path, gcond *);
97 edge find_taken_edge_switch (const vec<basic_block> &path, gswitch *);
779275c0
AH
98 virtual void debug ();
99 virtual void dump (FILE *out);
2e96b5f1 100
34cd97ff
AH
101 back_threader_registry m_registry;
102 back_threader_profitability m_profit;
4e0f56d7 103 path_range_query *m_solver;
2e96b5f1
AH
104
105 // Current path being analyzed.
106 auto_vec<basic_block> m_path;
107 // Hash to mark visited BBs while analyzing a path.
108 hash_set<basic_block> m_visited_bbs;
109 // The set of SSA names, any of which could potentially change the
110 // value of the final conditional in a path.
d71e1be7 111 auto_bitmap m_imports;
2e96b5f1
AH
112 // The last statement in the path.
113 gimple *m_last_stmt;
114 // This is a bit of a wart. It's used to pass the LHS SSA name to
115 // the profitability engine.
116 tree m_name;
117 // Marker to differentiate unreachable edges.
118 static const edge UNREACHABLE_EDGE;
401aaa59
AH
119 // Set to TRUE if unknown SSA names along a path should be resolved
120 // with the ranger. Otherwise, unknown SSA names are assumed to be
5d4d64fa 121 // VARYING. Setting to true is more precise but slower.
4e0f56d7
AH
122 function *m_fun;
123 unsigned m_flags;
bc5baac5
AH
124 // Set to TRUE for the first of each thread[12] pass or the first of
125 // each threadfull[12] pass. This is used to differentiate between
126 // the different threading passes so we can set up debug counters.
127 bool m_first;
2e96b5f1
AH
128};
129
130// Used to differentiate unreachable edges, so we may stop the search
131// in a the given direction.
132const edge back_threader::UNREACHABLE_EDGE = (edge) -1;
133
bc5baac5
AH
134back_threader::back_threader (function *fun, unsigned flags, bool first)
135 : m_profit (flags & BT_SPEED),
136 m_first (first)
2e96b5f1 137{
4e0f56d7
AH
138 if (flags & BT_SPEED)
139 loop_optimizer_init (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES);
140 else
141 loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
142
143 m_fun = fun;
144 m_flags = flags;
2e96b5f1 145 m_last_stmt = NULL;
eb5ee646
AH
146
147 // The path solver needs EDGE_DFS_BACK in resolving mode.
148 if (flags & BT_RESOLVE)
149 mark_dfs_back_edges ();
83ad3a96 150 m_solver = new path_range_query (flags & BT_RESOLVE);
4e0f56d7
AH
151}
152
153back_threader::~back_threader ()
154{
155 delete m_solver;
4e0f56d7
AH
156
157 loop_optimizer_finalize ();
2e96b5f1
AH
158}
159
bc5baac5
AH
160// A wrapper for the various debug counters for the threading passes.
161// Returns TRUE if it's OK to register the current threading
162// candidate.
163
164bool
165back_threader::debug_counter ()
166{
167 // The ethread pass is mostly harmless ;-).
168 if ((m_flags & BT_SPEED) == 0)
169 return true;
170
171 if (m_flags & BT_RESOLVE)
172 {
173 if (m_first && !dbg_cnt (back_threadfull1))
174 return false;
175
176 if (!m_first && !dbg_cnt (back_threadfull2))
177 return false;
178 }
179 else
180 {
181 if (m_first && !dbg_cnt (back_thread1))
182 return false;
183
184 if (!m_first && !dbg_cnt (back_thread2))
185 return false;
186 }
187 return true;
188}
189
a2ab1a5a
AH
190static void
191dump_path (FILE *dump_file, const vec<basic_block> &path)
192{
193 for (unsigned i = path.length (); i > 0; --i)
194 {
195 basic_block bb = path[i - 1];
196 fprintf (dump_file, "%d", bb->index);
197 if (i > 1)
198 fprintf (dump_file, "->");
199 }
200}
201
53080c5b
AH
202// Dump details of an attempt to register a path.
203
204void
205back_threader::maybe_register_path_dump (edge taken)
206{
207 if (m_path.is_empty ())
208 return;
209
210 fprintf (dump_file, "path: ");
a2ab1a5a 211 dump_path (dump_file, m_path);
53080c5b
AH
212 fprintf (dump_file, "->");
213
214 if (taken == UNREACHABLE_EDGE)
215 fprintf (dump_file, "xx REJECTED (unreachable)\n");
216 else if (taken)
217 fprintf (dump_file, "%d SUCCESS\n", taken->dest->index);
218 else
219 fprintf (dump_file, "xx REJECTED\n");
220}
221
222// If an outgoing edge can be determined out of the current path,
223// register it for jump threading and return the taken edge.
cbeeadff 224//
2b59cf47
AH
225// Return NULL if it is unprofitable to thread this path, or the
226// outgoing edge is unknown. Return UNREACHABLE_EDGE if the path is
227// unreachable.
2e96b5f1 228
cbeeadff
AH
229edge
230back_threader::maybe_register_path ()
2e96b5f1 231{
cbeeadff 232 edge taken_edge = find_taken_edge (m_path);
2e96b5f1 233
cbeeadff 234 if (taken_edge && taken_edge != UNREACHABLE_EDGE)
2e96b5f1 235 {
e53fbb17 236 if (m_visited_bbs.contains (taken_edge->dest))
cbeeadff 237 {
2b59cf47
AH
238 // Avoid circular paths by indicating there is nothing to
239 // see in this direction.
240 taken_edge = UNREACHABLE_EDGE;
241 }
242 else
243 {
244 bool irreducible = false;
245 if (m_profit.profitable_path_p (m_path, m_name, taken_edge,
246 &irreducible)
247 && debug_counter ())
248 {
249 m_registry.register_path (m_path, taken_edge);
250
251 if (irreducible)
252 vect_free_loop_info_assumptions (m_path[0]->loop_father);
253 }
254 else
255 taken_edge = NULL;
cbeeadff 256 }
2e96b5f1 257 }
53080c5b
AH
258
259 if (dump_file && (dump_flags & TDF_DETAILS))
260 maybe_register_path_dump (taken_edge);
261
cbeeadff 262 return taken_edge;
2e96b5f1
AH
263}
264
265// Return the known taken edge out of a path. If the path can be
266// determined to be unreachable, return UNREACHABLE_EDGE. If no
267// outgoing edge can be calculated, return NULL.
268
269edge
270back_threader::find_taken_edge (const vec<basic_block> &path)
271{
272 gcc_checking_assert (path.length () > 1);
273 switch (gimple_code (m_last_stmt))
274 {
275 case GIMPLE_COND:
276 return find_taken_edge_cond (path, as_a<gcond *> (m_last_stmt));
277
278 case GIMPLE_SWITCH:
279 return find_taken_edge_switch (path, as_a<gswitch *> (m_last_stmt));
280
281 default:
282 return NULL;
283 }
284}
285
286// Same as find_taken_edge, but for paths ending in a switch.
287
288edge
289back_threader::find_taken_edge_switch (const vec<basic_block> &path,
290 gswitch *sw)
291{
292 tree name = gimple_switch_index (sw);
293 int_range_max r;
294
4e0f56d7
AH
295 m_solver->compute_ranges (path, m_imports);
296 m_solver->range_of_expr (r, name, sw);
2e96b5f1
AH
297
298 if (r.undefined_p ())
299 return UNREACHABLE_EDGE;
300
301 if (r.varying_p ())
302 return NULL;
303
113dab2b
AH
304 tree label = find_case_label_range (sw, &r);
305 if (!label)
306 return NULL;
2e96b5f1 307
113dab2b 308 return find_edge (gimple_bb (sw), label_to_block (cfun, CASE_LABEL (label)));
2e96b5f1
AH
309}
310
311// Same as find_taken_edge, but for paths ending in a GIMPLE_COND.
312
313edge
314back_threader::find_taken_edge_cond (const vec<basic_block> &path,
315 gcond *cond)
316{
2e96b5f1 317 int_range_max r;
2e96b5f1 318
4e0f56d7
AH
319 m_solver->compute_ranges (path, m_imports);
320 m_solver->range_of_stmt (r, cond);
2e96b5f1 321
4e0f56d7 322 if (m_solver->unreachable_path_p ())
90ef1535
AH
323 return UNREACHABLE_EDGE;
324
2e96b5f1
AH
325 int_range<2> true_range (boolean_true_node, boolean_true_node);
326 int_range<2> false_range (boolean_false_node, boolean_false_node);
327
328 if (r == true_range || r == false_range)
329 {
330 edge e_true, e_false;
331 basic_block bb = gimple_bb (cond);
332 extract_true_false_edges_from_block (bb, &e_true, &e_false);
333 return r == true_range ? e_true : e_false;
334 }
335 return NULL;
336}
337
338// Populate a vector of trees from a bitmap.
339
340static inline void
a3d3e8c3 341populate_worklist (vec<tree> &worklist, bitmap bits)
2e96b5f1
AH
342{
343 bitmap_iterator bi;
344 unsigned i;
345
346 EXECUTE_IF_SET_IN_BITMAP (bits, 0, i, bi)
347 {
348 tree name = ssa_name (i);
349 worklist.quick_push (name);
350 }
351}
352
8a04a5fb 353// Find jump threading paths that go through a PHI.
2e96b5f1 354
8a04a5fb 355void
2e96b5f1
AH
356back_threader::resolve_phi (gphi *phi, bitmap interesting)
357{
358 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_phi_result (phi)))
8a04a5fb 359 return;
2e96b5f1 360
2e96b5f1
AH
361 for (size_t i = 0; i < gimple_phi_num_args (phi); ++i)
362 {
363 edge e = gimple_phi_arg_edge (phi, i);
364
365 // This is like path_crosses_loops in profitable_path_p but more
bfa04d0e
AH
366 // restrictive to avoid peeling off loop iterations (see
367 // tree-ssa/pr14341.c for an example).
2e96b5f1
AH
368 bool profitable_p = m_path[0]->loop_father == e->src->loop_father;
369 if (!profitable_p)
370 {
371 if (dump_file && (dump_flags & TDF_DETAILS))
a2ab1a5a
AH
372 {
373 fprintf (dump_file,
374 " FAIL: path through PHI in bb%d (incoming bb:%d) crosses loop\n",
375 e->dest->index, e->src->index);
376 fprintf (dump_file, "path: %d->", e->src->index);
377 dump_path (dump_file, m_path);
378 fprintf (dump_file, "->xx REJECTED\n");
379 }
2e96b5f1
AH
380 continue;
381 }
382
383 tree arg = gimple_phi_arg_def (phi, i);
8a04a5fb 384 unsigned v = 0;
2e96b5f1 385
8a04a5fb
AH
386 if (TREE_CODE (arg) == SSA_NAME
387 && !bitmap_bit_p (interesting, SSA_NAME_VERSION (arg)))
388 {
389 // Record that ARG is interesting when searching down this path.
390 v = SSA_NAME_VERSION (arg);
391 gcc_checking_assert (v != 0);
2e96b5f1
AH
392 bitmap_set_bit (interesting, v);
393 bitmap_set_bit (m_imports, v);
2e96b5f1 394 }
8a04a5fb
AH
395
396 find_paths_to_names (e->src, interesting);
397
398 if (v)
399 bitmap_clear_bit (interesting, v);
2e96b5f1 400 }
2e96b5f1
AH
401}
402
2e96b5f1
AH
403// Find jump threading paths to any of the SSA names in the
404// INTERESTING bitmap, and register any such paths.
405//
2e96b5f1
AH
406// BB is the current path being processed.
407
98b212c1 408void
2e96b5f1
AH
409back_threader::find_paths_to_names (basic_block bb, bitmap interesting)
410{
411 if (m_visited_bbs.add (bb))
98b212c1 412 return;
2e96b5f1
AH
413
414 m_path.safe_push (bb);
415
f6d01233 416 // Try to resolve the path without looking back.
98b212c1
AH
417 if (m_path.length () > 1
418 && (!m_profit.profitable_path_p (m_path, m_name, NULL)
419 || maybe_register_path ()))
401aaa59
AH
420 {
421 m_path.pop ();
422 m_visited_bbs.remove (bb);
98b212c1 423 return;
401aaa59
AH
424 }
425
2e96b5f1 426 auto_bitmap processed;
2e96b5f1 427 bool done = false;
2e96b5f1
AH
428 // We use a worklist instead of iterating through the bitmap,
429 // because we may add new items in-flight.
430 auto_vec<tree> worklist (bitmap_count_bits (interesting));
431 populate_worklist (worklist, interesting);
432 while (!worklist.is_empty ())
433 {
434 tree name = worklist.pop ();
435 unsigned i = SSA_NAME_VERSION (name);
bfa04d0e
AH
436 gimple *def_stmt = SSA_NAME_DEF_STMT (name);
437 basic_block def_bb = gimple_bb (def_stmt);
2e96b5f1 438
bfa04d0e 439 // Process any PHIs defined in this block.
98b212c1
AH
440 if (def_bb == bb
441 && bitmap_set_bit (processed, i)
bfa04d0e 442 && gimple_code (def_stmt) == GIMPLE_PHI)
2e96b5f1 443 {
bfa04d0e 444 resolve_phi (as_a<gphi *> (def_stmt), interesting);
98b212c1
AH
445 done = true;
446 break;
2e96b5f1 447 }
2e96b5f1 448 }
2e96b5f1 449 // If there are interesting names not yet processed, keep looking.
98b212c1 450 if (!done)
2e96b5f1 451 {
98b212c1
AH
452 bitmap_and_compl_into (interesting, processed);
453 if (!bitmap_empty_p (interesting))
454 {
455 edge_iterator iter;
456 edge e;
457 FOR_EACH_EDGE (e, iter, bb->preds)
458 if ((e->flags & EDGE_ABNORMAL) == 0)
459 find_paths_to_names (e->src, interesting);
460 }
2e96b5f1
AH
461 }
462
98b212c1
AH
463 // Reset things to their original state.
464 bitmap_ior_into (interesting, processed);
2e96b5f1
AH
465 m_path.pop ();
466 m_visited_bbs.remove (bb);
2e96b5f1
AH
467}
468
469// Search backwards from BB looking for paths where the final
470// conditional out of BB can be determined. NAME is the LHS of the
471// final conditional. Register such paths for jump threading.
472
473void
474back_threader::find_paths (basic_block bb, tree name)
475{
476 gimple *stmt = last_stmt (bb);
477 if (!stmt
478 || (gimple_code (stmt) != GIMPLE_COND
479 && gimple_code (stmt) != GIMPLE_SWITCH))
480 return;
481
482 if (EDGE_COUNT (bb->succs) > 1
483 || single_succ_to_potentially_threadable_block (bb))
484 {
485 m_last_stmt = stmt;
486 m_visited_bbs.empty ();
487 m_path.truncate (0);
488 m_name = name;
bfa04d0e 489 m_solver->compute_imports (m_imports, bb);
2e96b5f1
AH
490
491 auto_bitmap interesting;
2e96b5f1
AH
492 bitmap_copy (interesting, m_imports);
493 find_paths_to_names (bb, interesting);
494 }
495}
496
34cd97ff
AH
497// Simple helper to get the last statement from BB, which is assumed
498// to be a control statement. Return NULL if the last statement is
499// not a control statement.
21f0717a 500
3d466672
JL
501static gimple *
502get_gimple_control_stmt (basic_block bb)
503{
21f0717a 504 gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
3d466672
JL
505
506 if (gsi_end_p (gsi))
507 return NULL;
508
509 gimple *stmt = gsi_stmt (gsi);
510 enum gimple_code code = gimple_code (stmt);
21f0717a
JL
511 if (code == GIMPLE_COND || code == GIMPLE_SWITCH || code == GIMPLE_GOTO)
512 return stmt;
513 return NULL;
3d466672
JL
514}
515
34cd97ff
AH
516// Search backwards from BB looking for paths where the final
517// conditional maybe threaded to a successor block. Record such paths
518// for jump threading.
0732f75f 519
34cd97ff
AH
520void
521back_threader::maybe_thread_block (basic_block bb)
0732f75f 522{
34cd97ff
AH
523 gimple *stmt = get_gimple_control_stmt (bb);
524 if (!stmt)
525 return;
0732f75f 526
34cd97ff
AH
527 enum gimple_code code = gimple_code (stmt);
528 tree name;
529 if (code == GIMPLE_SWITCH)
530 name = gimple_switch_index (as_a <gswitch *> (stmt));
531 else if (code == GIMPLE_COND)
532 name = gimple_cond_lhs (stmt);
533 else if (code == GIMPLE_GOTO)
534 name = gimple_goto_dest (stmt);
535 else
536 name = NULL;
537
538 find_paths (bb, name);
539}
540
34cd97ff
AH
541DEBUG_FUNCTION void
542debug (const vec <basic_block> &path)
543{
544 dump_path (stderr, path);
a2ab1a5a 545 fputc ('\n', stderr);
0732f75f
JL
546}
547
779275c0
AH
548void
549back_threader::dump (FILE *out)
550{
4e0f56d7 551 m_solver->dump (out);
779275c0
AH
552 fprintf (out, "\nCandidates for pre-computation:\n");
553 fprintf (out, "===================================\n");
554
555 bitmap_iterator bi;
556 unsigned i;
557
558 EXECUTE_IF_SET_IN_BITMAP (m_imports, 0, i, bi)
559 {
560 tree name = ssa_name (i);
561 print_generic_expr (out, name, TDF_NONE);
562 fprintf (out, "\n");
563 }
564}
565
566void
567back_threader::debug ()
568{
569 dump (stderr);
570}
571
69e55442
AH
572/* Examine jump threading path PATH and return TRUE if it is profitable to
573 thread it, otherwise return FALSE.
bb5e62d6
JL
574
575 NAME is the SSA_NAME of the variable we found to have a constant
69e55442 576 value on PATH. If unknown, SSA_NAME is NULL.
bb5e62d6 577
69e55442
AH
578 If the taken edge out of the path is known ahead of time it is passed in
579 TAKEN_EDGE, otherwise it is NULL.
bb5e62d6 580
69e55442 581 CREATES_IRREDUCIBLE_LOOP, if non-null is set to TRUE if threading this path
01b50387
AH
582 would create an irreducible loop.
583
584 ?? It seems we should be able to loosen some of the restrictions in
585 this function after loop optimizations have run. */
69e55442
AH
586
587bool
588back_threader_profitability::profitable_path_p (const vec<basic_block> &m_path,
589 tree name,
590 edge taken_edge,
591 bool *creates_irreducible_loop)
bb5e62d6 592{
69e55442 593 gcc_checking_assert (!m_path.is_empty ());
ad071b2b 594
69e55442
AH
595 /* We can an empty path here (excluding the DEF block) when the
596 statement that makes a conditional generate a compile-time
597 constant result is in the same block as the conditional.
ad071b2b
JL
598
599 That's not really a jump threading opportunity, but instead is
600 simple cprop & simplification. We could handle it here if we
601 wanted by wiring up all the incoming edges. If we run this
602 early in IPA, that might be worth doing. For now we just
603 reject that case. */
69e55442
AH
604 if (m_path.length () <= 1)
605 return false;
ad071b2b 606
82cd78f2
AH
607 if (m_path.length () > (unsigned) param_max_fsm_thread_length)
608 {
609 if (dump_file && (dump_flags & TDF_DETAILS))
610 fprintf (dump_file, " FAIL: Jump-thread path not considered: "
611 "the number of basic blocks on the path "
612 "exceeds PARAM_MAX_FSM_THREAD_LENGTH.\n");
613 return false;
614 }
615
bb5e62d6
JL
616 int n_insns = 0;
617 gimple_stmt_iterator gsi;
cde30fe0 618 loop_p loop = m_path[0]->loop_father;
bb5e62d6
JL
619 bool threaded_through_latch = false;
620 bool multiway_branch_in_path = false;
621 bool threaded_multiway_branch = false;
0f0c2cc3
JH
622 bool contains_hot_bb = false;
623
624 if (dump_file && (dump_flags & TDF_DETAILS))
625 fprintf (dump_file, "Checking profitability of path (backwards): ");
bb5e62d6
JL
626
627 /* Count the number of instructions on the path: as these instructions
628 will have to be duplicated, we will not record the path if there
629 are too many instructions on the path. Also check that all the
630 blocks in the path belong to a single loop. */
cde30fe0 631 for (unsigned j = 0; j < m_path.length (); j++)
bb5e62d6 632 {
cde30fe0 633 basic_block bb = m_path[j];
bb5e62d6 634
0f0c2cc3
JH
635 if (dump_file && (dump_flags & TDF_DETAILS))
636 fprintf (dump_file, " bb:%i", bb->index);
a7753db4
AH
637 /* Remember, blocks in the path are stored in opposite order in
638 the PATH array. The last entry in the array represents the
639 block with an outgoing edge that we will redirect to the jump
640 threading path. Thus we don't care how many statements are
641 in that block because it will not be copied or whether or not
642 it ends in a multiway branch. */
cde30fe0 643 if (j < m_path.length () - 1)
bb5e62d6 644 {
0f0c2cc3 645 int orig_n_insns = n_insns;
bb5e62d6
JL
646 /* PHIs in the path will create degenerate PHIS in the
647 copied path which will then get propagated away, so
648 looking at just the duplicate path the PHIs would
649 seem unimportant.
650
651 But those PHIs, because they're assignments to objects
652 typically with lives that exist outside the thread path,
653 will tend to generate PHIs (or at least new PHI arguments)
654 at points where we leave the thread path and rejoin
655 the original blocks. So we do want to account for them.
656
657 We ignore virtual PHIs. We also ignore cases where BB
658 has a single incoming edge. That's the most common
659 degenerate PHI we'll see here. Finally we ignore PHIs
660 that are associated with the value we're tracking as
661 that object likely dies. */
662 if (EDGE_COUNT (bb->succs) > 1 && EDGE_COUNT (bb->preds) > 1)
663 {
664 for (gphi_iterator gsip = gsi_start_phis (bb);
665 !gsi_end_p (gsip);
666 gsi_next (&gsip))
667 {
668 gphi *phi = gsip.phi ();
669 tree dst = gimple_phi_result (phi);
670
671 /* Note that if both NAME and DST are anonymous
672 SSA_NAMEs, then we do not have enough information
673 to consider them associated. */
fda5c810 674 if (dst != name
69e55442
AH
675 && name
676 && TREE_CODE (name) == SSA_NAME
fda5c810
RB
677 && (SSA_NAME_VAR (dst) != SSA_NAME_VAR (name)
678 || !SSA_NAME_VAR (dst))
bb5e62d6
JL
679 && !virtual_operand_p (dst))
680 ++n_insns;
681 }
682 }
683
cde30fe0 684 if (!contains_hot_bb && m_speed_p)
0f0c2cc3 685 contains_hot_bb |= optimize_bb_for_speed_p (bb);
bb5e62d6
JL
686 for (gsi = gsi_after_labels (bb);
687 !gsi_end_p (gsi);
688 gsi_next_nondebug (&gsi))
689 {
70a62009
IL
690 /* Do not allow OpenACC loop markers and __builtin_constant_p on
691 threading paths. The latter is disallowed, because an
692 expression might be constant on two threading paths, and
693 become non-constant (i.e.: phi) when they merge. */
bb5e62d6 694 gimple *stmt = gsi_stmt (gsi);
70a62009
IL
695 if (gimple_call_internal_p (stmt, IFN_UNIQUE)
696 || gimple_call_builtin_p (stmt, BUILT_IN_CONSTANT_P))
69e55442 697 return false;
bb5e62d6
JL
698 /* Do not count empty statements and labels. */
699 if (gimple_code (stmt) != GIMPLE_NOP
bb5e62d6 700 && !is_gimple_debug (stmt))
0f0c2cc3 701 n_insns += estimate_num_insns (stmt, &eni_size_weights);
bb5e62d6 702 }
0f0c2cc3
JH
703 if (dump_file && (dump_flags & TDF_DETAILS))
704 fprintf (dump_file, " (%i insns)", n_insns-orig_n_insns);
bb5e62d6
JL
705
706 /* We do not look at the block with the threaded branch
707 in this loop. So if any block with a last statement that
708 is a GIMPLE_SWITCH or GIMPLE_GOTO is seen, then we have a
709 multiway branch on our path.
710
711 The block in PATH[0] is special, it's the block were we're
712 going to be able to eliminate its branch. */
713 gimple *last = last_stmt (bb);
714 if (last && (gimple_code (last) == GIMPLE_SWITCH
715 || gimple_code (last) == GIMPLE_GOTO))
716 {
717 if (j == 0)
718 threaded_multiway_branch = true;
719 else
720 multiway_branch_in_path = true;
721 }
722 }
723
724 /* Note if we thread through the latch, we will want to include
725 the last entry in the array when determining if we thread
726 through the loop latch. */
727 if (loop->latch == bb)
01b50387
AH
728 {
729 threaded_through_latch = true;
730 if (dump_file && (dump_flags & TDF_DETAILS))
731 fprintf (dump_file, " (latch)");
732 }
bb5e62d6
JL
733 }
734
cde30fe0 735 gimple *stmt = get_gimple_control_stmt (m_path[0]);
27bddc4a
JH
736 gcc_assert (stmt);
737
bb5e62d6
JL
738 /* We are going to remove the control statement at the end of the
739 last block in the threading path. So don't count it against our
740 statement count. */
bb5e62d6 741
0f0c2cc3
JH
742 int stmt_insns = estimate_num_insns (stmt, &eni_size_weights);
743 n_insns-= stmt_insns;
744
745 if (dump_file && (dump_flags & TDF_DETAILS))
746 fprintf (dump_file, "\n Control statement insns: %i\n"
747 " Overall: %i insns\n",
748 stmt_insns, n_insns);
27bddc4a 749
69e55442 750 if (creates_irreducible_loop)
bb5e62d6 751 {
69e55442
AH
752 /* If this path threaded through the loop latch back into the
753 same loop and the destination does not dominate the loop
754 latch, then this thread would create an irreducible loop. */
755 *creates_irreducible_loop = false;
756 if (taken_edge
757 && threaded_through_latch
758 && loop == taken_edge->dest->loop_father
759 && (determine_bb_domination_status (loop, taken_edge->dest)
760 == DOMST_NONDOMINATING))
761 *creates_irreducible_loop = true;
bb5e62d6
JL
762 }
763
0f0c2cc3
JH
764 /* Threading is profitable if the path duplicated is hot but also
765 in a case we separate cold path from hot path and permit optimization
766 of the hot path later. Be on the agressive side here. In some testcases,
767 as in PR 78407 this leads to noticeable improvements. */
69e55442
AH
768 if (m_speed_p
769 && ((taken_edge && optimize_edge_for_speed_p (taken_edge))
770 || contains_hot_bb))
27bddc4a 771 {
028d4092 772 if (n_insns >= param_max_fsm_thread_path_insns)
27bddc4a
JH
773 {
774 if (dump_file && (dump_flags & TDF_DETAILS))
c7a669af 775 fprintf (dump_file, " FAIL: Jump-thread path not considered: "
27bddc4a
JH
776 "the number of instructions on the path "
777 "exceeds PARAM_MAX_FSM_THREAD_PATH_INSNS.\n");
69e55442 778 return false;
27bddc4a 779 }
49ba4fde
RB
780 edge entry = find_edge (m_path[m_path.length () - 1],
781 m_path[m_path.length () - 2]);
782 if (probably_never_executed_edge_p (cfun, entry))
783 {
784 if (dump_file && (dump_flags & TDF_DETAILS))
785 fprintf (dump_file, " FAIL: Jump-thread path not considered: "
786 "path entry is probably never executed.\n");
787 return false;
788 }
27bddc4a 789 }
69e55442 790 else if (!m_speed_p && n_insns > 1)
bb5e62d6
JL
791 {
792 if (dump_file && (dump_flags & TDF_DETAILS))
c7a669af 793 fprintf (dump_file, " FAIL: Jump-thread path not considered: "
27bddc4a
JH
794 "duplication of %i insns is needed and optimizing for size.\n",
795 n_insns);
69e55442 796 return false;
bb5e62d6
JL
797 }
798
799 /* We avoid creating irreducible inner loops unless we thread through
800 a multiway branch, in which case we have deemed it worth losing
801 other loop optimizations later.
802
803 We also consider it worth creating an irreducible inner loop if
804 the number of copied statement is low relative to the length of
805 the path -- in that case there's little the traditional loop
806 optimizer would have done anyway, so an irreducible loop is not
807 so bad. */
69e55442
AH
808 if (!threaded_multiway_branch
809 && creates_irreducible_loop
810 && *creates_irreducible_loop
028d4092 811 && (n_insns * (unsigned) param_fsm_scale_path_stmts
cde30fe0 812 > (m_path.length () *
028d4092 813 (unsigned) param_fsm_scale_path_blocks)))
bb5e62d6
JL
814
815 {
816 if (dump_file && (dump_flags & TDF_DETAILS))
817 fprintf (dump_file,
c7a669af 818 " FAIL: Would create irreducible loop without threading "
bb5e62d6 819 "multiway branch.\n");
69e55442 820 return false;
bb5e62d6
JL
821 }
822
c7a669af
AH
823 /* The generic copier used by the backthreader does not re-use an
824 existing threading path to reduce code duplication. So for that
825 case, drastically reduce the number of statements we are allowed
826 to copy. */
bb5e62d6 827 if (!(threaded_through_latch && threaded_multiway_branch)
028d4092
ML
828 && (n_insns * param_fsm_scale_path_stmts
829 >= param_max_jump_thread_duplication_stmts))
bb5e62d6
JL
830 {
831 if (dump_file && (dump_flags & TDF_DETAILS))
832 fprintf (dump_file,
c7a669af 833 " FAIL: Did not thread around loop and would copy too "
bb5e62d6 834 "many statements.\n");
69e55442 835 return false;
bb5e62d6
JL
836 }
837
838 /* When there is a multi-way branch on the path, then threading can
839 explode the CFG due to duplicating the edges for that multi-way
840 branch. So like above, only allow a multi-way branch on the path
841 if we actually thread a multi-way branch. */
842 if (!threaded_multiway_branch && multiway_branch_in_path)
843 {
844 if (dump_file && (dump_flags & TDF_DETAILS))
845 fprintf (dump_file,
c7a669af 846 " FAIL: Thread through multiway branch without threading "
bb5e62d6 847 "a multiway branch.\n");
69e55442 848 return false;
bb5e62d6 849 }
01b50387
AH
850
851 /* Threading through an empty latch would cause code to be added to
852 the latch. This could alter the loop form sufficiently to cause
853 loop optimizations to fail. Disable these threads until after
854 loop optimizations have run. */
855 if ((threaded_through_latch
856 || (taken_edge && taken_edge->dest == loop->latch))
857 && !(cfun->curr_properties & PROP_loop_opts_done)
858 && empty_block_p (loop->latch))
859 {
860 if (dump_file && (dump_flags & TDF_DETAILS))
861 fprintf (dump_file,
c7a669af 862 " FAIL: Thread through latch before loop opts would create non-empty latch\n");
01b50387
AH
863 return false;
864
865 }
69e55442
AH
866 return true;
867}
868
cde30fe0
AH
869/* The current path PATH is a vector of blocks forming a jump threading
870 path in reverse order. TAKEN_EDGE is the edge taken from path[0].
081fdda6 871
cde30fe0 872 Convert the current path into the form used by register_jump_thread and
69e55442 873 register it.
081fdda6 874
69e55442
AH
875 Return TRUE if successful or FALSE otherwise. */
876
877bool
878back_threader_registry::register_path (const vec<basic_block> &m_path,
879 edge taken_edge)
081fdda6 880{
7f6c2258 881 vec<jump_thread_edge *> *jump_thread_path = allocate_thread_path ();
081fdda6 882
c7a669af
AH
883 // The generic copier ignores the edge type. We can build the
884 // thread edges with any type.
cde30fe0 885 for (unsigned int j = 0; j + 1 < m_path.length (); j++)
081fdda6 886 {
cde30fe0
AH
887 basic_block bb1 = m_path[m_path.length () - j - 1];
888 basic_block bb2 = m_path[m_path.length () - j - 2];
8af01c66 889
081fdda6
JL
890 edge e = find_edge (bb1, bb2);
891 gcc_assert (e);
7f6c2258 892 push_edge (jump_thread_path, e, EDGE_COPY_SRC_BLOCK);
081fdda6
JL
893 }
894
7f6c2258
AH
895 push_edge (jump_thread_path, taken_edge, EDGE_NO_COPY_SRC_BLOCK);
896 register_jump_thread (jump_thread_path);
69e55442 897 return true;
081fdda6
JL
898}
899
4e0f56d7 900// Thread all suitable paths in the current function.
5d4d64fa 901//
4e0f56d7 902// Return TODO_flags.
8b2ef235 903
4e0f56d7
AH
904unsigned int
905back_threader::thread_blocks ()
8b2ef235 906{
8b2ef235 907 basic_block bb;
4e0f56d7
AH
908 FOR_EACH_BB_FN (bb, m_fun)
909 if (EDGE_COUNT (bb->succs) > 1)
910 maybe_thread_block (bb);
bb7ebad1 911
4e0f56d7 912 bool changed = m_registry.thread_through_all_blocks (true);
5d4d64fa 913
4e0f56d7
AH
914 if (m_flags & BT_SPEED)
915 return changed ? TODO_cleanup_cfg : 0;
5d4d64fa 916
4e0f56d7 917 return false;
8b2ef235 918}
b720e919
JH
919
920namespace {
921
922const pass_data pass_data_early_thread_jumps =
923{
924 GIMPLE_PASS,
925 "ethread",
926 OPTGROUP_NONE,
927 TV_TREE_SSA_THREAD_JUMPS,
928 ( PROP_cfg | PROP_ssa ),
929 0,
930 0,
931 0,
932 ( TODO_cleanup_cfg | TODO_update_ssa ),
933};
934
5d4d64fa
AH
935const pass_data pass_data_thread_jumps =
936{
937 GIMPLE_PASS,
938 "thread",
939 OPTGROUP_NONE,
940 TV_TREE_SSA_THREAD_JUMPS,
941 ( PROP_cfg | PROP_ssa ),
942 0,
943 0,
944 0,
945 TODO_update_ssa,
946};
947
948const pass_data pass_data_thread_jumps_full =
949{
950 GIMPLE_PASS,
4b3a325f 951 "threadfull",
5d4d64fa
AH
952 OPTGROUP_NONE,
953 TV_TREE_SSA_THREAD_JUMPS,
954 ( PROP_cfg | PROP_ssa ),
955 0,
956 0,
957 0,
958 TODO_update_ssa,
959};
960
961// Early jump threading pass optimizing for size.
b720e919
JH
962class pass_early_thread_jumps : public gimple_opt_pass
963{
964public:
965 pass_early_thread_jumps (gcc::context *ctxt)
966 : gimple_opt_pass (pass_data_early_thread_jumps, ctxt)
967 {}
968
5d4d64fa
AH
969 opt_pass * clone () override
970 {
971 return new pass_early_thread_jumps (m_ctxt);
972 }
bc5baac5
AH
973 void set_pass_param (unsigned int, bool param) override
974 {
975 m_first = param;
976 }
5d4d64fa
AH
977 bool gate (function *) override
978 {
979 return flag_thread_jumps;
980 }
981 unsigned int execute (function *fun) override
982 {
bc5baac5 983 back_threader threader (fun, BT_NONE, m_first);
4e0f56d7 984 return threader.thread_blocks ();
5d4d64fa 985 }
bc5baac5
AH
986private:
987 bool m_first;
b720e919
JH
988};
989
5d4d64fa
AH
990// Jump threading pass without resolving of unknown SSAs.
991class pass_thread_jumps : public gimple_opt_pass
b720e919 992{
5d4d64fa
AH
993public:
994 pass_thread_jumps (gcc::context *ctxt)
995 : gimple_opt_pass (pass_data_thread_jumps, ctxt)
996 {}
997 opt_pass * clone (void) override
998 {
999 return new pass_thread_jumps (m_ctxt);
1000 }
bc5baac5
AH
1001 void set_pass_param (unsigned int, bool param) override
1002 {
1003 m_first = param;
1004 }
5d4d64fa
AH
1005 bool gate (function *) override
1006 {
1007 return flag_thread_jumps && flag_expensive_optimizations;
1008 }
1009 unsigned int execute (function *fun) override
1010 {
bc5baac5 1011 back_threader threader (fun, BT_SPEED, m_first);
4e0f56d7 1012 return threader.thread_blocks ();
5d4d64fa 1013 }
bc5baac5
AH
1014private:
1015 bool m_first;
5d4d64fa 1016};
b720e919 1017
5d4d64fa
AH
1018// Jump threading pass that fully resolves unknown SSAs.
1019class pass_thread_jumps_full : public gimple_opt_pass
b720e919 1020{
5d4d64fa
AH
1021public:
1022 pass_thread_jumps_full (gcc::context *ctxt)
1023 : gimple_opt_pass (pass_data_thread_jumps_full, ctxt)
1024 {}
1025 opt_pass * clone (void) override
1026 {
dece6ae7 1027 return new pass_thread_jumps_full (m_ctxt);
5d4d64fa 1028 }
bc5baac5
AH
1029 void set_pass_param (unsigned int, bool param) override
1030 {
1031 m_first = param;
1032 }
5d4d64fa
AH
1033 bool gate (function *) override
1034 {
1035 return flag_thread_jumps && flag_expensive_optimizations;
1036 }
1037 unsigned int execute (function *fun) override
1038 {
bc5baac5 1039 back_threader threader (fun, BT_SPEED | BT_RESOLVE, m_first);
4e0f56d7 1040 return threader.thread_blocks ();
5d4d64fa 1041 }
bc5baac5
AH
1042private:
1043 bool m_first;
5d4d64fa 1044};
108fdd6d 1045
5d4d64fa 1046} // namespace {
108fdd6d 1047
5d4d64fa
AH
1048gimple_opt_pass *
1049make_pass_thread_jumps (gcc::context *ctxt)
1050{
1051 return new pass_thread_jumps (ctxt);
b720e919
JH
1052}
1053
5d4d64fa
AH
1054gimple_opt_pass *
1055make_pass_thread_jumps_full (gcc::context *ctxt)
1056{
1057 return new pass_thread_jumps_full (ctxt);
b720e919
JH
1058}
1059
1060gimple_opt_pass *
1061make_pass_early_thread_jumps (gcc::context *ctxt)
1062{
1063 return new pass_early_thread_jumps (ctxt);
1064}