Line data Source code
1 : /* Gimple range phi analysis.
2 : Copyright (C) 2023-2026 Free Software Foundation, Inc.
3 : Contributed by Andrew MacLeod <amacleod@redhat.com>.
4 :
5 : This file is part of GCC.
6 :
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.
11 :
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.
16 :
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/>. */
20 :
21 : #include "config.h"
22 : #include "system.h"
23 : #include "coretypes.h"
24 : #include "backend.h"
25 : #include "insn-codes.h"
26 : #include "tree.h"
27 : #include "gimple.h"
28 : #include "ssa.h"
29 : #include "gimple-pretty-print.h"
30 : #include "gimple-range.h"
31 : #include "gimple-range-cache.h"
32 : #include "value-range-storage.h"
33 : #include "tree-cfg.h"
34 : #include "target.h"
35 : #include "attribs.h"
36 : #include "gimple-iterator.h"
37 : #include "gimple-walk.h"
38 : #include "cfganal.h"
39 :
40 : // Invoke a phi analyzer. It will process all the current PHI groups
41 : // and export any ranges found to set_range_info.
42 : // When finished, it will simply dispose of itself.
43 :
44 : void
45 4233720 : phi_analysis (range_query &q)
46 : {
47 4233720 : phi_analyzer analyze (q);
48 4233720 : }
49 :
50 : // Initialize a phi_group from another group G.
51 :
52 696295 : phi_group::phi_group (const phi_group &g)
53 : {
54 696295 : m_group = g.m_group;
55 696295 : m_modifier = g.m_modifier;
56 696295 : m_modifier_op = g.m_modifier_op;
57 696295 : m_vr = g.m_vr;
58 696295 : }
59 :
60 : // Create a new phi_group with members BM, initial range INIT_RANGE, modifier
61 : // statement MOD on edge MOD_EDGE, and resolve values using query Q. Calculate
62 : // the range for the group if possible, otherwise set it to VARYING.
63 :
64 1095869 : phi_group::phi_group (bitmap bm, irange &init_range, gimple *mod,
65 1095869 : range_query *q)
66 : {
67 : // we dont expect a modifer and no inital value, so trap to have a look.
68 : // perhaps they are dead cycles and we can just used UNDEFINED.
69 1095869 : gcc_checking_assert (!init_range.undefined_p ());
70 1095869 : gcc_checking_assert (!init_range.varying_p ());
71 :
72 1095869 : m_modifier_name = NULL_TREE;
73 1095869 : m_modifier_op = is_modifier_p (mod, bm, &m_modifier_name);
74 1095869 : m_group = bm;
75 1095869 : m_vr = init_range;
76 1095869 : m_modifier = mod;
77 : // No modifier means the initial range is the full range.
78 : // Otherwise try to calculate a range.
79 1095869 : if (!m_modifier_op || calculate_using_modifier (q))
80 696769 : return;
81 : // Couldn't calculate a range, set to varying.
82 399100 : m_vr.set_varying (init_range.type ());
83 : }
84 :
85 : // Return 0 if S is not a modifier statement for group members BM.
86 : // If it could be a modifier, return which operand position (1 or 2)
87 : // the phi member occurs in.
88 : unsigned
89 4933500 : phi_group::is_modifier_p (gimple *s, const bitmap bm, tree *op)
90 : {
91 4933500 : if (!s)
92 : return 0;
93 4904043 : gimple_range_op_handler handler (s);
94 4904043 : if (handler)
95 : {
96 4085558 : tree op1 = gimple_range_ssa_p (handler.operand1 ());
97 4085558 : tree op2 = gimple_range_ssa_p (handler.operand2 ());
98 : // Also disallow modifiers that have 2 ssa-names.
99 7527988 : if (op1 && !op2 && bitmap_bit_p (bm, SSA_NAME_VERSION (op1)))
100 : {
101 2444543 : if (op)
102 1066411 : *op = op1;
103 2444543 : return 1;
104 : }
105 1669607 : else if (op2 && !op1 && bitmap_bit_p (bm, SSA_NAME_VERSION (op2)))
106 : {
107 59 : if (op)
108 1 : *op = op2;
109 59 : return 2;
110 : }
111 : }
112 : return 0;
113 : }
114 :
115 : // Calulcate the range of the phi group using range_query Q.
116 :
117 : bool
118 1066412 : phi_group::calculate_using_modifier (range_query *q)
119 : {
120 : // Look at the modifier for any relation
121 1066412 : relation_trio trio = fold_relations (m_modifier, q);
122 1066412 : relation_kind k = VREL_VARYING;
123 1066412 : if (m_modifier_op == 1)
124 1066411 : k = trio.lhs_op1 ();
125 1 : else if (m_modifier_op == 2)
126 1 : k = trio.lhs_op2 ();
127 : else
128 : return false;
129 :
130 : // If we can resolve the range using relations, use that range.
131 1066412 : if (refine_using_relation (k))
132 : return true;
133 :
134 : // Examine modifier and run iteration evaluations to see if it convergences.
135 : // The constructor initilaized m_vr to the initial value already.
136 411361 : int_range_max nv;
137 411361 : int_range_max iter_value = m_vr;
138 411361 : int_range_max iter_reach;
139 :
140 : // Determine the maximum range of the var reaching here. The back edge
141 : // usually has a guard restircting the range. Default to VARYING.
142 411361 : if (!m_modifier_name
143 411361 : || !q->range_of_expr (iter_reach, m_modifier_name, m_modifier))
144 0 : iter_reach.set_varying (m_vr.type ());
145 :
146 : // Iterative evaluation can be expensive, so heuristically :
147 : // - PLUS and MINUS are 98% of the cases, and usually handled well enough
148 : // by loop analysis, The exception is if the reaching range has multiple
149 : // subranges, those are often worth examining.
150 : // - All other operations (2%) are worth checking.
151 411361 : bool do_iterative = false;
152 411361 : if (gimple_code (m_modifier) == GIMPLE_ASSIGN)
153 411223 : switch (gimple_assign_rhs_code (m_modifier))
154 : {
155 405483 : case PLUS_EXPR:
156 405483 : case MINUS_EXPR:
157 405483 : if (iter_reach.num_pairs () > 1)
158 : do_iterative = true;
159 : break;
160 : default:
161 : do_iterative = true;
162 : }
163 :
164 : // Limit iterations to 1 more than the number of bits.
165 : unsigned num_iter;
166 : if (do_iterative)
167 26951 : num_iter = TYPE_PRECISION (m_vr.type ()) + 1;
168 : else
169 : num_iter = 0;
170 :
171 1290065 : for (unsigned x = 0; x < num_iter; x++)
172 : {
173 891099 : if (!fold_range (nv, m_modifier, iter_value, q))
174 : break;
175 : // Ensure nothing calculated is outside outside the reaching range.
176 891099 : nv.intersect (iter_reach);
177 : // If union does nothing, then we have convergence.
178 891099 : if (!iter_value.union_ (nv))
179 : {
180 12395 : if (iter_value.varying_p ())
181 : break;
182 : // The last iteration Will also reach the PHI node, add it in.
183 12261 : fold_range (nv, m_modifier, iter_value, q);
184 12261 : iter_value.union_ (nv);
185 12261 : m_vr = iter_value;
186 12261 : return true;
187 : }
188 : }
189 :
190 : // Never converged, so bail for now. we could examine the pattern
191 : // from m_initial to m_vr as an extension Especially if we had a way
192 : // to project the actual number of iterations (SCEV?)
193 : //
194 : // We can also try to identify "parallel" phis to get loop counts and
195 : // determine the number of iterations of these parallel PHIs.
196 :
197 : return false;
198 411361 : }
199 :
200 :
201 : // IF the modifier statement has a relation K between the modifier and the
202 : // PHI member in it, we can project a range based on that.
203 : // ie, a_2 = PHI <0, a_3> and a_3 = a_2 + 1
204 : // if the relation a_3 > a_2 is present, the know the range is [0, +INF]
205 : // m_vr contains the initial value for the PHI range.
206 :
207 : bool
208 1066412 : phi_group::refine_using_relation (relation_kind k)
209 : {
210 1066412 : if (k == VREL_VARYING)
211 : return false;
212 1048850 : tree type = m_vr.type ();
213 : // If the type wraps, then relations dont tell us much.
214 1048850 : if (TYPE_OVERFLOW_WRAPS (type))
215 : return false;
216 :
217 655051 : int_range<2> type_range;
218 655051 : type_range.set_varying (type);
219 655051 : switch (k)
220 : {
221 18895 : case VREL_LT:
222 18895 : case VREL_LE:
223 18895 : {
224 : // Value always decreases.
225 18895 : m_vr.set (type, type_range.lower_bound (), m_vr.upper_bound ());
226 18895 : return true;
227 : }
228 :
229 636156 : case VREL_GT:
230 636156 : case VREL_GE:
231 636156 : {
232 : // Value always increases.
233 636156 : m_vr.set (type, m_vr.lower_bound (), type_range.upper_bound ());
234 636156 : return true;
235 : }
236 :
237 : // If its always equal, then its simply the initial value.
238 : // which is what m_vr has already been set to.
239 : case VREL_EQ:
240 : return true;
241 :
242 : default:
243 : break;
244 : }
245 :
246 : return false;
247 655051 : }
248 :
249 : // Dump the information for a phi group to file F.
250 :
251 : void
252 3 : phi_group::dump (FILE *f)
253 : {
254 3 : unsigned i;
255 3 : bitmap_iterator bi;
256 3 : fprintf (f, "PHI GROUP < ");
257 :
258 6 : EXECUTE_IF_SET_IN_BITMAP (m_group, 0, i, bi)
259 : {
260 3 : print_generic_expr (f, ssa_name (i), TDF_SLIM);
261 3 : fputc (' ',f);
262 : }
263 3 : fprintf (f, "> : range : ");
264 3 : m_vr.dump (f);
265 3 : fprintf (f, "\n Modifier : ");
266 3 : if (m_modifier)
267 3 : print_gimple_stmt (f, m_modifier, 0, TDF_SLIM);
268 : else
269 0 : fprintf (f, "NONE\n");
270 3 : }
271 :
272 : // -------------------------------------------------------------------------
273 :
274 : // Construct a phi analyzer which uses range_query G to pick up values.
275 :
276 4233720 : phi_analyzer::phi_analyzer (range_query &query) : m_phi_groups (vNULL)
277 : {
278 4233720 : m_work.create (0);
279 4233720 : m_work.safe_grow (20);
280 :
281 4233720 : m_tab.create (0);
282 8467440 : m_tab.safe_grow_cleared (num_ssa_names + 10);
283 :
284 4233720 : bitmap_obstack_initialize (&m_bitmaps);
285 4233720 : m_simple = BITMAP_ALLOC (&m_bitmaps);
286 4233720 : m_current = BITMAP_ALLOC (&m_bitmaps);
287 :
288 4233720 : basic_block bb;
289 4233720 : gphi_iterator gphi;
290 :
291 4233720 : if (dump_file && (dump_flags & TDF_DETAILS))
292 45 : fprintf (dump_file, "PHI ANALYZER : processing PHIS.\n");
293 :
294 : // Process each PHI node to see if it belongs in a group with others.
295 : // Then calculate an initial value for the group.
296 36940266 : FOR_EACH_BB_FN (bb, cfun)
297 : {
298 32706546 : for (gphi = gsi_start_nonvirtual_phis (bb);
299 40634210 : !gsi_end_p (gphi);
300 7927664 : gsi_next_nonvirtual_phi (&gphi))
301 7927664 : process_phi (gphi.phi (), query);
302 : }
303 4233720 : if (dump_file && (dump_flags & TDF_DETAILS))
304 45 : fprintf (dump_file, "PHI ANALYZER : Finished processing PHIS.\n");
305 4233720 : }
306 :
307 : // Destruct a PHI analyzer.
308 :
309 4233720 : phi_analyzer::~phi_analyzer ()
310 : {
311 4233720 : bitmap_obstack_release (&m_bitmaps);
312 4233720 : m_tab.release ();
313 4233720 : m_work.release ();
314 5303357 : for (auto grp : m_phi_groups)
315 1392590 : delete grp;
316 4233720 : m_phi_groups.release ();
317 4233720 : }
318 :
319 : // Return the group, if any, that NAME is part of. Do no analysis.
320 :
321 : phi_group *
322 11899541 : phi_analyzer::group (tree name) const
323 : {
324 11899541 : gcc_checking_assert (TREE_CODE (name) == SSA_NAME);
325 11899541 : if (!is_a<gphi *> (SSA_NAME_DEF_STMT (name)))
326 : return NULL;
327 7370684 : unsigned v = SSA_NAME_VERSION (name);
328 7370684 : if (v >= m_tab.length ())
329 : return NULL;
330 7370684 : return m_tab[v];
331 : }
332 :
333 : // Return the group NAME is associated with, if any. If name has not been
334 : // procvessed yet, do the analysis to determine if it is part of a group
335 : // and return that.
336 :
337 : phi_group *
338 0 : phi_analyzer::operator[] (tree name)
339 : {
340 0 : gcc_checking_assert (TREE_CODE (name) == SSA_NAME);
341 :
342 : // Initial support for irange only.
343 0 : if (!irange::supports_p (TREE_TYPE (name)))
344 : return NULL;
345 0 : if (!is_a<gphi *> (SSA_NAME_DEF_STMT (name)))
346 : return NULL;
347 :
348 0 : unsigned v = SSA_NAME_VERSION (name);
349 0 : if (v >= m_tab.length ())
350 : return NULL;
351 0 : return m_tab[v];
352 : }
353 :
354 : // Process phi node PHI to see if it is part of a group. Use QUERY
355 : // to deteremine ranges.
356 :
357 : void
358 7927664 : phi_analyzer::process_phi (gphi *phi, range_query &query)
359 : {
360 7927664 : tree def = gimple_phi_result (phi);
361 7927664 : unsigned v = SSA_NAME_VERSION (def);
362 :
363 7927664 : gcc_checking_assert (v < m_tab.length ());
364 : // If this is already on a group, or identified as a simple phi, or
365 : // not an irange, do not process it.
366 15716645 : if (m_tab[v] || bitmap_bit_p (m_simple, v)
367 15295633 : || !irange::supports_p (TREE_TYPE (def)))
368 7231369 : return;
369 :
370 4899319 : bool cycle_p = true;
371 :
372 : // Start with the LHS of the PHI in the worklist.
373 4899319 : unsigned x;
374 4899319 : m_work.truncate (0);
375 4899319 : m_work.safe_push (def);
376 4899319 : unsigned phi_count = 1;
377 4899319 : bitmap_clear (m_current);
378 :
379 : // We can only have 2 externals: an initial value and a modifier.
380 : // Any more than that and this fails to be a group.
381 4899319 : unsigned m_num_extern = 0;
382 4899319 : tree m_external[2];
383 4899319 : edge m_ext_edge[2];
384 4899319 : int_range_max init_range;
385 4899319 : init_range.set_undefined ();
386 :
387 15356674 : while (m_work.length () > 0)
388 : {
389 5558036 : tree phi_def = m_work.pop ();
390 5558036 : gphi *phi_stmt = as_a<gphi *> (SSA_NAME_DEF_STMT (phi_def));
391 : // if the phi is already in a different cycle, we don't try to merge.
392 5558036 : if (group (phi_def))
393 : {
394 : cycle_p = false;
395 : break;
396 : }
397 5558036 : bitmap_set_bit (m_current, SSA_NAME_VERSION (phi_def));
398 : // Process the args.
399 14699815 : for (x = 0; x < gimple_phi_num_args (phi_stmt); x++)
400 : {
401 10486152 : tree arg = gimple_phi_arg_def (phi_stmt, x);
402 10486152 : if (arg == phi_def)
403 1197567 : continue;
404 10482927 : enum tree_code code = TREE_CODE (arg);
405 10482927 : if (code == SSA_NAME)
406 : {
407 6873905 : unsigned v = SSA_NAME_VERSION (arg);
408 : // Already a member of this potential group.
409 6873905 : if (bitmap_bit_p (m_current, v))
410 532400 : continue;
411 : // Part of a different group ends cycle possibility.
412 6341505 : if (group (arg) || bitmap_bit_p (m_simple, v))
413 : {
414 : cycle_p = false;
415 1344373 : break;
416 : }
417 : // Check if its a PHI to examine.
418 5187574 : gimple *arg_stmt = SSA_NAME_DEF_STMT (arg);
419 5187574 : if (arg_stmt && is_a<gphi *> (arg_stmt))
420 : {
421 658717 : phi_count++;
422 658717 : m_work.safe_push (arg);
423 658717 : continue;
424 : }
425 : // More than 2 outside names is too complicated.
426 4528857 : if (m_num_extern >= 2)
427 : {
428 : cycle_p = false;
429 : break;
430 : }
431 4338415 : m_external[m_num_extern] = arg;
432 4338415 : m_ext_edge[m_num_extern++] = gimple_phi_arg_edge (phi_stmt, x);
433 : }
434 3609022 : else if (code == INTEGER_CST)
435 : {
436 : // Constants are just added to the initialization value.
437 7218044 : int_range<1> val (TREE_TYPE (arg), wi::to_wide (arg),
438 7218044 : wi::to_wide (arg));
439 3609022 : init_range.union_ (val);
440 3609022 : }
441 : else
442 : {
443 : // Everything else terminates the cycle.
444 : cycle_p = false;
445 : break;
446 : }
447 : }
448 : }
449 :
450 4899319 : if (phi_count < 1)
451 : return;
452 :
453 4899319 : gcc_checking_assert (!bitmap_empty_p (m_current));
454 :
455 4899319 : phi_group *g = NULL;
456 4899319 : gimple *mod = NULL;
457 4899319 : bool valid = false;
458 4899319 : signed init_idx = -1;
459 4899319 : int_range_max init_sym;
460 4899319 : if (cycle_p)
461 : {
462 : valid = true;
463 : // At this point all the PHIs have been added to the bitmap.
464 : // the external list needs to be checked for initial values and modifiers.
465 7428801 : for (x = 0; x < m_num_extern; x++)
466 : {
467 3837631 : tree name = m_external[x];
468 5215821 : if (TREE_CODE (name) == SSA_NAME
469 3837631 : && phi_group::is_modifier_p (SSA_NAME_DEF_STMT (name), m_current))
470 : {
471 : // Can't have multiple modifiers.
472 1378190 : if (mod)
473 8763 : valid = false;
474 1378190 : mod = SSA_NAME_DEF_STMT (name);
475 1378190 : continue;
476 : }
477 : // Can't have 2 initializers either.
478 2459441 : if (init_idx != -1)
479 647037 : valid = false;
480 2459441 : init_idx = x;
481 : }
482 : // If there is an symbolic initializer as well, include it here.
483 3591170 : if (valid && init_idx != -1)
484 : {
485 1165367 : if (query.range_on_edge (init_sym, m_ext_edge[init_idx],
486 : m_external[init_idx]))
487 1165367 : init_range.union_ (init_sym);
488 : else
489 : valid = false;
490 : }
491 : }
492 : // If there are less than 2 names, . This PHI may be included
493 : // by another PHI, making it simple or a group of one will prevent a larger
494 : // group from being formed.
495 : // The exception will be pattern matching:
496 : // a_1 = a_2 OP X
497 : // a_2 = PHI <const, a_1>
498 4899319 : if (phi_count == 1
499 4899319 : && (m_num_extern != 1 || init_range.undefined_p () || !mod))
500 : valid = false;
501 1287932 : if (valid && !init_range.varying_p () && !init_range.undefined_p ())
502 : {
503 : // Try to create a group based on m_current. If a result comes back
504 : // with a range that isn't varying, create the group.
505 1095869 : phi_group cyc (m_current, init_range, mod, &query);
506 1095869 : if (!cyc.range ().varying_p ())
507 : {
508 696295 : g = new phi_group (cyc);
509 696295 : m_phi_groups.safe_push (g);
510 696295 : if (dump_file && (dump_flags & TDF_DETAILS))
511 : {
512 3 : fprintf (dump_file, "PHI ANALYZER : New ");
513 3 : g->dump (dump_file);
514 3 : fprintf (dump_file," Initial range was ");
515 3 : init_range.dump (dump_file);
516 3 : if (init_idx != -1)
517 : {
518 0 : fprintf (dump_file, " including symbolic ");
519 0 : print_generic_expr (dump_file, m_external[init_idx],
520 : TDF_SLIM);
521 0 : fprintf (dump_file, " on edge %d->%d with range ",
522 0 : m_ext_edge[init_idx]->src->index,
523 0 : m_ext_edge[init_idx]->dest->index);
524 0 : init_sym.dump (dump_file);
525 : }
526 3 : fputc ('\n',dump_file);
527 : }
528 : }
529 1095869 : }
530 : // If this doesn't form a group, all members are instead simple phis.
531 4899319 : if (!g)
532 : {
533 4203024 : bitmap_ior_into (m_simple, m_current);
534 4203024 : return;
535 : }
536 :
537 : // Now set all entries in the group to this record.
538 696295 : unsigned i;
539 696295 : bitmap_iterator bi;
540 1531273 : EXECUTE_IF_SET_IN_BITMAP (m_current, 0, i, bi)
541 : {
542 : // Can't be in more than one group.
543 834978 : gcc_checking_assert (m_tab[i] == NULL);
544 834978 : m_tab[i] = g;
545 : // Set the new range in the range query.
546 834978 : query.update_range_info (ssa_name (i), g->range ());
547 : }
548 : // Allocate a new bitmap for the next time as the original one is now part
549 : // of the new phi group.
550 696295 : m_current = BITMAP_ALLOC (&m_bitmaps);
551 4899319 : }
552 :
553 : void
554 0 : phi_analyzer::dump (FILE *f)
555 : {
556 0 : bool header = false;
557 0 : bitmap_clear (m_current);
558 0 : for (unsigned x = 0; x < m_tab.length (); x++)
559 : {
560 0 : if (bitmap_bit_p (m_simple, x))
561 0 : continue;
562 0 : if (bitmap_bit_p (m_current, x))
563 0 : continue;
564 0 : if (m_tab[x] == NULL)
565 0 : continue;
566 0 : phi_group *g = m_tab[x];
567 0 : bitmap_ior_into (m_current, g->group ());
568 0 : if (!header)
569 : {
570 0 : header = true;
571 0 : fprintf (f, "\nPHI GROUPS:\n");
572 : }
573 0 : g->dump (f);
574 : }
575 0 : }
|