Skip to content

Commit 8ce7997

Browse files
authored
Bound the recursion depth of size_stmt (#519)
Limit recursive calls on if-then-else statements to avoid quadratic behaviors. Also: put a fixed upper limit on the return value of size_stmt, since large values of the size are meaningless and make the `more_likely` criterion unstable.
1 parent 0ffc516 commit 8ce7997

File tree

1 file changed

+24
-6
lines changed

1 file changed

+24
-6
lines changed

backend/RTLgenaux.ml

+24-6
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,19 @@ let size_eos = function
6767
| Coq_inl e -> size_expr e
6868
| Coq_inr id -> 0
6969

70-
let rec size_stmt = function
70+
(* [more_likely] is called once for every if-then-else conditional in
71+
the current function. Therefore, [size_stmt] is called once for
72+
every "then" or "else" branch of a conditional. This can result in
73+
time quadratic in the size of the function. To avoid this,
74+
we bound the recursion depth of [size_stmt] w.r.t. if-then-else
75+
conditionals. With a maximal depth of [D], each statement of the current
76+
function is visited at most [D + 1] times. *)
77+
78+
let max_depth = 4
79+
let max_size = 100
80+
81+
let rec size_stmt depth s =
82+
match s with
7183
| Sskip -> 0
7284
| Sassign(id, a) -> size_expr a
7385
| Sstore(chunk, addr, args, src) -> 1 + size_exprs args + size_expr src
@@ -77,18 +89,24 @@ let rec size_stmt = function
7789
3 + size_eos eos + size_exprs args + length_exprs args
7890
| Sbuiltin(_, (EF_annot _ | EF_debug _), _) -> 0
7991
| Sbuiltin(optid, ef, args) -> 1 + size_builtin_args args
80-
| Sseq(s1, s2) -> size_stmt s1 + size_stmt s2
92+
| Sseq(s1, s2) -> size_stmt depth s1 + size_stmt depth s2
8193
| Sifthenelse(ce, s1, s2) ->
82-
size_condexpr ce + max (size_stmt s1) (size_stmt s2)
83-
| Sloop s -> 1 + 4 * size_stmt s
84-
| Sblock s -> size_stmt s
94+
if depth <= 0
95+
then max_size
96+
else size_condexpr ce
97+
+ max (size_stmt (depth - 1) s1) (size_stmt (depth - 1) s2)
98+
| Sloop s -> 1 + 4 * size_stmt depth s
99+
| Sblock s -> size_stmt depth s
85100
| Sexit n -> 1
86101
| Sswitch xe -> size_exitexpr xe
87102
| Sreturn None -> 2
88103
| Sreturn (Some arg) -> 2 + size_expr arg
89-
| Slabel(lbl, s) -> size_stmt s
104+
| Slabel(lbl, s) -> size_stmt depth s
90105
| Sgoto lbl -> 1
91106

107+
let size_stmt s =
108+
min (size_stmt max_depth s) max_size
109+
92110
let more_likely (c: condexpr) (ifso: stmt) (ifnot: stmt) =
93111
size_stmt ifso > size_stmt ifnot
94112

0 commit comments

Comments
 (0)