Skip to content

Commit 32dc6d6

Browse files
committed
Use sharing_mapt to store propagation map
goto-symex copies a state, which contains a propagation map, at each branching point. The paths originating at that branch point typically share most of the constants being propagated. Thus the copy is unnecessarily expensive, and so is the merge at the next join point, which will also result in one of the propagation maps to be destroyed. With sharing_mapt, the copy has constant cost, and the cost of destruction only depends on the size of the delta.
1 parent 5a2a09e commit 32dc6d6

File tree

6 files changed

+29
-15
lines changed

6 files changed

+29
-15
lines changed

src/goto-symex/goto_state.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ Author: Romain Brenguier, [email protected]
1717
/// because there aren't any current callers.
1818
void goto_statet::output_propagation_map(std::ostream &out)
1919
{
20-
for(const auto &name_value : propagation)
20+
sharing_mapt<irep_idt, exprt>::viewt view;
21+
propagation.get_view(view);
22+
23+
for(const auto &name_value : view)
2124
{
2225
out << name_value.first << " <- " << format(name_value.second) << "\n";
2326
}
@@ -86,7 +89,11 @@ void goto_statet::apply_condition(
8689
increase_generation(
8790
l1_identifier, l1_lhs, previous_state.get_l2_name_provider());
8891

89-
propagation[l1_identifier] = rhs;
92+
const auto propagation_entry = propagation.find(l1_identifier);
93+
if(!propagation_entry.has_value())
94+
propagation.insert(l1_identifier, rhs);
95+
else if(propagation_entry->get() != rhs)
96+
propagation.replace(l1_identifier, rhs);
9097

9198
value_set.assign(l1_lhs, rhs, ns, true, false);
9299
}

src/goto-symex/goto_state.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Author: Romain Brenguier, [email protected]
1212
#ifndef CPROVER_GOTO_SYMEX_GOTO_STATE_H
1313
#define CPROVER_GOTO_SYMEX_GOTO_STATE_H
1414

15+
#include <util/sharing_map.h>
16+
1517
#include <analyses/guard.h>
1618
#include <analyses/local_safe_pointers.h>
1719
#include <pointer-analysis/value_set.h>
@@ -54,7 +56,7 @@ class goto_statet
5456
// "constants" can include symbols, but only in the context of an address-of
5557
// op (i.e. &x can be propagated), and an address-taken thing should only be
5658
// L1.
57-
std::map<irep_idt, exprt> propagation;
59+
sharing_mapt<irep_idt, exprt> propagation;
5860

5961
void output_propagation_map(std::ostream &);
6062

src/goto-symex/goto_symex_state.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -201,8 +201,14 @@ void goto_symex_statet::assignment(
201201
// for value propagation -- the RHS is L2
202202

203203
if(!is_shared && record_value && goto_symex_is_constantt()(rhs))
204-
propagation[l1_identifier] = rhs;
205-
else
204+
{
205+
const auto propagation_entry = propagation.find(l1_identifier);
206+
if(!propagation_entry.has_value())
207+
propagation.insert(l1_identifier, rhs);
208+
else if(propagation_entry->get() != rhs)
209+
propagation.replace(l1_identifier, rhs);
210+
}
211+
else if(propagation.has_key(l1_identifier))
206212
propagation.erase(l1_identifier);
207213

208214
{
@@ -289,8 +295,8 @@ goto_symex_statet::rename(exprt expr, const namespacet &ns)
289295
// L1 identifiers are used for propagation!
290296
auto p_it = propagation.find(ssa.get_identifier());
291297

292-
if(p_it != propagation.end())
293-
expr=p_it->second; // already L2
298+
if(p_it.has_value())
299+
expr = *p_it; // already L2
294300
else
295301
ssa = set_indices<L2>(std::move(ssa), ns).get();
296302
}

src/goto-symex/symex_assign.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ void goto_symext::symex_assign_symbol(
502502
// Erase the composite symbol from our working state. Note that we need to
503503
// have it in the propagation table and the value set while doing the field
504504
// assignments, thus we cannot skip putting it in there above.
505-
state.propagation.erase(l1_lhs.get_identifier());
505+
state.propagation.erase_if_exists(l1_lhs.get_identifier());
506506
state.value_set.erase_symbol(l1_lhs, ns);
507507
}
508508

src/goto-symex/symex_dead.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,8 @@ void goto_symext::symex_dead(statet &state)
3434
// information is not local to a path, but removing it from the propagation
3535
// map and value-set is safe as 1) it is local to a path and 2) this
3636
// instance can no longer appear.
37-
if(state.value_set.values.has_key(l1_identifier))
38-
state.value_set.values.erase(l1_identifier);
39-
state.propagation.erase(l1_identifier);
37+
state.value_set.values.erase_if_exists(l1_identifier);
38+
state.propagation.erase_if_exists(l1_identifier);
4039
// Remove from the local L2 renaming map; this means any reads from the dead
4140
// identifier will use generation 0 (e.g. x!N@M#0, where N and M are
4241
// positive integers), which is never defined by any write, and will be

src/goto-symex/symex_goto.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -522,17 +522,17 @@ static void merge_names(
522522
{
523523
const auto p_it = goto_state.propagation.find(l1_identifier);
524524

525-
if(p_it != goto_state.propagation.end())
526-
goto_state_rhs = p_it->second;
525+
if(p_it.has_value())
526+
goto_state_rhs = *p_it;
527527
else
528528
to_ssa_expr(goto_state_rhs).set_level_2(goto_count);
529529
}
530530

531531
{
532532
const auto p_it = dest_state.propagation.find(l1_identifier);
533533

534-
if(p_it != dest_state.propagation.end())
535-
dest_state_rhs = p_it->second;
534+
if(p_it.has_value())
535+
dest_state_rhs = *p_it;
536536
else
537537
to_ssa_expr(dest_state_rhs).set_level_2(dest_count);
538538
}

0 commit comments

Comments
 (0)