Skip to content

Commit

Permalink
Add a cache for eval in string dependences
Browse files Browse the repository at this point in the history
This improves the performances since the model for one string can depend
on the model for two other strings, which model may have already been
computed.
The cache must be cleared every time the model changes.
  • Loading branch information
romainbrenguier committed Mar 14, 2018
1 parent 095d57b commit fb676d5
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 4 deletions.
2 changes: 2 additions & 0 deletions src/solvers/refinement/string_refinement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,7 @@ decision_proceduret::resultt string_refinementt::dec_solve()

// Initial try without index set
const auto get = [this](const exprt &expr) { return this->get(expr); };
dependencies.clean_cache();
const decision_proceduret::resultt res=supert::dec_solve();
if(res==resultt::D_SATISFIABLE)
{
Expand Down Expand Up @@ -804,6 +805,7 @@ decision_proceduret::resultt string_refinementt::dec_solve()

while((loop_bound_--)>0)
{
dependencies.clean_cache();
const decision_proceduret::resultt res=supert::dec_solve();

if(res==resultt::D_SATISFIABLE)
Expand Down
27 changes: 23 additions & 4 deletions src/solvers/refinement/string_refinement_util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,17 +537,36 @@ optionalt<exprt> string_dependenciest::eval(
const array_string_exprt &s,
const std::function<exprt(const exprt &)> &get_value) const
{
const auto node = node_at(s);
if(node && node->dependencies.size() == 1)
const auto &it = node_index_pool.find(s);
if(it == node_index_pool.end())
return {};

if(eval_string_cache[it->second])
return eval_string_cache[it->second];

const auto node = string_nodes[it->second];

if(node.dependencies.size() == 1)
{
const auto &f = get_builtin_function(node->dependencies[0]);
const auto &f = get_builtin_function(node.dependencies[0]);
const auto result = f.string_result();
if(result && *result == s)
return f.eval(get_value);
{
const auto value_opt = f.eval(get_value);
eval_string_cache[it->second] = value_opt;
return value_opt;
}
}
return {};
}

void string_dependenciest::clean_cache()
{
eval_string_cache.resize(string_nodes.size());
for(auto &e : eval_string_cache)
e.reset();
}

bool add_node(
string_dependenciest &dependencies,
const equal_exprt &equation,
Expand Down
7 changes: 7 additions & 0 deletions src/solvers/refinement/string_refinement_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -339,10 +339,15 @@ class string_dependenciest

/// Attempt to evaluate the given string from the dependencies and valuation
/// of strings on which it depends
/// Warning: eval uses a cache which must be cleaned everytime the valuations
/// given by get_value can change.
optionalt<exprt> eval(
const array_string_exprt &s,
const std::function<exprt(const exprt &)> &get_value) const;

/// Clean the cache used by `eval`
void clean_cache();

void output_dot(std::ostream &stream) const;

private:
Expand All @@ -352,6 +357,8 @@ class string_dependenciest
/// Set of nodes representing strings
std::vector<string_nodet> string_nodes;

mutable std::vector<optionalt<exprt>> eval_string_cache;

/// Nodes describing dependencies of a string: values of the map correspond
/// to indexes in the vector `string_nodes`.
std::unordered_map<array_string_exprt, std::size_t, irep_hash>
Expand Down

0 comments on commit fb676d5

Please sign in to comment.