From d5faa267c4a7856491aadc30d3f006a6c9237873 Mon Sep 17 00:00:00 2001 From: Mehdi Amini Date: Tue, 12 Apr 2016 21:35:28 +0000 Subject: [PATCH] Add a pass to name anonymous/nameless function Summary: For correct handling of alias to nameless function, we need to be able to refer them through a GUID in the summary. Here we name them using a hash of the non-private global names in the module. Reviewers: tejohnson Subscribers: joker.eph, llvm-commits Differential Revision: http://reviews.llvm.org/D18883 From: Mehdi Amini llvm-svn: 266132 --- llvm/include/llvm/InitializePasses.h | 1 + llvm/include/llvm/Transforms/Scalar.h | 3 + llvm/include/llvm/Transforms/Utils/ModuleUtils.h | 5 ++ llvm/lib/Transforms/IPO/PassManagerBuilder.cpp | 2 + llvm/lib/Transforms/Utils/CMakeLists.txt | 1 + llvm/lib/Transforms/Utils/NameAnonFunctions.cpp | 102 +++++++++++++++++++++++ llvm/lib/Transforms/Utils/Utils.cpp | 1 + llvm/test/Transforms/NameAnonFunctions/rename.ll | 27 ++++++ 8 files changed, 142 insertions(+) create mode 100644 llvm/lib/Transforms/Utils/NameAnonFunctions.cpp create mode 100644 llvm/test/Transforms/NameAnonFunctions/rename.ll diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index 924b79cf..d0af153 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -221,6 +221,7 @@ void initializeMergedLoadStoreMotionPass(PassRegistry &); void initializeMetaRenamerPass(PassRegistry&); void initializeMergeFunctionsPass(PassRegistry&); void initializeModuleDebugInfoPrinterPass(PassRegistry&); +void initializeNameAnonFunctionPass(PassRegistry &); void initializeNaryReassociatePass(PassRegistry&); void initializeNoAAPass(PassRegistry&); void initializeObjCARCAAWrapperPassPass(PassRegistry&); diff --git a/llvm/include/llvm/Transforms/Scalar.h b/llvm/include/llvm/Transforms/Scalar.h index c2bd77c..774d826 100644 --- a/llvm/include/llvm/Transforms/Scalar.h +++ b/llvm/include/llvm/Transforms/Scalar.h @@ -503,6 +503,9 @@ FunctionPass *createLoopVersioningPass(); // FunctionPass *createLoopDataPrefetchPass(); +///===---------------------------------------------------------------------===// +ModulePass *createNameAnonFunctionPass(); + } // End llvm namespace #endif diff --git a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h index 1b7180c..9184375 100644 --- a/llvm/include/llvm/Transforms/Utils/ModuleUtils.h +++ b/llvm/include/llvm/Transforms/Utils/ModuleUtils.h @@ -61,6 +61,11 @@ std::pair createSanitizerCtorAndInitFunctions( Module &M, StringRef CtorName, StringRef InitName, ArrayRef InitArgTypes, ArrayRef InitArgs, StringRef VersionCheckName = StringRef()); + +/// Rename all the anon functions in the module using a hash computed from +/// the list of public globals in the module. +bool nameUnamedFunctions(Module &M); + } // End llvm namespace #endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H diff --git a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp index e15cf1f..880dffa 100644 --- a/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp +++ b/llvm/lib/Transforms/IPO/PassManagerBuilder.cpp @@ -247,6 +247,8 @@ void PassManagerBuilder::addFunctionSimplificationPasses( if (PrepareForThinLTO) { MPM.add(createAggressiveDCEPass()); // Delete dead instructions addInstructionCombiningPass(MPM); // Combine silly seq's + // Rename anon function to export them + MPM.add(createNameAnonFunctionPass()); return; } // Rotate Loop - disable header duplication at -Oz diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt b/llvm/lib/Transforms/Utils/CMakeLists.txt index 04d2ace..5aec0dc 100644 --- a/llvm/lib/Transforms/Utils/CMakeLists.txt +++ b/llvm/lib/Transforms/Utils/CMakeLists.txt @@ -31,6 +31,7 @@ add_llvm_library(LLVMTransformUtils MemorySSA.cpp MetaRenamer.cpp ModuleUtils.cpp + NameAnonFunctions.cpp PromoteMemoryToRegister.cpp SSAUpdater.cpp SanitizerStats.cpp diff --git a/llvm/lib/Transforms/Utils/NameAnonFunctions.cpp b/llvm/lib/Transforms/Utils/NameAnonFunctions.cpp new file mode 100644 index 0000000..8a2208e --- /dev/null +++ b/llvm/lib/Transforms/Utils/NameAnonFunctions.cpp @@ -0,0 +1,102 @@ +//===- NameAnonFunctions.cpp - ThinLTO Summary-based Function Import ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements naming anonymous function to make sure they can be +// refered to by ThinLTO. +// +//===----------------------------------------------------------------------===// + +#include "llvm/ADT/SmallString.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/MD5.h" +#include "llvm/Transforms/Utils/ModuleUtils.h" + +using namespace llvm; + +// Compute a "unique" hash for the module based on the name of the public +// functions. +class ModuleHasher { + Module &TheModule; + std::string TheHash; + +public: + ModuleHasher(Module &M) : TheModule(M) {} + + /// Return the lazily computed hash. + std::string &get() { + if (!TheHash.empty()) + // Cache hit :) + return TheHash; + + MD5 Hasher; + for (auto &F : TheModule) { + if (F.isDeclaration() || F.hasLocalLinkage() || !F.hasName()) + continue; + auto Name = F.getName(); + Hasher.update(Name); + } + for (auto &GV : TheModule.globals()) { + if (GV.isDeclaration() || GV.hasLocalLinkage() || !GV.hasName()) + continue; + auto Name = GV.getName(); + Hasher.update(Name); + } + + // Now return the result. + MD5::MD5Result Hash; + Hasher.final(Hash); + SmallString<32> Result; + MD5::stringifyResult(Hash, Result); + TheHash = Result.str(); + return TheHash; + } +}; + +// Rename all the anon functions in the module +bool llvm::nameUnamedFunctions(Module &M) { + bool Changed = false; + ModuleHasher ModuleHash(M); + int count = 0; + for (auto &F : M) { + if (F.hasName()) + continue; + F.setName(Twine("anon.") + ModuleHash.get() + "." + Twine(count++)); + Changed = true; + } + return Changed; +} + +namespace { + +// Simple pass that provides a name to every anon function. +class NameAnonFunction : public ModulePass { + +public: + /// Pass identification, replacement for typeid + static char ID; + + /// Specify pass name for debug output + const char *getPassName() const override { return "Name Anon Functions"; } + + explicit NameAnonFunction() : ModulePass(ID) {} + + bool runOnModule(Module &M) override { return nameUnamedFunctions(M); } +}; +char NameAnonFunction::ID = 0; + +} // anonymous namespace + +INITIALIZE_PASS_BEGIN(NameAnonFunction, "name-anon-functions", + "Provide a name to nameless functions", false, false) +INITIALIZE_PASS_END(NameAnonFunction, "name-anon-functions", + "Provide a name to nameless functions", false, false) + +namespace llvm { +Pass *createNameAnonFunctionPass() { return new NameAnonFunction(); } +} diff --git a/llvm/lib/Transforms/Utils/Utils.cpp b/llvm/lib/Transforms/Utils/Utils.cpp index 4e5cece0..7e129c4 100644 --- a/llvm/lib/Transforms/Utils/Utils.cpp +++ b/llvm/lib/Transforms/Utils/Utils.cpp @@ -28,6 +28,7 @@ void llvm::initializeTransformUtils(PassRegistry &Registry) { initializeLoopSimplifyPass(Registry); initializeLowerInvokePass(Registry); initializeLowerSwitchPass(Registry); + initializeNameAnonFunctionPass(Registry); initializePromotePassPass(Registry); initializeUnifyFunctionExitNodesPass(Registry); initializeInstSimplifierPass(Registry); diff --git a/llvm/test/Transforms/NameAnonFunctions/rename.ll b/llvm/test/Transforms/NameAnonFunctions/rename.ll new file mode 100644 index 0000000..851746f --- /dev/null +++ b/llvm/test/Transforms/NameAnonFunctions/rename.ll @@ -0,0 +1,27 @@ +; RUN: opt -S -name-anon-functions < %s | FileCheck %s + + +; foo contribute to the unique hash for the module +define void @foo() { + ret void +} + +; bar is internal, and does not contribute to the unique hash for the module +define internal void @bar() { + ret void +} + +; CHECK: define void @anon.acbd18db4cc2f85cedef654fccc4a4d8.0() +; CHECK: define void @anon.acbd18db4cc2f85cedef654fccc4a4d8.1() +; CHECK: define void @anon.acbd18db4cc2f85cedef654fccc4a4d8.2() + +define void @0() { + ret void +} +define void @1() { + ret void +} +define void @2() { + ret void +} + -- 2.7.4