Skip to content

Commit f59007d

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 9d2ca43 commit f59007d

File tree

5 files changed

+28
-12
lines changed

5 files changed

+28
-12
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_dead.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ void goto_symext::symex_dead(statet &state)
3636
// instance can no longer appear.
3737
if(state.value_set.values.has_key(l1_identifier))
3838
state.value_set.values.erase(l1_identifier);
39-
state.propagation.erase(l1_identifier);
39+
if(state.propagation.has_key(l1_identifier))
40+
state.propagation.erase(l1_identifier);
4041
// Remove from the local L2 renaming map; this means any reads from the dead
4142
// identifier will use generation 0 (e.g. x!N@M#0, where N and M are
4243
// 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)