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