Skip to content

Commit 441eb6c

Browse files
committed
Use sharing_mapt as container in value_sett
goto-symex copies a state, which contains a value set, at each branching point. The paths originating at that branch point typically share most of the points-to information. Thus the copy is unnecessarily expensive, and so is the merge at the next join point, which will also result in one of the value sets to be destroyed. With sharing_mapt, the copy has constant cost, merging can make use of the delta view, and the cost of destruction only depends on the size of the delta.
1 parent ba576c4 commit 441eb6c

File tree

4 files changed

+111
-141
lines changed

4 files changed

+111
-141
lines changed

src/goto-symex/symex_main.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -676,14 +676,14 @@ void goto_symext::try_filter_value_sets(
676676
}
677677
if(jump_taken_value_set && !erase_from_jump_taken_value_set.empty())
678678
{
679-
value_sett::entryt *entry = jump_taken_value_set->get_entry_for_symbol(
679+
auto entry = jump_taken_value_set->get_index_of_symbol(
680680
symbol_expr->get_identifier(), symbol_type, "", ns);
681681
jump_taken_value_set->erase_values_from_entry(
682682
*entry, erase_from_jump_taken_value_set);
683683
}
684684
if(jump_not_taken_value_set && !erase_from_jump_not_taken_value_set.empty())
685685
{
686-
value_sett::entryt *entry = jump_not_taken_value_set->get_entry_for_symbol(
686+
auto entry = jump_not_taken_value_set->get_index_of_symbol(
687687
symbol_expr->get_identifier(), symbol_type, "", ns);
688688
jump_not_taken_value_set->erase_values_from_entry(
689689
*entry, erase_from_jump_not_taken_value_set);

src/pointer-analysis/value_set.cpp

Lines changed: 79 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,17 @@ bool value_sett::field_sensitive(const irep_idt &id, const typet &type)
4848
return type.id() == ID_struct || type.id() == ID_struct_tag;
4949
}
5050

51-
value_sett::entryt *value_sett::find_entry(const irep_idt &id)
52-
{
53-
auto found = values.find(id);
54-
return found == values.end() ? nullptr : &found->second;
55-
}
56-
5751
const value_sett::entryt *value_sett::find_entry(const irep_idt &id) const
5852
{
5953
auto found = values.find(id);
60-
return found == values.end() ? nullptr : &found->second;
54+
return !found.has_value() ? nullptr : &(found->get());
6155
}
6256

63-
value_sett::entryt &value_sett::get_entry(const entryt &e, const typet &type)
57+
void value_sett::update_entry(
58+
const entryt &e,
59+
const typet &type,
60+
const object_mapt &new_values,
61+
bool add_to_sets)
6462
{
6563
irep_idt index;
6664

@@ -69,10 +67,22 @@ value_sett::entryt &value_sett::get_entry(const entryt &e, const typet &type)
6967
else
7068
index=e.identifier;
7169

72-
std::pair<valuest::iterator, bool> r =
73-
values.insert(std::pair<irep_idt, entryt>(index, e));
74-
75-
return r.first->second;
70+
auto existing_entry = values.find(index);
71+
if(existing_entry.has_value())
72+
{
73+
entryt replacement = *existing_entry;
74+
if(add_to_sets)
75+
make_union(replacement.object_map, new_values);
76+
else
77+
replacement.object_map = new_values;
78+
values.replace(index, std::move(replacement));
79+
}
80+
else
81+
{
82+
entryt new_entry = e;
83+
new_entry.object_map = new_values;
84+
values.insert(index, std::move(new_entry));
85+
}
7686
}
7787

7888
bool value_sett::insert(
@@ -103,7 +113,10 @@ void value_sett::output(
103113
const namespacet &ns,
104114
std::ostream &out) const
105115
{
106-
for(const auto &values_entry : values)
116+
valuest::viewt view;
117+
values.get_view(view);
118+
119+
for(const auto &values_entry : view)
107120
{
108121
irep_idt identifier, display_name;
109122

@@ -210,36 +223,26 @@ bool value_sett::make_union(const value_sett::valuest &new_values)
210223
{
211224
bool result=false;
212225

213-
valuest::iterator v_it=values.begin();
226+
value_sett::valuest::delta_viewt delta_view;
214227

215-
for(valuest::const_iterator
216-
it=new_values.begin();
217-
it!=new_values.end();
218-
) // no it++
228+
new_values.get_delta_view(values, delta_view, false);
229+
230+
for(const auto &delta_entry : delta_view)
219231
{
220-
if(v_it==values.end() || it->first<v_it->first)
232+
if(delta_entry.in_both)
221233
{
222-
values.insert(v_it, *it);
223-
result=true;
224-
it++;
225-
continue;
234+
entryt merged_entry = *values.find(delta_entry.k);
235+
if(make_union(merged_entry.object_map, delta_entry.m.object_map))
236+
{
237+
values.replace(delta_entry.k, std::move(merged_entry));
238+
result = true;
239+
}
226240
}
227-
else if(v_it->first<it->first)
241+
else
228242
{
229-
v_it++;
230-
continue;
243+
values.insert(delta_entry.k, delta_entry.m);
244+
result = true;
231245
}
232-
233-
assert(v_it->first==it->first);
234-
235-
entryt &e=v_it->second;
236-
const entryt &new_e=it->second;
237-
238-
if(make_union(e.object_map, new_e.object_map))
239-
result=true;
240-
241-
v_it++;
242-
it++;
243246
}
244247

245248
return result;
@@ -371,77 +374,55 @@ static std::string strip_first_field_from_suffix(
371374
return suffix.substr(field.length() + 1);
372375
}
373376

374-
template <class maybe_const_value_sett>
375-
auto value_sett::get_entry_for_symbol(
376-
maybe_const_value_sett &value_set,
377-
const irep_idt identifier,
377+
optionalt<irep_idt> value_sett::get_index_of_symbol(
378+
irep_idt identifier,
378379
const typet &type,
379380
const std::string &suffix,
380-
const namespacet &ns) ->
381-
typename std::conditional<std::is_const<maybe_const_value_sett>::value,
382-
const value_sett::entryt *,
383-
value_sett::entryt *>::type
381+
const namespacet &ns) const
384382
{
385383
if(
386384
type.id() != ID_pointer && type.id() != ID_signedbv &&
387385
type.id() != ID_unsignedbv && type.id() != ID_array &&
388386
type.id() != ID_struct && type.id() != ID_struct_tag &&
389387
type.id() != ID_union && type.id() != ID_union_tag)
390388
{
391-
return nullptr;
389+
return {};
392390
}
393391

392+
// look it up
393+
irep_idt index = id2string(identifier) + suffix;
394+
auto *entry = find_entry(index);
395+
if(entry)
396+
return std::move(index);
397+
394398
const typet &followed_type = type.id() == ID_struct_tag
395399
? ns.follow_tag(to_struct_tag_type(type))
396400
: type.id() == ID_union_tag
397401
? ns.follow_tag(to_union_tag_type(type))
398402
: type;
399403

400-
// look it up
401-
auto *entry = value_set.find_entry(id2string(identifier) + suffix);
402-
403404
// try first component name as suffix if not yet found
404-
if(
405-
!entry &&
406-
(followed_type.id() == ID_struct || followed_type.id() == ID_union))
405+
if(followed_type.id() == ID_struct || followed_type.id() == ID_union)
407406
{
408407
const struct_union_typet &struct_union_type =
409408
to_struct_union_type(followed_type);
410409

411410
const irep_idt &first_component_name =
412411
struct_union_type.components().front().get_name();
413412

414-
entry = value_set.find_entry(
415-
id2string(identifier) + "." + id2string(first_component_name) + suffix);
416-
}
417-
418-
if(!entry)
419-
{
420-
// not found? try without suffix
421-
entry = value_set.find_entry(identifier);
413+
index =
414+
id2string(identifier) + "." + id2string(first_component_name) + suffix;
415+
entry = find_entry(index);
416+
if(entry)
417+
return std::move(index);
422418
}
423419

424-
return entry;
425-
}
426-
427-
// Explicitly instantiate the two possible versions of the method above:
428-
429-
value_sett::entryt *value_sett::get_entry_for_symbol(
430-
irep_idt identifier,
431-
const typet &type,
432-
const std::string &suffix,
433-
const namespacet &ns)
434-
{
435-
return get_entry_for_symbol(*this, identifier, type, suffix, ns);
436-
}
420+
// not found? try without suffix
421+
entry = find_entry(identifier);
422+
if(entry)
423+
return std::move(identifier);
437424

438-
const value_sett::entryt *value_sett::get_entry_for_symbol(
439-
irep_idt identifier,
440-
const typet &type,
441-
const std::string &suffix,
442-
const namespacet &ns) const
443-
{
444-
return get_entry_for_symbol(*this, identifier, type, suffix, ns);
425+
return {};
445426
}
446427

447428
void value_sett::get_value_set_rec(
@@ -491,11 +472,11 @@ void value_sett::get_value_set_rec(
491472
}
492473
else if(expr.id()==ID_symbol)
493474
{
494-
const entryt *entry = get_entry_for_symbol(
475+
auto entry = get_index_of_symbol(
495476
to_symbol_expr(expr).get_identifier(), expr_type, suffix, ns);
496477

497-
if(entry)
498-
make_union(dest, entry->object_map);
478+
if(entry.has_value())
479+
make_union(dest, find_entry(*entry)->object_map);
499480
else
500481
insert(dest, exprt(ID_unknown, original_type));
501482
}
@@ -1314,12 +1295,8 @@ void value_sett::assign_rec(
13141295
{
13151296
const irep_idt &identifier=to_symbol_expr(lhs).get_identifier();
13161297

1317-
entryt &e = get_entry(entryt(identifier, suffix), lhs.type());
1318-
1319-
if(add_to_sets)
1320-
make_union(e.object_map, values_rhs);
1321-
else
1322-
e.object_map=values_rhs;
1298+
update_entry(
1299+
entryt{identifier, suffix}, lhs.type(), values_rhs, add_to_sets);
13231300
}
13241301
else if(lhs.id()==ID_dynamic_object)
13251302
{
@@ -1330,9 +1307,7 @@ void value_sett::assign_rec(
13301307
"value_set::dynamic_object"+
13311308
std::to_string(dynamic_object.get_instance());
13321309

1333-
entryt &e = get_entry(entryt(name, suffix), lhs.type());
1334-
1335-
make_union(e.object_map, values_rhs);
1310+
update_entry(entryt{name, suffix}, lhs.type(), values_rhs, true);
13361311
}
13371312
else if(lhs.id()==ID_dereference)
13381313
{
@@ -1640,12 +1615,19 @@ void value_sett::guard(
16401615
}
16411616

16421617
void value_sett::erase_values_from_entry(
1643-
entryt &entry,
1618+
const irep_idt &index,
16441619
const std::unordered_set<exprt, irep_hash> &values_to_erase)
16451620
{
1621+
if(values_to_erase.empty())
1622+
return;
1623+
1624+
auto entry = find_entry(index);
1625+
if(!entry)
1626+
return;
1627+
16461628
std::vector<object_map_dt::key_type> keys_to_erase;
16471629

1648-
for(auto &key_value : entry.object_map.read())
1630+
for(auto &key_value : entry->object_map.read())
16491631
{
16501632
const auto &rhs_object = to_expr(key_value);
16511633
if(values_to_erase.count(rhs_object))
@@ -1659,8 +1641,10 @@ void value_sett::erase_values_from_entry(
16591641
"value_sett::erase_value_from_entry() should erase exactly one value for "
16601642
"each element in the set it is given");
16611643

1644+
entryt replacement = *entry;
16621645
for(const auto &key_to_erase : keys_to_erase)
16631646
{
1664-
entry.object_map.write().erase(key_to_erase);
1647+
replacement.object_map.write().erase(key_to_erase);
16651648
}
1649+
values.replace(index, std::move(replacement));
16661650
}

0 commit comments

Comments
 (0)