Skip to content

Commit c5a948c

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

File tree

2 files changed

+131
-48
lines changed

2 files changed

+131
-48
lines changed

src/goto-symex/goto_symex_state.cpp

Lines changed: 130 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -368,9 +368,15 @@ exprt goto_symex_statet::rename(exprt expr, const namespacet &ns)
368368
else if(expr.id()==ID_address_of)
369369
{
370370
auto &address_of_expr = to_address_of_expr(expr);
371-
rename_address<level>(address_of_expr.object(), ns);
372-
to_pointer_type(expr.type()).subtype() =
373-
as_const(address_of_expr).object().type();
371+
auto renamed_object = rename_address<level>(address_of_expr.object(), ns);
372+
373+
if(renamed_object.has_value())
374+
{
375+
address_of_exprt result = address_of_expr;
376+
result.object() = std::move(*renamed_object);
377+
to_pointer_type(result.type()).subtype() = result.object().type();
378+
expr = std::move(result);
379+
}
374380
}
375381
else
376382
{
@@ -574,12 +580,13 @@ bool goto_symex_statet::l2_thread_write_encoding(
574580
}
575581

576582
template <goto_symex_statet::levelt level>
577-
void goto_symex_statet::rename_address(exprt &expr, const namespacet &ns)
583+
optionalt<exprt>
584+
goto_symex_statet::rename_address(const exprt &expr, const namespacet &ns)
578585
{
579586
if(expr.id()==ID_symbol &&
580587
expr.get_bool(ID_C_SSA_symbol))
581588
{
582-
ssa_exprt &ssa=to_ssa_expr(expr);
589+
ssa_exprt ssa = to_ssa_expr(expr);
583590

584591
// only do L1!
585592
set_l1_indices(ssa, ns);
@@ -591,68 +598,144 @@ void goto_symex_statet::rename_address(exprt &expr, const namespacet &ns)
591598
ssa.type() = std::move(*renamed_type);
592599
ssa.update_type();
593600
}
601+
602+
return std::move(ssa);
594603
}
595604
else if(expr.id()==ID_symbol)
596605
{
597-
expr=ssa_exprt(expr);
598-
rename_address<level>(expr, ns);
606+
ssa_exprt ssa(expr);
607+
if(auto renamed = rename_address<level>(ssa, ns))
608+
return renamed;
609+
else
610+
return std::move(ssa);
599611
}
600-
else
612+
else if(expr.id() == ID_index)
601613
{
602-
if(expr.id()==ID_index)
603-
{
604-
index_exprt &index_expr=to_index_expr(expr);
614+
const index_exprt &index_expr = to_index_expr(expr);
605615

606-
rename_address<level>(index_expr.array(), ns);
607-
PRECONDITION(index_expr.array().type().id() == ID_array);
608-
expr.type() = to_array_type(index_expr.array().type()).subtype();
616+
auto renamed_array = rename_address<level>(index_expr.array(), ns);
609617

610-
// the index is not an address
611-
index_expr.index() = rename<level>(std::move(index_expr.index()), ns);
612-
}
613-
else if(expr.id()==ID_if)
618+
// the index is not an address
619+
auto renamed_index = rename<level>(index_expr.index(), ns);
620+
621+
if(renamed_array.has_value() || renamed_index != index_expr.index())
614622
{
615-
// the condition is not an address
616-
if_exprt &if_expr=to_if_expr(expr);
617-
if_expr.cond() = rename<level>(std::move(if_expr.cond()), ns);
618-
rename_address<level>(if_expr.true_case(), ns);
619-
rename_address<level>(if_expr.false_case(), ns);
623+
index_exprt result = index_expr;
624+
625+
if(renamed_array.has_value())
626+
{
627+
result.array() = std::move(*renamed_array);
628+
result.type() = to_array_type(result.array().type()).subtype();
629+
}
620630

621-
if_expr.type()=if_expr.true_case().type();
631+
if(renamed_index != index_expr.index())
632+
result.index() = std::move(renamed_index);
633+
634+
return std::move(result);
622635
}
623-
else if(expr.id()==ID_member)
636+
else
637+
return {};
638+
}
639+
else if(expr.id() == ID_if)
640+
{
641+
// the condition is not an address
642+
const if_exprt &if_expr = to_if_expr(expr);
643+
auto renamed_cond = rename<level>(if_expr.cond(), ns);
644+
auto renamed_true = rename_address<level>(if_expr.true_case(), ns);
645+
auto renamed_false = rename_address<level>(if_expr.false_case(), ns);
646+
647+
if(
648+
renamed_cond != if_expr.cond() || renamed_true.has_value() ||
649+
renamed_false.has_value())
624650
{
625-
member_exprt &member_expr=to_member_expr(expr);
651+
if_exprt result = if_expr;
626652

627-
rename_address<level>(member_expr.struct_op(), ns);
653+
if(renamed_cond != if_expr.cond())
654+
result.cond() = std::move(renamed_cond);
628655

629-
// type might not have been renamed in case of nesting of
630-
// structs and pointers/arrays
631-
if(
632-
member_expr.struct_op().type().id() != ID_symbol_type &&
633-
member_expr.struct_op().type().id() != ID_struct_tag &&
634-
member_expr.struct_op().type().id() != ID_union_tag)
656+
if(renamed_true.has_value())
635657
{
636-
const struct_union_typet &su_type=
637-
to_struct_union_type(member_expr.struct_op().type());
638-
const struct_union_typet::componentt &comp=
639-
su_type.get_component(member_expr.get_component_name());
640-
PRECONDITION(comp.is_not_nil());
641-
expr.type()=comp.type();
658+
result.true_case() = std::move(*renamed_true);
659+
result.type() = result.true_case().type();
642660
}
643-
else
644-
rename<level>(expr.type(), irep_idt(), ns);
661+
662+
if(renamed_false.has_value())
663+
result.false_case() = std::move(*renamed_false);
664+
665+
return std::move(result);
666+
}
667+
else
668+
return {};
669+
}
670+
else if(expr.id() == ID_member)
671+
{
672+
const member_exprt &member_expr = to_member_expr(expr);
673+
674+
auto renamed_struct_op = rename_address<level>(member_expr.struct_op(), ns);
675+
676+
// type might not have been renamed in case of nesting of
677+
// structs and pointers/arrays
678+
optionalt<typet> renamed_type;
679+
if(
680+
renamed_struct_op.has_value() &&
681+
renamed_struct_op->type().id() != ID_symbol_type &&
682+
renamed_struct_op->type().id() != ID_struct_tag &&
683+
renamed_struct_op->type().id() != ID_union_tag)
684+
{
685+
const struct_union_typet &su_type =
686+
to_struct_union_type(renamed_struct_op->type());
687+
const struct_union_typet::componentt &comp =
688+
su_type.get_component(member_expr.get_component_name());
689+
PRECONDITION(comp.is_not_nil());
690+
renamed_type = comp.type();
645691
}
646692
else
693+
renamed_type = rename_type<level>(expr.type(), irep_idt(), ns);
694+
695+
if(renamed_struct_op.has_value() || renamed_type.has_value())
696+
{
697+
member_exprt result = member_expr;
698+
699+
if(renamed_struct_op.has_value())
700+
result.struct_op() = std::move(*renamed_struct_op);
701+
702+
if(renamed_type.has_value())
703+
result.type() = std::move(*renamed_type);
704+
705+
return std::move(result);
706+
}
707+
else
708+
return {};
709+
}
710+
else
711+
{
712+
exprt result = expr;
713+
bool modified = false;
714+
715+
// this could go wrong, but we would have to re-typecheck ...
716+
if(auto renamed_type = rename_type<level>(expr.type(), irep_idt(), ns))
647717
{
648-
// this could go wrong, but we would have to re-typecheck ...
649-
rename<level>(expr.type(), irep_idt(), ns);
718+
result.type() = std::move(*renamed_type);
719+
modified = true;
720+
}
650721

651-
// do this recursively; we assume here
652-
// that all the operands are addresses
653-
Forall_operands(it, expr)
654-
rename_address<level>(*it, ns);
722+
// do this recursively; we assume here
723+
// that all the operands are addresses
724+
exprt::operandst::iterator op_it = result.operands().begin();
725+
forall_operands(it, expr)
726+
{
727+
if(auto renamed_op = rename_address<level>(*it, ns))
728+
{
729+
*op_it = std::move(*renamed_op);
730+
modified = true;
731+
}
732+
++op_it;
655733
}
734+
735+
if(modified)
736+
return std::move(result);
737+
else
738+
return {};
656739
}
657740
}
658741

src/goto-symex/goto_symex_state.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ class goto_symex_statet final : public goto_statet
200200

201201
protected:
202202
template <levelt>
203-
void rename_address(exprt &expr, const namespacet &ns);
203+
optionalt<exprt> rename_address(const exprt &expr, const namespacet &ns);
204204
template <levelt>
205205
optionalt<typet> rename_type(
206206
const typet &type,

0 commit comments

Comments
 (0)