Index: lib/Transforms/IPO/LowerTypeTests.cpp =================================================================== --- lib/Transforms/IPO/LowerTypeTests.cpp +++ lib/Transforms/IPO/LowerTypeTests.cpp @@ -1702,11 +1702,28 @@ return false; // If only some of the modules were split, we cannot correctly handle - // code that contains type tests. - if (TypeTestFunc && !TypeTestFunc->use_empty() && - ((ExportSummary && ExportSummary->partiallySplitLTOUnits()) || - (ImportSummary && ImportSummary->partiallySplitLTOUnits()))) - report_fatal_error("inconsistent LTO Unit splitting with llvm.type.test"); + // code that contains type tests. Check this during the serial whole program + // analysis export phase. + if (ExportSummary && ExportSummary->partiallySplitLTOUnits()) { + // First check if there are type tests in the merged LTO module IR. + if (TypeTestFunc && !TypeTestFunc->use_empty()) + report_fatal_error("inconsistent LTO Unit splitting with llvm.type.test"); + + // Otherwise check if there are any recorded in the summary from the + // ThinLTO module. + for (auto &P : *ExportSummary) { + for (auto &S : P.second.SummaryList) { + auto *FS = dyn_cast(S.get()); + if (!FS) + continue; + if (!FS->type_test_assume_vcalls().empty() || + !FS->type_test_assume_const_vcalls().empty() || + !FS->type_tests().empty()) + report_fatal_error( + "inconsistent LTO Unit splitting with llvm.type.test"); + } + } + } if (ImportSummary) { if (TypeTestFunc) { Index: lib/Transforms/IPO/WholeProgramDevirt.cpp =================================================================== --- lib/Transforms/IPO/WholeProgramDevirt.cpp +++ lib/Transforms/IPO/WholeProgramDevirt.cpp @@ -1563,13 +1563,32 @@ Function *AssumeFunc = M.getFunction(Intrinsic::getName(Intrinsic::assume)); // If only some of the modules were split, we cannot correctly handle - // code that contains type tests or type checked loads. - if ((ExportSummary && ExportSummary->partiallySplitLTOUnits()) || - (ImportSummary && ImportSummary->partiallySplitLTOUnits())) { + // code that contains type tests or type checked loads. Check this during + // the serial whole program analysis export phase. + if (ExportSummary && ExportSummary->partiallySplitLTOUnits()) { + // First check if there are type tests / type checked loads in the + // merged LTO module IR. if ((TypeTestFunc && !TypeTestFunc->use_empty()) || (TypeCheckedLoadFunc && !TypeCheckedLoadFunc->use_empty())) report_fatal_error("inconsistent LTO Unit splitting with llvm.type.test " "or llvm.type.checked.load"); + // Otherwise check if there are any recorded in the summary from the + // ThinLTO module. + for (auto &P : *ExportSummary) { + for (auto &S : P.second.SummaryList) { + auto *FS = dyn_cast(S.get()); + if (!FS) + continue; + if (!FS->type_test_assume_vcalls().empty() || + !FS->type_checked_load_vcalls().empty() || + !FS->type_test_assume_const_vcalls().empty() || + !FS->type_checked_load_const_vcalls().empty() || + !FS->type_tests().empty()) + report_fatal_error( + "inconsistent LTO Unit splitting with llvm.type.test " + "or llvm.type.checked.load"); + } + } return false; } Index: test/ThinLTO/X86/cfi-devirt.ll =================================================================== --- test/ThinLTO/X86/cfi-devirt.ll +++ test/ThinLTO/X86/cfi-devirt.ll @@ -20,8 +20,8 @@ ; RUN: -r=%t.o,_ZN1B1fEi, \ ; RUN: -r=%t.o,_ZN1C1fEi, \ ; RUN: -r=%t.o,_ZTV1B,px \ -; RUN: -r=%t.o,_ZTV1C,px 2>&1 | FileCheck %s --check-prefix=REMARK -dump-input=always -; RUN: llvm-dis %t3.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR -dump-input=always +; RUN: -r=%t.o,_ZTV1C,px 2>&1 | FileCheck %s --check-prefix=REMARK +; RUN: llvm-dis %t3.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR ; New PM ; FIXME: Fix machine verifier issues and remove -verify-machineinstrs=0. PR39436. @@ -39,17 +39,18 @@ ; RUN: -r=%t.o,_ZN1B1fEi, \ ; RUN: -r=%t.o,_ZN1C1fEi, \ ; RUN: -r=%t.o,_ZTV1B,px \ -; RUN: -r=%t.o,_ZTV1C,px 2>&1 | FileCheck %s --check-prefix=REMARK -dump-input=always -; RUN: llvm-dis %t3.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR -dump-input=always +; RUN: -r=%t.o,_ZTV1C,px 2>&1 | FileCheck %s --check-prefix=REMARK +; RUN: llvm-dis %t3.1.4.opt.bc -o - | FileCheck %s --check-prefix=CHECK-IR ; REMARK: single-impl: devirtualized a call to _ZN1A1nEi ; Next check that we emit an error when trying to LTO link this module ; containing an llvm.type.checked.load (with a split LTO Unit) with one -; that does not have a split LTO Unit. +; that does not have a split LTO Unit. Use -thinlto-distributed-indexes +; to ensure it is being caught in the thin link. ; RUN: opt -thinlto-bc -o %t2.o %S/Inputs/empty.ll -; RUN: not llvm-lto2 run %t.o %t2.o -save-temps -pass-remarks=. \ -; RUN: -verify-machineinstrs=0 -thinlto-threads=1 \ +; RUN: not llvm-lto2 run %t.o %t2.o -thinlto-distributed-indexes \ +; RUN: -verify-machineinstrs=0 \ ; RUN: -o %t3 \ ; RUN: -r=%t.o,test,px \ ; RUN: -r=%t.o,_ZN1A1nEi,p \ @@ -62,7 +63,7 @@ ; RUN: -r=%t.o,_ZN1B1fEi, \ ; RUN: -r=%t.o,_ZN1C1fEi, \ ; RUN: -r=%t.o,_ZTV1B,px \ -; RUN: -r=%t.o,_ZTV1C,px 2>&1 | FileCheck %s --check-prefix=ERROR -dump-input=always +; RUN: -r=%t.o,_ZTV1C,px 2>&1 | FileCheck %s --check-prefix=ERROR ; ERROR: LLVM ERROR: inconsistent LTO Unit splitting with llvm.type.test or llvm.type.checked.load target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"