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<bool>
+    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,43 @@
   for (auto &IF : M->ifuncs())
     AddGlobal(IF);
 
+  if (!ExportsSymbols) {
+    Md5.update(M->getModuleIdentifier());
+    Md5.update(ArrayRef<uint8_t>{0});
+
+    auto AddWeakerGlobal = [&](const GlobalValue &GV) {
+      if (GV.isDeclaration() || GV.getName().startswith("llvm.") ||
+          GV.hasWeakLinkage()) {
+        ExportsSymbols = true;
+        Md5.update(GV.getName());
+        Md5.update(ArrayRef<uint8_t>{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<const GlobalValue*(const Value*)> fun) {
+      if (auto *Used = M->getNamedGlobal(array))
+        if (const auto *A = dyn_cast<ConstantArray>(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<GlobalValue>(Op->stripPointerCasts());
+    });
+    AddArrayElt("llvm.global_ctors", [&] (const Value* Op) -> const GlobalValue* {
+      if (const auto *CS = dyn_cast<ConstantStruct>(Op))
+        if (const auto *GV = dyn_cast<GlobalValue>(CS->getAggregateElement(1)))
+          return GV;
+      return nullptr;
+    });
+
+    for (auto &GV : M->globals())
+      AddWeakerGlobal(GV);
+  }
+
   if (!ExportsSymbols)
     return "";
 
@@ -324,6 +369,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"}