]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/gimple-ssa-evrp.c
[Ada] Define the -fdump-scos option in lang.opt
[thirdparty/gcc.git] / gcc / gimple-ssa-evrp.c
CommitLineData
9c015ccf 1/* Support routines for Value Range Propagation (VRP).
fbd26352 2 Copyright (C) 2005-2019 Free Software Foundation, Inc.
9c015ccf 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 "tree.h"
25#include "gimple.h"
26#include "tree-pass.h"
27#include "ssa.h"
28#include "gimple-pretty-print.h"
29#include "cfganal.h"
30#include "gimple-fold.h"
31#include "tree-eh.h"
32#include "gimple-iterator.h"
33#include "tree-cfg.h"
34#include "tree-ssa-loop-manip.h"
35#include "tree-ssa-loop.h"
36#include "cfgloop.h"
37#include "tree-scalar-evolution.h"
38#include "tree-ssa-propagate.h"
39#include "alloc-pool.h"
40#include "domwalk.h"
41#include "tree-cfgcleanup.h"
42#include "vr-values.h"
8bd73801 43#include "gimple-ssa-evrp-analyze.h"
9c015ccf 44
45class evrp_folder : public substitute_and_fold_engine
46{
47 public:
48 tree get_value (tree) FINAL OVERRIDE;
c561e1e7 49 evrp_folder (class vr_values *vr_values_) : vr_values (vr_values_) { }
d19574de 50 bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
51 { return vr_values->simplify_stmt_using_ranges (gsi); }
9c015ccf 52 class vr_values *vr_values;
c561e1e7 53
54 private:
55 DISABLE_COPY_AND_ASSIGN (evrp_folder);
9c015ccf 56};
57
58tree
59evrp_folder::get_value (tree op)
60{
61 return vr_values->op_with_constant_singleton_value_range (op);
62}
63
64/* evrp_dom_walker visits the basic blocks in the dominance order and set
65 the Value Ranges (VR) for SSA_NAMEs in the scope. Use this VR to
66 discover more VRs. */
67
68class evrp_dom_walker : public dom_walker
69{
70public:
c561e1e7 71 evrp_dom_walker ()
72 : dom_walker (CDI_DOMINATORS),
447602ef 73 evrp_range_analyzer (true),
5e3bbe77 74 evrp_folder (evrp_range_analyzer.get_vr_values ())
9c015ccf 75 {
76 need_eh_cleanup = BITMAP_ALLOC (NULL);
77 }
78 ~evrp_dom_walker ()
79 {
80 BITMAP_FREE (need_eh_cleanup);
81 }
82 virtual edge before_dom_children (basic_block);
83 virtual void after_dom_children (basic_block);
a62a30a4 84 void cleanup (void);
85
86 private:
87 DISABLE_COPY_AND_ASSIGN (evrp_dom_walker);
9c015ccf 88 bitmap need_eh_cleanup;
89 auto_vec<gimple *> stmts_to_fixup;
90 auto_vec<gimple *> stmts_to_remove;
91
71ddacbb 92 class evrp_range_analyzer evrp_range_analyzer;
c561e1e7 93 class evrp_folder evrp_folder;
9c015ccf 94};
95
5c56ab3e 96edge
97evrp_dom_walker::before_dom_children (basic_block bb)
98{
99 if (dump_file && (dump_flags & TDF_DETAILS))
100 fprintf (dump_file, "Visiting BB%d\n", bb->index);
101
71ddacbb 102 evrp_range_analyzer.enter (bb);
5c56ab3e 103
104 for (gphi_iterator gpi = gsi_start_phis (bb);
105 !gsi_end_p (gpi); gsi_next (&gpi))
106 {
107 gphi *phi = gpi.phi ();
108 tree lhs = PHI_RESULT (phi);
109 if (virtual_operand_p (lhs))
110 continue;
111
448df21a 112 const value_range *vr = evrp_range_analyzer.get_value_range (lhs);
5c56ab3e 113 /* Mark PHIs whose lhs we fully propagate for removal. */
7809986b 114 tree val;
115 if (vr->singleton_p (&val) && may_propagate_copy (lhs, val))
5c56ab3e 116 {
117 stmts_to_remove.safe_push (phi);
118 continue;
119 }
120 }
9c015ccf 121
122 edge taken_edge = NULL;
123
124 /* Visit all other stmts and discover any new VRs possible. */
125 for (gimple_stmt_iterator gsi = gsi_start_bb (bb);
126 !gsi_end_p (gsi); gsi_next (&gsi))
127 {
128 gimple *stmt = gsi_stmt (gsi);
129 tree output = NULL_TREE;
130 gimple *old_stmt = stmt;
131 bool was_noreturn = (is_gimple_call (stmt)
132 && gimple_call_noreturn_p (stmt));
133
134 if (dump_file && (dump_flags & TDF_DETAILS))
135 {
136 fprintf (dump_file, "Visiting stmt ");
137 print_gimple_stmt (dump_file, stmt, 0);
138 }
139
4b69806c 140 evrp_range_analyzer.record_ranges_from_stmt (stmt, false);
71ddacbb 141
9c015ccf 142 if (gcond *cond = dyn_cast <gcond *> (stmt))
143 {
c561e1e7 144 evrp_range_analyzer.vrp_visit_cond_stmt (cond, &taken_edge);
9c015ccf 145 if (taken_edge)
146 {
147 if (taken_edge->flags & EDGE_TRUE_VALUE)
148 gimple_cond_make_true (cond);
149 else if (taken_edge->flags & EDGE_FALSE_VALUE)
150 gimple_cond_make_false (cond);
151 else
152 gcc_unreachable ();
153 update_stmt (stmt);
154 }
155 }
156 else if (stmt_interesting_for_vrp (stmt))
157 {
5c56ab3e 158 output = get_output_for_vrp (stmt);
159 if (output)
9c015ccf 160 {
71ddacbb 161 tree val;
448df21a 162 const value_range *vr
163 = evrp_range_analyzer.get_value_range (output);
9c015ccf 164
165 /* Mark stmts whose output we fully propagate for removal. */
7809986b 166 if (vr->singleton_p (&val)
9c015ccf 167 && may_propagate_copy (output, val)
aac19106 168 && !stmt_could_throw_p (cfun, stmt)
9c015ccf 169 && !gimple_has_side_effects (stmt))
170 {
171 stmts_to_remove.safe_push (stmt);
172 continue;
173 }
9c015ccf 174 }
175 }
176
177 /* Try folding stmts with the VR discovered. */
9c015ccf 178 bool did_replace = evrp_folder.replace_uses_in (stmt);
5ebf19e5 179 gimple_stmt_iterator prev_gsi = gsi;
180 gsi_prev (&prev_gsi);
9c015ccf 181 if (fold_stmt (&gsi, follow_single_use_edges)
182 || did_replace)
183 {
184 stmt = gsi_stmt (gsi);
185 update_stmt (stmt);
186 did_replace = true;
187 }
d19574de 188 if (evrp_folder.simplify_stmt_using_ranges (&gsi))
189 {
190 stmt = gsi_stmt (gsi);
191 update_stmt (stmt);
192 did_replace = true;
193 }
9c015ccf 194
195 if (did_replace)
196 {
5ebf19e5 197 /* If we wound up generating new stmts during folding
198 drop all their defs to VARYING. We can't easily
199 process them because we've already instantiated
200 ranges on uses on STMT that only hold after it. */
201 if (gsi_end_p (prev_gsi))
202 prev_gsi = gsi_start_bb (bb);
203 else
204 gsi_next (&prev_gsi);
205 while (gsi_stmt (prev_gsi) != gsi_stmt (gsi))
206 {
207 evrp_range_analyzer.get_vr_values ()
208 ->set_defs_to_varying (gsi_stmt (prev_gsi));
209 gsi_next (&prev_gsi);
210 }
211
9c015ccf 212 /* If we cleaned up EH information from the statement,
213 remove EH edges. */
214 if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt))
215 bitmap_set_bit (need_eh_cleanup, bb->index);
216
217 /* If we turned a not noreturn call into a noreturn one
218 schedule it for fixup. */
219 if (!was_noreturn
220 && is_gimple_call (stmt)
221 && gimple_call_noreturn_p (stmt))
222 stmts_to_fixup.safe_push (stmt);
223
224 if (gimple_assign_single_p (stmt))
225 {
226 tree rhs = gimple_assign_rhs1 (stmt);
227 if (TREE_CODE (rhs) == ADDR_EXPR)
228 recompute_tree_invariant_for_addr_expr (rhs);
229 }
230 }
231 }
232
233 /* Visit BB successor PHI nodes and replace PHI args. */
5c56ab3e 234 edge e;
235 edge_iterator ei;
9c015ccf 236 FOR_EACH_EDGE (e, ei, bb->succs)
237 {
238 for (gphi_iterator gpi = gsi_start_phis (e->dest);
239 !gsi_end_p (gpi); gsi_next (&gpi))
240 {
241 gphi *phi = gpi.phi ();
242 use_operand_p use_p = PHI_ARG_DEF_PTR_FROM_EDGE (phi, e);
243 tree arg = USE_FROM_PTR (use_p);
244 if (TREE_CODE (arg) != SSA_NAME
245 || virtual_operand_p (arg))
246 continue;
448df21a 247 const value_range *vr = evrp_range_analyzer.get_value_range (arg);
7809986b 248 tree val;
249 if (vr->singleton_p (&val) && may_propagate_copy (arg, val))
9c015ccf 250 propagate_value (use_p, val);
251 }
252 }
253
9c015ccf 254 return taken_edge;
255}
256
71ddacbb 257void
258evrp_dom_walker::after_dom_children (basic_block bb)
259{
260 evrp_range_analyzer.leave (bb);
261}
262
a62a30a4 263/* Perform any cleanups after the main phase of EVRP has completed. */
9c015ccf 264
a62a30a4 265void
266evrp_dom_walker::cleanup (void)
9c015ccf 267{
9c015ccf 268 if (dump_file)
269 {
270 fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
c561e1e7 271 evrp_range_analyzer.dump_all_value_ranges (dump_file);
9c015ccf 272 fprintf (dump_file, "\n");
273 }
274
275 /* Remove stmts in reverse order to make debug stmt creation possible. */
a62a30a4 276 while (! stmts_to_remove.is_empty ())
9c015ccf 277 {
a62a30a4 278 gimple *stmt = stmts_to_remove.pop ();
9c015ccf 279 if (dump_file && dump_flags & TDF_DETAILS)
280 {
281 fprintf (dump_file, "Removing dead stmt ");
282 print_gimple_stmt (dump_file, stmt, 0);
283 fprintf (dump_file, "\n");
284 }
285 gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
286 if (gimple_code (stmt) == GIMPLE_PHI)
287 remove_phi_node (&gsi, true);
288 else
289 {
290 unlink_stmt_vdef (stmt);
291 gsi_remove (&gsi, true);
292 release_defs (stmt);
293 }
294 }
295
a62a30a4 296 if (!bitmap_empty_p (need_eh_cleanup))
297 gimple_purge_all_dead_eh_edges (need_eh_cleanup);
9c015ccf 298
299 /* Fixup stmts that became noreturn calls. This may require splitting
300 blocks and thus isn't possible during the dominator walk. Do this
301 in reverse order so we don't inadvertedly remove a stmt we want to
302 fixup by visiting a dominating now noreturn call first. */
a62a30a4 303 while (!stmts_to_fixup.is_empty ())
9c015ccf 304 {
a62a30a4 305 gimple *stmt = stmts_to_fixup.pop ();
9c015ccf 306 fixup_noreturn_call (stmt);
307 }
d443f534 308
309 evrp_folder.vr_values->cleanup_edges_and_switches ();
a62a30a4 310}
311
312/* Main entry point for the early vrp pass which is a simplified non-iterative
313 version of vrp where basic blocks are visited in dominance order. Value
314 ranges discovered in early vrp will also be used by ipa-vrp. */
315
316static unsigned int
317execute_early_vrp ()
318{
a62a30a4 319 /* Ideally this setup code would move into the ctor for the dominator
320 walk. However, this setup can change the number of blocks which
321 invalidates the internal arrays that are set up by the dominator
322 walker. */
323 loop_optimizer_init (LOOPS_NORMAL | LOOPS_HAVE_RECORDED_EXITS);
324 rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
325 scev_initialize ();
326 calculate_dominance_info (CDI_DOMINATORS);
a62a30a4 327
328 /* Walk stmts in dominance order and propagate VRP. */
329 evrp_dom_walker walker;
330 walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
331 walker.cleanup ();
9c015ccf 332
333 scev_finalize ();
334 loop_optimizer_finalize ();
335 return 0;
336}
337
338namespace {
339
340const pass_data pass_data_early_vrp =
341{
342 GIMPLE_PASS, /* type */
343 "evrp", /* name */
344 OPTGROUP_NONE, /* optinfo_flags */
345 TV_TREE_EARLY_VRP, /* tv_id */
346 PROP_ssa, /* properties_required */
347 0, /* properties_provided */
348 0, /* properties_destroyed */
349 0, /* todo_flags_start */
350 ( TODO_cleanup_cfg | TODO_update_ssa | TODO_verify_all ),
351};
352
353class pass_early_vrp : public gimple_opt_pass
354{
355public:
356 pass_early_vrp (gcc::context *ctxt)
357 : gimple_opt_pass (pass_data_early_vrp, ctxt)
358 {}
359
360 /* opt_pass methods: */
361 opt_pass * clone () { return new pass_early_vrp (m_ctxt); }
362 virtual bool gate (function *)
363 {
364 return flag_tree_vrp != 0;
365 }
366 virtual unsigned int execute (function *)
367 { return execute_early_vrp (); }
368
369}; // class pass_vrp
370} // anon namespace
371
372gimple_opt_pass *
373make_pass_early_vrp (gcc::context *ctxt)
374{
375 return new pass_early_vrp (ctxt);
376}
377