Skip to content

Commit 04a75b1

Browse files
committed
Do not unnecessarily break sharing during SSA renaming (part 1: types)
Instead of editing the object in place, return an optional<typet> that is set if, and only if, a modification took place.
1 parent ba421e0 commit 04a75b1

File tree

2 files changed

+135
-26
lines changed

2 files changed

+135
-26
lines changed

src/goto-symex/goto_symex_state.cpp

Lines changed: 130 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -281,10 +281,13 @@ ssa_exprt goto_symex_statet::rename_ssa(ssa_exprt ssa, const namespacet &ns)
281281
return ssa;
282282
}
283283

284-
/// Ensure `rename_ssa` gets compiled for L0
284+
// explicitly instantiate templates
285285
template ssa_exprt goto_symex_statet::rename_ssa<goto_symex_statet::L0>(
286286
ssa_exprt ssa,
287287
const namespacet &ns);
288+
template ssa_exprt goto_symex_statet::rename_ssa<goto_symex_statet::L1>(
289+
ssa_exprt ssa,
290+
const namespacet &ns);
288291

289292
template <goto_symex_statet::levelt level>
290293
exprt goto_symex_statet::rename(exprt expr, const namespacet &ns)
@@ -298,17 +301,15 @@ exprt goto_symex_statet::rename(exprt expr, const namespacet &ns)
298301

299302
if(level == L0)
300303
{
301-
ssa = rename_ssa<L0>(std::move(ssa), ns);
304+
set_l0_indices(ssa, ns);
302305
}
303306
else if(level == L1)
304307
{
305-
ssa = rename_ssa<L1>(std::move(ssa), ns);
308+
set_l1_indices(ssa, ns);
306309
}
307310
else if(level==L2)
308311
{
309312
set_l1_indices(ssa, ns);
310-
rename<level>(expr.type(), ssa.get_identifier(), ns);
311-
ssa.update_type();
312313

313314
if(l2_thread_read_encoding(ssa, ns))
314315
{
@@ -327,15 +328,40 @@ exprt goto_symex_statet::rename(exprt expr, const namespacet &ns)
327328
if(p_it != propagation.end())
328329
expr=p_it->second; // already L2
329330
else
331+
{
332+
if(
333+
auto renamed_type =
334+
rename_type<level>(expr.type(), ssa.get_identifier(), ns))
335+
{
336+
ssa.type() = std::move(*renamed_type);
337+
ssa.update_type();
338+
}
339+
330340
set_l2_indices(ssa, ns);
341+
}
331342
}
332343
}
344+
345+
if(
346+
auto renamed_type =
347+
rename_type<level>(expr.type(), ssa.get_identifier(), ns))
348+
{
349+
ssa.type() = std::move(*renamed_type);
350+
ssa.update_type();
351+
}
333352
}
334353
else if(expr.id()==ID_symbol)
335354
{
336355
// we never rename function symbols
337-
if(as_const(expr).type().id() == ID_code)
338-
rename<level>(expr.type(), to_symbol_expr(expr).get_identifier(), ns);
356+
if(expr.type().id() == ID_code)
357+
{
358+
if(
359+
auto renamed_type = rename_type<level>(
360+
expr.type(), to_symbol_expr(expr).get_identifier(), ns))
361+
{
362+
expr.type() = std::move(*renamed_type);
363+
}
364+
}
339365
else
340366
expr = rename<level>(ssa_exprt{expr}, ns);
341367
}
@@ -348,7 +374,10 @@ exprt goto_symex_statet::rename(exprt expr, const namespacet &ns)
348374
}
349375
else
350376
{
351-
rename<level>(expr.type(), irep_idt(), ns);
377+
if(auto renamed_type = rename_type<level>(expr.type(), irep_idt(), ns))
378+
{
379+
expr.type() = std::move(*renamed_type);
380+
}
352381

353382
// do this recursively
354383
Forall_operands(it, expr)
@@ -555,8 +584,13 @@ void goto_symex_statet::rename_address(exprt &expr, const namespacet &ns)
555584
// only do L1!
556585
set_l1_indices(ssa, ns);
557586

558-
rename<level>(expr.type(), ssa.get_identifier(), ns);
559-
ssa.update_type();
587+
if(
588+
auto renamed_type =
589+
rename_type<level>(expr.type(), ssa.get_identifier(), ns))
590+
{
591+
ssa.type() = std::move(*renamed_type);
592+
ssa.update_type();
593+
}
560594
}
561595
else if(expr.id()==ID_symbol)
562596
{
@@ -680,11 +714,27 @@ void goto_symex_statet::rename(
680714
typet &type,
681715
const irep_idt &l1_identifier,
682716
const namespacet &ns)
717+
{
718+
if(auto renamed = rename_type<level>(type, l1_identifier, ns))
719+
type = std::move(*renamed);
720+
}
721+
722+
// explicitly instantiate templates
723+
template void goto_symex_statet::rename<goto_symex_statet::L2>(
724+
typet &type,
725+
const irep_idt &l1_identifier,
726+
const namespacet &ns);
727+
728+
template <goto_symex_statet::levelt level>
729+
optionalt<typet> goto_symex_statet::rename_type(
730+
const typet &type,
731+
const irep_idt &l1_identifier,
732+
const namespacet &ns)
683733
{
684734
// check whether there are symbol expressions in the type; if not, there
685735
// is no need to expand the struct/union tags in the type
686736
if(!requires_renaming(type, ns))
687-
return; // no action
737+
return {};
688738

689739
// rename all the symbols with their last known value
690740
// to the given level
@@ -706,46 +756,100 @@ void goto_symex_statet::rename(
706756
to_array_type(type).is_incomplete() ||
707757
to_array_type(type_prev).is_complete())
708758
{
709-
type=l1_type_entry.first->second;
710-
return;
759+
return l1_type_entry.first->second;
711760
}
712761
}
713762
}
714763

715-
// expand struct and union tag types
716-
type = ns.follow(type);
764+
optionalt<typet> result;
717765

718766
if(type.id()==ID_array)
719767
{
720768
auto &array_type = to_array_type(type);
721-
rename<level>(array_type.subtype(), irep_idt(), ns);
722-
array_type.size() = rename<level>(std::move(array_type.size()), ns);
769+
auto renamed_subtype =
770+
rename_type<level>(array_type.subtype(), irep_idt(), ns);
771+
auto renamed_size = rename<level>(array_type.size(), ns);
772+
773+
if(renamed_subtype.has_value() || renamed_size != array_type.size())
774+
{
775+
array_typet result_type = array_type;
776+
777+
if(renamed_subtype.has_value())
778+
result_type.subtype() = std::move(*renamed_subtype);
779+
780+
if(renamed_size != array_type.size())
781+
result_type.size() = std::move(renamed_size);
782+
783+
result = std::move(result_type);
784+
}
723785
}
724786
else if(type.id() == ID_struct || type.id() == ID_union)
725787
{
726-
struct_union_typet &s_u_type=to_struct_union_type(type);
727-
struct_union_typet::componentst &components=s_u_type.components();
788+
struct_union_typet s_u_type = to_struct_union_type(type);
789+
bool modified = false;
728790

729-
for(auto &component : components)
791+
struct_union_typet::componentst::iterator comp_it =
792+
s_u_type.components().begin();
793+
for(auto &component : to_struct_union_type(type).components())
730794
{
731795
// be careful, or it might get cyclic
732796
if(component.type().id() == ID_array)
733797
{
734798
auto &array_type = to_array_type(component.type());
735-
array_type.size() = rename<level>(std::move(array_type.size()), ns);
799+
auto renamed_expr = rename<level>(array_type.size(), ns);
800+
if(renamed_expr != array_type.size())
801+
{
802+
to_array_type(comp_it->type()).size() = std::move(renamed_expr);
803+
modified = true;
804+
}
736805
}
737806
else if(component.type().id() != ID_pointer)
738-
rename<level>(component.type(), irep_idt(), ns);
807+
{
808+
if(
809+
auto renamed_type =
810+
rename_type<level>(component.type(), irep_idt(), ns))
811+
{
812+
comp_it->type() = std::move(*renamed_type);
813+
modified = true;
814+
}
815+
}
816+
817+
++comp_it;
739818
}
819+
820+
if(modified)
821+
result = std::move(s_u_type);
740822
}
741823
else if(type.id()==ID_pointer)
742824
{
743-
rename<level>(to_pointer_type(type).subtype(), irep_idt(), ns);
825+
if(
826+
auto renamed_subtype =
827+
rename_type<level>(to_pointer_type(type).subtype(), irep_idt(), ns))
828+
{
829+
pointer_typet pointer_type = to_pointer_type(type);
830+
pointer_type.subtype() = std::move(*renamed_subtype);
831+
result = std::move(pointer_type);
832+
}
833+
}
834+
else if(type.id() == ID_symbol_type)
835+
{
836+
const symbolt &symbol = ns.lookup(to_symbol_type(type));
837+
result = rename_type<level>(symbol.type, l1_identifier, ns);
838+
if(!result.has_value())
839+
result = symbol.type;
840+
}
841+
else if(type.id() == ID_struct_tag || type.id() == ID_union_tag)
842+
{
843+
const symbolt &symbol = ns.lookup(to_tag_type(type));
844+
result = rename_type<level>(symbol.type, l1_identifier, ns);
845+
if(!result.has_value())
846+
result = symbol.type;
744847
}
745848

746-
if(level==L2 &&
747-
!l1_identifier.empty())
748-
l1_type_entry.first->second=type;
849+
if(level == L2 && !l1_identifier.empty() && result.has_value())
850+
l1_type_entry.first->second = *result;
851+
852+
return result;
749853
}
750854

751855
static void get_l1_name(exprt &expr)

src/goto-symex/goto_symex_state.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,11 @@ class goto_symex_statet final : public goto_statet
201201
protected:
202202
template <levelt>
203203
void rename_address(exprt &expr, const namespacet &ns);
204+
template <levelt>
205+
optionalt<typet> rename_type(
206+
const typet &type,
207+
const irep_idt &l1_identifier,
208+
const namespacet &ns);
204209

205210
/// Update level 0 values.
206211
void set_l0_indices(ssa_exprt &expr, const namespacet &ns);

0 commit comments

Comments
 (0)