1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 20:51:52 +01:00

[Support] Make llvm::Error and Expected faster.

Whenever LLVM_ENABLE_ABI_BREAKING_CHECKS is enabled, which
is usually the case for example when asserts are enabled,
Error's destructor does some additional checking to make sure
that that it does not represent an error condition and that it
was checked.

However, this is -- by definition -- not the likely codepath.
Some profiling shows that at least with some compilers, simply
calling assertIsChecked -- in a release build with full
optimizations -- can account for up to 15% of the entire
runtime of the program, even though this function should almost
literally be a no-op.

The problem is that the assertIsChecked function can be considered
too big to inline depending on the compiler's inliner.  Since it's
unlikely to ever need to failure path though, we can move it out
of line and force it to not be inlined, so that the fast path
can be inlined.

In my test (using lld to link clang with CMAKE_BUILD_TYPE=Release
and LLVM_ENABLE_ASSERTIONS=ON), this reduces link time from 27
seconds to 23.5 seconds, which is a solid 15% gain.

llvm-svn: 317824
This commit is contained in:
Zachary Turner 2017-11-09 19:31:52 +00:00
parent 827225754a
commit 61d980d677
2 changed files with 42 additions and 21 deletions

View File

@ -246,18 +246,20 @@ public:
}
private:
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
// assertIsChecked() happens very frequently, but under normal circumstances
// is supposed to be a no-op. So we want it to be inlined, but having a bunch
// of debug prints can cause the function to be too large for inlining. So
// it's important that we define this function out of line so that it can't be
// inlined.
LLVM_ATTRIBUTE_NORETURN
void fatalUncheckedError() const;
#endif
void assertIsChecked() {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
if (!getChecked() || getPtr()) {
dbgs() << "Program aborted due to an unhandled Error:\n";
if (getPtr())
getPtr()->log(dbgs());
else
dbgs()
<< "Error value was Success. (Note: Success values must still be "
"checked prior to being destroyed).\n";
abort();
}
if (LLVM_UNLIKELY(!getChecked() || getPtr()))
fatalUncheckedError();
#endif
}
@ -632,19 +634,26 @@ private:
#endif
}
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
LLVM_ATTRIBUTE_NORETURN
LLVM_ATTRIBUTE_NOINLINE
void fatalUncheckedExpected() const {
dbgs() << "Expected<T> must be checked before access or destruction.\n";
if (HasError) {
dbgs() << "Unchecked Expected<T> contained error:\n";
(*getErrorStorage())->log(dbgs());
} else
dbgs() << "Expected<T> value was in success state. (Note: Expected<T> "
"values in success mode must still be checked prior to being "
"destroyed).\n";
abort();
}
#endif
void assertIsChecked() {
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
if (Unchecked) {
dbgs() << "Expected<T> must be checked before access or destruction.\n";
if (HasError) {
dbgs() << "Unchecked Expected<T> contained error:\n";
(*getErrorStorage())->log(dbgs());
} else
dbgs() << "Expected<T> value was in success state. (Note: Expected<T> "
"values in success mode must still be checked prior to being "
"destroyed).\n";
abort();
}
if (LLVM_UNLIKELY(Unchecked))
fatalUncheckedExpected();
#endif
}

View File

@ -91,6 +91,18 @@ std::error_code errorToErrorCode(Error Err) {
return EC;
}
#if LLVM_ENABLE_ABI_BREAKING_CHECKS
void Error::fatalUncheckedError() const {
dbgs() << "Program aborted due to an unhandled Error:\n";
if (getPtr())
getPtr()->log(dbgs());
else
dbgs() << "Error value was Success. (Note: Success values must still be "
"checked prior to being destroyed).\n";
abort();
}
#endif
StringError::StringError(const Twine &S, std::error_code EC)
: Msg(S.str()), EC(EC) {}