[llvm] [LowerGlobalDtors] Skip __cxa_atexit call completely when arg0 is unused (PR #68758)

via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 10 19:08:09 PDT 2023


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Sam Clegg (sbc100)

<details>
<summary>Changes</summary>

In emscripten we have a build mode (the default actually) where the runtime never exits and there for `__cxa_atexit` is a dummy/stub function that does nothing.  In this case we would like to be able completely DCE any otherwise-unused global dtor functions.

Fixes: https://github.com/emscripten-core/emscripten/issues/19993

---
Full diff: https://github.com/llvm/llvm-project/pull/68758.diff


2 Files Affected:

- (modified) llvm/lib/Transforms/Utils/LowerGlobalDtors.cpp (+11) 
- (added) llvm/test/Transforms/LowerGlobalDestructors/lower-global-dtors-unused.ll (+17) 


``````````diff
diff --git a/llvm/lib/Transforms/Utils/LowerGlobalDtors.cpp b/llvm/lib/Transforms/Utils/LowerGlobalDtors.cpp
index 195c274ff18e2cd..f67a1eb53b8976a 100644
--- a/llvm/lib/Transforms/Utils/LowerGlobalDtors.cpp
+++ b/llvm/lib/Transforms/Utils/LowerGlobalDtors.cpp
@@ -140,6 +140,17 @@ static bool runImpl(Module &M) {
                         {PointerType::get(AtExitFuncTy, 0), VoidStar, VoidStar},
                         /*isVarArg=*/false));
 
+  // If __cxa_atexit is defined (e.g. in the case of LTO) and arg0 is not
+  // actually used (i.e. it's dummy/stub function as used in emscripten when
+  // the program never exits) we can simply return early and clear out
+  // @llvm.global_dtors.
+  if (auto F = dyn_cast<Function>(AtExit.getCallee())) {
+    if (F && F->hasExactDefinition() && F->getArg(0)->getNumUses() == 0) {
+      GV->eraseFromParent();
+      return true;
+    }
+  }
+
   // Declare __dso_local.
   Type *DsoHandleTy = Type::getInt8Ty(C);
   Constant *DsoHandle = M.getOrInsertGlobal("__dso_handle", DsoHandleTy, [&] {
diff --git a/llvm/test/Transforms/LowerGlobalDestructors/lower-global-dtors-unused.ll b/llvm/test/Transforms/LowerGlobalDestructors/lower-global-dtors-unused.ll
new file mode 100644
index 000000000000000..a6e7133b2947ee4
--- /dev/null
+++ b/llvm/test/Transforms/LowerGlobalDestructors/lower-global-dtors-unused.ll
@@ -0,0 +1,17 @@
+; RUN: opt -passes=lower-global-dtors -S < %s | FileCheck %s --implicit-check-not=llvm.global_dtors
+
+; Test that @llvm.global_dtors is completely removed if __cxa_atexit
+; is a no-op (i.e. doesn't use its first argument).
+
+declare void @orig_dtor()
+
+define i32 @__cxa_atexit(ptr, ptr, ptr) {
+  ret i32 0
+}
+
+ at llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [
+  { i32, ptr, ptr } { i32 0, ptr @orig_dtor, ptr null }
+]
+
+; CHECK-NOT: @llvm.global_dtors
+; CHECK-NOT: call void @orig_dtor()

``````````

</details>


https://github.com/llvm/llvm-project/pull/68758


More information about the llvm-commits mailing list