1 /* Basic block path solver.
2 Copyright (C) 2021 Free Software Foundation, Inc.
3 Contributed by Aldy Hernandez <aldyh@redhat.com>.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
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"
28 #include "value-range.h"
29 #include "gimple-range.h"
30 #include "tree-pretty-print.h"
31 #include "gimple-range-path.h"
34 #include "gimple-iterator.h"
36 // Internal construct to help facilitate debugging of solver.
37 #define DEBUG_SOLVER (dump_file && (param_threader_debug == THREADER_DEBUG_ALL))
39 path_range_query::path_range_query (gimple_ranger
*ranger
, bool resolve
)
40 : m_cache (new ssa_global_cache
),
41 m_has_cache_entry (BITMAP_ALLOC (NULL
)),
44 m_alloced_ranger (false)
46 m_oracle
= new path_oracle (ranger
->oracle ());
49 path_range_query::path_range_query (bool resolve
)
50 : m_cache (new ssa_global_cache
),
51 m_has_cache_entry (BITMAP_ALLOC (NULL
)),
52 m_ranger (new gimple_ranger
),
54 m_alloced_ranger (true)
56 m_oracle
= new path_oracle (m_ranger
->oracle ());
59 path_range_query::~path_range_query ()
61 BITMAP_FREE (m_has_cache_entry
);
68 // Mark cache entry for NAME as unused.
71 path_range_query::clear_cache (tree name
)
73 unsigned v
= SSA_NAME_VERSION (name
);
74 bitmap_clear_bit (m_has_cache_entry
, v
);
77 // If NAME has a cache entry, return it in R, and return TRUE.
80 path_range_query::get_cache (irange
&r
, tree name
)
82 if (!gimple_range_ssa_p (name
))
83 return get_global_range_query ()->range_of_expr (r
, name
);
85 unsigned v
= SSA_NAME_VERSION (name
);
86 if (bitmap_bit_p (m_has_cache_entry
, v
))
87 return m_cache
->get_global_range (r
, name
);
92 // Set the cache entry for NAME to R.
95 path_range_query::set_cache (const irange
&r
, tree name
)
97 unsigned v
= SSA_NAME_VERSION (name
);
98 bitmap_set_bit (m_has_cache_entry
, v
);
99 m_cache
->set_global_range (name
, r
);
103 path_range_query::dump (FILE *dump_file
)
105 push_dump_file
save (dump_file
, dump_flags
& ~TDF_DETAILS
);
107 if (m_path
.is_empty ())
113 dump_ranger (dump_file
, m_path
);
115 fprintf (dump_file
, "Imports:\n");
116 EXECUTE_IF_SET_IN_BITMAP (m_imports
, 0, i
, bi
)
118 tree name
= ssa_name (i
);
119 print_generic_expr (dump_file
, name
, TDF_SLIM
);
120 fprintf (dump_file
, "\n");
123 m_cache
->dump (dump_file
);
127 path_range_query::debug ()
132 // Return TRUE if NAME is defined outside the current path.
135 path_range_query::defined_outside_path (tree name
)
137 gimple
*def
= SSA_NAME_DEF_STMT (name
);
138 basic_block bb
= gimple_bb (def
);
140 return !bb
|| !m_path
.contains (bb
);
143 // Return the range of NAME on entry to the path.
146 path_range_query::range_on_path_entry (irange
&r
, tree name
)
148 gcc_checking_assert (defined_outside_path (name
));
149 basic_block entry
= entry_bb ();
151 // Prefer to use range_of_expr if we have a statement to look at,
152 // since it has better caching than range_on_edge.
153 gimple
*last
= last_stmt (entry
);
156 if (m_ranger
->range_of_expr (r
, name
, last
))
161 // If we have no statement, look at all the incoming ranges to the
162 // block. This can happen when we're querying a block with only an
163 // outgoing edge (no statement but the fall through edge), but for
164 // which we can determine a range on entry to the block.
166 bool changed
= false;
168 for (unsigned i
= 0; i
< EDGE_COUNT (entry
->preds
); ++i
)
170 edge e
= EDGE_PRED (entry
, i
);
171 if (e
->src
!= ENTRY_BLOCK_PTR_FOR_FN (cfun
)
172 && m_ranger
->range_on_edge (tmp
, e
, name
))
179 // Make sure we don't return UNDEFINED by mistake.
181 r
.set_varying (TREE_TYPE (name
));
184 // Return the range of NAME at the end of the path being analyzed.
187 path_range_query::internal_range_of_expr (irange
&r
, tree name
, gimple
*stmt
)
189 if (!irange::supports_type_p (TREE_TYPE (name
)))
192 if (get_cache (r
, name
))
195 if (m_resolve
&& defined_outside_path (name
))
197 range_on_path_entry (r
, name
);
202 basic_block bb
= stmt
? gimple_bb (stmt
) : exit_bb ();
203 if (stmt
&& range_defined_in_block (r
, name
, bb
))
205 if (TREE_CODE (name
) == SSA_NAME
)
206 r
.intersect (gimple_range_global (name
));
212 r
.set_varying (TREE_TYPE (name
));
217 path_range_query::range_of_expr (irange
&r
, tree name
, gimple
*stmt
)
219 if (internal_range_of_expr (r
, name
, stmt
))
221 if (r
.undefined_p ())
222 m_undefined_path
= true;
230 path_range_query::unreachable_path_p ()
232 return m_undefined_path
;
235 // Initialize the current path to PATH. The current block is set to
236 // the entry block to the path.
238 // Note that the blocks are in reverse order, so the exit block is
242 path_range_query::set_path (const vec
<basic_block
> &path
)
244 gcc_checking_assert (path
.length () > 1);
245 m_path
= path
.copy ();
246 m_pos
= m_path
.length () - 1;
247 bitmap_clear (m_has_cache_entry
);
250 // Return the range of the result of PHI in R.
253 path_range_query::ssa_range_in_phi (irange
&r
, gphi
*phi
)
255 tree name
= gimple_phi_result (phi
);
256 basic_block bb
= gimple_bb (phi
);
260 if (m_resolve
&& m_ranger
->range_of_expr (r
, name
, phi
))
263 // Try fold just in case we can resolve simple things like PHI <5(99), 6(88)>.
264 if (!fold_range (r
, phi
, this))
265 r
.set_varying (TREE_TYPE (name
));
270 basic_block prev
= prev_bb ();
271 edge e_in
= find_edge (prev
, bb
);
272 unsigned nargs
= gimple_phi_num_args (phi
);
274 for (size_t i
= 0; i
< nargs
; ++i
)
275 if (e_in
== gimple_phi_arg_edge (phi
, i
))
277 tree arg
= gimple_phi_arg_def (phi
, i
);
279 if (!get_cache (r
, arg
))
284 // Using both the range on entry to the path, and the
285 // range on this edge yields significantly better
287 if (defined_outside_path (arg
))
288 range_on_path_entry (r
, arg
);
290 r
.set_varying (TREE_TYPE (name
));
291 m_ranger
->range_on_edge (tmp
, e_in
, arg
);
295 r
.set_varying (TREE_TYPE (name
));
302 // If NAME is defined in BB, set R to the range of NAME, and return
303 // TRUE. Otherwise, return FALSE.
306 path_range_query::range_defined_in_block (irange
&r
, tree name
, basic_block bb
)
308 gimple
*def_stmt
= SSA_NAME_DEF_STMT (name
);
309 basic_block def_bb
= gimple_bb (def_stmt
);
314 if (get_cache (r
, name
))
317 if (gimple_code (def_stmt
) == GIMPLE_PHI
)
318 ssa_range_in_phi (r
, as_a
<gphi
*> (def_stmt
));
322 get_path_oracle ()->killing_def (name
);
324 if (!range_of_stmt (r
, def_stmt
, name
))
325 r
.set_varying (TREE_TYPE (name
));
329 m_non_null
.adjust_range (r
, name
, bb
);
331 if (DEBUG_SOLVER
&& (bb
|| !r
.varying_p ()))
333 fprintf (dump_file
, "range_defined_in_block (BB%d) for ", bb
? bb
->index
: -1);
334 print_generic_expr (dump_file
, name
, TDF_SLIM
);
335 fprintf (dump_file
, " is ");
337 fprintf (dump_file
, "\n");
343 // Compute ranges defined in the current block, or exported to the
347 path_range_query::compute_ranges_in_block (basic_block bb
)
350 int_range_max r
, cached_range
;
353 if (m_resolve
&& !at_entry ())
354 compute_phi_relations (bb
, prev_bb ());
356 // Force recalculation of any names in the cache that are defined in
357 // this block. This can happen on interdependent SSA/phis in loops.
358 EXECUTE_IF_SET_IN_BITMAP (m_imports
, 0, i
, bi
)
360 tree name
= ssa_name (i
);
361 gimple
*def_stmt
= SSA_NAME_DEF_STMT (name
);
362 basic_block def_bb
= gimple_bb (def_stmt
);
368 // Solve imports defined in this block.
369 EXECUTE_IF_SET_IN_BITMAP (m_imports
, 0, i
, bi
)
371 tree name
= ssa_name (i
);
373 if (range_defined_in_block (r
, name
, bb
))
380 // Solve imports that are exported to the next block.
381 basic_block next
= next_bb ();
382 edge e
= find_edge (bb
, next
);
383 EXECUTE_IF_SET_IN_BITMAP (m_imports
, 0, i
, bi
)
385 tree name
= ssa_name (i
);
386 gori_compute
&g
= m_ranger
->gori ();
387 bitmap exports
= g
.exports (bb
);
389 if (bitmap_bit_p (exports
, i
))
391 if (g
.outgoing_edge_range_p (r
, e
, name
, *this))
393 if (get_cache (cached_range
, name
))
394 r
.intersect (cached_range
);
399 fprintf (dump_file
, "outgoing_edge_range_p for ");
400 print_generic_expr (dump_file
, name
, TDF_SLIM
);
401 fprintf (dump_file
, " on edge %d->%d ",
402 e
->src
->index
, e
->dest
->index
);
403 fprintf (dump_file
, "is ");
405 fprintf (dump_file
, "\n");
412 compute_outgoing_relations (bb
, next
);
415 // Adjust all pointer imports in BB with non-null information.
418 path_range_query::adjust_for_non_null_uses (basic_block bb
)
424 EXECUTE_IF_SET_IN_BITMAP (m_imports
, 0, i
, bi
)
426 tree name
= ssa_name (i
);
428 if (!POINTER_TYPE_P (TREE_TYPE (name
)))
431 if (get_cache (r
, name
))
437 r
.set_varying (TREE_TYPE (name
));
439 if (m_non_null
.adjust_range (r
, name
, bb
))
444 // If NAME is a supported SSA_NAME, add it the bitmap in IMPORTS.
447 path_range_query::add_to_imports (tree name
, bitmap imports
)
449 if (TREE_CODE (name
) == SSA_NAME
450 && irange::supports_type_p (TREE_TYPE (name
)))
451 return bitmap_set_bit (imports
, SSA_NAME_VERSION (name
));
455 // Compute the imports to the path ending in EXIT. These are
456 // essentially the SSA names used to calculate the final conditional
459 // They are hints for the solver. Adding more elements doesn't slow
460 // us down, because we don't solve anything that doesn't appear in the
461 // path. On the other hand, not having enough imports will limit what
465 path_range_query::compute_imports (bitmap imports
, basic_block exit
)
467 // Start with the imports from the exit block...
468 bitmap r_imports
= m_ranger
->gori ().imports (exit
);
469 bitmap_copy (imports
, r_imports
);
471 auto_vec
<tree
> worklist (bitmap_count_bits (imports
));
474 EXECUTE_IF_SET_IN_BITMAP (imports
, 0, i
, bi
)
476 tree name
= ssa_name (i
);
477 worklist
.quick_push (name
);
480 // ...and add any operands used to define these imports.
481 while (!worklist
.is_empty ())
483 tree name
= worklist
.pop ();
484 gimple
*def_stmt
= SSA_NAME_DEF_STMT (name
);
486 if (is_gimple_assign (def_stmt
))
488 add_to_imports (gimple_assign_rhs1 (def_stmt
), imports
);
489 tree rhs
= gimple_assign_rhs2 (def_stmt
);
490 if (rhs
&& add_to_imports (rhs
, imports
))
491 worklist
.safe_push (rhs
);
492 rhs
= gimple_assign_rhs3 (def_stmt
);
493 if (rhs
&& add_to_imports (rhs
, imports
))
494 worklist
.safe_push (rhs
);
496 else if (gphi
*phi
= dyn_cast
<gphi
*> (def_stmt
))
498 for (size_t i
= 0; i
< gimple_phi_num_args (phi
); ++i
)
500 edge e
= gimple_phi_arg_edge (phi
, i
);
501 tree arg
= gimple_phi_arg (phi
, i
)->def
;
503 if (TREE_CODE (arg
) == SSA_NAME
504 && m_path
.contains (e
->src
)
505 && bitmap_set_bit (imports
, SSA_NAME_VERSION (arg
)))
506 worklist
.safe_push (arg
);
512 // Compute the ranges for IMPORTS along PATH.
514 // IMPORTS are the set of SSA names, any of which could potentially
515 // change the value of the final conditional in PATH. Default to the
516 // imports of the last block in the path if none is given.
519 path_range_query::compute_ranges (const vec
<basic_block
> &path
,
520 const bitmap_head
*imports
)
523 fprintf (dump_file
, "\n==============================================\n");
526 m_undefined_path
= false;
529 bitmap_copy (m_imports
, imports
);
531 compute_imports (m_imports
, exit_bb ());
534 get_path_oracle ()->reset_path ();
538 fprintf (dump_file
, "path_range_query: compute_ranges for path: ");
539 for (unsigned i
= path
.length (); i
> 0; --i
)
541 basic_block bb
= path
[i
- 1];
542 fprintf (dump_file
, "%d", bb
->index
);
544 fprintf (dump_file
, "->");
546 fprintf (dump_file
, "\n");
551 basic_block bb
= curr_bb ();
555 gori_compute
&gori
= m_ranger
->gori ();
558 // Exported booleans along the path, may help conditionals.
559 // Add them as interesting imports.
560 FOR_EACH_GORI_EXPORT_NAME (gori
, bb
, name
)
561 if (TREE_CODE (TREE_TYPE (name
)) == BOOLEAN_TYPE
)
562 bitmap_set_bit (m_imports
, SSA_NAME_VERSION (name
));
565 compute_ranges_in_block (bb
);
566 adjust_for_non_null_uses (bb
);
576 get_path_oracle ()->dump (dump_file
);
581 // Convenience function to compute ranges along a path consisting of
582 // E->SRC and E->DEST.
585 path_range_query::compute_ranges (edge e
)
587 auto_vec
<basic_block
> bbs (2);
588 bbs
.quick_push (e
->dest
);
589 bbs
.quick_push (e
->src
);
590 compute_ranges (bbs
);
593 // A folding aid used to register and query relations along a path.
594 // When queried, it returns relations as they would appear on exit to
597 // Relations are registered on entry so the path_oracle knows which
598 // block to query the root oracle at when a relation lies outside the
599 // path. However, when queried we return the relation on exit to the
600 // path, since the root_oracle ignores the registered.
602 class jt_fur_source
: public fur_depend
605 jt_fur_source (gimple
*s
, path_range_query
*, gori_compute
*,
606 const vec
<basic_block
> &);
607 relation_kind
query_relation (tree op1
, tree op2
) override
;
608 void register_relation (gimple
*, relation_kind
, tree op1
, tree op2
) override
;
609 void register_relation (edge
, relation_kind
, tree op1
, tree op2
) override
;
614 jt_fur_source::jt_fur_source (gimple
*s
,
615 path_range_query
*query
,
617 const vec
<basic_block
> &path
)
618 : fur_depend (s
, gori
, query
)
620 gcc_checking_assert (!path
.is_empty ());
622 m_entry
= path
[path
.length () - 1];
624 if (dom_info_available_p (CDI_DOMINATORS
))
625 m_oracle
= query
->oracle ();
630 // Ignore statement and register relation on entry to path.
633 jt_fur_source::register_relation (gimple
*, relation_kind k
, tree op1
, tree op2
)
636 m_oracle
->register_relation (m_entry
, k
, op1
, op2
);
639 // Ignore edge and register relation on entry to path.
642 jt_fur_source::register_relation (edge
, relation_kind k
, tree op1
, tree op2
)
645 m_oracle
->register_relation (m_entry
, k
, op1
, op2
);
649 jt_fur_source::query_relation (tree op1
, tree op2
)
654 if (TREE_CODE (op1
) != SSA_NAME
|| TREE_CODE (op2
) != SSA_NAME
)
657 return m_oracle
->query_relation (m_entry
, op1
, op2
);
660 // Return the range of STMT at the end of the path being analyzed.
663 path_range_query::range_of_stmt (irange
&r
, gimple
*stmt
, tree
)
665 tree type
= gimple_range_type (stmt
);
667 if (!irange::supports_type_p (type
))
670 // If resolving unknowns, fold the statement as it would have
671 // appeared at the end of the path.
675 jt_fur_source
src (stmt
, this, &m_ranger
->gori (), m_path
);
676 if (!f
.fold_stmt (r
, stmt
, src
))
677 r
.set_varying (type
);
679 // Otherwise, use the global ranger to fold it as it would appear in
680 // the original IL. This is more conservative, but faster.
681 else if (!fold_range (r
, stmt
, this))
682 r
.set_varying (type
);
688 path_range_query::maybe_register_phi_relation (gphi
*phi
, tree arg
)
690 basic_block bb
= gimple_bb (phi
);
691 tree result
= gimple_phi_result (phi
);
692 gimple
*def
= SSA_NAME_DEF_STMT (arg
);
694 // Avoid recording the equivalence if the arg is defined in this
695 // block, as that would create an ordering problem.
696 if (def
&& gimple_bb (def
) == bb
)
699 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
700 fprintf (dump_file
, " from bb%d:", bb
->index
);
702 get_path_oracle ()->killing_def (result
);
703 m_oracle
->register_relation (entry_bb (), EQ_EXPR
, arg
, result
);
706 // Compute relations for each PHI in BB. For example:
708 // x_5 = PHI<y_9(5),...>
710 // If the path flows through BB5, we can register that x_5 == y_9.
713 path_range_query::compute_phi_relations (basic_block bb
, basic_block prev
)
718 edge e_in
= find_edge (prev
, bb
);
720 for (gphi_iterator iter
= gsi_start_phis (bb
); !gsi_end_p (iter
);
723 gphi
*phi
= iter
.phi ();
724 tree result
= gimple_phi_result (phi
);
725 unsigned nargs
= gimple_phi_num_args (phi
);
727 if (!import_p (result
))
730 for (size_t i
= 0; i
< nargs
; ++i
)
731 if (e_in
== gimple_phi_arg_edge (phi
, i
))
733 tree arg
= gimple_phi_arg_def (phi
, i
);
735 if (gimple_range_ssa_p (arg
))
736 maybe_register_phi_relation (phi
, arg
);
742 // Compute outgoing relations from BB to NEXT.
745 path_range_query::compute_outgoing_relations (basic_block bb
, basic_block next
)
747 gimple
*stmt
= last_stmt (bb
);
750 && gimple_code (stmt
) == GIMPLE_COND
751 && (import_p (gimple_cond_lhs (stmt
))
752 || import_p (gimple_cond_rhs (stmt
))))
755 gcond
*cond
= as_a
<gcond
*> (stmt
);
756 edge e0
= EDGE_SUCC (bb
, 0);
757 edge e1
= EDGE_SUCC (bb
, 1);
759 if (e0
->dest
== next
)
760 gcond_edge_range (r
, e0
);
761 else if (e1
->dest
== next
)
762 gcond_edge_range (r
, e1
);
766 jt_fur_source
src (NULL
, this, &m_ranger
->gori (), m_path
);
767 src
.register_outgoing_edges (cond
, r
, e0
, e1
);