Skip to content

Commit 699d8d2

Browse files
committed
Do not unnecessarily break sharing during SSA renaming (part 2: 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 821da14 commit 699d8d2

File tree

2 files changed

+132
-46
lines changed

2 files changed

+132
-46
lines changed

src/goto-symex/goto_symex_state.cpp

Lines changed: 131 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -350,9 +350,10 @@ exprt goto_symex_statet::rename(exprt expr, const namespacet &ns)
350350
else if(expr.id()==ID_address_of)
351351
{
352352
auto &address_of_expr = to_address_of_expr(expr);
353-
rename_address<level>(address_of_expr.object(), ns);
354-
to_pointer_type(expr.type()).subtype() =
355-
as_const(address_of_expr).object().type();
353+
auto renamed_object = rename_address<level>(address_of_expr.object(), ns);
354+
355+
if(renamed_object.has_value())
356+
expr = address_of_exprt{std::move(*renamed_object)};
356357
}
357358
else
358359
{
@@ -551,12 +552,13 @@ bool goto_symex_statet::l2_thread_write_encoding(
551552
}
552553

553554
template <levelt level>
554-
void goto_symex_statet::rename_address(exprt &expr, const namespacet &ns)
555+
optionalt<exprt>
556+
goto_symex_statet::rename_address(const exprt &expr, const namespacet &ns)
555557
{
556558
if(expr.id()==ID_symbol &&
557559
expr.get_bool(ID_C_SSA_symbol))
558560
{
559-
ssa_exprt &ssa=to_ssa_expr(expr);
561+
ssa_exprt ssa = to_ssa_expr(expr);
560562

561563
// only do L1!
562564
ssa = set_indices<L1>(std::move(ssa), ns).get();
@@ -568,67 +570,151 @@ void goto_symex_statet::rename_address(exprt &expr, const namespacet &ns)
568570
ssa.type() = std::move(*renamed_type);
569571
ssa.update_type();
570572
}
573+
574+
return std::move(ssa);
571575
}
572576
else if(expr.id()==ID_symbol)
573577
{
574-
expr=ssa_exprt(expr);
575-
rename_address<level>(expr, ns);
578+
ssa_exprt ssa{expr};
579+
if(auto renamed = rename_address<level>(ssa, ns))
580+
return renamed;
581+
else
582+
return std::move(ssa);
576583
}
577-
else
584+
else if(expr.id() == ID_index)
578585
{
579-
if(expr.id()==ID_index)
586+
const index_exprt &index_expr = to_index_expr(expr);
587+
588+
auto renamed_array = rename_address<level>(index_expr.array(), ns);
589+
590+
// the index is not an address
591+
auto renamed_index = rename<level>(index_expr.index(), ns);
592+
593+
if(renamed_array.has_value() || renamed_index != index_expr.index())
580594
{
581-
index_exprt &index_expr=to_index_expr(expr);
595+
index_exprt result = index_expr;
596+
597+
if(renamed_array.has_value())
598+
{
599+
result.array() = std::move(*renamed_array);
600+
result.type() = to_array_type(result.array().type()).subtype();
601+
}
602+
603+
if(renamed_index != index_expr.index())
604+
result.index() = std::move(renamed_index);
605+
606+
return std::move(result);
607+
}
608+
else
609+
return {};
610+
}
611+
else if(expr.id() == ID_if)
612+
{
613+
// the condition is not an address
614+
const if_exprt &if_expr = to_if_expr(expr);
615+
auto renamed_cond = rename<level>(if_expr.cond(), ns);
616+
auto renamed_true = rename_address<level>(if_expr.true_case(), ns);
617+
auto renamed_false = rename_address<level>(if_expr.false_case(), ns);
618+
619+
if(
620+
renamed_cond != if_expr.cond() || renamed_true.has_value() ||
621+
renamed_false.has_value())
622+
{
623+
if_exprt result = if_expr;
624+
625+
if(renamed_cond != if_expr.cond())
626+
result.cond() = std::move(renamed_cond);
627+
628+
if(renamed_true.has_value())
629+
{
630+
result.true_case() = std::move(*renamed_true);
631+
result.type() = result.true_case().type();
632+
}
633+
634+
if(renamed_false.has_value())
635+
result.false_case() = std::move(*renamed_false);
582636

583-
rename_address<level>(index_expr.array(), ns);
584-
PRECONDITION(index_expr.array().type().id() == ID_array);
585-
expr.type() = to_array_type(index_expr.array().type()).subtype();
637+
return std::move(result);
638+
}
639+
else
640+
return {};
641+
}
642+
else if(expr.id() == ID_member)
643+
{
644+
const member_exprt &member_expr = to_member_expr(expr);
586645

587-
// the index is not an address
588-
index_expr.index() = rename<level>(std::move(index_expr.index()), ns);
646+
auto renamed_struct_op = rename_address<level>(member_expr.struct_op(), ns);
647+
648+
// type might not have been renamed in case of nesting of
649+
// structs and pointers/arrays
650+
optionalt<typet> renamed_type;
651+
if(
652+
renamed_struct_op.has_value() &&
653+
renamed_struct_op->type().id() != ID_struct_tag &&
654+
renamed_struct_op->type().id() != ID_union_tag)
655+
{
656+
const struct_union_typet &su_type =
657+
to_struct_union_type(renamed_struct_op->type());
658+
const struct_union_typet::componentt &comp =
659+
su_type.get_component(member_expr.get_component_name());
660+
DATA_INVARIANT(comp.is_not_nil(), "component should exist");
661+
renamed_type = comp.type();
589662
}
590-
else if(expr.id()==ID_if)
663+
else
664+
renamed_type = rename_type<level>(expr.type(), irep_idt(), ns);
665+
666+
if(renamed_struct_op.has_value() || renamed_type.has_value())
591667
{
592-
// the condition is not an address
593-
if_exprt &if_expr=to_if_expr(expr);
594-
if_expr.cond() = rename<level>(std::move(if_expr.cond()), ns);
595-
rename_address<level>(if_expr.true_case(), ns);
596-
rename_address<level>(if_expr.false_case(), ns);
668+
member_exprt result = member_expr;
669+
670+
if(renamed_struct_op.has_value())
671+
result.struct_op() = std::move(*renamed_struct_op);
597672

598-
if_expr.type()=if_expr.true_case().type();
673+
if(renamed_type.has_value())
674+
result.type() = std::move(*renamed_type);
675+
676+
return std::move(result);
599677
}
600-
else if(expr.id()==ID_member)
678+
else
679+
return {};
680+
}
681+
else
682+
{
683+
optionalt<exprt> result;
684+
685+
// this could go wrong, but we would have to re-typecheck ...
686+
if(auto renamed_type = rename_type<level>(expr.type(), irep_idt(), ns))
601687
{
602-
member_exprt &member_expr=to_member_expr(expr);
688+
result = expr;
689+
result->type() = std::move(*renamed_type);
690+
}
603691

604-
rename_address<level>(member_expr.struct_op(), ns);
692+
// do this recursively; we assume here
693+
// that all the operands are addresses
694+
optionalt<exprt::operandst> result_operands;
695+
std::size_t op_index = 0;
605696

606-
// type might not have been renamed in case of nesting of
607-
// structs and pointers/arrays
608-
if(
609-
member_expr.struct_op().type().id() != ID_struct_tag &&
610-
member_expr.struct_op().type().id() != ID_union_tag)
697+
for(auto &op : expr.operands())
698+
{
699+
if(auto renamed_op = rename_address<level>(op, ns))
611700
{
612-
const struct_union_typet &su_type=
613-
to_struct_union_type(member_expr.struct_op().type());
614-
const struct_union_typet::componentt &comp=
615-
su_type.get_component(member_expr.get_component_name());
616-
PRECONDITION(comp.is_not_nil());
617-
expr.type()=comp.type();
701+
if(!result_operands.has_value())
702+
result_operands = expr.operands();
703+
704+
(*result_operands)[op_index] = std::move(*renamed_op);
618705
}
619-
else
620-
rename<level>(expr.type(), irep_idt(), ns);
706+
++op_index;
621707
}
622-
else
708+
709+
if(result_operands.has_value())
623710
{
624-
// this could go wrong, but we would have to re-typecheck ...
625-
rename<level>(expr.type(), irep_idt(), ns);
711+
if(!result.has_value())
712+
result = expr;
626713

627-
// do this recursively; we assume here
628-
// that all the operands are addresses
629-
Forall_operands(it, expr)
630-
rename_address<level>(*it, ns);
714+
result->operands() = std::move(*result_operands);
631715
}
716+
717+
return result;
632718
}
633719
}
634720

src/goto-symex/goto_symex_state.h

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

114114
protected:
115115
template <levelt>
116-
void rename_address(exprt &expr, const namespacet &ns);
116+
optionalt<exprt> rename_address(const exprt &expr, const namespacet &ns);
117117
template <levelt>
118118
optionalt<typet> rename_type(
119119
const typet &type,

0 commit comments

Comments
 (0)