Skip to content

__builtin_assume with embedded function calls are ignored #91612

Closed
@davidben

Description

@davidben

I'm not sure if this is a bug or working as intended, but it surprised me. Consider this code:

bool f1(std::string_view sv, size_t n) {
    return n <= sv.size();
}

bool f2(std::string_view sv, size_t n) {
    __builtin_assume(n <= sv.size());
    return n <= sv.size();
}

bool f3(std::string_view sv, size_t n) {
    size_t size = sv.size();
    __builtin_assume(n <= size);
    return n <= sv.size();
}

https://godbolt.org/z/1G6cao4ss

While this is a toy function, this is a minimized version of plausible patterns in real world code that wishes to simultaneously use bounds-checked STL mode, but also needs to manually annotate a few performance-critical invariants that the compiler is unable to discover.

Although f2 and f3 look like they would be the same, Clang only deletes the check in f3. Now, Clang does emit a warning, so perhaps this is intended, but the warning says:

<source>:8:22: warning: the argument to '__builtin_assume' has side effects that will be discarded [-Wassume]
    8 |     __builtin_assume(n <= sv.size());
      |    

This reads to me like saying that the side effects in sv.size() will be discarded at program runtime, but not that the compiler will also discard the stated invariant. As a programmer, I would read this and think, well, okay, sv.size() actually no side effects but the type system doesn't know that, so I can silence that warning, and assume that the optimizer will still figure it out.

However, it seems that it actually means that the whole invariant is discarded and the optimizer doesn't use the invariant. This is a bit non-obvious. It can be worked around with the pattern in f3, but:

  • The programmer needs to know to do that
  • It is more verbose
  • Presumably __builtin_assume will actually be a macro that expands to nothing on non-Clang compilers, but then we'll get a warning about unused size, which is extra tedious.

Metadata

Metadata

Assignees

Labels

clang:diagnosticsNew/improved warning or error message in Clang, but not in clang-tidy or static analyzer

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions