@@ -19,19 +19,22 @@ void letifyt::collect_bindings(
19
19
seen_expressionst &map,
20
20
std::vector<exprt> &let_order)
21
21
{
22
+ // do not letify things with no children
23
+ if (expr.operands ().empty ())
24
+ return ;
25
+
26
+ // did we already see the expression?
22
27
seen_expressionst::iterator entry = map.find (expr);
23
28
24
29
if (entry != map.end ())
25
30
{
31
+ // yes, seen before, increase counter
26
32
let_count_idt &count_id = entry->second ;
27
33
++(count_id.count );
28
34
return ;
29
35
}
30
36
31
- // do not letify things with no children
32
- if (expr.operands ().empty ())
33
- return ;
34
-
37
+ // not seen before
35
38
for (auto &op : expr.operands ())
36
39
collect_bindings (op, map, let_order);
37
40
@@ -46,26 +49,32 @@ void letifyt::collect_bindings(
46
49
let_order.push_back (expr);
47
50
}
48
51
49
- exprt letifyt::letify_rec (
52
+ // / Construct a nested let expression for expressions
53
+ // / in let_order that are used more than once
54
+ exprt letifyt::letify (
50
55
const exprt &expr,
51
- std::vector<exprt> &let_order,
52
- const seen_expressionst &map,
53
- std::size_t i)
56
+ const std::vector<exprt> &let_order,
57
+ const seen_expressionst &map)
54
58
{
55
- if (i >= let_order.size ())
56
- return substitute_let (expr, map);
59
+ exprt result = substitute_let (expr, map);
57
60
58
- exprt current = let_order[i];
59
- INVARIANT (
60
- map.find (current) != map.end (), " expression should have been seen already" );
61
+ // we build inside out, so go backwards in let order
62
+ for (auto r_it = let_order.rbegin (); r_it != let_order.rend (); r_it++)
63
+ {
64
+ const exprt ¤t = *r_it;
61
65
62
- if ( map.find (current)-> second . count < LET_COUNT)
63
- return letify_rec (expr, let_order, map, i + 1 );
66
+ auto m_it = map.find (current);
67
+ PRECONDITION (m_it != map. end () );
64
68
65
- return let_exprt (
66
- map.find (current)->second .let_symbol ,
67
- substitute_let (current, map),
68
- letify_rec (expr, let_order, map, i + 1 ));
69
+ // Used more than once? Then a let pays off.
70
+ if (m_it->second .count > 1 )
71
+ {
72
+ result = let_exprt (
73
+ m_it->second .let_symbol , substitute_let (current, map), result);
74
+ }
75
+ }
76
+
77
+ return result;
69
78
}
70
79
71
80
exprt letifyt::operator ()(const exprt &expr)
@@ -75,7 +84,7 @@ exprt letifyt::operator()(const exprt &expr)
75
84
76
85
collect_bindings (expr, map, let_order);
77
86
78
- return letify_rec (expr, let_order, map, 0 );
87
+ return letify (expr, let_order, map);
79
88
}
80
89
81
90
exprt letifyt::substitute_let (const exprt &expr, const seen_expressionst &map)
@@ -89,7 +98,9 @@ exprt letifyt::substitute_let(const exprt &expr, const seen_expressionst &map)
89
98
{
90
99
op.visit ([&map](exprt &expr) {
91
100
seen_expressionst::const_iterator it = map.find (expr);
92
- if (it != map.end () && it->second .count >= letifyt::LET_COUNT)
101
+
102
+ // replace subexpression by let symbol if used more than once
103
+ if (it != map.end () && it->second .count > 1 )
93
104
expr = it->second .let_symbol ;
94
105
});
95
106
}
0 commit comments