Index: llvm/lib/Transforms/Utils/ModuleUtils.cpp =================================================================== --- llvm/lib/Transforms/Utils/ModuleUtils.cpp +++ llvm/lib/Transforms/Utils/ModuleUtils.cpp @@ -17,12 +17,17 @@ #include "llvm/IR/IRBuilder.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Support/xxhash.h" using namespace llvm; #define DEBUG_TYPE "moduleutils" +static cl::opt EmptyModuleId("empty-moduleid", cl::init(false), + cl::Hidden, + cl::desc("Always emit an empty ModuleID")); + static void appendToGlobalArray(StringRef ArrayName, Module &M, Function *F, int Priority, Constant *Data) { IRBuilder<> IRB(M.getContext()); @@ -296,6 +301,9 @@ } std::string llvm::getUniqueModuleId(Module *M) { + if (EmptyModuleId) + return ""; + MD5 Md5; bool ExportsSymbols = false; auto AddGlobal = [&](GlobalValue &GV) { @@ -316,6 +324,47 @@ for (auto &IF : M->ifuncs()) AddGlobal(IF); + if (!ExportsSymbols) { + Md5.update(M->getModuleIdentifier()); + Md5.update(ArrayRef{0}); + + auto AddWeakerGlobal = [&](const GlobalValue &GV) { + if (GV.isDeclaration() || GV.getName().startswith("llvm.") || + GV.hasWeakLinkage()) { + ExportsSymbols = true; + Md5.update(GV.getName()); + Md5.update(ArrayRef{0}); + } + }; + + // When UnifiedLTO is enabled, we always need to generate split modules + // which requires a ModuleID. Using more types of metadata to generate this + // hash helps to ensure this. + auto AddArrayElt = + [&](const char *array, + std::function fun) { + if (auto *Used = M->getNamedGlobal(array)) + if (const auto *A = dyn_cast(Used->getInitializer())) + for (const Value *Op : A->operands()) + if (const GlobalValue *GV = fun(Op)) + AddWeakerGlobal(*GV); + }; + AddArrayElt("llvm.used", [&](const Value *Op) -> const GlobalValue * { + return dyn_cast(Op->stripPointerCasts()); + }); + AddArrayElt("llvm.global_ctors", + [&](const Value *Op) -> const GlobalValue * { + if (const auto *CS = dyn_cast(Op)) + if (const auto *GV = + dyn_cast(CS->getAggregateElement(1))) + return GV; + return nullptr; + }); + + for (auto &GV : M->globals()) + AddWeakerGlobal(GV); + } + if (!ExportsSymbols) return ""; @@ -324,6 +373,9 @@ SmallString<32> Str; MD5::stringifyResult(R, Str); + + LLVM_DEBUG(dbgs() << "Generated ModuleID: " << Str.str() << "\n"); + return ("." + Str).str(); } Index: llvm/test/CodeGen/PowerPC/aix-static-init-no-unique-module-id.ll =================================================================== --- llvm/test/CodeGen/PowerPC/aix-static-init-no-unique-module-id.ll +++ llvm/test/CodeGen/PowerPC/aix-static-init-no-unique-module-id.ll @@ -1,5 +1,5 @@ -; RUN: llc -mtriple powerpc-ibm-aix-xcoff < %s | FileCheck %s -; RUN: llc -mtriple powerpc64-ibm-aix-xcoff < %s | FileCheck %s +; RUN: llc -mtriple powerpc-ibm-aix-xcoff -empty-moduleid < %s | FileCheck %s +; RUN: llc -mtriple powerpc64-ibm-aix-xcoff -empty-moduleid < %s | FileCheck %s @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @foo, ptr null }] Index: llvm/test/LTO/Resolution/X86/llvm-used-moduleid.ll =================================================================== --- /dev/null +++ llvm/test/LTO/Resolution/X86/llvm-used-moduleid.ll @@ -0,0 +1,19 @@ +; RUN: opt <%s -thinlto-bc -thinlto-split-lto-unit -o %t0 +; RUN: llvm-bcanalyzer %t0 | FileCheck %s + +target triple="x86_64-pc-linux-gnu" + +@llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @a to i8*)], !type !0 + +declare i1 @llvm.type.test(i8*, metadata) +declare void @llvm.assume(i1) + +; CHECK: GLOBALVAL_SUMMARY_BLOCK +; CHECK: FULL_LTO_GLOBALVAL_SUMMARY_BLOCK +define internal void @a() { + %1 = call i1 @llvm.type.test(i8* undef, metadata !"a") + call void @llvm.assume(i1 %1) + ret void +} + +!0 = !{i64 16, !"a"} Index: llvm/test/LTO/Resolution/X86/weak-linkage-moduleid.ll =================================================================== --- /dev/null +++ llvm/test/LTO/Resolution/X86/weak-linkage-moduleid.ll @@ -0,0 +1,19 @@ +; RUN: opt <%s -thinlto-bc -thinlto-split-lto-unit -o %t0 +; RUN: llvm-bcanalyzer %t0 | FileCheck %s + +target triple="x86_64-pc-linux-gnu" + +@p = weak global void ()* @a, !type !0 + +declare i1 @llvm.type.test(i8*, metadata) +declare void @llvm.assume(i1) + +; CHECK: GLOBALVAL_SUMMARY_BLOCK +; CHECK: FULL_LTO_GLOBALVAL_SUMMARY_BLOCK +define internal void @a() { + %1 = call i1 @llvm.type.test(i8* undef, metadata !"a") + call void @llvm.assume(i1 %1) + ret void +} + +!0 = !{i64 16, !"a"} Index: llvm/test/LTO/X86/path-moduleid.ll =================================================================== --- /dev/null +++ llvm/test/LTO/X86/path-moduleid.ll @@ -0,0 +1,27 @@ +; REQUIRES: asserts +; Test that chaning the path to the module doesn't effect the ModuleID. This +; file and Inputs/path-moduleid.ll have the same content, and thus should have +; the same ModuleID. +; RUN: opt -o /dev/null -thinlto-bc -thinlto-split-lto-unit=1 --debug-only=moduleutils %s 2>%t0 +; RUN: mkdir -p %t; cp %s %t/path-moduleid.ll +; RUN: opt -o /dev/null -thinlto-bc -thinlto-split-lto-unit=1 --debug-only=moduleutils %t/path-moduleid.ll 2>%t1 +; RUN: FileCheck %s <%t0 +; RUN: FileCheck %s <%t1 +; RUN: not diff %t0 %t1 + +; CHECK: Generated ModuleID: +target triple="x86_64-pc-linux-gnu" + +@llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @a to i8*)], !type !0 + +declare i1 @llvm.type.test(i8*, metadata) +declare void @llvm.assume(i1) + +define internal void @a() { + %1 = call i1 @llvm.type.test(i8* undef, metadata !"a") + call void @llvm.assume(i1 %1) + ret void +} + + +!0 = !{i64 16, !"a"} Index: llvm/test/ThinLTO/X86/cfi-unsat.ll =================================================================== --- llvm/test/ThinLTO/X86/cfi-unsat.ll +++ llvm/test/ThinLTO/X86/cfi-unsat.ll @@ -12,8 +12,8 @@ ; so the resolution is Unsat and the type.checked.load instructions are ; converted to type tests that evaluate to false. -; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t.o %s -; RUN: opt -thinlto-bc -thinlto-split-lto-unit -o %t1.o %p/Inputs/cfi-unsat.ll +; RUN: opt -thinlto-bc -empty-moduleid -thinlto-split-lto-unit -o %t.o %s +; RUN: opt -thinlto-bc -empty-moduleid -thinlto-split-lto-unit -o %t1.o %p/Inputs/cfi-unsat.ll ; RUN: llvm-lto2 run %t.o %t1.o -save-temps -pass-remarks=. \ ; RUN: -whole-program-visibility \ Index: llvm/test/ThinLTO/X86/nodevirt-nonpromoted-typeid.ll =================================================================== --- llvm/test/ThinLTO/X86/nodevirt-nonpromoted-typeid.ll +++ llvm/test/ThinLTO/X86/nodevirt-nonpromoted-typeid.ll @@ -8,7 +8,7 @@ ; metadata summary entries, and no promotion will occur. ; Generate unsplit module with summary for ThinLTO index-based WPD. -; RUN: opt -thinlto-bc -thinlto-split-lto-unit=false -o %t2.o %s +; RUN: opt -thinlto-bc -thinlto-split-lto-unit=false -empty-moduleid -o %t2.o %s ; Check that we don't have module flag when splitting not enabled for ThinLTO, ; and that we generate summary information needed for index-based WPD. Index: llvm/test/Transforms/ThinLTOBitcodeWriter/unsplittable.ll =================================================================== --- llvm/test/Transforms/ThinLTOBitcodeWriter/unsplittable.ll +++ llvm/test/Transforms/ThinLTOBitcodeWriter/unsplittable.ll @@ -1,4 +1,4 @@ -; RUN: opt -thinlto-bc -thin-link-bitcode-file=%t2 -thinlto-split-lto-unit -o %t %s +; RUN: opt -thinlto-bc -thin-link-bitcode-file=%t2 -thinlto-split-lto-unit -empty-moduleid -o %t %s ; RUN: llvm-dis -o - %t | FileCheck %s ; RUN: llvm-bcanalyzer -dump %t | FileCheck --check-prefix=BCA %s ; When not splitting the module, the thin link bitcode file should simply be a Index: llvm/test/Transforms/Util/generate-moduleid.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/Util/generate-moduleid.ll @@ -0,0 +1,17 @@ +; REQUIRES: asserts +; RUN: opt --thinlto-split-lto-unit=1 --thinlto-bc -o %t0 -debug-only=moduleutils <%s 2>&1 | FileCheck %s +; CHECK: Generated ModuleID + +target triple="x86_64-pc-linux-gnu" + +declare i1 @llvm.type.test(i8*, metadata) + +define internal void @foo() !type !1{ +entry: + %0 = tail call i1 @llvm.type.test(i8* null, metadata !"") + ret void +} + +@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 103, void ()* @foo, i8* null }] + +!1 = !{i64 0, !"foo"}