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
|
/* Header file for gimple ranger SSA cache.
Copyright (C) 2017-2024 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"
#include "gimple-range-infer.h"
#include "gimple-range-phi.h"
// 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 vrange &v);
bool get_bb_range (vrange &v, 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);
class vrange_allocator *m_range_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_cache : public range_query
{
public:
ssa_cache ();
~ssa_cache ();
virtual bool has_range (tree name) const;
virtual bool get_range (vrange &r, tree name) const;
virtual bool set_range (tree name, const vrange &r);
virtual bool merge_range (tree name, const vrange &r);
virtual void clear_range (tree name);
virtual void clear ();
void dump (FILE *f = stderr);
virtual bool range_of_expr (vrange &r, tree expr, gimple *stmt = NULL);
protected:
vec<vrange_storage *> m_tab;
vrange_allocator *m_range_allocator;
};
// This is the same as global cache, except it maintains an active bitmap
// rather than depending on a zero'd out vector of pointers. This is better
// for sparsely/lightly used caches.
class ssa_lazy_cache : public ssa_cache
{
public:
inline ssa_lazy_cache () { active_p = BITMAP_ALLOC (NULL); }
inline ~ssa_lazy_cache () { BITMAP_FREE (active_p); }
inline bool empty_p () const { return bitmap_empty_p (active_p); }
virtual bool has_range (tree name) const;
virtual bool set_range (tree name, const vrange &r);
virtual bool merge_range (tree name, const vrange &r);
virtual bool get_range (vrange &r, tree name) const;
virtual void clear_range (tree name);
virtual void clear ();
protected:
bitmap active_p;
};
// 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, bool use_imm_uses);
~ranger_cache ();
bool range_of_expr (vrange &r, tree name, gimple *stmt) final override;
bool range_on_edge (vrange &r, edge e, tree expr) final override;
bool block_range (vrange &r, basic_block bb, tree name, bool calc = true);
bool get_global_range (vrange &r, tree name) const;
bool get_global_range (vrange &r, tree name, bool ¤t_p);
void set_global_range (tree name, const vrange &r, bool changed = true);
range_query &const_query () { return m_globals; }
void propagate_updated_value (tree name, basic_block bb);
void register_inferred_value (const vrange &r, tree name, basic_block bb);
void apply_inferred_ranges (gimple *s);
gori_compute m_gori;
infer_range_manager m_exit;
void dump_bb (FILE *f, basic_block bb);
virtual void dump (FILE *f) override;
private:
ssa_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);
enum rfd_mode
{
RFD_NONE, // Only look at current block cache.
RFD_READ_ONLY, // Scan DOM tree, do not write to cache.
RFD_FILL // Scan DOM tree, updating important nodes.
};
bool range_from_dom (vrange &r, tree name, basic_block bb, enum rfd_mode);
void resolve_dom (vrange &r, tree name, basic_block bb);
void range_of_def (vrange &r, tree name, basic_block bb = NULL);
void entry_range (vrange &r, tree expr, basic_block bb, enum rfd_mode);
void exit_range (vrange &r, tree expr, basic_block bb, enum rfd_mode);
bool edge_range (vrange &r, edge e, tree name, enum rfd_mode);
vec<basic_block> m_workback;
class update_list *m_update;
};
#endif // GCC_SSA_RANGE_CACHE_H
|