Skip to content

Commit 6f13ddd

Browse files
committed
Optimise symex state management for straight-line code with GOTOs
In the situation of merge on a state that hasn't been traversed (with a false guard) try and move the names into the destination state instead of a merge or copy operation
1 parent 1413144 commit 6f13ddd

File tree

5 files changed

+35
-15
lines changed

5 files changed

+35
-15
lines changed

src/goto-symex/goto_symex_state.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -494,7 +494,8 @@ bool goto_symex_statet::l2_thread_read_encoding(
494494

495495
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
496496
/// latest generation on this path.
497-
void goto_symex_statet::increase_generation(
497+
/// \return the newly allocated generation number
498+
std::size_t goto_symex_statet::increase_generation(
498499
const irep_idt l1_identifier,
499500
const ssa_exprt &lhs)
500501
{
@@ -503,6 +504,8 @@ void goto_symex_statet::increase_generation(
503504

504505
current_emplace_res.first->second.second =
505506
fresh_l2_name_provider(l1_identifier);
507+
508+
return current_emplace_res.first->second.second;
506509
}
507510

508511
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the

src/goto-symex/goto_symex_state.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ class goto_symex_statet final : public goto_statet
205205

206206
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
207207
// latest generation on this path.
208-
void increase_generation(const irep_idt l1_identifier, const ssa_exprt &lhs);
208+
std::size_t
209+
increase_generation(const irep_idt l1_identifier, const ssa_exprt &lhs);
209210

210211
/// Increases the generation of the L1 identifier. Does nothing if there
211212
/// isn't an expression keyed by it.

src/goto-symex/symex_dead.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,6 @@ void goto_symext::symex_dead(statet &state)
4343
// map is safe as 1) it is local to a path and 2) this instance can no longer
4444
// appear
4545
state.propagation.erase(l1_identifier);
46-
4746
// increment the L2 index to ensure a merge on join points will propagate the
4847
// value for branches that are still live
4948
state.increase_generation_if_exists(l1_identifier);

src/goto-symex/symex_decl.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,10 +66,8 @@ void goto_symext::symex_decl(statet &state, const symbol_exprt &expr)
6666
}
6767

6868
// L2 renaming
69-
bool is_new =
70-
state.level2.current_names.emplace(l1_identifier, std::make_pair(ssa, 1))
71-
.second;
72-
CHECK_RETURN(is_new);
69+
std::size_t generation = state.increase_generation(l1_identifier, ssa);
70+
CHECK_RETURN(generation == 1);
7371

7472
const bool record_events=state.record_events;
7573
state.record_events=false;

src/goto-symex/symex_goto.cpp

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,17 @@ void goto_symext::symex_goto(statet &state)
210210
// merge_gotos when we visit new_state_pc
211211
framet::goto_state_listt &goto_state_list =
212212
state.call_stack().top().goto_state_map[new_state_pc];
213-
goto_state_list.emplace_back(state);
213+
214+
// If the guard is true (and the alternative branch unreachable) we can move
215+
// the state in this case as it'll never be accessed on the alternate branch.
216+
if(new_guard.is_true())
217+
{
218+
goto_state_list.emplace_back(state);
219+
}
220+
else
221+
{
222+
goto_state_list.emplace_back(state);
223+
}
214224

215225
symex_transition(state, state_pc, backward);
216226

@@ -314,14 +324,23 @@ void goto_symext::merge_goto(goto_statet &&goto_state, statet &state)
314324
"atomic sections differ across branches",
315325
state.source.pc->source_location);
316326

317-
// do SSA phi functions
318-
phi_function(goto_state, state);
327+
if(!goto_state.guard.is_false())
328+
{
329+
if(state.guard.is_false())
330+
{
331+
state.level2 = std::move(goto_state.level2);
332+
state.propagation = std::move(goto_state.propagation);
333+
state.value_set = std::move(goto_state.value_set);
334+
}
335+
else
336+
{
337+
// do SSA phi functions
338+
phi_function(goto_state, state);
319339

320-
// merge value sets
321-
if(state.guard.is_false() && !goto_state.guard.is_false())
322-
state.value_set = std::move(goto_state.value_set);
323-
else if(!goto_state.guard.is_false())
324-
state.value_set.make_union(goto_state.value_set);
340+
// merge value sets
341+
state.value_set.make_union(goto_state.value_set);
342+
}
343+
}
325344

326345
// adjust guard
327346
state.guard|=goto_state.guard;

0 commit comments

Comments
 (0)