Skip to content

Commit 7dadeee

Browse files
authored
Merge pull request #4199 from JohnDumbell/jd/enhancement/symex_state_moving
Move instead of merge symex L2 renaming map when possible
2 parents f9f0733 + 939a169 commit 7dadeee

17 files changed

+184
-64
lines changed

src/goto-instrument/accelerate/scratch_program.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ bool scratch_programt::check_sat(bool do_slice, guard_managert &guard_manager)
3737

3838
symex_state = util_make_unique<goto_symex_statet>(
3939
symex_targett::sourcet(goto_functionst::entry_point(), *this),
40-
guard_manager);
40+
guard_manager,
41+
[this](const irep_idt &id) {
42+
return path_storage.get_unique_l2_index(id);
43+
});
44+
4145
symex.symex_with_state(
4246
*symex_state,
4347
[this](const irep_idt &key) -> const goto_functionst::goto_functiont & {

src/goto-symex/auto_objects.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,9 @@ void goto_symext::trigger_auto_object(const exprt &expr, statet &state)
9191
if(has_prefix(id2string(symbol.base_name), "auto_object"))
9292
{
9393
// done already?
94-
if(state.level2.current_names.find(ssa_expr.get_identifier())==
95-
state.level2.current_names.end())
94+
if(
95+
state.get_level2().current_names.find(ssa_expr.get_identifier()) ==
96+
state.get_level2().current_names.end())
9697
{
9798
initialize_auto_object(expr, state);
9899
}

src/goto-symex/goto_state.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,15 @@ class goto_statet
2828
/// Distance from entry
2929
unsigned depth = 0;
3030

31+
protected:
3132
symex_level2t level2;
3233

34+
public:
35+
const symex_level2t &get_level2() const
36+
{
37+
return level2;
38+
}
39+
3340
/// Uses level 1 names, and is used to do dereferencing
3441
value_sett value_set;
3542

@@ -55,6 +62,12 @@ class goto_statet
5562
unsigned atomic_section_id = 0;
5663

5764
/// Constructors
65+
goto_statet() = default;
66+
goto_statet &operator=(const goto_statet &other) = default;
67+
goto_statet &operator=(goto_statet &&other) = default;
68+
goto_statet(const goto_statet &other) = default;
69+
goto_statet(goto_statet &&other) = default;
70+
5871
explicit goto_statet(const class goto_symex_statet &s);
5972

6073
explicit goto_statet(guard_managert &guard_manager)

src/goto-symex/goto_symex_state.cpp

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@ static void get_l1_name(exprt &expr);
3131

3232
goto_symex_statet::goto_symex_statet(
3333
const symex_targett::sourcet &_source,
34-
guard_managert &manager)
34+
guard_managert &manager,
35+
std::function<std::size_t(const irep_idt &)> fresh_l2_name_provider)
3536
: goto_statet(manager),
3637
source(_source),
3738
guard_manager(manager),
3839
symex_target(nullptr),
3940
record_events(true),
40-
dirty()
41+
dirty(),
42+
fresh_l2_name_provider(fresh_l2_name_provider)
4143
{
4244
threads.emplace_back(guard_manager);
4345
call_stack().new_frame(source);
@@ -213,9 +215,7 @@ void goto_symex_statet::assignment(
213215
#endif
214216

215217
// do the l2 renaming
216-
const auto level2_it =
217-
level2.current_names.emplace(l1_identifier, std::make_pair(lhs, 0)).first;
218-
symex_renaming_levelt::increase_counter(level2_it);
218+
increase_generation(l1_identifier, lhs);
219219
lhs = set_indices<L2>(std::move(lhs), ns).get();
220220

221221
// in case we happen to be multi-threaded, record the memory access
@@ -440,10 +440,7 @@ bool goto_symex_statet::l2_thread_read_encoding(
440440

441441
if(a_s_read.second.empty())
442442
{
443-
auto level2_it =
444-
level2.current_names.emplace(l1_identifier, std::make_pair(ssa_l1, 0))
445-
.first;
446-
symex_renaming_levelt::increase_counter(level2_it);
443+
increase_generation(l1_identifier, ssa_l1);
447444
a_s_read.first=level2.current_count(l1_identifier);
448445
}
449446
const renamedt<ssa_exprt, L2> l2_false_case = set_indices<L2>(ssa_l1, ns);
@@ -477,10 +474,6 @@ bool goto_symex_statet::l2_thread_read_encoding(
477474
return true;
478475
}
479476

480-
const auto level2_it =
481-
level2.current_names.emplace(l1_identifier, std::make_pair(ssa_l1, 0))
482-
.first;
483-
484477
// No event and no fresh index, but avoid constant propagation
485478
if(!record_events)
486479
{
@@ -489,7 +482,7 @@ bool goto_symex_statet::l2_thread_read_encoding(
489482
}
490483

491484
// produce a fresh L2 name
492-
symex_renaming_levelt::increase_counter(level2_it);
485+
increase_generation(l1_identifier, ssa_l1);
493486
expr = set_indices<L2>(std::move(ssa_l1), ns).get();
494487

495488
// and record that
@@ -500,6 +493,35 @@ bool goto_symex_statet::l2_thread_read_encoding(
500493
return true;
501494
}
502495

496+
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
497+
/// latest generation on this path.
498+
/// \return the newly allocated generation number
499+
std::size_t goto_symex_statet::increase_generation(
500+
const irep_idt l1_identifier,
501+
const ssa_exprt &lhs)
502+
{
503+
auto current_emplace_res =
504+
level2.current_names.emplace(l1_identifier, std::make_pair(lhs, 0));
505+
506+
current_emplace_res.first->second.second =
507+
fresh_l2_name_provider(l1_identifier);
508+
509+
return current_emplace_res.first->second.second;
510+
}
511+
512+
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
513+
/// latest generation on this path. Does nothing if there isn't an expression
514+
/// keyed by the l1 identifier.
515+
void goto_symex_statet::increase_generation_if_exists(const irep_idt identifier)
516+
{
517+
// If we can't find the name in the local scope, this is a no-op.
518+
auto current_names_iter = level2.current_names.find(identifier);
519+
if(current_names_iter == level2.current_names.end())
520+
return;
521+
522+
current_names_iter->second.second = fresh_l2_name_provider(identifier);
523+
}
524+
503525
/// thread encoding
504526
bool goto_symex_statet::l2_thread_write_encoding(
505527
const ssa_exprt &expr,

src/goto-symex/goto_symex_state.h

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ Author: Daniel Kroening, [email protected]
4242
class goto_symex_statet final : public goto_statet
4343
{
4444
public:
45-
goto_symex_statet(const symex_targett::sourcet &, guard_managert &manager);
45+
goto_symex_statet(
46+
const symex_targett::sourcet &,
47+
guard_managert &manager,
48+
std::function<std::size_t(const irep_idt &)> fresh_l2_name_provider);
4649
~goto_symex_statet();
4750

4851
/// \brief Fake "copy constructor" that initializes the `symex_target` member
@@ -202,7 +205,24 @@ class goto_symex_statet final : public goto_statet
202205
unsigned total_vccs = 0;
203206
unsigned remaining_vccs = 0;
204207

208+
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
209+
// latest generation on this path.
210+
std::size_t
211+
increase_generation(const irep_idt l1_identifier, const ssa_exprt &lhs);
212+
213+
/// Increases the generation of the L1 identifier. Does nothing if there
214+
/// isn't an expression keyed by it.
215+
void increase_generation_if_exists(const irep_idt identifier);
216+
217+
/// Drops an L1 name from the local L2 map
218+
void drop_l1_name(symex_renaming_levelt::current_namest::const_iterator it)
219+
{
220+
level2.current_names.erase(it);
221+
}
222+
205223
private:
224+
std::function<std::size_t(const irep_idt &)> fresh_l2_name_provider;
225+
206226
/// \brief Dangerous, do not use
207227
///
208228
/// Copying a state S1 to S2 risks S2 pointing to a deallocated

src/goto-symex/path_storage.h

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -98,15 +98,16 @@ class path_storaget
9898
/// error-handling paths.
9999
std::unordered_map<irep_idt, local_safe_pointerst> safe_pointers;
100100

101-
/// Provide a unique index for a given \p id, starting from \p minimum_index.
102-
std::size_t get_unique_index(const irep_idt &id, std::size_t minimum_index)
101+
/// Provide a unique L1 index for a given \p id, starting from
102+
/// \p minimum_index.
103+
std::size_t get_unique_l1_index(const irep_idt &id, std::size_t minimum_index)
103104
{
104-
auto entry = unique_index_map.emplace(id, minimum_index);
105-
106-
if(!entry.second)
107-
entry.first->second = std::max(entry.first->second + 1, minimum_index);
105+
return get_unique_index(l1_indices, id, minimum_index);
106+
}
108107

109-
return entry.first->second;
108+
std::size_t get_unique_l2_index(const irep_idt &id)
109+
{
110+
return get_unique_index(l2_indices, id, 1);
110111
}
111112

112113
private:
@@ -115,8 +116,24 @@ class path_storaget
115116
virtual patht &private_peek() = 0;
116117
virtual void private_pop() = 0;
117118

119+
typedef std::unordered_map<irep_idt, std::size_t> name_index_mapt;
120+
121+
std::size_t get_unique_index(
122+
name_index_mapt &unique_index_map,
123+
const irep_idt &id,
124+
std::size_t minimum_index)
125+
{
126+
auto entry = unique_index_map.emplace(id, minimum_index);
127+
128+
if(!entry.second)
129+
entry.first->second = std::max(entry.first->second + 1, minimum_index);
130+
131+
return entry.first->second;
132+
}
133+
118134
/// Storage used by \ref get_unique_index.
119-
std::unordered_map<irep_idt, std::size_t> unique_index_map;
135+
name_index_mapt l1_indices;
136+
name_index_mapt l2_indices;
120137
};
121138

122139
/// \brief LIFO save queue: depth-first search, try to finish paths

src/goto-symex/renaming_level.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,7 @@ operator()(renamedt<ssa_exprt, L1> l1_expr) const
7373
return renamedt<ssa_exprt, L2>{std::move(l1_expr.value)};
7474
}
7575

76-
void symex_level1t::restore_from(
77-
const symex_renaming_levelt::current_namest &other)
76+
void symex_level1t::restore_from(const current_namest &other)
7877
{
7978
auto it = current_names.begin();
8079
for(const auto &pair : other)

src/goto-symex/renaming_level.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,13 @@ enum levelt
3232
/// during symex to ensure static single assignment (SSA) form.
3333
struct symex_renaming_levelt
3434
{
35+
symex_renaming_levelt() = default;
3536
virtual ~symex_renaming_levelt() = default;
37+
symex_renaming_levelt &
38+
operator=(const symex_renaming_levelt &other) = default;
39+
symex_renaming_levelt &operator=(symex_renaming_levelt &&other) = default;
40+
symex_renaming_levelt(const symex_renaming_levelt &other) = default;
41+
symex_renaming_levelt(symex_renaming_levelt &&other) = default;
3642

3743
/// Map identifier to ssa_exprt and counter
3844
typedef std::map<irep_idt, std::pair<ssa_exprt, unsigned>> current_namest;
@@ -125,6 +131,10 @@ struct symex_level2t : public symex_renaming_levelt
125131

126132
symex_level2t() = default;
127133
~symex_level2t() override = default;
134+
symex_level2t &operator=(const symex_level2t &other) = default;
135+
symex_level2t &operator=(symex_level2t &&other) = default;
136+
symex_level2t(const symex_level2t &other) = default;
137+
symex_level2t(symex_level2t &&other) = default;
128138
};
129139

130140
/// Undo all levels of renaming

src/goto-symex/symex_atomic_section.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ void goto_symext::symex_atomic_end(statet &state)
7070
for(const auto &pair : state.written_in_atomic_section)
7171
{
7272
ssa_exprt w = pair.first;
73-
w.set_level_2(state.level2.current_count(w.get_identifier()));
73+
w.set_level_2(state.get_level2().current_count(w.get_identifier()));
7474

7575
// guard is the disjunction over writes
7676
PRECONDITION(!pair.second.empty());

src/goto-symex/symex_dead.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,5 @@ void goto_symext::symex_dead(statet &state)
4545
state.propagation.erase(l1_identifier);
4646
// increment the L2 index to ensure a merge on join points will propagate the
4747
// value for branches that are still live
48-
auto level2_it = state.level2.current_names.find(l1_identifier);
49-
if(level2_it != state.level2.current_names.end())
50-
symex_renaming_levelt::increase_counter(level2_it);
48+
state.increase_generation_if_exists(l1_identifier);
5149
}

src/goto-symex/symex_decl.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
4343
ssa_exprt ssa = state.add_object(
4444
expr,
4545
[this](const irep_idt &l0_name) {
46-
return path_storage.get_unique_index(l0_name, 1);
46+
return path_storage.get_unique_l1_index(l0_name, 1);
4747
},
4848
ns);
4949
const irep_idt &l1_identifier = ssa.get_identifier();
@@ -66,10 +66,9 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
6666
}
6767

6868
// L2 renaming
69-
bool is_new =
70-
state.level2.current_names.emplace(l1_identifier, std::make_pair(ssa, 1))
71-
.second;
72-
CHECK_RETURN(is_new);
69+
std::size_t generation = state.increase_generation(l1_identifier, ssa);
70+
CHECK_RETURN(generation == 1);
71+
7372
const bool record_events=state.record_events;
7473
state.record_events=false;
7574
exprt expr_l2 = state.rename(std::move(ssa), ns);

src/goto-symex/symex_function_call.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -349,8 +349,8 @@ static void pop_frame(goto_symext::statet &state)
349349
state.level1.restore_from(frame.old_level1);
350350

351351
// clear function-locals from L2 renaming
352-
for(auto c_it = state.level2.current_names.begin();
353-
c_it != state.level2.current_names.end();) // no ++c_it
352+
for(auto c_it = state.get_level2().current_names.begin();
353+
c_it != state.get_level2().current_names.end();) // no ++c_it
354354
{
355355
const irep_idt l1_o_id=c_it->second.first.get_l1_object_identifier();
356356
// could use iteration over local_objects as l1_o_id is prefix
@@ -364,7 +364,7 @@ static void pop_frame(goto_symext::statet &state)
364364
}
365365
auto cur = c_it;
366366
++c_it;
367-
state.level2.current_names.erase(cur);
367+
state.drop_l1_name(cur);
368368
}
369369
}
370370

@@ -402,7 +402,7 @@ static void locality(
402402
(void)state.add_object(
403403
ns.lookup(param).symbol_expr(),
404404
[&path_storage, &frame_nr](const irep_idt &l0_name) {
405-
return path_storage.get_unique_index(l0_name, frame_nr);
405+
return path_storage.get_unique_l1_index(l0_name, frame_nr);
406406
},
407407
ns);
408408
}

0 commit comments

Comments
 (0)