Skip to content

Add function inlining pass to improve DSA precision - #809

Open
shaobo-he wants to merge 5 commits into
developfrom
function-inlining
Open

Add function inlining pass to improve DSA precision#809
shaobo-he wants to merge 5 commits into
developfrom
function-inlining

Conversation

@shaobo-he

Copy link
Copy Markdown
Contributor

Inline small functions (especially pointer-involving ones) before sea-dsa analysis to reduce unnecessary node merges caused by context-insensitive analysis. Uses SCC-based recursion detection and bottom-up call graph processing.

Inline small functions (especially pointer-involving ones) before
sea-dsa analysis to reduce unnecessary node merges caused by
context-insensitive analysis. Uses SCC-based recursion detection
and bottom-up call graph processing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@shaobo-he
shaobo-he requested a review from keram88 March 14, 2026 18:22
shaobo-he and others added 4 commits March 14, 2026 11:34
The inlining pass is useful for DSA precision but may not be
desired in all contexts. Disable it by default and enable it
in the SVCOMP frontend via --inline-funcs flag.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
`-fsanitize=unsigned-integer-overflow` was added to frontend.py by commit
8a69c5d ("updates") alongside genuine inliner work. It was committed by
mistake and has nothing to do with function inlining.

It was not inert. Because the condition is on the integer encoding rather
than on any check being requested, it applied to every run that did not pass
`--integer-encoding=bit-vector` -- i.e. the default. clang then emitted
`llvm.uadd/usub/umul.with.overflow` intrinsics, which IntegerOverflowChecker
matches without discriminating signed from unsigned
(lib/smack/IntegerOverflowChecker.cpp:28), so `--check=integer-overflow`
reported an error for plain unsigned wraparound:

    unsigned x = __VERIFIER_nondet_unsigned_int();
    unsigned y = x + 1;

    before: SMACK found an error: integer overflow.
    after:  SMACK found no errors with unroll bound 1.

Unsigned wraparound is well-defined modular arithmetic (C17 6.2.5p9), which
is why clang leaves this check out of -fsanitize=undefined.

On the default unbounded-integer encoding the instrumentation could not even
buy precision, since $trunc and $zext are identity functions there. It only
added, per unsigned +/-/*, a branch and a call to a bodyless external, plus a
pair of ubsan descriptor globals per file. Two further side effects: the
rewrite dropped the `{:cexpr}` recording for the assigned variable, so error
traces stopped naming it, and one of the new globals embeds the absolute
source path, which made $GLOBALS_BOTTOM -- and hence the generated Boogie --
depend on the directory the input happened to live in.

The existing suite did not catch any of this: the integer-overflow tests in
test/c/targeted-checks and test/c/bits pin --integer-encoding=bit-vector, so
the added condition was false for all of them.

share/smack/frontend.py is now byte-identical to the merge base again.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant