gcc/ada/
[official-gcc.git] / gcc / tree-ssa-phiprop.c
blob96d48b142e7db5cf79db5ea2dd23e3d65e88aaae
1 /* Backward propagation of indirect loads through PHIs.
2 Copyright (C) 2007-2014 Free Software Foundation, Inc.
3 Contributed by Richard Guenther <rguenther@suse.de>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "tree.h"
26 #include "tm_p.h"
27 #include "predict.h"
28 #include "vec.h"
29 #include "hashtab.h"
30 #include "hash-set.h"
31 #include "machmode.h"
32 #include "hard-reg-set.h"
33 #include "input.h"
34 #include "function.h"
35 #include "dominance.h"
36 #include "cfg.h"
37 #include "basic-block.h"
38 #include "gimple-pretty-print.h"
39 #include "tree-ssa-alias.h"
40 #include "internal-fn.h"
41 #include "tree-eh.h"
42 #include "gimple-expr.h"
43 #include "is-a.h"
44 #include "gimple.h"
45 #include "gimplify.h"
46 #include "gimple-iterator.h"
47 #include "gimple-ssa.h"
48 #include "tree-phinodes.h"
49 #include "ssa-iterators.h"
50 #include "stringpool.h"
51 #include "tree-ssanames.h"
52 #include "tree-pass.h"
53 #include "langhooks.h"
54 #include "flags.h"
56 /* This pass propagates indirect loads through the PHI node for its
57 address to make the load source possibly non-addressable and to
58 allow for PHI optimization to trigger.
60 For example the pass changes
62 # addr_1 = PHI <&a, &b>
63 tmp_1 = *addr_1;
67 # tmp_1 = PHI <a, b>
69 but also handles more complex scenarios like
71 D.2077_2 = &this_1(D)->a1;
72 ...
74 # b_12 = PHI <&c(2), D.2077_2(3)>
75 D.2114_13 = *b_12;
76 ...
78 # b_15 = PHI <b_12(4), &b(5)>
79 D.2080_5 = &this_1(D)->a0;
80 ...
82 # b_18 = PHI <D.2080_5(6), &c(7)>
83 ...
85 # b_21 = PHI <b_15(8), b_18(9)>
86 D.2076_8 = *b_21;
88 where the addresses loaded are defined by PHIs itself.
89 The above happens for
91 std::max(std::min(a0, c), std::min(std::max(a1, c), b))
93 where this pass transforms it to a form later PHI optimization
94 recognizes and transforms it to the simple
96 D.2109_10 = this_1(D)->a1;
97 D.2110_11 = c;
98 D.2114_31 = MAX_EXPR <D.2109_10, D.2110_11>;
99 D.2115_14 = b;
100 D.2125_17 = MIN_EXPR <D.2115_14, D.2114_31>;
101 D.2119_16 = this_1(D)->a0;
102 D.2124_32 = MIN_EXPR <D.2110_11, D.2119_16>;
103 D.2076_33 = MAX_EXPR <D.2125_17, D.2124_32>;
105 The pass does a dominator walk processing loads using a basic-block
106 local analysis and stores the result for use by transformations on
107 dominated basic-blocks. */
110 /* Structure to keep track of the value of a dereferenced PHI result
111 and the virtual operand used for that dereference. */
113 struct phiprop_d
115 tree value;
116 tree vuse;
119 /* Verify if the value recorded for NAME in PHIVN is still valid at
120 the start of basic block BB. */
122 static bool
123 phivn_valid_p (struct phiprop_d *phivn, tree name, basic_block bb)
125 tree vuse = phivn[SSA_NAME_VERSION (name)].vuse;
126 gimple use_stmt;
127 imm_use_iterator ui2;
128 bool ok = true;
130 /* The def stmts of the virtual uses need to be dominated by bb. */
131 gcc_assert (vuse != NULL_TREE);
133 FOR_EACH_IMM_USE_STMT (use_stmt, ui2, vuse)
135 /* If BB does not dominate a VDEF, the value is invalid. */
136 if ((gimple_vdef (use_stmt) != NULL_TREE
137 || gimple_code (use_stmt) == GIMPLE_PHI)
138 && !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), bb))
140 ok = false;
141 BREAK_FROM_IMM_USE_STMT (ui2);
145 return ok;
148 /* Insert a new phi node for the dereference of PHI at basic_block
149 BB with the virtual operands from USE_STMT. */
151 static tree
152 phiprop_insert_phi (basic_block bb, gimple phi, gimple use_stmt,
153 struct phiprop_d *phivn, size_t n)
155 tree res;
156 gimple new_phi;
157 edge_iterator ei;
158 edge e;
160 gcc_assert (is_gimple_assign (use_stmt)
161 && gimple_assign_rhs_code (use_stmt) == MEM_REF);
163 /* Build a new PHI node to replace the definition of
164 the indirect reference lhs. */
165 res = gimple_assign_lhs (use_stmt);
166 new_phi = create_phi_node (res, bb);
168 if (dump_file && (dump_flags & TDF_DETAILS))
170 fprintf (dump_file, "Inserting PHI for result of load ");
171 print_gimple_stmt (dump_file, use_stmt, 0, 0);
174 /* Add PHI arguments for each edge inserting loads of the
175 addressable operands. */
176 FOR_EACH_EDGE (e, ei, bb->preds)
178 tree old_arg, new_var;
179 gimple tmp;
180 source_location locus;
182 old_arg = PHI_ARG_DEF_FROM_EDGE (phi, e);
183 locus = gimple_phi_arg_location_from_edge (phi, e);
184 while (TREE_CODE (old_arg) == SSA_NAME
185 && (SSA_NAME_VERSION (old_arg) >= n
186 || phivn[SSA_NAME_VERSION (old_arg)].value == NULL_TREE))
188 gimple def_stmt = SSA_NAME_DEF_STMT (old_arg);
189 old_arg = gimple_assign_rhs1 (def_stmt);
190 locus = gimple_location (def_stmt);
193 if (TREE_CODE (old_arg) == SSA_NAME)
195 if (dump_file && (dump_flags & TDF_DETAILS))
197 fprintf (dump_file, " for edge defining ");
198 print_generic_expr (dump_file, PHI_ARG_DEF_FROM_EDGE (phi, e), 0);
199 fprintf (dump_file, " reusing PHI result ");
200 print_generic_expr (dump_file,
201 phivn[SSA_NAME_VERSION (old_arg)].value, 0);
202 fprintf (dump_file, "\n");
204 /* Reuse a formerly created dereference. */
205 new_var = phivn[SSA_NAME_VERSION (old_arg)].value;
207 else
209 tree rhs = gimple_assign_rhs1 (use_stmt);
210 gcc_assert (TREE_CODE (old_arg) == ADDR_EXPR);
211 new_var = make_ssa_name (TREE_TYPE (rhs), NULL);
212 if (!is_gimple_min_invariant (old_arg))
213 old_arg = PHI_ARG_DEF_FROM_EDGE (phi, e);
214 else
215 old_arg = unshare_expr (old_arg);
216 tmp = gimple_build_assign (new_var,
217 fold_build2 (MEM_REF, TREE_TYPE (rhs),
218 old_arg,
219 TREE_OPERAND (rhs, 1)));
220 gimple_set_location (tmp, locus);
222 gsi_insert_on_edge (e, tmp);
223 update_stmt (tmp);
225 if (dump_file && (dump_flags & TDF_DETAILS))
227 fprintf (dump_file, " for edge defining ");
228 print_generic_expr (dump_file, PHI_ARG_DEF_FROM_EDGE (phi, e), 0);
229 fprintf (dump_file, " inserting load ");
230 print_gimple_stmt (dump_file, tmp, 0, 0);
234 add_phi_arg (new_phi, new_var, e, locus);
237 update_stmt (new_phi);
239 if (dump_file && (dump_flags & TDF_DETAILS))
240 print_gimple_stmt (dump_file, new_phi, 0, 0);
242 return res;
245 /* Propagate between the phi node arguments of PHI in BB and phi result
246 users. For now this matches
247 # p_2 = PHI <&x, &y>
248 <Lx>:;
249 p_3 = p_2;
250 z_2 = *p_3;
251 and converts it to
252 # z_2 = PHI <x, y>
253 <Lx>:;
254 Returns true if a transformation was done and edge insertions
255 need to be committed. Global data PHIVN and N is used to track
256 past transformation results. We need to be especially careful here
257 with aliasing issues as we are moving memory reads. */
259 static bool
260 propagate_with_phi (basic_block bb, gimple phi, struct phiprop_d *phivn,
261 size_t n)
263 tree ptr = PHI_RESULT (phi);
264 gimple use_stmt;
265 tree res = NULL_TREE;
266 gimple_stmt_iterator gsi;
267 imm_use_iterator ui;
268 use_operand_p arg_p, use;
269 ssa_op_iter i;
270 bool phi_inserted;
271 tree type = NULL_TREE;
273 if (!POINTER_TYPE_P (TREE_TYPE (ptr))
274 || !is_gimple_reg_type (TREE_TYPE (TREE_TYPE (ptr))))
275 return false;
277 /* Check if we can "cheaply" dereference all phi arguments. */
278 FOR_EACH_PHI_ARG (arg_p, phi, i, SSA_OP_USE)
280 tree arg = USE_FROM_PTR (arg_p);
281 /* Walk the ssa chain until we reach a ssa name we already
282 created a value for or we reach a definition of the form
283 ssa_name_n = &var; */
284 while (TREE_CODE (arg) == SSA_NAME
285 && !SSA_NAME_IS_DEFAULT_DEF (arg)
286 && (SSA_NAME_VERSION (arg) >= n
287 || phivn[SSA_NAME_VERSION (arg)].value == NULL_TREE))
289 gimple def_stmt = SSA_NAME_DEF_STMT (arg);
290 if (!gimple_assign_single_p (def_stmt))
291 return false;
292 arg = gimple_assign_rhs1 (def_stmt);
294 if (TREE_CODE (arg) != ADDR_EXPR
295 && !(TREE_CODE (arg) == SSA_NAME
296 && SSA_NAME_VERSION (arg) < n
297 && phivn[SSA_NAME_VERSION (arg)].value != NULL_TREE
298 && (!type
299 || types_compatible_p
300 (type, TREE_TYPE (phivn[SSA_NAME_VERSION (arg)].value)))
301 && phivn_valid_p (phivn, arg, bb)))
302 return false;
303 if (!type
304 && TREE_CODE (arg) == SSA_NAME)
305 type = TREE_TYPE (phivn[SSA_NAME_VERSION (arg)].value);
308 /* Find a dereferencing use. First follow (single use) ssa
309 copy chains for ptr. */
310 while (single_imm_use (ptr, &use, &use_stmt)
311 && gimple_assign_ssa_name_copy_p (use_stmt))
312 ptr = gimple_assign_lhs (use_stmt);
314 /* Replace the first dereference of *ptr if there is one and if we
315 can move the loads to the place of the ptr phi node. */
316 phi_inserted = false;
317 FOR_EACH_IMM_USE_STMT (use_stmt, ui, ptr)
319 gimple def_stmt;
320 tree vuse;
322 /* Only replace loads in blocks that post-dominate the PHI node. That
323 makes sure we don't end up speculating loads. */
324 if (!dominated_by_p (CDI_POST_DOMINATORS,
325 bb, gimple_bb (use_stmt)))
326 continue;
328 /* Check whether this is a load of *ptr. */
329 if (!(is_gimple_assign (use_stmt)
330 && TREE_CODE (gimple_assign_lhs (use_stmt)) == SSA_NAME
331 && gimple_assign_rhs_code (use_stmt) == MEM_REF
332 && TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 0) == ptr
333 && integer_zerop (TREE_OPERAND (gimple_assign_rhs1 (use_stmt), 1))
334 && (!type
335 || types_compatible_p
336 (TREE_TYPE (gimple_assign_lhs (use_stmt)), type))
337 /* We cannot replace a load that may throw or is volatile. */
338 && !stmt_can_throw_internal (use_stmt)))
339 continue;
341 /* Check if we can move the loads. The def stmt of the virtual use
342 needs to be in a different basic block dominating bb. */
343 vuse = gimple_vuse (use_stmt);
344 def_stmt = SSA_NAME_DEF_STMT (vuse);
345 if (!SSA_NAME_IS_DEFAULT_DEF (vuse)
346 && (gimple_bb (def_stmt) == bb
347 || !dominated_by_p (CDI_DOMINATORS,
348 bb, gimple_bb (def_stmt))))
349 goto next;
351 /* Found a proper dereference. Insert a phi node if this
352 is the first load transformation. */
353 if (!phi_inserted)
355 res = phiprop_insert_phi (bb, phi, use_stmt, phivn, n);
356 type = TREE_TYPE (res);
358 /* Remember the value we created for *ptr. */
359 phivn[SSA_NAME_VERSION (ptr)].value = res;
360 phivn[SSA_NAME_VERSION (ptr)].vuse = vuse;
362 /* Remove old stmt. The phi is taken care of by DCE, if we
363 want to delete it here we also have to delete all intermediate
364 copies. */
365 gsi = gsi_for_stmt (use_stmt);
366 gsi_remove (&gsi, true);
368 phi_inserted = true;
370 else
372 /* Further replacements are easy, just make a copy out of the
373 load. */
374 gimple_assign_set_rhs1 (use_stmt, res);
375 update_stmt (use_stmt);
378 next:;
379 /* Continue searching for a proper dereference. */
382 return phi_inserted;
385 /* Main entry for phiprop pass. */
387 namespace {
389 const pass_data pass_data_phiprop =
391 GIMPLE_PASS, /* type */
392 "phiprop", /* name */
393 OPTGROUP_NONE, /* optinfo_flags */
394 TV_TREE_PHIPROP, /* tv_id */
395 ( PROP_cfg | PROP_ssa ), /* properties_required */
396 0, /* properties_provided */
397 0, /* properties_destroyed */
398 0, /* todo_flags_start */
399 TODO_update_ssa, /* todo_flags_finish */
402 class pass_phiprop : public gimple_opt_pass
404 public:
405 pass_phiprop (gcc::context *ctxt)
406 : gimple_opt_pass (pass_data_phiprop, ctxt)
409 /* opt_pass methods: */
410 virtual bool gate (function *) { return flag_tree_phiprop; }
411 virtual unsigned int execute (function *);
413 }; // class pass_phiprop
415 unsigned int
416 pass_phiprop::execute (function *fun)
418 vec<basic_block> bbs;
419 struct phiprop_d *phivn;
420 bool did_something = false;
421 basic_block bb;
422 gimple_stmt_iterator gsi;
423 unsigned i;
424 size_t n;
426 calculate_dominance_info (CDI_DOMINATORS);
427 calculate_dominance_info (CDI_POST_DOMINATORS);
429 n = num_ssa_names;
430 phivn = XCNEWVEC (struct phiprop_d, n);
432 /* Walk the dominator tree in preorder. */
433 bbs = get_all_dominated_blocks (CDI_DOMINATORS,
434 single_succ (ENTRY_BLOCK_PTR_FOR_FN (fun)));
435 FOR_EACH_VEC_ELT (bbs, i, bb)
436 for (gsi = gsi_start_phis (bb); !gsi_end_p (gsi); gsi_next (&gsi))
437 did_something |= propagate_with_phi (bb, gsi_stmt (gsi), phivn, n);
439 if (did_something)
440 gsi_commit_edge_inserts ();
442 bbs.release ();
443 free (phivn);
445 free_dominance_info (CDI_POST_DOMINATORS);
447 return 0;
450 } // anon namespace
452 gimple_opt_pass *
453 make_pass_phiprop (gcc::context *ctxt)
455 return new pass_phiprop (ctxt);