2016-09-08 Steven G. Kargl <kargl@gcc.gnu.org>
[official-gcc.git] / gcc / tree-ssa-threadbackward.c
blob506078f23581a59eb6c81f4b51f5405ddb299cda
1 /* SSA Jump Threading
2 Copyright (C) 2005-2016 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>. */
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"
32 #include "params.h"
33 #include "tree-ssa-loop.h"
34 #include "cfganal.h"
35 #include "tree-pass.h"
36 #include "gimple-ssa.h"
37 #include "tree-phinodes.h"
38 #include "tree-inline.h"
40 static int max_threaded_paths;
42 /* Simple helper to get the last statement from BB, which is assumed
43 to be a control statement. Return NULL if the last statement is
44 not a control statement. */
46 static gimple *
47 get_gimple_control_stmt (basic_block bb)
49 gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
51 if (gsi_end_p (gsi))
52 return NULL;
54 gimple *stmt = gsi_stmt (gsi);
55 enum gimple_code code = gimple_code (stmt);
56 if (code == GIMPLE_COND || code == GIMPLE_SWITCH || code == GIMPLE_GOTO)
57 return stmt;
58 return NULL;
61 /* Return true if the CFG contains at least one path from START_BB to END_BB.
62 When a path is found, record in PATH the blocks from END_BB to START_BB.
63 VISITED_BBS is used to make sure we don't fall into an infinite loop. Bound
64 the recursion to basic blocks belonging to LOOP. */
66 static bool
67 fsm_find_thread_path (basic_block start_bb, basic_block end_bb,
68 vec<basic_block, va_gc> *&path,
69 hash_set<basic_block> *visited_bbs, loop_p loop)
71 if (loop != start_bb->loop_father)
72 return false;
74 if (start_bb == end_bb)
76 vec_safe_push (path, start_bb);
77 return true;
80 if (!visited_bbs->add (start_bb))
82 edge e;
83 edge_iterator ei;
84 FOR_EACH_EDGE (e, ei, start_bb->succs)
85 if (fsm_find_thread_path (e->dest, end_bb, path, visited_bbs, loop))
87 vec_safe_push (path, start_bb);
88 return true;
92 return false;
95 /* Examine jump threading path PATH to which we want to add BBI.
97 If the resulting path is profitable to thread, then return the
98 final taken edge from the path, NULL otherwise.
100 NAME is the SSA_NAME of the variable we found to have a constant
101 value on PATH. ARG is the value of that SSA_NAME.
103 BBI will be appended to PATH when we have a profitable jump threading
104 path. Callers are responsible for removing BBI from PATH in that case. */
106 static edge
107 profitable_jump_thread_path (vec<basic_block, va_gc> *&path,
108 basic_block bbi, tree name, tree arg)
110 /* Note BBI is not in the path yet, hence the +1 in the test below
111 to make sure BBI is accounted for in the path length test. */
112 int path_length = path->length ();
114 /* We can get a length of 0 here when the statement that
115 makes a conditional generate a compile-time constant
116 result is in the same block as the conditional.
118 That's not really a jump threading opportunity, but instead is
119 simple cprop & simplification. We could handle it here if we
120 wanted by wiring up all the incoming edges. If we run this
121 early in IPA, that might be worth doing. For now we just
122 reject that case. */
123 if (path_length == 0)
124 return NULL;
126 if (path_length + 1 > PARAM_VALUE (PARAM_MAX_FSM_THREAD_LENGTH))
128 if (dump_file && (dump_flags & TDF_DETAILS))
129 fprintf (dump_file, "FSM jump-thread path not considered: "
130 "the number of basic blocks on the path "
131 "exceeds PARAM_MAX_FSM_THREAD_LENGTH.\n");
132 return NULL;
135 if (max_threaded_paths <= 0)
137 if (dump_file && (dump_flags & TDF_DETAILS))
138 fprintf (dump_file, "FSM jump-thread path not considered: "
139 "the number of previously recorded FSM paths to "
140 "thread exceeds PARAM_MAX_FSM_THREAD_PATHS.\n");
141 return NULL;
144 /* Add BBI to the path.
145 From this point onward, if we decide we the path is not profitable
146 to thread, we must remove BBI from the path. */
147 vec_safe_push (path, bbi);
148 ++path_length;
150 int n_insns = 0;
151 gimple_stmt_iterator gsi;
152 int j;
153 loop_p loop = (*path)[0]->loop_father;
154 bool path_crosses_loops = false;
155 bool threaded_through_latch = false;
156 bool multiway_branch_in_path = false;
157 bool threaded_multiway_branch = false;
159 /* Count the number of instructions on the path: as these instructions
160 will have to be duplicated, we will not record the path if there
161 are too many instructions on the path. Also check that all the
162 blocks in the path belong to a single loop. */
163 for (j = 0; j < path_length; j++)
165 basic_block bb = (*path)[j];
167 /* Remember, blocks in the path are stored in opposite order
168 in the PATH array. The last entry in the array represents
169 the block with an outgoing edge that we will redirect to the
170 jump threading path. Thus we don't care about that block's
171 loop father, nor how many statements are in that block because
172 it will not be copied or whether or not it ends in a multiway
173 branch. */
174 if (j < path_length - 1)
176 if (bb->loop_father != loop)
178 path_crosses_loops = true;
179 break;
182 /* PHIs in the path will create degenerate PHIS in the
183 copied path which will then get propagated away, so
184 looking at just the duplicate path the PHIs would
185 seem unimportant.
187 But those PHIs, because they're assignments to objects
188 typically with lives that exist outside the thread path,
189 will tend to generate PHIs (or at least new PHI arguments)
190 at points where we leave the thread path and rejoin
191 the original blocks. So we do want to account for them.
193 We ignore virtual PHIs. We also ignore cases where BB
194 has a single incoming edge. That's the most common
195 degenerate PHI we'll see here. Finally we ignore PHIs
196 that are associated with the value we're tracking as
197 that object likely dies. */
198 if (EDGE_COUNT (bb->succs) > 1 && EDGE_COUNT (bb->preds) > 1)
200 for (gphi_iterator gsip = gsi_start_phis (bb);
201 !gsi_end_p (gsip);
202 gsi_next (&gsip))
204 gphi *phi = gsip.phi ();
205 tree dst = gimple_phi_result (phi);
207 /* Note that if both NAME and DST are anonymous
208 SSA_NAMEs, then we do not have enough information
209 to consider them associated. */
210 if (dst != name
211 && (SSA_NAME_VAR (dst) != SSA_NAME_VAR (name)
212 || !SSA_NAME_VAR (dst))
213 && !virtual_operand_p (dst))
214 ++n_insns;
218 for (gsi = gsi_after_labels (bb);
219 !gsi_end_p (gsi);
220 gsi_next_nondebug (&gsi))
222 gimple *stmt = gsi_stmt (gsi);
223 /* Do not count empty statements and labels. */
224 if (gimple_code (stmt) != GIMPLE_NOP
225 && !(gimple_code (stmt) == GIMPLE_ASSIGN
226 && gimple_assign_rhs_code (stmt) == ASSERT_EXPR)
227 && !is_gimple_debug (stmt))
228 n_insns += estimate_num_insns (stmt, &eni_size_weights);
231 /* We do not look at the block with the threaded branch
232 in this loop. So if any block with a last statement that
233 is a GIMPLE_SWITCH or GIMPLE_GOTO is seen, then we have a
234 multiway branch on our path.
236 The block in PATH[0] is special, it's the block were we're
237 going to be able to eliminate its branch. */
238 gimple *last = last_stmt (bb);
239 if (last && (gimple_code (last) == GIMPLE_SWITCH
240 || gimple_code (last) == GIMPLE_GOTO))
242 if (j == 0)
243 threaded_multiway_branch = true;
244 else
245 multiway_branch_in_path = true;
249 /* Note if we thread through the latch, we will want to include
250 the last entry in the array when determining if we thread
251 through the loop latch. */
252 if (loop->latch == bb)
253 threaded_through_latch = true;
256 gimple *stmt = get_gimple_control_stmt ((*path)[0]);
257 gcc_assert (stmt);
259 /* We are going to remove the control statement at the end of the
260 last block in the threading path. So don't count it against our
261 statement count. */
263 n_insns-= estimate_num_insns (stmt, &eni_size_weights);
265 /* We have found a constant value for ARG. For GIMPLE_SWITCH
266 and GIMPLE_GOTO, we use it as-is. However, for a GIMPLE_COND
267 we need to substitute, fold and simplify so we can determine
268 the edge taken out of the last block. */
269 if (gimple_code (stmt) == GIMPLE_COND)
271 enum tree_code cond_code = gimple_cond_code (stmt);
273 /* We know the underyling format of the condition. */
274 arg = fold_binary (cond_code, boolean_type_node,
275 arg, gimple_cond_rhs (stmt));
278 /* If this path threaded through the loop latch back into the
279 same loop and the destination does not dominate the loop
280 latch, then this thread would create an irreducible loop.
282 We have to know the outgoing edge to figure this out. */
283 edge taken_edge = find_taken_edge ((*path)[0], arg);
285 /* There are cases where we may not be able to extract the
286 taken edge. For example, a computed goto to an absolute
287 address. Handle those cases gracefully. */
288 if (taken_edge == NULL)
290 path->pop ();
291 return NULL;
294 bool creates_irreducible_loop = false;
295 if (threaded_through_latch
296 && loop == taken_edge->dest->loop_father
297 && (determine_bb_domination_status (loop, taken_edge->dest)
298 == DOMST_NONDOMINATING))
299 creates_irreducible_loop = true;
301 if (path_crosses_loops)
303 if (dump_file && (dump_flags & TDF_DETAILS))
304 fprintf (dump_file, "FSM jump-thread path not considered: "
305 "the path crosses loops.\n");
306 path->pop ();
307 return NULL;
310 if (optimize_edge_for_speed_p (taken_edge))
312 if (n_insns >= PARAM_VALUE (PARAM_MAX_FSM_THREAD_PATH_INSNS))
314 if (dump_file && (dump_flags & TDF_DETAILS))
315 fprintf (dump_file, "FSM jump-thread path not considered: "
316 "the number of instructions on the path "
317 "exceeds PARAM_MAX_FSM_THREAD_PATH_INSNS.\n");
318 path->pop ();
319 return NULL;
322 else if (n_insns > 1)
324 if (dump_file && (dump_flags & TDF_DETAILS))
325 fprintf (dump_file, "FSM jump-thread path not considered: "
326 "duplication of %i insns is needed and optimizing for size.\n",
327 n_insns);
328 path->pop ();
329 return NULL;
332 /* We avoid creating irreducible inner loops unless we thread through
333 a multiway branch, in which case we have deemed it worth losing
334 other loop optimizations later.
336 We also consider it worth creating an irreducible inner loop if
337 the number of copied statement is low relative to the length of
338 the path -- in that case there's little the traditional loop
339 optimizer would have done anyway, so an irreducible loop is not
340 so bad. */
341 if (!threaded_multiway_branch && creates_irreducible_loop
342 && (n_insns * PARAM_VALUE (PARAM_FSM_SCALE_PATH_STMTS)
343 > path_length * PARAM_VALUE (PARAM_FSM_SCALE_PATH_BLOCKS)))
346 if (dump_file && (dump_flags & TDF_DETAILS))
347 fprintf (dump_file,
348 "FSM would create irreducible loop without threading "
349 "multiway branch.\n");
350 path->pop ();
351 return NULL;
355 /* If this path does not thread through the loop latch, then we are
356 using the FSM threader to find old style jump threads. This
357 is good, except the FSM threader does not re-use an existing
358 threading path to reduce code duplication.
360 So for that case, drastically reduce the number of statements
361 we are allowed to copy. */
362 if (!(threaded_through_latch && threaded_multiway_branch)
363 && (n_insns * PARAM_VALUE (PARAM_FSM_SCALE_PATH_STMTS)
364 >= PARAM_VALUE (PARAM_MAX_JUMP_THREAD_DUPLICATION_STMTS)))
366 if (dump_file && (dump_flags & TDF_DETAILS))
367 fprintf (dump_file,
368 "FSM did not thread around loop and would copy too "
369 "many statements.\n");
370 path->pop ();
371 return NULL;
374 /* When there is a multi-way branch on the path, then threading can
375 explode the CFG due to duplicating the edges for that multi-way
376 branch. So like above, only allow a multi-way branch on the path
377 if we actually thread a multi-way branch. */
378 if (!threaded_multiway_branch && multiway_branch_in_path)
380 if (dump_file && (dump_flags & TDF_DETAILS))
381 fprintf (dump_file,
382 "FSM Thread through multiway branch without threading "
383 "a multiway branch.\n");
384 path->pop ();
385 return NULL;
387 return taken_edge;
390 /* PATH is vector of blocks forming a jump threading path in reverse
391 order. TAKEN_EDGE is the edge taken from path[0].
393 Convert that path into the form used by register_jump_thread and
394 register the path. */
396 static void
397 convert_and_register_jump_thread_path (vec<basic_block, va_gc> *path,
398 edge taken_edge)
400 vec<jump_thread_edge *> *jump_thread_path = new vec<jump_thread_edge *> ();
402 /* Record the edges between the blocks in PATH. */
403 for (unsigned int j = 0; j < path->length () - 1; j++)
405 basic_block bb1 = (*path)[path->length () - j - 1];
406 basic_block bb2 = (*path)[path->length () - j - 2];
408 edge e = find_edge (bb1, bb2);
409 gcc_assert (e);
410 jump_thread_edge *x = new jump_thread_edge (e, EDGE_FSM_THREAD);
411 jump_thread_path->safe_push (x);
414 /* Add the edge taken when the control variable has value ARG. */
415 jump_thread_edge *x
416 = new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK);
417 jump_thread_path->safe_push (x);
419 register_jump_thread (jump_thread_path);
420 --max_threaded_paths;
423 /* We trace the value of the SSA_NAME NAME back through any phi nodes looking
424 for places where it gets a constant value and save the path. Stop after
425 having recorded MAX_PATHS jump threading paths. */
427 static void
428 fsm_find_control_statement_thread_paths (tree name,
429 hash_set<basic_block> *visited_bbs,
430 vec<basic_block, va_gc> *&path,
431 bool seen_loop_phi)
433 /* If NAME appears in an abnormal PHI, then don't try to trace its
434 value back through PHI nodes. */
435 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
436 return;
438 gimple *def_stmt = SSA_NAME_DEF_STMT (name);
439 basic_block var_bb = gimple_bb (def_stmt);
441 if (var_bb == NULL)
442 return;
444 /* We allow the SSA chain to contains PHIs and simple copies and constant
445 initializations. */
446 if (gimple_code (def_stmt) != GIMPLE_PHI
447 && gimple_code (def_stmt) != GIMPLE_ASSIGN)
448 return;
450 if (gimple_code (def_stmt) == GIMPLE_PHI
451 && (gimple_phi_num_args (def_stmt)
452 >= (unsigned) PARAM_VALUE (PARAM_FSM_MAXIMUM_PHI_ARGUMENTS)))
453 return;
455 if (gimple_code (def_stmt) == GIMPLE_ASSIGN
456 && gimple_assign_rhs_code (def_stmt) != INTEGER_CST
457 && gimple_assign_rhs_code (def_stmt) != SSA_NAME)
458 return;
460 /* Avoid infinite recursion. */
461 if (visited_bbs->add (var_bb))
462 return;
464 int next_path_length = 0;
465 basic_block last_bb_in_path = path->last ();
467 if (loop_containing_stmt (def_stmt)->header == gimple_bb (def_stmt))
469 /* Do not walk through more than one loop PHI node. */
470 if (seen_loop_phi)
471 return;
472 seen_loop_phi = true;
475 if (bb_loop_depth (last_bb_in_path) > bb_loop_depth (var_bb))
476 return;
478 /* Following the chain of SSA_NAME definitions, we jumped from a definition in
479 LAST_BB_IN_PATH to a definition in VAR_BB. When these basic blocks are
480 different, append to PATH the blocks from LAST_BB_IN_PATH to VAR_BB. */
481 if (var_bb != last_bb_in_path)
483 edge e;
484 int e_count = 0;
485 edge_iterator ei;
486 vec<basic_block, va_gc> *next_path;
487 vec_alloc (next_path, 10);
489 /* When VAR_BB == LAST_BB_IN_PATH, then the first block in the path
490 will already be in VISITED_BBS. When they are not equal, then we
491 must ensure that first block is accounted for to ensure we do not
492 create bogus jump threading paths. */
493 visited_bbs->add ((*path)[0]);
494 FOR_EACH_EDGE (e, ei, last_bb_in_path->preds)
496 hash_set<basic_block> *visited_bbs = new hash_set<basic_block>;
498 if (fsm_find_thread_path (var_bb, e->src, next_path, visited_bbs,
499 e->src->loop_father))
500 ++e_count;
502 delete visited_bbs;
504 /* If there is more than one path, stop. */
505 if (e_count > 1)
507 vec_free (next_path);
508 return;
512 /* Stop if we have not found a path: this could occur when the recursion
513 is stopped by one of the bounds. */
514 if (e_count == 0)
516 vec_free (next_path);
517 return;
520 /* Make sure we haven't already visited any of the nodes in
521 NEXT_PATH. Don't add them here to avoid pollution. */
522 for (unsigned int i = 0; i < next_path->length () - 1; i++)
524 if (visited_bbs->contains ((*next_path)[i])
525 || (bb_loop_depth (last_bb_in_path)
526 > bb_loop_depth ((*next_path)[i])))
528 vec_free (next_path);
529 return;
533 /* Now add the nodes to VISISTED_BBS. */
534 for (unsigned int i = 0; i < next_path->length () - 1; i++)
535 visited_bbs->add ((*next_path)[i]);
537 /* Append all the nodes from NEXT_PATH to PATH. */
538 vec_safe_splice (path, next_path);
539 next_path_length = next_path->length ();
540 vec_free (next_path);
543 gcc_assert (path->last () == var_bb);
545 /* Iterate over the arguments of PHI. */
546 unsigned int i;
547 if (gimple_code (def_stmt) == GIMPLE_PHI)
549 gphi *phi = as_a <gphi *> (def_stmt);
550 for (i = 0; i < gimple_phi_num_args (phi); i++)
552 tree arg = gimple_phi_arg_def (phi, i);
553 basic_block bbi = gimple_phi_arg_edge (phi, i)->src;
555 /* Skip edges pointing outside the current loop. */
556 if (!arg || var_bb->loop_father != bbi->loop_father)
557 continue;
559 if (TREE_CODE (arg) == SSA_NAME)
561 vec_safe_push (path, bbi);
562 /* Recursively follow SSA_NAMEs looking for a constant
563 definition. */
564 fsm_find_control_statement_thread_paths (arg, visited_bbs, path,
565 seen_loop_phi);
567 path->pop ();
568 continue;
571 if (TREE_CODE (arg) != INTEGER_CST)
572 continue;
574 /* If this is a profitable jump thread path, then convert it
575 into the canonical form and register it. */
576 edge taken_edge = profitable_jump_thread_path (path, bbi, name, arg);
577 if (taken_edge)
579 if (bb_loop_depth (taken_edge->src)
580 >= bb_loop_depth (taken_edge->dest))
581 convert_and_register_jump_thread_path (path, taken_edge);
582 path->pop ();
586 else if (gimple_code (def_stmt) == GIMPLE_ASSIGN)
588 tree arg = gimple_assign_rhs1 (def_stmt);
590 if (TREE_CODE (arg) == SSA_NAME)
591 fsm_find_control_statement_thread_paths (arg, visited_bbs,
592 path, seen_loop_phi);
594 else
596 /* profitable_jump_thread_path is going to push the current
597 block onto the path. But the path will always have the current
598 block at this point. So we can just pop it. */
599 path->pop ();
601 edge taken_edge = profitable_jump_thread_path (path, var_bb,
602 name, arg);
603 if (taken_edge)
605 if (bb_loop_depth (taken_edge->src)
606 >= bb_loop_depth (taken_edge->dest))
607 convert_and_register_jump_thread_path (path, taken_edge);
608 path->pop ();
611 /* And put the current block back onto the path so that the
612 state of the stack is unchanged when we leave. */
613 vec_safe_push (path, var_bb);
617 /* Remove all the nodes that we added from NEXT_PATH. */
618 if (next_path_length)
619 vec_safe_truncate (path, (path->length () - next_path_length));
622 /* Search backwards from BB looking for paths where NAME (an SSA_NAME)
623 is a constant. Record such paths for jump threading.
625 It is assumed that BB ends with a control statement and that by
626 finding a path where NAME is a constant, we can thread the path. */
628 void
629 find_jump_threads_backwards (basic_block bb)
631 gimple *stmt = get_gimple_control_stmt (bb);
632 if (!stmt)
633 return;
635 enum gimple_code code = gimple_code (stmt);
636 tree name = NULL;
637 if (code == GIMPLE_SWITCH)
638 name = gimple_switch_index (as_a <gswitch *> (stmt));
639 else if (code == GIMPLE_GOTO)
640 name = gimple_goto_dest (stmt);
641 else if (code == GIMPLE_COND)
643 if (TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME
644 && TREE_CODE (gimple_cond_rhs (stmt)) == INTEGER_CST
645 && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
646 || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))))
647 name = gimple_cond_lhs (stmt);
650 if (!name || TREE_CODE (name) != SSA_NAME)
651 return;
653 vec<basic_block, va_gc> *bb_path;
654 vec_alloc (bb_path, 10);
655 vec_safe_push (bb_path, bb);
656 hash_set<basic_block> *visited_bbs = new hash_set<basic_block>;
658 max_threaded_paths = PARAM_VALUE (PARAM_MAX_FSM_THREAD_PATHS);
659 fsm_find_control_statement_thread_paths (name, visited_bbs, bb_path, false);
661 delete visited_bbs;
662 vec_free (bb_path);
665 namespace {
667 const pass_data pass_data_thread_jumps =
669 GIMPLE_PASS,
670 "thread",
671 OPTGROUP_NONE,
672 TV_TREE_SSA_THREAD_JUMPS,
673 ( PROP_cfg | PROP_ssa ),
677 TODO_update_ssa,
680 class pass_thread_jumps : public gimple_opt_pass
682 public:
683 pass_thread_jumps (gcc::context *ctxt)
684 : gimple_opt_pass (pass_data_thread_jumps, ctxt)
687 opt_pass * clone (void) { return new pass_thread_jumps (m_ctxt); }
688 virtual bool gate (function *);
689 virtual unsigned int execute (function *);
692 bool
693 pass_thread_jumps::gate (function *fun ATTRIBUTE_UNUSED)
695 return flag_expensive_optimizations;
699 unsigned int
700 pass_thread_jumps::execute (function *fun)
702 loop_optimizer_init (LOOPS_HAVE_PREHEADERS | LOOPS_HAVE_SIMPLE_LATCHES);
704 /* Try to thread each block with more than one successor. */
705 basic_block bb;
706 FOR_EACH_BB_FN (bb, fun)
708 if (EDGE_COUNT (bb->succs) > 1)
709 find_jump_threads_backwards (bb);
711 bool changed = thread_through_all_blocks (true);
713 loop_optimizer_finalize ();
714 return changed ? TODO_cleanup_cfg : 0;
719 gimple_opt_pass *
720 make_pass_thread_jumps (gcc::context *ctxt)
722 return new pass_thread_jumps (ctxt);