Skip to content

Commit 7068354

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 d5c50b7 commit 7068354

File tree

5 files changed

+37
-19
lines changed

5 files changed

+37
-19
lines changed

src/goto-symex/goto_symex_state.cpp

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

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

505506
current_emplace_res.first->second.second =
506507
fresh_l2_name_provider(l1_identifier);
508+
509+
return current_emplace_res.first->second.second;
507510
}
508511

509512
/// 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
@@ -207,7 +207,8 @@ class goto_symex_statet final : public goto_statet
207207

208208
/// Allocates a fresh L2 name for the given L1 identifier, and makes it the
209209
// latest generation on this path.
210-
void increase_generation(const irep_idt l1_identifier, const ssa_exprt &lhs);
210+
std::size_t
211+
increase_generation(const irep_idt l1_identifier, const ssa_exprt &lhs);
211212

212213
/// Increases the generation of the L1 identifier. Does nothing if there
213214
/// 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: 29 additions & 12 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.source, 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.source, std::move(state));
219+
}
220+
else
221+
{
222+
goto_state_list.emplace_back(state.source, state);
223+
}
214224

215225
symex_transition(state, state_pc, backward);
216226

@@ -319,20 +329,27 @@ void goto_symext::merge_goto(
319329
"atomic sections differ across branches",
320330
state.source.pc->source_location);
321331

322-
// do SSA phi functions
323-
phi_function(goto_state, state);
332+
if(!goto_state.guard.is_false())
333+
{
334+
if(state.guard.is_false())
335+
{
336+
static_cast<goto_statet &>(state) = std::move(goto_state);
337+
}
338+
else
339+
{
340+
// do SSA phi functions
341+
phi_function(goto_state, state);
324342

325-
// merge value sets
326-
if(state.guard.is_false() && !goto_state.guard.is_false())
327-
state.value_set = std::move(goto_state.value_set);
328-
else if(!goto_state.guard.is_false())
329-
state.value_set.make_union(goto_state.value_set);
343+
// merge value sets
344+
state.value_set.make_union(goto_state.value_set);
330345

331-
// adjust guard
332-
state.guard|=goto_state.guard;
346+
// adjust guard
347+
state.guard |= goto_state.guard;
333348

334-
// adjust depth
335-
state.depth=std::min(state.depth, goto_state.depth);
349+
// adjust depth
350+
state.depth = std::min(state.depth, goto_state.depth);
351+
}
352+
}
336353
}
337354

338355
/// Applies f to `(k, ssa, i, j)` if the first map maps k to (ssa, i) and

0 commit comments

Comments
 (0)