-
Notifications
You must be signed in to change notification settings - Fork 12.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Why generate __throw_length_error, __throw_bad_array_new_length in std::vector with -fno-exceptions? #64132
Comments
@llvm/issue-subscribers-clang-codegen |
Because we want to abort when an assumption is not met. If we didn't do that the code would do very weird things if you hit these cases. Although this seems quite obvious to me, so I guess you want something specific? |
Probably vector::resize calls allocator::allocate, where __throw_bad_array_new_length is called in call cases. _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
_Tp* allocate(size_t __n) {
if (__n > allocator_traits<allocator>::max_size(*this))
__throw_bad_array_new_length();
if (__libcpp_is_constant_evaluated()) {
return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
} else {
return static_cast<_Tp*>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)));
}
} I think |
btw, gcc doesn't throw or call abort in this case (with or without -fno-exceptions) https://godbolt.org/z/TrvGsc3a6 |
Why would we want to do that? It's not like throwing will ever be a hot path.
No. That would just result in having to handle the case in more places. Whether we abort in |
That's because gcc ends up inlining more aggressively; libstdc++ has the same checks, the code just gets folded away. Which I guess could be considered an LLVM bug, but it only affects the case where the argument to resize() is a constant. There's another missed optimization that seems more significant, though: I think the call to __throw_bad_array_new_length is unreachable, but LLVM can't manage to eliminate it. Not sure if there's some simple LLVM fix for that, or if the implementation of __append is structured in a way that makes the optimization impractical.
I think the idea here is to reduce the codesize of the cold codepath? Something along the lines of |
I haven't looked at the code of libstdc++ but from this example (https://godbolt.org/z/3r1nGn4Pr) resize with unknown number doesn't generate a
Code size is an issue for sure. |
Yes, it does: https://godbolt.org/z/zv3zWPjqn
"Way more frequently used" and "hot path" are completely different things. If 99.9% of calls don't take a path, that path is cold no matter how often the code is called. We don't want to pessimize the 99.9% of cases to get marginally better performance in the 0.01% of cases. |
Ah i see. the outlined cold function
sure, my intent was not to pessimize remaining code. I was only looking for ways where we can avoid generating calls to throw when possible, as in the motivating testcase for this issue. |
I don't find you example to be particularly motivating TBH. This probably saves you just about nothing, since it will most likely just get generated by a different TU. It's also just a few bytes of code plus a tiny bit of data. |
Focusing on what we can do instead of what we can't do, I see the following possible sources of savings:
|
A related PR is under review: #69498 |
Closing, since I don't see anything actionable here. |
Opened #87010 for the redundant bounds-check. |
$ clang++ -O3 -stdlib=libc++ -fno-exceptions -std=c++20
The text was updated successfully, but these errors were encountered: