[PATCH] D39761: [Support] Make llvm::Error faster

Zachary Turner via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 7 16:50:21 PST 2017


zturner updated this revision to Diff 122020.
zturner added a comment.
Herald added a subscriber: hiraditya.

I went ahead and applied the same optimization for `llvm::Expected`, and also incorporated other suggestions.  Even though `Expected` wasn't showing up on the profile, this only arose because we happened to be a heavy user of `Error`.  If someone else happened to be a heavy user of `Expected`, we'd see the same issues arise.

To answer @lhames question about the Error destructor, It's hard for me to check the total time in Error's destructor, or at least I don't know how to do it with this particular profiler.  I can either get exclusive samples, in which case the number won't account for nested calls inside of the destructor, or I can get inclusive samples, in which case I'll need to find every callsite of an `Error` destructor.  I'm sure there's a way, I just don't know this profiler tht well.

What I can say though is that before the patch, on one particular run `lld-link` had 23,271 total samples, 2,017 samples of which were in `assertUnchecked`.    After the patch, `lld-link` had 25,493 total samples, 0 of which were in `assertUnchecked`  (i.e. it wasn't even on the profile).


https://reviews.llvm.org/D39761

Files:
  llvm/include/llvm/Support/Error.h
  llvm/lib/Support/Error.cpp


Index: llvm/lib/Support/Error.cpp
===================================================================
--- llvm/lib/Support/Error.cpp
+++ llvm/lib/Support/Error.cpp
@@ -91,6 +91,18 @@
   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) {}
 
Index: llvm/include/llvm/Support/Error.h
===================================================================
--- llvm/include/llvm/Support/Error.h
+++ llvm/include/llvm/Support/Error.h
@@ -246,18 +246,20 @@
   }
 
 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 @@
 #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
   }
 


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D39761.122020.patch
Type: text/x-patch
Size: 3048 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20171108/ed9b8d8b/attachment.bin>


More information about the llvm-commits mailing list