perf(library/type_context): add caching for type_context::infer

This commit is contained in:
Leonardo de Moura 2016-02-02 15:17:18 -08:00
parent bd52e58294
commit bc86e9f179
5 changed files with 41 additions and 13 deletions

View file

@ -264,11 +264,11 @@ class blastenv {
return m_benv.m_curr_state.mk_metavar(type); return m_benv.m_curr_state.mk_metavar(type);
} }
virtual void push() override { virtual void push_core() override {
m_stack.push_back(m_benv.m_curr_state.save_assignment()); m_stack.push_back(m_benv.m_curr_state.save_assignment());
} }
virtual void pop() override { virtual void pop_core() override {
m_benv.m_curr_state.restore_assignment(m_stack.back()); m_benv.m_curr_state.restore_assignment(m_stack.back());
m_stack.pop_back(); m_stack.pop_back();
} }

View file

@ -35,6 +35,7 @@ void tmp_type_context::clear() {
m_eassignment.clear(); m_eassignment.clear();
m_trail.clear(); m_trail.clear();
m_scopes.clear(); m_scopes.clear();
clear_infer_cache();
} }
void tmp_type_context::set_next_uvar_idx(unsigned next_idx) { void tmp_type_context::set_next_uvar_idx(unsigned next_idx) {
@ -111,7 +112,7 @@ expr tmp_type_context::mk_mvar(expr const & type) {
return mk_idx_metavar(idx, type); return mk_idx_metavar(idx, type);
} }
void tmp_type_context::push() { void tmp_type_context::push_core() {
m_scopes.push_back(scope()); m_scopes.push_back(scope());
scope & s = m_scopes.back(); scope & s = m_scopes.back();
s.m_uassignment_sz = m_uassignment.size(); s.m_uassignment_sz = m_uassignment.size();
@ -119,7 +120,7 @@ void tmp_type_context::push() {
s.m_trail_sz = m_trail.size(); s.m_trail_sz = m_trail.size();
} }
void tmp_type_context::pop() { void tmp_type_context::pop_core() {
lean_assert(!m_scopes.empty()); lean_assert(!m_scopes.empty());
scope const & s = m_scopes.back(); scope const & s = m_scopes.back();
unsigned old_sz = s.m_trail_sz; unsigned old_sz = s.m_trail_sz;

View file

@ -77,8 +77,8 @@ public:
virtual level mk_uvar(); virtual level mk_uvar();
virtual expr mk_mvar(expr const &); virtual expr mk_mvar(expr const &);
virtual void push(); virtual void push_core();
virtual void pop(); virtual void pop_core();
virtual unsigned get_num_check_points() const; virtual unsigned get_num_check_points() const;
virtual void commit(); virtual void commit();

View file

@ -124,6 +124,16 @@ type_context::~type_context() {
delete m_local_gen; delete m_local_gen;
} }
void type_context::push() {
m_infer_cache.push();
push_core();
}
void type_context::pop() {
pop_core();
m_infer_cache.pop();
}
expr type_context::mk_internal_local(name const & n, expr const & type, binder_info const & bi) { expr type_context::mk_internal_local(name const & n, expr const & type, binder_info const & bi) {
return mk_local(m_ngen.next(), n, type, bi); return mk_local(m_ngen.next(), n, type, bi);
} }
@ -1187,7 +1197,9 @@ expr type_context::infer(expr const & e) {
lean_assert(!is_var(e)); lean_assert(!is_var(e));
lean_assert(closed(e)); lean_assert(closed(e));
check_system("infer_type"); check_system("infer_type");
auto it = m_infer_cache.find(e);
if (it != m_infer_cache.end())
return it->second;
expr r; expr r;
switch (e.kind()) { switch (e.kind()) {
case expr_kind::Local: case expr_kind::Local:
@ -1217,13 +1229,18 @@ expr type_context::infer(expr const & e) {
r = infer_app(e); r = infer_app(e);
break; break;
} }
// TODO(Leo): cache results if we have performance problems m_infer_cache.insert(mk_pair(e, r));
return r; return r;
} }
void type_context::clear_cache() { void type_context::clear_cache() {
m_ci_cache.clear(); m_ci_cache.clear();
m_ss_cache.clear(); m_ss_cache.clear();
clear_infer_cache();
}
void type_context::clear_infer_cache() {
m_infer_cache.clear();
} }
/** \brief If the constant \c e is a class, return its name */ /** \brief If the constant \c e is a class, return its name */

View file

@ -5,8 +5,10 @@ Released under Apache 2.0 license as described in the file LICENSE.
Author: Leonardo de Moura Author: Leonardo de Moura
*/ */
#pragma once #pragma once
#include <functional>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include "util/scoped_map.h"
#include "kernel/environment.h" #include "kernel/environment.h"
#include "library/io_state.h" #include "library/io_state.h"
#include "library/io_state_stream.h" #include "library/io_state_stream.h"
@ -184,6 +186,9 @@ class type_context {
We use it when inferring types and we want to be sure a type is Pi-type. */ We use it when inferring types and we want to be sure a type is Pi-type. */
bool m_relax_is_opaque; bool m_relax_is_opaque;
typedef scoped_map<expr, expr, expr_hash, std::equal_to<expr>> infer_cache;
infer_cache m_infer_cache;
bool is_opaque(declaration const & d) const; bool is_opaque(declaration const & d) const;
optional<expr> reduce_projection(expr const & e); optional<expr> reduce_projection(expr const & e);
optional<expr> norm_ext(expr const & e); optional<expr> norm_ext(expr const & e);
@ -430,9 +435,9 @@ public:
virtual expr mk_mvar(expr const &) = 0; virtual expr mk_mvar(expr const &) = 0;
/** \brief Save the current assignment and metavariable declarations */ /** \brief Save the current assignment and metavariable declarations */
virtual void push() = 0; virtual void push_core() = 0;
/** \brief Retore assignment (inverse for push) */ /** \brief Retore assignment (inverse for push) */
virtual void pop() = 0; virtual void pop_core() = 0;
/** \brief Return the number of checkpoints created using \c push and not popped yet. */ /** \brief Return the number of checkpoints created using \c push and not popped yet. */
virtual unsigned get_num_check_points() const = 0; virtual unsigned get_num_check_points() const = 0;
/** \brief Keep the changes since last push */ /** \brief Keep the changes since last push */
@ -453,6 +458,9 @@ public:
bool has_assigned_uvar(levels const & ls) const; bool has_assigned_uvar(levels const & ls) const;
bool has_assigned_uvar_mvar(expr const & e) const; bool has_assigned_uvar_mvar(expr const & e) const;
void push();
void pop();
/** \brief Expand macro using extension context */ /** \brief Expand macro using extension context */
optional<expr> expand_macro(expr const & m); optional<expr> expand_macro(expr const & m);
@ -524,8 +532,10 @@ public:
/** \brief Similar to \c force_assign but sets m_relax_is_opaque */ /** \brief Similar to \c force_assign but sets m_relax_is_opaque */
bool relaxed_force_assign(expr const & ma, expr const & v); bool relaxed_force_assign(expr const & ma, expr const & v);
/** \brief Clear internal caches used to speedup computation */ /** \brief Clear all internal caches used to speedup computation */
void clear_cache(); void clear_cache();
/** \brief Clear internal type inference cache used to speedup computation */
void clear_infer_cache();
/** \brief Update configuration options. /** \brief Update configuration options.
Return true iff the new options do not change the behavior of the object. Return true iff the new options do not change the behavior of the object.
@ -604,8 +614,8 @@ public:
virtual expr mk_mvar(expr const &); virtual expr mk_mvar(expr const &);
virtual expr infer_local(expr const & e) const { return mlocal_type(e); } virtual expr infer_local(expr const & e) const { return mlocal_type(e); }
virtual expr infer_metavar(expr const & e) const { return mlocal_type(e); } virtual expr infer_metavar(expr const & e) const { return mlocal_type(e); }
virtual void push() { m_trail.push_back(m_assignment); } virtual void push_core() { m_trail.push_back(m_assignment); }
virtual void pop() { lean_assert(!m_trail.empty()); m_assignment = m_trail.back(); m_trail.pop_back(); } virtual void pop_core() { lean_assert(!m_trail.empty()); m_assignment = m_trail.back(); m_trail.pop_back(); }
virtual unsigned get_num_check_points() const { return m_trail.size(); } virtual unsigned get_num_check_points() const { return m_trail.size(); }
virtual void commit() { lean_assert(!m_trail.empty()); m_trail.pop_back(); } virtual void commit() { lean_assert(!m_trail.empty()); m_trail.pop_back(); }
virtual optional<expr> mk_subsingleton_instance(expr const & type); virtual optional<expr> mk_subsingleton_instance(expr const & type);