Skip to content

Commit 4899b46

Browse files
committed
Make new LIFO path exploration the default
This commits adds the "lifo" strategy, which explores program paths using depth-first search. This is now the default strategy due to its favourable memory consumption compared to other strategies; tests on a few benchmarks show that its memory usage is basically constant and comparable to regular model-checking, since this strategy finishes paths as quickly as possible rather than saving them for later.
1 parent d4535bf commit 4899b46

File tree

6 files changed

+232
-3
lines changed

6 files changed

+232
-3
lines changed
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
CORE
2+
main.c
3+
--paths lifo
4+
activate-multi-line-match
5+
EXIT=0
6+
SIGNAL=0
7+
--
8+
^warning: ignoring
9+
--
10+
This tests that the next path is resumed before the jump path.
11+
12+
Test that the following happens in order:
13+
execute line 4
14+
save next 5
15+
save jump 7
16+
any lines
17+
execute line 4
18+
resume jump 7
19+
execute line 7
20+
any lines
21+
path is successful
22+
any lines
23+
execute line 4
24+
resume next 5
25+
any lines
26+
path is successful
27+
end
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
CORE
2+
main.c
3+
--unwind 2 --paths lifo
4+
activate-multi-line-match
5+
SIGNAL=0
6+
EXIT=10
7+
--
8+
^warning: ignoring
9+
--
10+
Test that the following happens in order:
11+
execute line 6
12+
save next 7
13+
save jump 9
14+
any lines
15+
execute line 6
16+
17+
// The path where we skip the loop body. Successful because the path is
18+
// implausible, we cannot have skipped the body if x == 1.
19+
resume jump 9
20+
execute line 9
21+
any lines
22+
path is successful
23+
24+
// The path where we execute the body once. x is 0 after that, so
25+
// assertion failure.
26+
any lines
27+
execute line 6
28+
resume next 7
29+
any lines
30+
save next 7
31+
save jump 9
32+
any lines
33+
resume jump 9
34+
any lines
35+
path is unsuccessful
36+
37+
// The path where we execute the body twice. Successful because infeasible
38+
any lines
39+
execute line 6
40+
resume next 7
41+
any lines
42+
path is successful
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
CORE
2+
main.c
3+
--paths lifo
4+
activate-multi-line-match
5+
EXIT=0
6+
SIGNAL=0
7+
--
8+
^warning: ignoring
9+
--
10+
Test that the following happens in order:
11+
12+
// Outer else, inner else
13+
execute line 4
14+
save next 6
15+
save jump 13
16+
any lines
17+
execute line 4
18+
resume jump 13
19+
execute line 13
20+
save next 14
21+
save jump 16
22+
any lines
23+
execute line 13
24+
resume jump 16
25+
execute line 16
26+
any lines
27+
path is successful
28+
29+
// Outer else, inner if
30+
any lines
31+
execute line 13
32+
resume next 14
33+
execute line 14
34+
any lines
35+
path is successful
36+
37+
// Outer if, inner else
38+
any lines
39+
execute line 4
40+
resume next 6
41+
execute line 6
42+
save next 7
43+
save jump 9
44+
any lines
45+
resume jump 9
46+
execute line 9
47+
any lines
48+
path is successful
49+
50+
// Outer if, inner if
51+
any lines
52+
execute line 6
53+
resume next 7
54+
execute line 7
55+
any lines
56+
path is successful
57+
end
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
CORE
2+
main.c
3+
--unwind 2 --paths lifo
4+
activate-multi-line-match
5+
EXIT=0
6+
SIGNAL=0
7+
--
8+
^warning: ignoring
9+
--
10+
Test that the following happens in order:
11+
12+
// skip the loop body
13+
save next 6
14+
save jump 8
15+
any lines
16+
execute line 4
17+
resume jump 8
18+
execute line 8
19+
any lines
20+
path is successful
21+
22+
// execute loop body once
23+
any lines
24+
execute line 4
25+
resume next 6
26+
execute line 6
27+
any lines
28+
save next 6
29+
save jump 8
30+
any lines
31+
resume jump 8
32+
execute line 8
33+
any lines
34+
path is successful
35+
36+
// execute loop body twice
37+
any lines
38+
execute line 4
39+
resume next 6
40+
execute line 6
41+
any lines
42+
path is successful

src/goto-symex/path_storage.cpp

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,39 @@ Author: Kareem Khazem <[email protected]>
1313
#include <util/exit_codes.h>
1414
#include <util/make_unique.h>
1515

16+
// _____________________________________________________________________________
17+
// path_lifot
18+
19+
path_storaget::patht &path_lifot::private_peek()
20+
{
21+
last_peeked = paths.end();
22+
--last_peeked;
23+
return paths.back();
24+
}
25+
26+
void path_lifot::push(
27+
const path_storaget::patht &next_instruction,
28+
const path_storaget::patht &jump_target)
29+
{
30+
paths.push_back(next_instruction);
31+
paths.push_back(jump_target);
32+
}
33+
34+
void path_lifot::private_pop()
35+
{
36+
PRECONDITION(last_peeked != paths.end());
37+
paths.erase(last_peeked);
38+
last_peeked = paths.end();
39+
}
40+
41+
std::size_t path_lifot::size() const
42+
{
43+
return paths.size();
44+
}
45+
46+
// _____________________________________________________________________________
47+
// path_fifot
48+
1649
path_storaget::patht &path_fifot::private_peek()
1750
{
1851
return paths.front();
@@ -36,6 +69,9 @@ std::size_t path_fifot::size() const
3669
return paths.size();
3770
}
3871

72+
// _____________________________________________________________________________
73+
// path_strategy_choosert
74+
3975
std::string path_strategy_choosert::show_strategies() const
4076
{
4177
std::stringstream ss;
@@ -69,10 +105,19 @@ void path_strategy_choosert::set_path_strategy_options(
69105

70106
path_strategy_choosert::path_strategy_choosert()
71107
: strategies(
72-
{{"fifo",
108+
{{"lifo",
109+
{" lifo next instruction is pushed before\n"
110+
" goto target; paths are popped in\n"
111+
" last-in, first-out order. Explores\n"
112+
" the program tree depth-first.\n",
113+
[]() { // NOLINT(whitespace/braces)
114+
return util_make_unique<path_lifot>();
115+
}}},
116+
{"fifo",
73117
{" fifo next instruction is pushed before\n"
74118
" goto target; paths are popped in\n"
75-
" first-in, first-out order\n",
119+
" first-in, first-out order. Explores\n"
120+
" the program tree breadth-first.\n",
76121
[]() { // NOLINT(whitespace/braces)
77122
return util_make_unique<path_fifot>();
78123
}}}})

src/goto-symex/path_storage.h

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,22 @@ class path_storaget
8484
virtual void private_pop() = 0;
8585
};
8686

87+
/// \brief LIFO save queue: depth-first search, try to finish paths
88+
class path_lifot : public path_storaget
89+
{
90+
public:
91+
void push(const patht &, const patht &) override;
92+
std::size_t size() const override;
93+
94+
protected:
95+
std::list<path_storaget::patht>::iterator last_peeked;
96+
std::list<patht> paths;
97+
98+
private:
99+
patht &private_peek() override;
100+
void private_pop() override;
101+
};
102+
87103
/// \brief FIFO save queue: paths are resumed in the order that they were saved
88104
class path_fifot : public path_storaget
89105
{
@@ -134,7 +150,7 @@ class path_strategy_choosert
134150
protected:
135151
std::string default_strategy() const
136152
{
137-
return "fifo";
153+
return "lifo";
138154
}
139155

140156
/// Map from the name of a strategy (to be supplied on the command line), to

0 commit comments

Comments
 (0)