Skip to content

Commit a4945f3

Browse files
committed
Reset unwinding counters when leaving a loop at the loop head
Constant propagation and simplification may determine that a loop cannot be unrolled further. This is determined at the loop head, which is a forward goto in case of for or while (but not do-while) loops. Before this patch, forward gotos would never cause loop counters to be reset. In nested loops, the inner loop(s) would thus have their unwinding counts added to previous (complete) loop executions.
1 parent 1cb1fd9 commit a4945f3

File tree

7 files changed

+56
-0
lines changed

7 files changed

+56
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
int main()
2+
{
3+
for(int i=0; i<2; ++i)
4+
for(int j=0; j<10; ++j);
5+
return 0;
6+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
main.c
3+
--unwind 11 --unwinding-assertions
4+
^EXIT=0$
5+
^SIGNAL=0$
6+
^VERIFICATION SUCCESSFUL$
7+
--
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
int main()
2+
{
3+
l2: goto l1;
4+
l1: int x=5;
5+
goto l2;
6+
7+
return 0;
8+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
main.c
3+
--unwind 3 --unwinding-assertions
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
int main()
2+
{
3+
int i=0;
4+
l2: if(i==1) int y=0;
5+
l1: int x=5;
6+
goto l2;
7+
8+
return 0;
9+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
CORE
2+
main.c
3+
--unwind 3 --unwinding-assertions
4+
^EXIT=10$
5+
^SIGNAL=0$
6+
^VERIFICATION FAILED$
7+
--

src/goto-symex/symex_goto.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,18 @@ void goto_symext::symex_goto(statet &state)
105105
return; // nothing else to do
106106
}
107107
}
108+
else if(new_guard.is_true() && !old_guard.is_true())
109+
{
110+
// we may have left a loop (i.e., the forward goto is beyond
111+
// the end of the loop) as the loop condition has become false
112+
// via constant propagation and simplification (the original
113+
// condition "old_guard" was not trivially true, but "new_guard"
114+
// is) -- reset all candidate loop counters
115+
for(const auto &i_e : instruction.incoming_edges)
116+
if(i_e->is_goto() && i_e->is_backwards_goto() &&
117+
goto_target->location_number>i_e->location_number)
118+
frame.loop_iterations[goto_programt::loop_id(i_e)].count=0;
119+
}
108120

109121
goto_programt::const_targett new_state_pc, state_pc;
110122
symex_targett::sourcet original_source=state.source;

0 commit comments

Comments
 (0)