1 /* Header file for gimple ranger SSA cache.
2 Copyright (C) 2017-2022 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 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
10 version.
11
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
15 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 #ifndef GCC_SSA_RANGE_CACHE_H
22 #define GCC_SSA_RANGE_CACHE_H
23
24 #include "gimple-range-gori.h"
25
26 // Class used to track non-null references of an SSA name. A vector
27 // of bitmaps indexed by SSA name is maintained. When indexed by
28 // basic block, an on-bit indicates there is a non-null dereference
29 // for that SSA in that block.
30
31 class non_null_ref
32 {
33 public:
34 non_null_ref ();
35 ~non_null_ref ();
36 bool non_null_deref_p (tree name, basic_block bb, bool search_dom = true);
37 bool adjust_range (irange &r, tree name, basic_block bb,
38 bool search_dom = true);
39 bool set_nonnull (basic_block bb, tree name);
40 private:
41 vec <bitmap> m_nn;
42 void process_name (tree name);
43 bitmap_obstack m_bitmaps;
44 };
45
46 // If NAME has a non-null dereference in block BB, adjust R with the
47 // non-zero information from non_null_deref_p, and return TRUE. If
48 // SEARCH_DOM is true, non_null_deref_p should search the dominator tree.
49
50 inline bool
adjust_range(irange & r,tree name,basic_block bb,bool search_dom)51 non_null_ref::adjust_range (irange &r, tree name, basic_block bb,
52 bool search_dom)
53 {
54 // Non-call exceptions mean we could throw in the middle of the
55 // block, so just punt on those for now.
56 if (cfun->can_throw_non_call_exceptions)
57 return false;
58 // We only care about the null / non-null property of pointers.
59 if (!POINTER_TYPE_P (TREE_TYPE (name)))
60 return false;
61 if (r.undefined_p () || r.lower_bound () != 0 || r.upper_bound () == 0)
62 return false;
63 // Check if pointers have any non-null dereferences.
64 if (non_null_deref_p (name, bb, search_dom))
65 {
66 // Remove zero from the range.
67 unsigned prec = TYPE_PRECISION (TREE_TYPE (name));
68 r.intersect (wi::one (prec), wi::max_value (prec, UNSIGNED));
69 return true;
70 }
71 return false;
72 }
73
74 // This class manages a vector of pointers to ssa_block ranges. It
75 // provides the basis for the "range on entry" cache for all
76 // SSA names.
77
78 class block_range_cache
79 {
80 public:
81 block_range_cache ();
82 ~block_range_cache ();
83
84 bool set_bb_range (tree name, const_basic_block bb, const irange &r);
85 bool get_bb_range (irange &r, tree name, const_basic_block bb);
86 bool bb_range_p (tree name, const_basic_block bb);
87
88 void dump (FILE *f);
89 void dump (FILE *f, basic_block bb, bool print_varying = true);
90 private:
91 vec<class ssa_block_ranges *> m_ssa_ranges;
92 ssa_block_ranges &get_block_ranges (tree name);
93 ssa_block_ranges *query_block_ranges (tree name);
94 irange_allocator *m_irange_allocator;
95 bitmap_obstack m_bitmaps;
96 };
97
98 // This global cache is used with the range engine as markers for what
99 // has been visited during this incarnation. Once the ranger evaluates
100 // a name, it is typically not re-evaluated again.
101
102 class ssa_global_cache
103 {
104 public:
105 ssa_global_cache ();
106 ~ssa_global_cache ();
107 bool get_global_range (irange &r, tree name) const;
108 bool set_global_range (tree name, const irange &r);
109 void clear_global_range (tree name);
110 void clear ();
111 void dump (FILE *f = stderr);
112 private:
113 vec<irange *> m_tab;
114 class irange_allocator *m_irange_allocator;
115 };
116
117 // This class provides all the caches a global ranger may need, and makes
118 // them available for gori-computes to query so outgoing edges can be
119 // properly calculated.
120
121 class ranger_cache : public range_query
122 {
123 public:
124 ranger_cache (int not_executable_flag);
125 ~ranger_cache ();
126
127 virtual bool range_of_expr (irange &r, tree name, gimple *stmt);
128 virtual bool range_on_edge (irange &r, edge e, tree expr);
129 bool block_range (irange &r, basic_block bb, tree name, bool calc = true);
130 bool range_from_dom (irange &r, tree name, basic_block bb);
131
132 bool get_global_range (irange &r, tree name) const;
133 bool get_global_range (irange &r, tree name, bool ¤t_p);
134 void set_global_range (tree name, const irange &r);
135
136 void propagate_updated_value (tree name, basic_block bb);
137
138 void block_apply_nonnull (gimple *s);
139 void update_to_nonnull (basic_block bb, tree name);
140 non_null_ref m_non_null;
141 gori_compute m_gori;
142
143 void dump_bb (FILE *f, basic_block bb);
144 virtual void dump (FILE *f) OVERRIDE;
145 private:
146 ssa_global_cache m_globals;
147 block_range_cache m_on_entry;
148 class temporal_cache *m_temporal;
149 void fill_block_cache (tree name, basic_block bb, basic_block def_bb);
150 void propagate_cache (tree name);
151
152 void range_of_def (irange &r, tree name, basic_block bb = NULL);
153 void entry_range (irange &r, tree expr, basic_block bb);
154 void exit_range (irange &r, tree expr, basic_block bb);
155
156 vec<basic_block> m_workback;
157 class update_list *m_update;
158 };
159
160 #endif // GCC_SSA_RANGE_CACHE_H
161