gori_ssa ()->exports (bb);
}
m_update = new update_list ();
+ m_stale = BITMAP_ALLOC (NULL);
}
ranger_cache::~ranger_cache ()
{
+ BITMAP_FREE (m_stale);
delete m_update;
destroy_infer_oracle ();
destroy_relation_oracle ();
return false;
}
+// Mark NAME as stale. The next query of NAME forces a recalculation.
+
+void
+ranger_cache::mark_stale (tree name)
+{
+ // Only mark it as stale if it has been processed. If it has no range
+ // it will be calculated at the next request anyway.
+ if (m_globals.has_range (name))
+ bitmap_set_bit (m_stale, SSA_NAME_VERSION (name));
+}
+
// Get the global range for NAME, and return in R. Return false if the
// global range is not set, and R will contain the legacy global value.
// CURRENT_P is set to true if the value was in cache and not stale.
m_globals.set_range (name, r);
}
+ // If NAME is out of date, clear the bit and mark as not current.
+ if (bitmap_bit_p (m_stale, SSA_NAME_VERSION (name)))
+ {
+ bitmap_clear_bit (m_stale, SSA_NAME_VERSION (name));
+ current_p = false;
+ }
+
// If the existing value was not current, mark it as always current.
if (!current_p)
m_temporal->set_always_current (name, 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);
+ void mark_stale (tree name);
void update_consumers (tree name);
range_query &const_query () { return m_globals; }
vec<basic_block> m_workback;
class update_list *m_update;
+ bitmap m_stale;
};
#endif // GCC_SSA_RANGE_CACHE_H
}
}
+// Indicate NAME should have its range recalculated next time it is used.
+
+void
+gimple_ranger::update_range_info (tree name)
+{
+ m_cache.mark_stale (name);
+}
+
// This is called to update ranger's concept of a global value for NAME
// with range R by an outside entity.
value_range current (TREE_TYPE (name));
m_cache.get_global_range (current, name);
if (current.intersect (r))
- m_cache.set_global_range (name, current, true);
+ {
+ m_cache.set_global_range (name, current, true);
+ m_cache.mark_stale (name);
+ }
}
// This routine will export whatever global ranges are known to GCC
virtual bool range_on_edge (vrange &r, edge e, tree name) override;
virtual bool range_on_entry (vrange &r, basic_block bb, tree name) override;
virtual bool range_on_exit (vrange &r, basic_block bb, tree name) override;
+ virtual void update_range_info (tree) override;
virtual void update_range_info (tree, const vrange &) override;
void export_global_ranges ();
virtual void dump (FILE *f) override;
#include "tree-ssa-alias.h"
#include "gimple-expr.h"
+#include "bitmap.h"
+#include "value-range.h"
+#include "value-query.h"
typedef gimple *gimple_seq_node;
gimple_set_modified (gimple *s, bool modifiedp)
{
if (gimple_has_ops (s))
- s->modified = (unsigned) modifiedp;
+ {
+ s->modified = (unsigned) modifiedp;
+ // Mark the LHS as out of date with the current range query.
+ if (modifiedp)
+ {
+ tree def = gimple_get_lhs (s);
+ if (def && TREE_CODE (def) == SSA_NAME)
+ get_range_query (cfun)->update_range_info (def);
+ }
+ }
}
return false;
}
+// Default for updating range info is to do nothing.
+void
+range_query::update_range_info (tree)
+{
+}
+
// Default for updating range info is to do nothing.
void
range_query::update_range_info (tree, const vrange &)
virtual bool range_on_entry (vrange &r, basic_block bb, tree expr);
virtual bool range_on_exit (vrange &r, basic_block bb, tree expr);
+ // Indicate that NAME should be considered for a range update.
+ virtual void update_range_info (tree name);
+ // Provide a specific range update to NAME.
virtual void update_range_info (tree name, const vrange &r);
inline class relation_oracle &relation () const { return *m_relation; }