1 /* Gimple range phi analysis.
2 Copyright (C) 2023-2024 Free Software Foundation, Inc.
3 Contributed by Andrew MacLeod <amacleod@redhat.com>.
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)
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/>. */
23 #include "coretypes.h"
25 #include "insn-codes.h"
29 #include "gimple-pretty-print.h"
30 #include "gimple-range.h"
31 #include "gimple-range-cache.h"
32 #include "value-range-storage.h"
36 #include "gimple-iterator.h"
37 #include "gimple-walk.h"
40 // There can be only one running at a time.
41 static phi_analyzer
*phi_analysis_object
= NULL
;
43 // Initialize a PHI analyzer with range query Q.
46 phi_analysis_initialize (range_query
&q
)
48 gcc_checking_assert (!phi_analysis_object
);
49 phi_analysis_object
= new phi_analyzer (q
);
52 // Terminate the current PHI analyzer. if F is non-null, dump the tables
55 phi_analysis_finalize ()
57 gcc_checking_assert (phi_analysis_object
);
58 delete phi_analysis_object
;
59 phi_analysis_object
= NULL
;
62 // Return TRUE is there is a PHI analyzer operating.
64 phi_analysis_available_p ()
66 return phi_analysis_object
!= NULL
;
69 // Return the phi analyzer object.
71 phi_analyzer
&phi_analysis ()
73 gcc_checking_assert (phi_analysis_object
);
74 return *phi_analysis_object
;
77 // Initialize a phi_group from another group G.
79 phi_group::phi_group (const phi_group
&g
)
82 m_modifier
= g
.m_modifier
;
83 m_modifier_op
= g
.m_modifier_op
;
87 // Create a new phi_group with members BM, initial range INIT_RANGE, modifier
88 // statement MOD on edge MOD_EDGE, and resolve values using query Q. Calculate
89 // the range for the group if possible, otherwise set it to VARYING.
91 phi_group::phi_group (bitmap bm
, irange
&init_range
, gimple
*mod
,
94 // we dont expect a modifer and no inital value, so trap to have a look.
95 // perhaps they are dead cycles and we can just used UNDEFINED.
96 gcc_checking_assert (!init_range
.undefined_p ());
97 gcc_checking_assert (!init_range
.varying_p ());
99 m_modifier_op
= is_modifier_p (mod
, bm
);
103 // No modifier means the initial range is the full range.
104 // Otherwise try to calculate a range.
105 if (!m_modifier_op
|| calculate_using_modifier (q
))
107 // Couldn't calculate a range, set to varying.
108 m_vr
.set_varying (init_range
.type ());
111 // Return 0 if S is not a modifier statment for group members BM.
112 // If it could be a modifier, return which operand position (1 or 2)
113 // the phi member occurs in.
115 phi_group::is_modifier_p (gimple
*s
, const bitmap bm
)
119 gimple_range_op_handler
handler (s
);
122 tree op1
= gimple_range_ssa_p (handler
.operand1 ());
123 tree op2
= gimple_range_ssa_p (handler
.operand2 ());
124 // Also disallow modifiers that have 2 ssa-names.
125 if (op1
&& !op2
&& bitmap_bit_p (bm
, SSA_NAME_VERSION (op1
)))
127 else if (op2
&& !op1
&& bitmap_bit_p (bm
, SSA_NAME_VERSION (op2
)))
133 // Calulcate the range of the phi group using range_query Q.
136 phi_group::calculate_using_modifier (range_query
*q
)
138 // Look at the modifier for any relation
139 relation_trio trio
= fold_relations (m_modifier
, q
);
140 relation_kind k
= VREL_VARYING
;
141 if (m_modifier_op
== 1)
143 else if (m_modifier_op
== 2)
148 // Examine modifier and run 10 iterations to see if it convergences.
149 // The constructor initilaized m_vr to the initial value already.
150 const unsigned num_iter
= 10;
152 int_range_max iter_value
= m_vr
;
153 for (unsigned x
= 0; x
< num_iter
; x
++)
155 if (!fold_range (nv
, m_modifier
, iter_value
, q
))
157 // If union does nothing, then we have convergence.
158 if (!iter_value
.union_ (nv
))
160 if (iter_value
.varying_p ())
167 // If we can resolve the range using relations, use that range.
168 if (refine_using_relation (k
))
171 // Never converged, so bail for now. we could examine the pattern
172 // from m_initial to m_vr as an extension Especially if we had a way
173 // to project the actual number of iterations (SCEV?)
175 // We can also try to identify "parallel" phis to get loop counts and
176 // determine the number of iterations of these parallel PHIs.
182 // IF the modifier statement has a relation K between the modifier and the
183 // PHI member in it, we can project a range based on that.
184 // ie, a_2 = PHI <0, a_3> and a_3 = a_2 + 1
185 // if the relation a_3 > a_2 is present, the know the range is [0, +INF]
186 // m_vr contains the initial value for the PHI range.
189 phi_group::refine_using_relation (relation_kind k
)
191 if (k
== VREL_VARYING
)
193 tree type
= m_vr
.type ();
194 // If the type wraps, then relations dont tell us much.
195 if (TYPE_OVERFLOW_WRAPS (type
))
198 int_range
<2> type_range
;
199 type_range
.set_varying (type
);
205 // Value always decreases.
206 m_vr
.set (type
, type_range
.lower_bound (), m_vr
.upper_bound ());
213 // Value always increases.
214 m_vr
.set (type
, m_vr
.lower_bound (), type_range
.upper_bound ());
218 // If its always equal, then its simply the initial value.
219 // which is what m_vr has already been set to.
230 // Dump the information for a phi group to file F.
233 phi_group::dump (FILE *f
)
237 fprintf (f
, "PHI GROUP < ");
239 EXECUTE_IF_SET_IN_BITMAP (m_group
, 0, i
, bi
)
241 print_generic_expr (f
, ssa_name (i
), TDF_SLIM
);
244 fprintf (f
, "> : range : ");
246 fprintf (f
, "\n Modifier : ");
248 print_gimple_stmt (f
, m_modifier
, 0, TDF_SLIM
);
250 fprintf (f
, "NONE\n");
253 // -------------------------------------------------------------------------
255 // Construct a phi analyzer which uses range_query G to pick up values.
257 phi_analyzer::phi_analyzer (range_query
&g
) : m_global (g
)
260 m_work
.safe_grow (20);
263 // m_tab.safe_grow_cleared (num_ssa_names + 100);
264 bitmap_obstack_initialize (&m_bitmaps
);
265 m_simple
= BITMAP_ALLOC (&m_bitmaps
);
266 m_current
= BITMAP_ALLOC (&m_bitmaps
);
269 // Destruct a PHI analyzer.
271 phi_analyzer::~phi_analyzer ()
273 bitmap_obstack_release (&m_bitmaps
);
278 // Return the group, if any, that NAME is part of. Do no analysis.
281 phi_analyzer::group (tree name
) const
283 gcc_checking_assert (TREE_CODE (name
) == SSA_NAME
);
284 if (!is_a
<gphi
*> (SSA_NAME_DEF_STMT (name
)))
286 unsigned v
= SSA_NAME_VERSION (name
);
287 if (v
>= m_tab
.length ())
292 // Return the group NAME is associated with, if any. If name has not been
293 // procvessed yet, do the analysis to determine if it is part of a group
297 phi_analyzer::operator[] (tree name
)
299 gcc_checking_assert (TREE_CODE (name
) == SSA_NAME
);
301 // Initial support for irange only.
302 if (!irange::supports_p (TREE_TYPE (name
)))
304 if (!is_a
<gphi
*> (SSA_NAME_DEF_STMT (name
)))
307 unsigned v
= SSA_NAME_VERSION (name
);
308 // Already been processed and not part of a group.
309 if (bitmap_bit_p (m_simple
, v
))
312 if (v
>= m_tab
.length () || !m_tab
[v
])
314 process_phi (as_a
<gphi
*> (SSA_NAME_DEF_STMT (name
)));
315 if (bitmap_bit_p (m_simple
, v
))
317 // If m_simple bit isn't set, and process_phi didn't allocated the table
318 // no group was created, so return NULL.
319 if (v
>= m_tab
.length ())
325 // Process phi node PHI to see if it it part of a group.
328 phi_analyzer::process_phi (gphi
*phi
)
330 gcc_checking_assert (!group (gimple_phi_result (phi
)));
333 // Start with the LHS of the PHI in the worklist.
336 m_work
.safe_push (gimple_phi_result (phi
));
337 unsigned phi_count
= 1;
338 bitmap_clear (m_current
);
340 // We can only have 2 externals: an initial value and a modifier.
341 // Any more than that and this fails to be a group.
342 unsigned m_num_extern
= 0;
345 int_range_max init_range
;
346 init_range
.set_undefined ();
348 while (m_work
.length () > 0)
350 tree phi_def
= m_work
.pop ();
351 gphi
*phi_stmt
= as_a
<gphi
*> (SSA_NAME_DEF_STMT (phi_def
));
352 // if the phi is already in a different cycle, we don't try to merge.
358 bitmap_set_bit (m_current
, SSA_NAME_VERSION (phi_def
));
360 for (x
= 0; x
< gimple_phi_num_args (phi_stmt
); x
++)
362 tree arg
= gimple_phi_arg_def (phi_stmt
, x
);
365 enum tree_code code
= TREE_CODE (arg
);
366 if (code
== SSA_NAME
)
368 unsigned v
= SSA_NAME_VERSION (arg
);
369 // Already a member of this potential group.
370 if (bitmap_bit_p (m_current
, v
))
372 // Part of a different group ends cycle possibility.
373 if (group (arg
) || bitmap_bit_p (m_simple
, v
))
378 // Check if its a PHI to examine.
379 gimple
*arg_stmt
= SSA_NAME_DEF_STMT (arg
);
380 if (arg_stmt
&& is_a
<gphi
*> (arg_stmt
))
383 m_work
.safe_push (arg
);
386 // More than 2 outside names is too complicated.
387 if (m_num_extern
>= 2)
392 m_external
[m_num_extern
] = arg
;
393 m_ext_edge
[m_num_extern
++] = gimple_phi_arg_edge (phi_stmt
, x
);
395 else if (code
== INTEGER_CST
)
397 // Constants are just added to the initialization value.
398 int_range
<1> val (TREE_TYPE (arg
), wi::to_wide (arg
),
400 init_range
.union_ (val
);
404 // Everything else terminates the cycle.
411 // If there are less than 2 names, just return. This PHI may be included
412 // by another PHI, making it simple or a group of one will prevent a larger
413 // group from being formed.
416 gcc_checking_assert (!bitmap_empty_p (m_current
));
423 signed init_idx
= -1;
424 // At this point all the PHIs have been added to the bitmap.
425 // the external list needs to be checked for initial values and modifiers.
426 for (x
= 0; x
< m_num_extern
; x
++)
428 tree name
= m_external
[x
];
429 if (TREE_CODE (name
) == SSA_NAME
430 && phi_group::is_modifier_p (SSA_NAME_DEF_STMT (name
), m_current
))
432 // Can't have multiple modifiers.
435 mod
= SSA_NAME_DEF_STMT (name
);
438 // Can't have 2 initializers either.
443 int_range_max init_sym
;
444 // If there is an symbolic initializer as well, include it here.
445 if (valid
&& init_idx
!= -1)
447 if (m_global
.range_on_edge (init_sym
, m_ext_edge
[init_idx
],
448 m_external
[init_idx
]))
449 init_range
.union_ (init_sym
);
453 if (valid
&& !init_range
.varying_p () && !init_range
.undefined_p ())
455 // Try to create a group based on m_current. If a result comes back
456 // with a range that isn't varying, create the group.
457 phi_group
cyc (m_current
, init_range
, mod
, &m_global
);
458 if (!cyc
.range ().varying_p ())
460 g
= new phi_group (cyc
);
461 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
463 fprintf (dump_file
, "PHI ANALYZER : New ");
465 fprintf (dump_file
," Initial range was ");
466 init_range
.dump (dump_file
);
469 fprintf (dump_file
, " including symbolic ");
470 print_generic_expr (dump_file
, m_external
[init_idx
],
472 fprintf (dump_file
, " on edge %d->%d with range ",
473 m_ext_edge
[init_idx
]->src
->index
,
474 m_ext_edge
[init_idx
]->dest
->index
);
475 init_sym
.dump (dump_file
);
477 fputc ('\n',dump_file
);
482 // If this dpoesn;t form a group, all members are instead simple phis.
485 bitmap_ior_into (m_simple
, m_current
);
489 if (num_ssa_names
>= m_tab
.length ())
490 m_tab
.safe_grow_cleared (num_ssa_names
+ 100);
492 // Now set all entries in the group to this record.
495 EXECUTE_IF_SET_IN_BITMAP (m_current
, 0, i
, bi
)
497 // Can't be in more than one group.
498 gcc_checking_assert (m_tab
[i
] == NULL
);
501 // Allocate a new bitmap for the next time as the original one is now part
502 // of the new phi group.
503 m_current
= BITMAP_ALLOC (&m_bitmaps
);
507 phi_analyzer::dump (FILE *f
)
510 bitmap_clear (m_current
);
511 for (unsigned x
= 0; x
< m_tab
.length (); x
++)
513 if (bitmap_bit_p (m_simple
, x
))
515 if (bitmap_bit_p (m_current
, x
))
517 if (m_tab
[x
] == NULL
)
519 phi_group
*g
= m_tab
[x
];
520 bitmap_ior_into (m_current
, g
->group ());
524 fprintf (f
, "\nPHI GROUPS:\n");