[llvm] [Bolt] Teach bolt about no-return functions (PR #115616)

Gergely Bálint via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 28 05:18:26 PST 2024


================
@@ -0,0 +1,84 @@
+//===- bolt/Passes/ReorderSection.cpp - Reordering of section data --------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements DiscoverNoReturnPass class.
+//
+//===----------------------------------------------------------------------===//
+
+#include "bolt/Passes/DiscoverNoReturnPass.h"
+
+using namespace llvm;
+
+namespace opts {
+extern cl::OptionCategory BoltCategory;
+
+static cl::opt<bool> DiscoverNoReturnAnalysis(
+    "discover-no-return",
+    cl::desc("analyze the binary and mark no-return functions"), cl::init(true),
+    cl::cat(BoltCategory), cl::ReallyHidden);
+} // namespace opts
+
+namespace llvm {
+namespace bolt {
+
+Error DiscoverNoReturnPass::runOnFunctions(BinaryContext &BC) {
+  bool Changed;
+  do {
+    Changed = false;
+    for (auto &BFI : BC.getBinaryFunctions()) {
+      auto &Func = BFI.second;
+      bool PrevStat = BC.hasPathToNoReturn(&Func);
+      bool CurStat = traverseFromFunction(&Func, BC);
+      Changed |= (PrevStat != CurStat);
+    }
+  } while (Changed);
+
+  return Error::success();
+}
+
+bool DiscoverNoReturnPass::traverseFromFunction(BinaryFunction *Func,
+                                                BinaryContext &BC) {
+  // The Function cached before, so return its value
+  if (BC.cachedInNoReturnMap(Func))
+    return BC.hasPathToNoReturn(Func);
+
+  Visited[Func] = true;
+  bool Result = true;
+  bool hasCalls = 0;
+  bool hasReturns = 0;
+  for (auto &BB : *Func) {
+    if (!BB.getNumCalls())
+      continue;
+    for (auto &Inst : BB) {
+      if (BC.MIB->isCall(Inst)) {
+        hasCalls = true;
+        const MCSymbol *TargetSymbol = BC.MIB->getTargetSymbol(Inst);
+        BinaryFunction *TargetFunction = BC.SymbolToFunctionMap[TargetSymbol];
+        if (!Visited.count(TargetFunction))
+          Result &= traverseFromFunction(TargetFunction, BC);
+      }
+      hasReturns |= BC.MIB->isReturn(Inst);
+    }
+  }
+
+  // This functions is represented as a leaf in the call graph and doesn't
+  // have a no-return attribute.
+  if (!hasCalls && hasReturns)
+    Result = false;
+
+  // If the function doens't have a return instruction then it's a
+  // no-return function.
+  if (!hasReturns)
+    Result = true;
----------------
bgergely0 wrote:

Tailcalls should also be taken into account (`BC.MIB->isTailCall(Inst)`). If a function ends in a tailcall instruction, it depends on the Called function if it is NoReturn.

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


More information about the llvm-commits mailing list