1 /* Code for GIMPLE range related routines.
2 Copyright (C) 2019-2025 Free Software Foundation, Inc.
3 Contributed by Andrew MacLeod <amacleod@redhat.com>
4 and Aldy Hernandez <aldyh@redhat.com>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3, or (at your option)
13 GCC is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
29 #include "gimple-pretty-print.h"
30 #include "gimple-iterator.h"
32 #include "fold-const.h"
35 #include "tree-scalar-evolution.h"
36 #include "gimple-range.h"
37 #include "gimple-fold.h"
38 #include "gimple-walk.h"
40 gimple_ranger::gimple_ranger (bool use_imm_uses
) :
41 non_executable_edge_flag (cfun
),
42 m_cache (non_executable_edge_flag
, use_imm_uses
),
46 // Share the oracle from the cache.
47 share_query (m_cache
);
48 if (dump_file
&& (param_ranger_debug
& RANGER_DEBUG_TRACE
))
49 tracer
.enable_trace ();
50 m_stmt_list
.create (0);
51 m_stmt_list
.safe_grow (num_ssa_names
);
52 m_stmt_list
.truncate (0);
54 // Ensure the not_executable flag is clear everywhere.
58 FOR_ALL_BB_FN (bb
, cfun
)
62 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
63 gcc_checking_assert ((e
->flags
& non_executable_edge_flag
) == 0);
68 gimple_ranger::~gimple_ranger ()
70 m_stmt_list
.release ();
73 // Return a range_query which accesses just the known global values.
76 gimple_ranger::const_query ()
78 return m_cache
.const_query ();
82 gimple_ranger::range_of_expr (vrange
&r
, tree expr
, gimple
*stmt
)
85 if (!gimple_range_ssa_p (expr
))
86 return get_tree_range (r
, expr
, stmt
);
88 if ((idx
= tracer
.header ("range_of_expr(")))
90 print_generic_expr (dump_file
, expr
, TDF_SLIM
);
91 fputs (")", dump_file
);
94 fputs (" at stmt ", dump_file
);
95 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
98 fputs ("\n", dump_file
);
101 // If there is no statement, just get the global value.
104 value_range
tmp (TREE_TYPE (expr
));
105 // If there is no global range for EXPR yet, try to evaluate it.
106 // This call sets R to a global range regardless.
107 if (!m_cache
.get_global_range (r
, expr
))
109 gimple
*s
= SSA_NAME_DEF_STMT (expr
);
110 // Calculate a range for S if it is safe to do so.
111 if (s
&& gimple_bb (s
) && gimple_get_lhs (s
) == expr
)
112 return range_of_stmt (r
, s
);
114 // Pick up implied context information from the on-entry cache
115 // if current_bb is set. Do not attempt any new calculations.
116 if (current_bb
&& m_cache
.block_range (tmp
, current_bb
, expr
, false))
120 sprintf (str
, "picked up range from bb %d\n",current_bb
->index
);
122 tracer
.print (idx
, str
);
125 // For a debug stmt, pick the best value currently available, do not
126 // trigger new value calculations. PR 100781.
127 else if (is_gimple_debug (stmt
))
128 m_cache
.range_of_expr (r
, expr
, stmt
);
131 basic_block bb
= gimple_bb (stmt
);
132 gimple
*def_stmt
= SSA_NAME_DEF_STMT (expr
);
134 // If name is defined in this block, try to get an range from S.
135 if (def_stmt
&& gimple_bb (def_stmt
) == bb
)
137 // Declared in this block, if it has a global set, check for an
138 // override from a block walk, otherwise calculate it.
139 if (m_cache
.get_global_range (r
, expr
))
140 m_cache
.block_range (r
, bb
, expr
, false);
142 range_of_stmt (r
, def_stmt
, expr
);
144 // Otherwise OP comes from outside this block, use range on entry.
146 range_on_entry (r
, bb
, expr
);
149 tracer
.trailer (idx
, "range_of_expr", true, expr
, r
);
153 // Return the range of NAME on entry to block BB in R.
156 gimple_ranger::range_on_entry (vrange
&r
, basic_block bb
, tree name
)
158 if (!gimple_range_ssa_p (name
))
159 return get_tree_range (r
, name
, NULL
, bb
, NULL
);
161 value_range
entry_range (TREE_TYPE (name
));
164 if ((idx
= tracer
.header ("range_on_entry (")))
166 print_generic_expr (dump_file
, name
, TDF_SLIM
);
167 fprintf (dump_file
, ") to BB %d\n", bb
->index
);
170 // Start with any known range
171 range_of_stmt (r
, SSA_NAME_DEF_STMT (name
), name
);
173 // Now see if there is any on_entry value which may refine it.
174 if (m_cache
.block_range (entry_range
, bb
, name
))
175 r
.intersect (entry_range
);
178 tracer
.trailer (idx
, "range_on_entry", true, name
, r
);
182 // Calculate the range for NAME at the end of block BB and return it in R.
183 // Return false if no range can be calculated.
186 gimple_ranger::range_on_exit (vrange
&r
, basic_block bb
, tree name
)
188 if (!gimple_range_ssa_p (name
))
189 return get_tree_range (r
, name
, NULL
, NULL
, bb
);
192 if ((idx
= tracer
.header ("range_on_exit (")))
194 print_generic_expr (dump_file
, name
, TDF_SLIM
);
195 fprintf (dump_file
, ") from BB %d\n", bb
->index
);
198 gimple
*s
= SSA_NAME_DEF_STMT (name
);
199 basic_block def_bb
= gimple_bb (s
);
200 // If this is not the definition block, get the range on the last stmt in
201 // the block... if there is one.
203 s
= last_nondebug_stmt (bb
);
204 // If there is no statement provided, get the range_on_entry for this block.
206 range_of_expr (r
, name
, s
);
208 range_on_entry (r
, bb
, name
);
209 gcc_checking_assert (r
.undefined_p ()
210 || range_compatible_p (r
.type (), TREE_TYPE (name
)));
213 tracer
.trailer (idx
, "range_on_exit", true, name
, r
);
217 // Calculate a range for NAME on edge E and return it in R.
220 gimple_ranger::range_on_edge (vrange
&r
, edge e
, tree name
)
222 value_range
edge_range (TREE_TYPE (name
));
224 if (!r
.supports_type_p (TREE_TYPE (name
)))
227 // Do not process values along abnormal edges.
228 if (e
->flags
& EDGE_ABNORMAL
)
229 return get_tree_range (r
, name
, NULL
);
232 if ((idx
= tracer
.header ("range_on_edge (")))
234 print_generic_expr (dump_file
, name
, TDF_SLIM
);
235 fprintf (dump_file
, ") on edge %d->%d\n", e
->src
->index
, e
->dest
->index
);
238 // Check to see if the edge is executable.
239 if ((e
->flags
& non_executable_edge_flag
))
243 tracer
.trailer (idx
, "range_on_edge [Unexecutable] ", true,
249 if (!gimple_range_ssa_p (name
))
250 res
= get_tree_range (r
, name
, NULL
);
253 range_on_exit (r
, e
->src
, name
);
254 // If this is not an abnormal edge, check for a non-null exit .
255 if ((e
->flags
& (EDGE_EH
| EDGE_ABNORMAL
)) == 0)
256 infer_oracle ().maybe_adjust_range (r
, name
, e
->src
);
257 gcc_checking_assert (r
.undefined_p ()
258 || range_compatible_p (r
.type(), TREE_TYPE (name
)));
260 // Check to see if NAME is defined on edge e.
261 if (m_cache
.range_on_edge (edge_range
, e
, name
))
262 r
.intersect (edge_range
);
266 tracer
.trailer (idx
, "range_on_edge", res
, name
, r
);
270 // fold_range wrapper for range_of_stmt to use as an internal client.
273 gimple_ranger::fold_range_internal (vrange
&r
, gimple
*s
, tree name
)
276 fur_depend
src (s
, this);
277 return f
.fold_stmt (r
, s
, src
, name
);
280 // Calculate a range for statement S and return it in R. If NAME is
281 // provided it represents the SSA_NAME on the LHS of the statement.
282 // It is only required if there is more than one lhs/output. Check
283 // the global cache for NAME first to see if the evaluation can be
284 // avoided. If a range cannot be calculated, return false and UNDEFINED.
287 gimple_ranger::range_of_stmt (vrange
&r
, gimple
*s
, tree name
)
293 if ((idx
= tracer
.header ("range_of_stmt (")))
296 print_generic_expr (dump_file
, name
, TDF_SLIM
);
297 fputs (") at stmt ", dump_file
);
298 print_gimple_stmt (dump_file
, s
, 0, TDF_SLIM
);
302 name
= gimple_get_lhs (s
);
304 // If no name, simply call the base routine.
307 res
= fold_range_internal (r
, s
, NULL_TREE
);
308 if (res
&& is_a
<gcond
*> (s
))
310 // Update any exports in the cache if this is a gimple cond statement.
312 basic_block bb
= gimple_bb (s
);
313 FOR_EACH_GORI_EXPORT_NAME (gori_ssa (), bb
, exp
)
314 m_cache
.propagate_updated_value (exp
, bb
);
317 else if (!gimple_range_ssa_p (name
))
318 res
= get_tree_range (r
, name
, NULL
);
322 // Check if the stmt has already been processed.
323 if (m_cache
.get_global_range (r
, name
, current
))
325 // If it isn't stale, use this cached value.
329 tracer
.trailer (idx
, " cached", true, name
, r
);
334 prefill_stmt_dependencies (name
);
336 // Calculate a new value.
337 value_range
tmp (TREE_TYPE (name
));
338 fold_range_internal (tmp
, s
, name
);
340 // Combine the new value with the old value. This is required because
341 // the way value propagation works, when the IL changes on the fly we
342 // can sometimes get different results. See PR 97741.
343 bool changed
= r
.intersect (tmp
);
344 m_cache
.set_global_range (name
, r
, changed
);
349 tracer
.trailer (idx
, "range_of_stmt", res
, name
, r
);
354 // Check if NAME is a dependency that needs resolving, and push it on the
355 // stack if so. R is a scratch range.
358 gimple_ranger::prefill_name (vrange
&r
, tree name
)
360 if (!gimple_range_ssa_p (name
))
362 gimple
*stmt
= SSA_NAME_DEF_STMT (name
);
363 if (!gimple_range_op_handler::supported_p (stmt
) && !is_a
<gphi
*> (stmt
))
366 // If this op has not been processed yet, then push it on the stack
367 if (!m_cache
.get_global_range (r
, name
))
370 // Set the global cache value and mark as alway_current.
371 m_cache
.get_global_range (r
, name
, current
);
372 m_stmt_list
.safe_push (name
);
376 // This routine will seed the global cache with most of the dependencies of
377 // NAME. This prevents excessive call depth through the normal API.
380 gimple_ranger::prefill_stmt_dependencies (tree ssa
)
382 if (SSA_NAME_IS_DEFAULT_DEF (ssa
))
386 gimple
*stmt
= SSA_NAME_DEF_STMT (ssa
);
387 gcc_checking_assert (stmt
&& gimple_bb (stmt
));
389 // Only pre-process range-ops and phis.
390 if (!gimple_range_op_handler::supported_p (stmt
) && !is_a
<gphi
*> (stmt
))
393 // Mark where on the stack we are starting.
394 unsigned start
= m_stmt_list
.length ();
395 m_stmt_list
.safe_push (ssa
);
397 idx
= tracer
.header ("ROS dependence fill\n");
399 // Loop until back at the start point.
400 while (m_stmt_list
.length () > start
)
402 tree name
= m_stmt_list
.last ();
403 // NULL is a marker which indicates the next name in the stack has now
404 // been fully resolved, so we can fold it.
407 // Pop the NULL, then pop the name.
409 name
= m_stmt_list
.pop ();
410 // Don't fold initial request, it will be calculated upon return.
411 if (m_stmt_list
.length () > start
)
413 // Fold and save the value for NAME.
414 stmt
= SSA_NAME_DEF_STMT (name
);
415 value_range
r (TREE_TYPE (name
));
416 fold_range_internal (r
, stmt
, name
);
417 // Make sure we don't lose any current global info.
418 value_range
tmp (TREE_TYPE (name
));
419 m_cache
.get_global_range (tmp
, name
);
420 bool changed
= tmp
.intersect (r
);
421 m_cache
.set_global_range (name
, tmp
, changed
);
426 // Add marker indicating previous NAME in list should be folded
427 // when we get to this NULL.
428 m_stmt_list
.safe_push (NULL_TREE
);
429 stmt
= SSA_NAME_DEF_STMT (name
);
433 tracer
.print (idx
, "ROS dep fill (");
434 print_generic_expr (dump_file
, name
, TDF_SLIM
);
435 fputs (") at stmt ", dump_file
);
436 print_gimple_stmt (dump_file
, stmt
, 0, TDF_SLIM
);
439 gphi
*phi
= dyn_cast
<gphi
*> (stmt
);
442 value_range
r (TREE_TYPE (gimple_phi_result (phi
)));
443 for (unsigned x
= 0; x
< gimple_phi_num_args (phi
); x
++)
444 prefill_name (r
, gimple_phi_arg_def (phi
, x
));
448 gimple_range_op_handler
handler (stmt
);
451 tree op
= handler
.operand2 ();
454 value_range
r (TREE_TYPE (op
));
455 prefill_name (r
, op
);
457 op
= handler
.operand1 ();
460 value_range
r (TREE_TYPE (op
));
461 prefill_name (r
, op
);
469 tracer
.trailer (idx
, "ROS ", false, ssa
, r
);
474 // This routine will invoke the gimple fold_stmt routine, providing context to
475 // range_of_expr calls via an private internal API.
478 gimple_ranger::fold_stmt (gimple_stmt_iterator
*gsi
, tree (*valueize
) (tree
))
480 gimple
*stmt
= gsi_stmt (*gsi
);
481 current_bb
= gimple_bb (stmt
);
482 bool ret
= ::fold_stmt (gsi
, valueize
);
487 // Called during dominator walks to register any inferred ranges that take
488 // effect from this point forward.
491 gimple_ranger::register_inferred_ranges (gimple
*s
)
493 // First, export the LHS if it is a new global range.
494 tree lhs
= gimple_get_lhs (s
);
497 value_range
tmp (TREE_TYPE (lhs
));
498 if (range_of_stmt (tmp
, s
, lhs
) && !tmp
.varying_p ())
499 set_range_info (lhs
, tmp
);
501 m_cache
.apply_inferred_ranges (s
);
504 // This function will walk the statements in BB to determine if any
505 // discovered inferred ranges in the block have any transitive effects,
506 // and if so, register those effects in BB.
509 gimple_ranger::register_transitive_inferred_ranges (basic_block bb
)
511 // Return if there are no inferred ranges in BB.
512 if (!infer_oracle ().has_range_p (bb
))
515 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
516 fprintf (dump_file
, "Checking for transitive inferred ranges in BB %d\n",
519 for (gimple_stmt_iterator si
= gsi_start_bb (bb
); !gsi_end_p (si
);
522 gimple
*s
= gsi_stmt (si
);
523 tree lhs
= gimple_get_lhs (s
);
524 // If the LHS already has an inferred effect, leave it be.
525 if (!gimple_range_ssa_p (lhs
) || infer_oracle ().has_range_p (bb
, lhs
))
527 // Pick up global value.
528 value_range
g (TREE_TYPE (lhs
));
529 range_of_expr (g
, lhs
);
531 // If either dependency has an inferred range, check if recalculating
532 // the LHS is different than the global value. If so, register it as
533 // an inferred range as well.
534 value_range
r (TREE_TYPE (lhs
));
536 tree name1
= gori_ssa ()->depend1 (lhs
);
537 tree name2
= gori_ssa ()->depend2 (lhs
);
538 if ((name1
&& infer_oracle ().has_range_p (bb
, name1
))
539 || (name2
&& infer_oracle ().has_range_p (bb
, name2
)))
541 // Check if folding S produces a different result.
542 if (fold_range (r
, s
, this) && g
!= r
)
544 gimple_infer_range
ir (lhs
, r
);
545 infer_oracle ().add_ranges (s
, ir
);
546 m_cache
.register_inferred_value (r
, lhs
, bb
);
552 // This routine will export whatever global ranges are known to GCC
553 // SSA_RANGE_NAME_INFO and SSA_NAME_PTR_INFO fields.
556 gimple_ranger::export_global_ranges ()
560 /* Print the header only when there's something else
562 fprintf (dump_file
, "Exporting new global ranges:\n");
563 fprintf (dump_file
, "============================\n");
565 for (unsigned x
= 1; x
< num_ssa_names
; x
++)
567 tree name
= ssa_name (x
);
570 value_range
r (TREE_TYPE (name
));
571 if (name
&& !SSA_NAME_IN_FREE_LIST (name
) && gimple_range_ssa_p (name
)
572 && m_cache
.get_global_range (r
, name
) && !r
.varying_p())
573 set_range_info (name
, r
);
576 fprintf (dump_file
, "========= Done =============\n");
579 // Print the known table values to file F.
582 gimple_ranger::dump_bb (FILE *f
, basic_block bb
)
587 fprintf (f
, "\n=========== BB %d ============\n", bb
->index
);
588 m_cache
.dump_bb (f
, bb
);
590 ::dump_bb (f
, bb
, 4, TDF_NONE
);
592 // Now find any globals defined in this block.
593 for (x
= 1; x
< num_ssa_names
; x
++)
595 tree name
= ssa_name (x
);
596 if (!gimple_range_ssa_p (name
) || !SSA_NAME_DEF_STMT (name
))
598 value_range
range (TREE_TYPE (name
));
599 if (gimple_bb (SSA_NAME_DEF_STMT (name
)) == bb
600 && m_cache
.get_global_range (range
, name
))
602 if (!range
.varying_p ())
604 print_generic_expr (f
, name
, TDF_SLIM
);
613 // And now outgoing edges, if they define anything.
614 FOR_EACH_EDGE (e
, ei
, bb
->succs
)
616 for (x
= 1; x
< num_ssa_names
; x
++)
618 tree name
= gimple_range_ssa_p (ssa_name (x
));
619 if (!name
|| !gori ().has_edge_range_p (name
, e
))
622 value_range
range (TREE_TYPE (name
));
623 if (m_cache
.range_on_edge (range
, e
, name
))
625 gimple
*s
= SSA_NAME_DEF_STMT (name
);
626 value_range
tmp_range (TREE_TYPE (name
));
627 // Only print the range if this is the def block, or
628 // the on entry cache for either end of the edge is
630 if ((s
&& bb
== gimple_bb (s
)) ||
631 m_cache
.block_range (tmp_range
, bb
, name
, false) ||
632 m_cache
.block_range (tmp_range
, e
->dest
, name
, false))
634 if (!range
.varying_p ())
636 fprintf (f
, "%d->%d ", e
->src
->index
,
639 if (e
->flags
& EDGE_TRUE_VALUE
)
640 fprintf (f
, " (T)%c", c
);
641 else if (e
->flags
& EDGE_FALSE_VALUE
)
642 fprintf (f
, " (F)%c", c
);
645 print_generic_expr (f
, name
, TDF_SLIM
);
656 // Print the known table values to file F.
659 gimple_ranger::dump (FILE *f
)
663 FOR_EACH_BB_FN (bb
, cfun
)
670 gimple_ranger::debug ()
675 /* Create a new ranger instance and associate it with function FUN.
676 Each call must be paired with a call to disable_ranger to release
680 enable_ranger (struct function
*fun
, bool use_imm_uses
)
684 gcc_checking_assert (!fun
->x_range_query
);
685 r
= new gimple_ranger (use_imm_uses
);
686 fun
->x_range_query
= r
;
691 /* Destroy and release the ranger instance associated with function FUN
692 and replace it the global ranger. */
695 disable_ranger (struct function
*fun
)
697 gcc_checking_assert (fun
->x_range_query
);
698 delete fun
->x_range_query
;
699 fun
->x_range_query
= NULL
;
702 // ---------------------------------------------------------------------------
704 // The DOM based ranger assumes a single DOM walk through the IL, and is
705 // used by the fvrp_folder as a fast VRP.
706 // During the dom walk, the current block has an ssa_lazy_cache pointer
707 // m_bb[bb->index] which represents all the cumulative contextual ranges
708 // active in the block.
709 // These ranges are pure static ranges generated by branches, and must be
710 // combined with the equivlaent global range to produce the final range.
711 // A NULL pointer means there are no contextual ranges.
713 // Create a DOM based ranger for use by a DOM walk pass.
715 dom_ranger::dom_ranger () : m_global ()
717 bitmap_obstack_initialize (&m_bitmaps
);
718 m_freelist
.create (0);
719 m_freelist
.truncate (0);
721 m_bb
.safe_grow_cleared (last_basic_block_for_fn (cfun
));
722 if (dump_file
&& (param_ranger_debug
& RANGER_DEBUG_TRACE
))
723 tracer
.enable_trace ();
726 // Dispose of a DOM ranger.
728 dom_ranger::~dom_ranger ()
730 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
732 fprintf (dump_file
, "Non-varying global ranges:\n");
733 fprintf (dump_file
, "=========================:\n");
734 m_global
.dump (dump_file
);
737 m_freelist
.release ();
738 bitmap_obstack_release (&m_bitmaps
);
741 // Implement range of EXPR on stmt S, and return it in R.
742 // Return false if no range can be calculated.
745 dom_ranger::range_of_expr (vrange
&r
, tree expr
, gimple
*s
)
748 if (!gimple_range_ssa_p (expr
))
749 return get_tree_range (r
, expr
, s
);
751 if ((idx
= tracer
.header ("range_of_expr ")))
753 print_generic_expr (dump_file
, expr
, TDF_SLIM
);
756 fprintf (dump_file
, " at ");
757 print_gimple_stmt (dump_file
, s
, 0, TDF_SLIM
);
760 fprintf (dump_file
, "\n");
763 // If there is a statement, return the range in that statements block.
765 range_in_bb (r
, gimple_bb (s
), expr
);
767 m_global
.range_of_expr (r
, expr
, s
);
770 tracer
.trailer (idx
, " ", true, expr
, r
);
774 // Return the range of EXPR on edge E in R.
775 // Return false if no range can be calculated.
778 dom_ranger::range_on_edge (vrange
&r
, edge e
, tree expr
)
780 if (!gimple_range_ssa_p (expr
))
781 return get_tree_range (r
, expr
, NULL
);
783 basic_block bb
= e
->src
;
785 if ((idx
= tracer
.header ("range_on_edge ")))
787 fprintf (dump_file
, "%d->%d for ",e
->src
->index
, e
->dest
->index
);
788 print_generic_expr (dump_file
, expr
, TDF_SLIM
);
789 fputc ('\n',dump_file
);
792 range_in_bb (r
, bb
, expr
);
793 value_range
vr(TREE_TYPE (expr
));
794 if (gori_name_on_edge (vr
, expr
, e
, this))
798 tracer
.trailer (idx
, " ", true, expr
, r
);
802 // Return the range of NAME as it exists at the end of block BB in R.
805 dom_ranger::range_in_bb (vrange
&r
, basic_block bb
, tree name
)
807 // Start with the global value.
808 m_global
.range_of_expr (r
, name
);
810 // If there is a contextual range, intersect it with the global range
811 ssa_lazy_cache
*context
= m_bb
[bb
->index
];
812 if (context
&& context
->has_range (name
))
814 value_range
cr (TREE_TYPE (name
));
815 context
->get_range (cr
, name
);
820 // Calculate the range of NAME, as the def of stmt S and return it in R.
821 // Return FALSE if no range can be calculated.
822 // Also set the global range for NAME as this should only be called within
823 // the def block during a DOM walk.
826 dom_ranger::range_of_stmt (vrange
&r
, gimple
*s
, tree name
)
831 name
= gimple_get_lhs (s
);
833 if (name
&& !gimple_range_ssa_p (name
))
834 return get_tree_range (r
, name
, NULL
);
836 if ((idx
= tracer
.header ("range_of_stmt ")))
837 print_gimple_stmt (dump_file
, s
, 0, TDF_SLIM
);
839 // Its already been calculated.
840 if (name
&& m_global
.has_range (name
))
842 ret
= m_global
.range_of_expr (r
, name
, s
);
844 tracer
.trailer (idx
, " Already had value ", ret
, name
, r
);
848 // Fold using a fur_depend object so that relations are registered.
850 fur_depend
src (s
, this);
851 ret
= f
.fold_stmt (r
, s
, src
, name
);
853 // If there is a new calculated range and it is not varying, set
855 if (ret
&& name
&& m_global
.merge_range (name
, r
) && !r
.varying_p ())
856 set_range_info (name
, r
);
859 tracer
.trailer (idx
, " ", ret
, name
, r
);
863 // Preprocess block BB. If there is a single predecessor, start with any
864 // contextual ranges on the incoming edge, otherwise the initial list
865 // of ranges i empty for this block. Then Merge in any contextual ranges
866 // from the dominator block. Tihs will become the contextual ranges
867 // that apply to this block.
870 dom_ranger::pre_bb (basic_block bb
)
872 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
873 fprintf (dump_file
, "#FVRP entering BB %d\n", bb
->index
);
875 m_bb
[bb
->index
] = NULL
;
876 basic_block dom_bb
= get_immediate_dominator (CDI_DOMINATORS
, bb
);
878 ssa_lazy_cache
*e_cache
;
879 if (!m_freelist
.is_empty ())
880 e_cache
= m_freelist
.pop ();
882 e_cache
= new ssa_lazy_cache (&m_bitmaps
);
883 gcc_checking_assert (e_cache
->empty_p ());
885 // If there is a single pred, check if there are any ranges on
886 // the edge and start with those.
887 if (single_pred_p (bb
))
889 gori_on_edge (*e_cache
, EDGE_PRED (bb
, 0), this);
890 if (!e_cache
->empty_p () && dump_file
&& (dump_flags
& TDF_DETAILS
))
892 fprintf (dump_file
, "\nEdge ranges BB %d->%d\n",
893 EDGE_PRED (bb
, 0)->src
->index
, bb
->index
);
894 e_cache
->dump(dump_file
);
897 // If the dominator had any ranges registered, integrate those.
898 if (dom_bb
&& m_bb
[dom_bb
->index
])
899 e_cache
->merge (*(m_bb
[dom_bb
->index
]));
901 // If there are no ranges, this block has no contextual ranges.
902 if (e_cache
->empty_p ())
903 m_freelist
.safe_push (e_cache
);
905 m_bb
[bb
->index
] = e_cache
;
907 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
911 fprintf (dump_file
, "all contextual ranges active:\n");
912 m_bb
[bb
->index
]->dump (dump_file
);
915 fprintf (dump_file
, " NO contextual ranges active:\n");
919 // Perform any post block processing.
922 dom_ranger::post_bb (basic_block bb
)
924 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
925 fprintf (dump_file
, "#FVRP POST BB %d\n", bb
->index
);
926 // If there were contextual ranges, clear them and put the
927 // object on the freelist.
930 m_bb
[bb
->index
]->clear ();
931 m_freelist
.safe_push (m_bb
[bb
->index
]);
932 m_bb
[bb
->index
] = NULL
;