[RS6000] lqarx and stqcx. registers
[official-gcc.git] / gcc / tree-ssa-threadbackward.c
blob55dbcaddf69f4e8e86159536c937b461a57b92b5
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"
37 static int max_threaded_paths;
39 /* Simple helper to get the last statement from BB, which is assumed
40 to be a control statement. Return NULL if the last statement is
41 not a control statement. */
43 static gimple *
44 get_gimple_control_stmt (basic_block bb)
46 gimple_stmt_iterator gsi = gsi_last_nondebug_bb (bb);
48 if (gsi_end_p (gsi))
49 return NULL;
51 gimple *stmt = gsi_stmt (gsi);
52 enum gimple_code code = gimple_code (stmt);
53 if (code == GIMPLE_COND || code == GIMPLE_SWITCH || code == GIMPLE_GOTO)
54 return stmt;
55 return NULL;
58 /* Return true if the CFG contains at least one path from START_BB to END_BB.
59 When a path is found, record in PATH the blocks from END_BB to START_BB.
60 VISITED_BBS is used to make sure we don't fall into an infinite loop. Bound
61 the recursion to basic blocks belonging to LOOP. */
63 static bool
64 fsm_find_thread_path (basic_block start_bb, basic_block end_bb,
65 vec<basic_block, va_gc> *&path,
66 hash_set<basic_block> *visited_bbs, loop_p loop)
68 if (loop != start_bb->loop_father)
69 return false;
71 if (start_bb == end_bb)
73 vec_safe_push (path, start_bb);
74 return true;
77 if (!visited_bbs->add (start_bb))
79 edge e;
80 edge_iterator ei;
81 FOR_EACH_EDGE (e, ei, start_bb->succs)
82 if (fsm_find_thread_path (e->dest, end_bb, path, visited_bbs, loop))
84 vec_safe_push (path, start_bb);
85 return true;
89 return false;
92 /* We trace the value of the SSA_NAME NAME back through any phi nodes looking
93 for places where it gets a constant value and save the path. Stop after
94 having recorded MAX_PATHS jump threading paths. */
96 static void
97 fsm_find_control_statement_thread_paths (tree name,
98 hash_set<basic_block> *visited_bbs,
99 vec<basic_block, va_gc> *&path,
100 bool seen_loop_phi)
102 /* If NAME appears in an abnormal PHI, then don't try to trace its
103 value back through PHI nodes. */
104 if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (name))
105 return;
107 gimple *def_stmt = SSA_NAME_DEF_STMT (name);
108 basic_block var_bb = gimple_bb (def_stmt);
110 if (var_bb == NULL)
111 return;
113 /* For the moment we assume that an SSA chain only contains phi nodes, and
114 eventually one of the phi arguments will be an integer constant. In the
115 future, this could be extended to also handle simple assignments of
116 arithmetic operations. */
117 if (gimple_code (def_stmt) != GIMPLE_PHI
118 || (gimple_phi_num_args (def_stmt)
119 >= (unsigned) PARAM_VALUE (PARAM_FSM_MAXIMUM_PHI_ARGUMENTS)))
120 return;
122 /* Avoid infinite recursion. */
123 if (visited_bbs->add (var_bb))
124 return;
126 gphi *phi = as_a <gphi *> (def_stmt);
127 int next_path_length = 0;
128 basic_block last_bb_in_path = path->last ();
130 if (loop_containing_stmt (phi)->header == gimple_bb (phi))
132 /* Do not walk through more than one loop PHI node. */
133 if (seen_loop_phi)
134 return;
135 seen_loop_phi = true;
138 /* Following the chain of SSA_NAME definitions, we jumped from a definition in
139 LAST_BB_IN_PATH to a definition in VAR_BB. When these basic blocks are
140 different, append to PATH the blocks from LAST_BB_IN_PATH to VAR_BB. */
141 if (var_bb != last_bb_in_path)
143 edge e;
144 int e_count = 0;
145 edge_iterator ei;
146 vec<basic_block, va_gc> *next_path;
147 vec_alloc (next_path, 10);
149 /* When VAR_BB == LAST_BB_IN_PATH, then the first block in the path
150 will already be in VISITED_BBS. When they are not equal, then we
151 must ensure that first block is accounted for to ensure we do not
152 create bogus jump threading paths. */
153 visited_bbs->add ((*path)[0]);
154 FOR_EACH_EDGE (e, ei, last_bb_in_path->preds)
156 hash_set<basic_block> *visited_bbs = new hash_set<basic_block>;
158 if (fsm_find_thread_path (var_bb, e->src, next_path, visited_bbs,
159 e->src->loop_father))
160 ++e_count;
162 delete visited_bbs;
164 /* If there is more than one path, stop. */
165 if (e_count > 1)
167 vec_free (next_path);
168 return;
172 /* Stop if we have not found a path: this could occur when the recursion
173 is stopped by one of the bounds. */
174 if (e_count == 0)
176 vec_free (next_path);
177 return;
180 /* Make sure we haven't already visited any of the nodes in
181 NEXT_PATH. Don't add them here to avoid pollution. */
182 for (unsigned int i = 0; i < next_path->length () - 1; i++)
184 if (visited_bbs->contains ((*next_path)[i]))
186 vec_free (next_path);
187 return;
191 /* Now add the nodes to VISISTED_BBS. */
192 for (unsigned int i = 0; i < next_path->length () - 1; i++)
193 visited_bbs->add ((*next_path)[i]);
195 /* Append all the nodes from NEXT_PATH to PATH. */
196 vec_safe_splice (path, next_path);
197 next_path_length = next_path->length ();
198 vec_free (next_path);
201 gcc_assert (path->last () == var_bb);
203 /* Iterate over the arguments of PHI. */
204 unsigned int i;
205 if (gimple_phi_num_args (phi)
206 < (unsigned) PARAM_VALUE (PARAM_FSM_MAXIMUM_PHI_ARGUMENTS))
208 for (i = 0; i < gimple_phi_num_args (phi); i++)
210 tree arg = gimple_phi_arg_def (phi, i);
211 basic_block bbi = gimple_phi_arg_edge (phi, i)->src;
213 /* Skip edges pointing outside the current loop. */
214 if (!arg || var_bb->loop_father != bbi->loop_father)
215 continue;
217 if (TREE_CODE (arg) == SSA_NAME)
219 vec_safe_push (path, bbi);
220 /* Recursively follow SSA_NAMEs looking for a constant
221 definition. */
222 fsm_find_control_statement_thread_paths (arg, visited_bbs, path,
223 seen_loop_phi);
225 path->pop ();
226 continue;
229 if (TREE_CODE (arg) != INTEGER_CST)
230 continue;
232 /* Note BBI is not in the path yet, hence the +1 in the test below
233 to make sure BBI is accounted for in the path length test. */
234 int path_length = path->length ();
235 if (path_length + 1 > PARAM_VALUE (PARAM_MAX_FSM_THREAD_LENGTH))
237 if (dump_file && (dump_flags & TDF_DETAILS))
238 fprintf (dump_file, "FSM jump-thread path not considered: "
239 "the number of basic blocks on the path "
240 "exceeds PARAM_MAX_FSM_THREAD_LENGTH.\n");
241 continue;
244 if (max_threaded_paths <= 0)
246 if (dump_file && (dump_flags & TDF_DETAILS))
247 fprintf (dump_file, "FSM jump-thread path not considered: "
248 "the number of previously recorded FSM paths to "
249 "thread exceeds PARAM_MAX_FSM_THREAD_PATHS.\n");
250 continue;
253 /* Add BBI to the path. */
254 vec_safe_push (path, bbi);
255 ++path_length;
257 int n_insns = 0;
258 gimple_stmt_iterator gsi;
259 int j;
260 loop_p loop = (*path)[0]->loop_father;
261 bool path_crosses_loops = false;
262 bool threaded_through_latch = false;
263 bool multiway_branch_in_path = false;
264 bool threaded_multiway_branch = false;
266 /* Count the number of instructions on the path: as these instructions
267 will have to be duplicated, we will not record the path if there
268 are too many instructions on the path. Also check that all the
269 blocks in the path belong to a single loop. */
270 for (j = 0; j < path_length; j++)
272 basic_block bb = (*path)[j];
274 /* Remember, blocks in the path are stored in opposite order
275 in the PATH array. The last entry in the array represents
276 the block with an outgoing edge that we will redirect to the
277 jump threading path. Thus we don't care about that block's
278 loop father, nor how many statements are in that block because
279 it will not be copied or whether or not it ends in a multiway
280 branch. */
281 if (j < path_length - 1)
283 if (bb->loop_father != loop)
285 path_crosses_loops = true;
286 break;
289 for (gsi = gsi_after_labels (bb);
290 !gsi_end_p (gsi);
291 gsi_next_nondebug (&gsi))
293 gimple *stmt = gsi_stmt (gsi);
294 /* Do not count empty statements and labels. */
295 if (gimple_code (stmt) != GIMPLE_NOP
296 && !(gimple_code (stmt) == GIMPLE_ASSIGN
297 && gimple_assign_rhs_code (stmt) == ASSERT_EXPR)
298 && !is_gimple_debug (stmt))
299 ++n_insns;
302 /* We do not look at the block with the threaded branch
303 in this loop. So if any block with a last statement that
304 is a GIMPLE_SWITCH or GIMPLE_GOTO is seen, then we have a
305 multiway branch on our path.
307 The block in PATH[0] is special, it's the block were we're
308 going to be able to eliminate its branch. */
309 gimple *last = last_stmt (bb);
310 if (last && (gimple_code (last) == GIMPLE_SWITCH
311 || gimple_code (last) == GIMPLE_GOTO))
313 if (j == 0)
314 threaded_multiway_branch = true;
315 else
316 multiway_branch_in_path = true;
320 /* Note if we thread through the latch, we will want to include
321 the last entry in the array when determining if we thread
322 through the loop latch. */
323 if (loop->latch == bb)
324 threaded_through_latch = true;
327 gimple *stmt = get_gimple_control_stmt ((*path)[0]);
328 gcc_assert (stmt);
329 /* We have found a constant value for ARG. For GIMPLE_SWITCH
330 and GIMPLE_GOTO, we use it as-is. However, for a GIMPLE_COND
331 we need to substitute, fold and simplify so we can determine
332 the edge taken out of the last block. */
333 if (gimple_code (stmt) == GIMPLE_COND)
335 enum tree_code cond_code = gimple_cond_code (stmt);
337 /* We know the underyling format of the condition. */
338 arg = fold_binary (cond_code, boolean_type_node,
339 arg, gimple_cond_rhs (stmt));
342 /* If this path threaded through the loop latch back into the
343 same loop and the destination does not dominate the loop
344 latch, then this thread would create an irreducible loop.
346 We have to know the outgoing edge to figure this out. */
347 edge taken_edge = find_taken_edge ((*path)[0], arg);
348 bool creates_irreducible_loop = false;
349 if (threaded_through_latch
350 && loop == taken_edge->dest->loop_father
351 && (determine_bb_domination_status (loop, taken_edge->dest)
352 == DOMST_NONDOMINATING))
353 creates_irreducible_loop = true;
355 /* PHIs in the final target and only the final target will need
356 to be duplicated. So only count those against the number
357 of statements. */
358 gphi_iterator gsip;
359 for (gsip = gsi_start_phis (taken_edge->dest);
360 !gsi_end_p (gsip);
361 gsi_next (&gsip))
363 gphi *phi = gsip.phi ();
364 tree dst = gimple_phi_result (phi);
366 /* We consider any non-virtual PHI as a statement since it
367 count result in a constant assignment or copy
368 operation. */
369 if (!virtual_operand_p (dst))
370 ++n_insns;
373 if (path_crosses_loops)
375 if (dump_file && (dump_flags & TDF_DETAILS))
376 fprintf (dump_file, "FSM jump-thread path not considered: "
377 "the path crosses loops.\n");
378 path->pop ();
379 continue;
382 if (n_insns >= PARAM_VALUE (PARAM_MAX_FSM_THREAD_PATH_INSNS))
384 if (dump_file && (dump_flags & TDF_DETAILS))
385 fprintf (dump_file, "FSM jump-thread path not considered: "
386 "the number of instructions on the path "
387 "exceeds PARAM_MAX_FSM_THREAD_PATH_INSNS.\n");
388 path->pop ();
389 continue;
392 /* We avoid creating irreducible inner loops unless we thread through
393 a multiway branch, in which case we have deemed it worth losing
394 other loop optimizations later.
396 We also consider it worth creating an irreducible inner loop if
397 the number of copied statement is low relative to the length of
398 the path -- in that case there's little the traditional loop
399 optimizer would have done anyway, so an irreducible loop is not
400 so bad. */
401 if (!threaded_multiway_branch && creates_irreducible_loop
402 && (n_insns * PARAM_VALUE (PARAM_FSM_SCALE_PATH_STMTS)
403 > path_length * PARAM_VALUE (PARAM_FSM_SCALE_PATH_BLOCKS)))
406 if (dump_file && (dump_flags & TDF_DETAILS))
407 fprintf (dump_file,
408 "FSM would create irreducible loop without threading "
409 "multiway branch.\n");
410 path->pop ();
411 continue;
414 /* When there is a multi-way branch on the path, then threading can
415 explode the CFG due to duplicating the edges for that multi-way
416 branch. So like above, only allow a multi-way branch on the path
417 if we actually thread a multi-way branch. */
418 if (!threaded_multiway_branch && multiway_branch_in_path)
420 if (dump_file && (dump_flags & TDF_DETAILS))
421 fprintf (dump_file,
422 "FSM Thread through multiway branch without threading "
423 "a multiway branch.\n");
424 path->pop ();
425 continue;
428 vec<jump_thread_edge *> *jump_thread_path
429 = new vec<jump_thread_edge *> ();
431 /* Record the edges between the blocks in PATH. */
432 for (j = 0; j < path_length - 1; j++)
434 edge e = find_edge ((*path)[path_length - j - 1],
435 (*path)[path_length - j - 2]);
436 gcc_assert (e);
437 jump_thread_edge *x = new jump_thread_edge (e, EDGE_FSM_THREAD);
438 jump_thread_path->safe_push (x);
441 /* Add the edge taken when the control variable has value ARG. */
442 jump_thread_edge *x
443 = new jump_thread_edge (taken_edge, EDGE_NO_COPY_SRC_BLOCK);
444 jump_thread_path->safe_push (x);
446 register_jump_thread (jump_thread_path);
447 --max_threaded_paths;
449 /* Remove BBI from the path. */
450 path->pop ();
454 /* Remove all the nodes that we added from NEXT_PATH. */
455 if (next_path_length)
456 vec_safe_truncate (path, (path->length () - next_path_length));
459 /* Search backwards from BB looking for paths where NAME (an SSA_NAME)
460 is a constant. Record such paths for jump threading.
462 It is assumed that BB ends with a control statement and that by
463 finding a path where NAME is a constant, we can thread the path. */
465 void
466 find_jump_threads_backwards (edge e)
468 if (!flag_expensive_optimizations
469 || optimize_function_for_size_p (cfun)
470 || e->dest->loop_father != e->src->loop_father
471 || loop_depth (e->dest->loop_father) == 0)
472 return;
474 gimple *stmt = get_gimple_control_stmt (e->dest);
475 if (!stmt)
476 return;
478 enum gimple_code code = gimple_code (stmt);
479 tree name = NULL;
480 if (code == GIMPLE_SWITCH)
481 name = gimple_switch_index (as_a <gswitch *> (stmt));
482 else if (code == GIMPLE_GOTO)
483 name = gimple_goto_dest (stmt);
484 else if (code == GIMPLE_COND)
486 if (TREE_CODE (gimple_cond_lhs (stmt)) == SSA_NAME
487 && TREE_CODE (gimple_cond_rhs (stmt)) == INTEGER_CST
488 && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
489 || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))))
490 name = gimple_cond_lhs (stmt);
493 if (!name || TREE_CODE (name) != SSA_NAME)
494 return;
496 vec<basic_block, va_gc> *bb_path;
497 vec_alloc (bb_path, 10);
498 vec_safe_push (bb_path, e->dest);
499 hash_set<basic_block> *visited_bbs = new hash_set<basic_block>;
501 max_threaded_paths = PARAM_VALUE (PARAM_MAX_FSM_THREAD_PATHS);
502 fsm_find_control_statement_thread_paths (name, visited_bbs, bb_path, false);
504 delete visited_bbs;
505 vec_free (bb_path);