necipfazil created this revision. necipfazil added reviewers: lattner, morehouse, kcc, llvm-commits. Herald added subscribers: ormris, hiraditya, mgorny. necipfazil requested review of this revision. Herald added projects: clang, LLVM. Herald added a subscriber: cfe-commits.
Create comdats for functions whose symbols will be referenced from the call graph section. These comdats are used to create the call graph sections, so that, the sections can get discarded by the linker if the functions get removed. Original RFC: https://lists.llvm.org/pipermail/llvm-dev/2021-June/151044.html Updated RFC: https://lists.llvm.org/pipermail/llvm-dev/2021-July/151739.html Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D105911 Files: clang/lib/CodeGen/BackendUtil.cpp llvm/include/llvm/Transforms/Utils/CGSectionFuncComdatCreator.h llvm/lib/Passes/PassBuilder.cpp llvm/lib/Passes/PassRegistry.def llvm/lib/Transforms/Utils/CGSectionFuncComdatCreator.cpp llvm/lib/Transforms/Utils/CMakeLists.txt llvm/test/Transforms/Util/create-function-comdats.ll
Index: llvm/test/Transforms/Util/create-function-comdats.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/Util/create-function-comdats.ll @@ -0,0 +1,21 @@ +; Tests that we create function comdats properly and only for those with no +; comdats. + +; RUN: opt -passes='cg-section-func-comdat-creator' -S %s | FileCheck %s + +; CHECK: $f = comdat noduplicates +; CHECK: $g = comdat any +$g = comdat any + +; CHECK: define dso_local void @f() comdat { +define dso_local void @f() { +entry: + ret void +} + +; CHECK: define dso_local void @g() comdat { +define dso_local void @g() comdat { +entry: + ret void +} + Index: llvm/lib/Transforms/Utils/CMakeLists.txt =================================================================== --- llvm/lib/Transforms/Utils/CMakeLists.txt +++ llvm/lib/Transforms/Utils/CMakeLists.txt @@ -7,6 +7,7 @@ BreakCriticalEdges.cpp BuildLibCalls.cpp BypassSlowDivision.cpp + CGSectionFuncComdatCreator.cpp CallPromotionUtils.cpp CallGraphUpdater.cpp CanonicalizeAliases.cpp Index: llvm/lib/Transforms/Utils/CGSectionFuncComdatCreator.cpp =================================================================== --- /dev/null +++ llvm/lib/Transforms/Utils/CGSectionFuncComdatCreator.cpp @@ -0,0 +1,98 @@ +//===-- CGSectionFuncComdatCreator.cpp - CG section func comdat creator ---===// +// +// 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 pass creates comdats for functions whose symbols will be referenced +// from the call graph section. These comdats are used to create the call graph +// sections, so that, the sections can get discarded by the linker if the +// functions get removed. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Transforms/Utils/CGSectionFuncComdatCreator.h" + +#include "llvm/ADT/Triple.h" +#include "llvm/IR/Instructions.h" + +namespace llvm { + +namespace { +class ModuleCGSectionFuncComdatCreator { +public: + bool instrumentModule(Module &); + +private: + bool createFunctionComdat(Function &F, const Triple &T) const; + bool hasIndirectCalls(const Function &F) const; + bool isTargetToIndirectCalls(const Function &F) const; +}; + +bool ModuleCGSectionFuncComdatCreator::createFunctionComdat( + Function &F, const Triple &T) const { + if (auto *Comdat = F.getComdat()) + return false; + assert(F.hasName()); + Module *M = F.getParent(); + + // Make a new comdat for the function. Use the "no duplicates" selection kind + // if the object file format supports it. For COFF we restrict it to non-weak + // symbols. + Comdat *C = M->getOrInsertComdat(F.getName()); + if (T.isOSBinFormatELF() || (T.isOSBinFormatCOFF() && !F.isWeakForLinker())) + C->setSelectionKind(Comdat::NoDuplicates); + F.setComdat(C); + return true; +} + +bool ModuleCGSectionFuncComdatCreator::hasIndirectCalls( + const Function &F) const { + for (const auto &I : F) + if (const CallInst *CI = dyn_cast<CallInst>(&I)) + if (CI->isIndirectCall()) + return true; + return false; +} + +bool ModuleCGSectionFuncComdatCreator::isTargetToIndirectCalls( + const Function &F) const { + return !F.hasLocalLinkage() || + F.hasAddressTaken(nullptr, + /* IgnoreCallbackUses */ true, + /* IgnoreAssumeLikeCalls */ true, + /* IgnoreLLVMUsed */ false); +} + +bool ModuleCGSectionFuncComdatCreator::instrumentModule(Module &M) { + Triple TargetTriple = Triple(M.getTargetTriple()); + + bool CreatedComdats = false; + + for (Function &F : M) { + if (isTargetToIndirectCalls(F) || hasIndirectCalls(F)) { + if (TargetTriple.supportsCOMDAT() && !F.isInterposable() && + !F.isDeclarationForLinker()) { + CreatedComdats |= createFunctionComdat(F, TargetTriple); + } + } + } + + return CreatedComdats; +} + +} // namespace + +PreservedAnalyses +CGSectionFuncComdatCreatorPass::run(Module &M, ModuleAnalysisManager &AM) { + ModuleCGSectionFuncComdatCreator ModuleCG; + if (ModuleCG.instrumentModule(M)) { + return PreservedAnalyses::none(); + } + return PreservedAnalyses::all(); +} + +} // namespace llvm + Index: llvm/lib/Passes/PassRegistry.def =================================================================== --- llvm/lib/Passes/PassRegistry.def +++ llvm/lib/Passes/PassRegistry.def @@ -45,6 +45,7 @@ MODULE_PASS("attributor", AttributorPass()) MODULE_PASS("annotation2metadata", Annotation2MetadataPass()) MODULE_PASS("openmp-opt", OpenMPOptPass()) +MODULE_PASS("cg-section-func-comdat-creator", CGSectionFuncComdatCreatorPass()) MODULE_PASS("called-value-propagation", CalledValuePropagationPass()) MODULE_PASS("canonicalize-aliases", CanonicalizeAliasesPass()) MODULE_PASS("cg-profile", CGProfilePass()) Index: llvm/lib/Passes/PassBuilder.cpp =================================================================== --- llvm/lib/Passes/PassBuilder.cpp +++ llvm/lib/Passes/PassBuilder.cpp @@ -211,6 +211,7 @@ #include "llvm/Transforms/Utils/AddDiscriminators.h" #include "llvm/Transforms/Utils/AssumeBundleBuilder.h" #include "llvm/Transforms/Utils/BreakCriticalEdges.h" +#include "llvm/Transforms/Utils/CGSectionFuncComdatCreator.h" #include "llvm/Transforms/Utils/CanonicalizeAliases.h" #include "llvm/Transforms/Utils/CanonicalizeFreezeInLoops.h" #include "llvm/Transforms/Utils/EntryExitInstrumenter.h" Index: llvm/include/llvm/Transforms/Utils/CGSectionFuncComdatCreator.h =================================================================== --- /dev/null +++ llvm/include/llvm/Transforms/Utils/CGSectionFuncComdatCreator.h @@ -0,0 +1,32 @@ +//===-- CGSectionFuncComdatCreator.h - CG func comdat creator ---*- C++ -*-===// +// +// 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 pass creates comdats for functions whose symbols will be referenced +// from the call graph section. These comdats are used to create the call graph +// sections, so that, the sections can get discarded by the linker if the +// functions get removed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_CGSECTIONFUNCCOMDATCREATOR_H +#define LLVM_TRANSFORMS_UTILS_CGSECTIONFUNCCOMDATCREATOR_H + +#include "llvm/IR/PassManager.h" + +namespace llvm { + +class CGSectionFuncComdatCreatorPass + : public PassInfoMixin<CGSectionFuncComdatCreatorPass> { +public: + PreservedAnalyses run(Module &, ModuleAnalysisManager &); +}; + +} // namespace llvm + +#endif // LLVM_TRANSFORMS_UTILS_CGSECTIONFUNCCOMDATCREATOR_H + Index: clang/lib/CodeGen/BackendUtil.cpp =================================================================== --- clang/lib/CodeGen/BackendUtil.cpp +++ clang/lib/CodeGen/BackendUtil.cpp @@ -81,6 +81,7 @@ #include "llvm/Transforms/Scalar/GVN.h" #include "llvm/Transforms/Scalar/LowerMatrixIntrinsics.h" #include "llvm/Transforms/Utils.h" +#include "llvm/Transforms/Utils/CGSectionFuncComdatCreator.h" #include "llvm/Transforms/Utils/CanonicalizeAliases.h" #include "llvm/Transforms/Utils/Debugify.h" #include "llvm/Transforms/Utils/EntryExitInstrumenter.h" @@ -1415,6 +1416,10 @@ MPM.addPass(createModuleToFunctionPassAdaptor(MemProfilerPass())); MPM.addPass(ModuleMemProfilerPass()); } + + if (CodeGenOpts.CallGraphSection) { + MPM.addPass(CGSectionFuncComdatCreatorPass()); + } } // FIXME: We still use the legacy pass manager to do code generation. We
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits