[llvm] [BOLT] Add support for safe-icf (PR #116275)

Davide Italiano via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 19 13:17:11 PST 2024


================
@@ -341,6 +344,75 @@ typedef std::unordered_map<BinaryFunction *, std::vector<BinaryFunction *>,
 namespace llvm {
 namespace bolt {
 
+void IdenticalCodeFolding::processDataRelocations(
+    BinaryContext &BC, const SectionRef &SecRefRelData) {
+  for (const RelocationRef &Rel : SecRefRelData.relocations()) {
+    symbol_iterator SymbolIter = Rel.getSymbol();
+    const ObjectFile *OwningObj = Rel.getObject();
+    assert(SymbolIter != OwningObj->symbol_end() &&
+           "relocation Symbol expected");
+    const SymbolRef &Symbol = *SymbolIter;
+    const uint64_t SymbolAddress = cantFail(Symbol.getAddress());
+    const ELFObjectFileBase *ELFObj = dyn_cast<ELFObjectFileBase>(OwningObj);
+    if (!ELFObj)
+      llvm_unreachable("Only ELFObjectFileBase is supported");
+    const int64_t Addend = BinaryContext::getRelocationAddend(ELFObj, Rel);
+    BinaryFunction *BF = BC.getBinaryFunctionAtAddress(SymbolAddress + Addend);
+    if (!BF)
+      continue;
+    BF->setUnsafeICF();
+  }
+}
+
+Error IdenticalCodeFolding::markFunctionsUnsafeToFold(BinaryContext &BC) {
+  Error ErrorStatus = Error::success();
+  ErrorOr<BinarySection &> SecRelData = BC.getUniqueSectionByName(".rela.data");
+  if (!BC.HasRelocations)
+    ErrorStatus = joinErrors(
+        std::move(ErrorStatus),
+        createFatalBOLTError(Twine("BOLT-ERROR: Binary built without "
+                                   "relocations. Safe ICF is not supported")));
+  if (ErrorStatus)
+    return ErrorStatus;
+  if (SecRelData) {
+    SectionRef SecRefRelData = SecRelData->getSectionRef();
+    processDataRelocations(BC, SecRefRelData);
+  }
+
+  ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
+    if (BF.getState() == BinaryFunction::State::CFG) {
+      for (const BinaryBasicBlock *BB : BF.getLayout().blocks())
+        for (const MCInst &Inst : *BB)
+          BC.processInstructionForFuncReferences(Inst);
+    }
+  };
+  ParallelUtilities::PredicateTy SkipFunc =
+      [&](const BinaryFunction &BF) -> bool { return (bool)ErrorStatus; };
+  ParallelUtilities::runOnEachFunction(
+      BC, ParallelUtilities::SchedulingPolicy::SP_TRIVIAL, WorkFun, SkipFunc,
+      "markUnsafe", /*ForceSequential*/ false, 2);
+
+  LLVM_DEBUG({
+    std::vector<StringRef> Vect;
+    std::mutex PrintMutex;
+    ParallelUtilities::WorkFuncTy WorkFun = [&](BinaryFunction &BF) {
+      if (BF.isSafeToICF())
+        return;
+      std::lock_guard<std::mutex> Lock(PrintMutex);
+      Vect.push_back(BF.getOneName());
+    };
+    ParallelUtilities::PredicateTy SkipFunc =
+        [&](const BinaryFunction &BF) -> bool { return false; };
+    ParallelUtilities::runOnEachFunction(
+        BC, ParallelUtilities::SchedulingPolicy::SP_TRIVIAL, WorkFun, SkipFunc,
+        "markUnsafe", /*ForceSequential*/ false, 2);
+    llvm::sort(Vect);
----------------
dcci wrote:

Can you explain why you need this determinism?

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


More information about the llvm-commits mailing list