[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