Skip to content

Commit bf818c5

Browse files
danpoeDaniel Kroening
authored and
Daniel Kroening
committed
Use the sharing map for the renaming level maps
1 parent 5ee3271 commit bf818c5

9 files changed

+140
-112
lines changed

src/goto-symex/auto_objects.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,9 +90,8 @@ void goto_symext::trigger_auto_object(const exprt &expr, statet &state)
9090
if(has_prefix(id2string(symbol.base_name), "auto_object"))
9191
{
9292
// done already?
93-
if(
94-
state.get_level2().current_names.find(ssa_expr.get_identifier()) ==
95-
state.get_level2().current_names.end())
93+
if(!state.get_level2().current_names.has_key(
94+
ssa_expr.get_identifier()))
9695
{
9796
initialize_auto_object(e, state);
9897
}

src/goto-symex/goto_state.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,22 @@ std::size_t goto_statet::increase_generation(
3131
const ssa_exprt &lhs,
3232
std::function<std::size_t(const irep_idt &)> fresh_l2_name_provider)
3333
{
34-
auto current_emplace_res =
35-
level2.current_names.emplace(l1_identifier, std::make_pair(lhs, 0));
34+
std::size_t n = fresh_l2_name_provider(l1_identifier);
3635

37-
current_emplace_res.first->second.second =
38-
fresh_l2_name_provider(l1_identifier);
36+
const auto r_opt = level2.current_names.find(l1_identifier);
3937

40-
return current_emplace_res.first->second.second;
38+
if(!r_opt)
39+
{
40+
level2.current_names.insert(l1_identifier, std::make_pair(lhs, n));
41+
}
42+
else
43+
{
44+
std::pair<ssa_exprt, unsigned> copy = r_opt->get();
45+
copy.second = n;
46+
level2.current_names.replace(l1_identifier, std::move(copy));
47+
}
48+
49+
return n;
4150
}
4251

4352
/// Given a condition that must hold on this path, propagate as much knowledge

src/goto-symex/goto_symex_state.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -795,16 +795,21 @@ ssa_exprt goto_symex_statet::add_object(
795795
const irep_idt l0_name = ssa.get_identifier();
796796
const std::size_t l1_index = index_generator(l0_name);
797797

798-
// save old L1 name, if any
799-
auto existing_or_new_entry = level1.current_names.emplace(
800-
std::piecewise_construct,
801-
std::forward_as_tuple(l0_name),
802-
std::forward_as_tuple(ssa, l1_index));
798+
const auto r_opt = level1.current_names.find(l0_name);
803799

804-
if(!existing_or_new_entry.second)
800+
if(!r_opt)
805801
{
806-
frame.old_level1.emplace(l0_name, existing_or_new_entry.first->second);
807-
existing_or_new_entry.first->second = std::make_pair(ssa, l1_index);
802+
level1.current_names.insert(l0_name, std::make_pair(ssa, l1_index));
803+
}
804+
else
805+
{
806+
// save old L1 name
807+
if(!frame.old_level1.has_key(l0_name))
808+
{
809+
frame.old_level1.insert(l0_name, r_opt->get());
810+
}
811+
812+
level1.current_names.replace(l0_name, std::make_pair(ssa, l1_index));
808813
}
809814

810815
ssa = rename_ssa<L1>(std::move(ssa), ns).get();

src/goto-symex/goto_symex_state.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -226,15 +226,15 @@ class goto_symex_statet final : public goto_statet
226226
}
227227

228228
/// Drops an L1 name from the local L2 map
229-
void drop_l1_name(symex_renaming_levelt::current_namest::const_iterator it)
229+
void drop_existing_l1_name(const irep_idt &l1_identifier)
230230
{
231-
level2.current_names.erase(it);
231+
level2.current_names.erase(l1_identifier);
232232
}
233233

234234
/// Drops an L1 name from the local L2 map
235235
void drop_l1_name(const irep_idt &l1_identifier)
236236
{
237-
level2.current_names.erase(l1_identifier);
237+
level2.current_names.erase_if_exists(l1_identifier);
238238
}
239239

240240
std::function<std::size_t(const irep_idt &)> get_l2_name_provider() const

src/goto-symex/renaming_level.cpp

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -55,12 +55,15 @@ operator()(renamedt<ssa_exprt, L0> l0_expr) const
5555

5656
const irep_idt l0_name = l0_expr.get().get_l1_object_identifier();
5757

58-
const auto it = current_names.find(l0_name);
59-
if(it == current_names.end())
58+
const auto r_opt = current_names.find(l0_name);
59+
60+
if(!r_opt)
61+
{
6062
return renamedt<ssa_exprt, L1>{std::move(l0_expr.value())};
63+
}
6164

6265
// rename!
63-
l0_expr.value().set_level_1(it->second.second);
66+
l0_expr.value().set_level_1(r_opt->get().second);
6467
return renamedt<ssa_exprt, L1>{std::move(l0_expr.value())};
6568
}
6669

@@ -75,18 +78,21 @@ operator()(renamedt<ssa_exprt, L1> l1_expr) const
7578

7679
void symex_level1t::restore_from(const current_namest &other)
7780
{
78-
auto it = current_names.begin();
79-
for(const auto &pair : other)
81+
current_namest::delta_viewt delta_view;
82+
other.get_delta_view(current_names, delta_view, false);
83+
84+
for(const auto &delta_item : delta_view)
8085
{
81-
while(it != current_names.end() && it->first < pair.first)
82-
++it;
83-
if(it == current_names.end() || pair.first < it->first)
84-
current_names.insert(it, pair);
85-
else if(it != current_names.end())
86+
if(!delta_item.is_in_both_maps())
87+
{
88+
current_names.insert(delta_item.k, delta_item.m);
89+
}
90+
else
8691
{
87-
PRECONDITION(it->first == pair.first);
88-
it->second = pair.second;
89-
++it;
92+
if(delta_item.m != delta_item.get_other_map_value())
93+
{
94+
current_names.replace(delta_item.k, delta_item.m);
95+
}
9096
}
9197
}
9298
}

src/goto-symex/renaming_level.h

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ Author: Romain Brenguier, [email protected]
1616
#include <unordered_set>
1717

1818
#include <util/irep.h>
19+
#include <util/sharing_map.h>
1920
#include <util/simplify_expr.h>
2021
#include <util/ssa_expr.h>
2122

@@ -42,27 +43,26 @@ struct symex_renaming_levelt
4243
symex_renaming_levelt(symex_renaming_levelt &&other) = default;
4344

4445
/// Map identifier to ssa_exprt and counter
45-
typedef std::map<irep_idt, std::pair<ssa_exprt, unsigned>> current_namest;
46+
typedef sharing_mapt<irep_idt, std::pair<ssa_exprt, unsigned>> current_namest;
4647
current_namest current_names;
4748

4849
/// Counter corresponding to an identifier
4950
unsigned current_count(const irep_idt &identifier) const
5051
{
51-
const auto it = current_names.find(identifier);
52-
return it == current_names.end() ? 0 : it->second.second;
53-
}
54-
55-
/// Increase the counter corresponding to an identifier
56-
static void increase_counter(const current_namest::iterator &it)
57-
{
58-
++it->second.second;
52+
const auto r_opt = current_names.find(identifier);
53+
return !r_opt ? 0 : r_opt->get().second;
5954
}
6055

6156
/// Add the \c ssa_exprt of current_names to vars
6257
void get_variables(std::unordered_set<ssa_exprt, irep_hash> &vars) const
6358
{
64-
for(const auto &pair : current_names)
59+
current_namest::viewt view;
60+
current_names.get_view(view);
61+
62+
for(const auto &pair : view)
63+
{
6564
vars.insert(pair.second.first);
65+
}
6666
}
6767
};
6868

src/goto-symex/symex_function_call.cpp

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -351,23 +351,30 @@ pop_frame(goto_symext::statet &state, const path_storaget &path_storage)
351351
// restore L1 renaming
352352
state.level1.restore_from(frame.old_level1);
353353

354-
// clear function-locals from L2 renaming
355-
for(auto c_it = state.get_level2().current_names.begin();
356-
c_it != state.get_level2().current_names.end();) // no ++c_it
354+
symex_renaming_levelt::current_namest::viewt view;
355+
state.get_level2().current_names.get_view(view);
356+
357+
std::vector<irep_idt> keys_to_erase;
358+
359+
for(const auto &pair : view)
357360
{
358-
const irep_idt l1_o_id=c_it->second.first.get_l1_object_identifier();
361+
const irep_idt l1_o_id = pair.second.first.get_l1_object_identifier();
362+
359363
// could use iteration over local_objects as l1_o_id is prefix
360364
if(
361365
frame.local_objects.find(l1_o_id) == frame.local_objects.end() ||
362366
(state.threads.size() > 1 &&
363-
path_storage.dirty(c_it->second.first.get_object_name())))
367+
path_storage.dirty(pair.second.first.get_object_name())))
364368
{
365-
++c_it;
366369
continue;
367370
}
368-
auto cur = c_it;
369-
++c_it;
370-
state.drop_l1_name(cur);
371+
372+
keys_to_erase.push_back(pair.first);
373+
}
374+
375+
for(const irep_idt &key : keys_to_erase)
376+
{
377+
state.drop_existing_l1_name(key);
371378
}
372379
}
373380

src/goto-symex/symex_goto.cpp

Lines changed: 52 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -414,39 +414,6 @@ void goto_symext::merge_goto(
414414
}
415415
}
416416

417-
/// Applies f to `(k, ssa, i, j)` if the first map maps k to (ssa, i) and
418-
/// the second to (ssa', j). If the first map has an entry for k but not the
419-
/// second one then j is 0, and when the first map has no entry for k then i = 0
420-
static void for_each2(
421-
const std::map<irep_idt, std::pair<ssa_exprt, unsigned>> &first_map,
422-
const std::map<irep_idt, std::pair<ssa_exprt, unsigned>> &second_map,
423-
const std::function<void(const ssa_exprt &, unsigned, unsigned)> &f)
424-
{
425-
auto second_it = second_map.begin();
426-
for(const auto &first_pair : first_map)
427-
{
428-
while(second_it != second_map.end() && second_it->first < first_pair.first)
429-
{
430-
f(second_it->second.first, 0, second_it->second.second);
431-
++second_it;
432-
}
433-
const ssa_exprt &ssa = first_pair.second.first;
434-
const unsigned count = first_pair.second.second;
435-
if(second_it != second_map.end() && second_it->first == first_pair.first)
436-
{
437-
f(ssa, count, second_it->second.second);
438-
++second_it;
439-
}
440-
else
441-
f(ssa, count, 0);
442-
}
443-
while(second_it != second_map.end())
444-
{
445-
f(second_it->second.first, 0, second_it->second.second);
446-
++second_it;
447-
}
448-
}
449-
450417
/// Helper function for \c phi_function which merges the names of an identifier
451418
/// for two different states.
452419
/// \param goto_state: first state
@@ -596,23 +563,58 @@ void goto_symext::phi_function(
596563
// this gets the diff between the guards
597564
diff_guard -= dest_state.guard;
598565

599-
for_each2(
600-
goto_state.get_level2().current_names,
601-
dest_state.get_level2().current_names,
602-
[&](const ssa_exprt &ssa, unsigned goto_count, unsigned dest_count) {
603-
merge_names(
604-
goto_state,
605-
dest_state,
606-
ns,
607-
diff_guard,
608-
log,
609-
symex_config.simplify_opt,
610-
target,
611-
path_storage.dirty,
612-
ssa,
613-
goto_count,
614-
dest_count);
615-
});
566+
symex_renaming_levelt::current_namest::delta_viewt delta_view;
567+
goto_state.get_level2().current_names.get_delta_view(
568+
dest_state.get_level2().current_names, delta_view, false);
569+
570+
for(const auto &delta_item : delta_view)
571+
{
572+
const ssa_exprt &ssa = delta_item.m.first;
573+
unsigned goto_count = delta_item.m.second;
574+
unsigned dest_count = !delta_item.is_in_both_maps()
575+
? 0
576+
: delta_item.get_other_map_value().second;
577+
578+
merge_names(
579+
goto_state,
580+
dest_state,
581+
ns,
582+
diff_guard,
583+
log,
584+
symex_config.simplify_opt,
585+
target,
586+
path_storage.dirty,
587+
ssa,
588+
goto_count,
589+
dest_count);
590+
}
591+
592+
delta_view.clear();
593+
dest_state.get_level2().current_names.get_delta_view(
594+
goto_state.get_level2().current_names, delta_view, false);
595+
596+
for(const auto &delta_item : delta_view)
597+
{
598+
if(delta_item.is_in_both_maps())
599+
continue;
600+
601+
const ssa_exprt &ssa = delta_item.m.first;
602+
unsigned goto_count = 0;
603+
unsigned dest_count = delta_item.m.second;
604+
605+
merge_names(
606+
goto_state,
607+
dest_state,
608+
ns,
609+
diff_guard,
610+
log,
611+
symex_config.simplify_opt,
612+
target,
613+
path_storage.dirty,
614+
ssa,
615+
goto_count,
616+
dest_count);
617+
}
616618
}
617619

618620
void goto_symext::loop_bound_exceeded(

src/goto-symex/symex_start_thread.cpp

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,19 @@ void goto_symext::symex_start_thread(statet &state)
5252
// create a copy of the local variables for the new thread
5353
framet &frame = state.call_stack().top();
5454

55-
for(auto c_it = state.get_level2().current_names.begin();
56-
c_it != state.get_level2().current_names.end();
57-
++c_it)
55+
symex_renaming_levelt::current_namest::viewt view;
56+
state.get_level2().current_names.get_view(view);
57+
58+
for(const auto &pair : view)
5859
{
59-
const irep_idt l1_o_id=c_it->second.first.get_l1_object_identifier();
60+
const irep_idt l1_o_id = pair.second.first.get_l1_object_identifier();
61+
6062
// could use iteration over local_objects as l1_o_id is prefix
6163
if(frame.local_objects.find(l1_o_id)==frame.local_objects.end())
6264
continue;
6365

6466
// get original name
65-
ssa_exprt lhs(c_it->second.first.get_original_expr());
67+
ssa_exprt lhs(pair.second.first.get_original_expr());
6668

6769
// get L0 name for current thread
6870
lhs.set_level_0(t);
@@ -71,18 +73,16 @@ void goto_symext::symex_start_thread(statet &state)
7173
CHECK_RETURN(l1_index == 0);
7274

7375
// set up L1 name
74-
auto emplace_result = state.level1.current_names.emplace(
75-
std::piecewise_construct,
76-
std::forward_as_tuple(lhs.get_l1_object_identifier()),
77-
std::forward_as_tuple(lhs, 0));
78-
CHECK_RETURN(emplace_result.second);
76+
state.level1.current_names.insert(
77+
lhs.get_l1_object_identifier(), std::make_pair(lhs, 0));
78+
7979
const ssa_exprt lhs_l1 = state.rename_ssa<L1>(std::move(lhs), ns).get();
8080
const irep_idt l1_name = lhs_l1.get_l1_object_identifier();
8181
// store it
8282
new_thread.call_stack.back().local_objects.insert(l1_name);
8383

8484
// make copy
85-
ssa_exprt rhs=c_it->second.first;
85+
ssa_exprt rhs = pair.second.first;
8686

8787
exprt::operandst lhs_conditions;
8888
const bool record_events=state.record_events;

0 commit comments

Comments
 (0)