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 &current_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