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