[PATCH] D154923: [CodeGen] Support bitcode input containing multiple modules

2023-07-21 Thread Fangrui Song via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb2f7b5dbaefe: [CodeGen] Support bitcode input containing 
multiple modules (authored by MaskRay).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154923/new/

https://reviews.llvm.org/D154923

Files:
  clang/lib/CodeGen/CodeGenAction.cpp
  clang/test/CodeGen/split-lto-unit-input.cpp

Index: clang/test/CodeGen/split-lto-unit-input.cpp
===
--- /dev/null
+++ clang/test/CodeGen/split-lto-unit-input.cpp
@@ -0,0 +1,32 @@
+// REQUIRES: x86-registered-target
+/// When the input is a -fsplit-lto-unit bitcode file, link the regular LTO file like -mlink-bitcode-file.
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm-bc -flto=thin -flto-unit -fsplit-lto-unit %s -o %t.bc
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-obj %t.bc -o %t.o
+// RUN: llvm-nm %t.o | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %t.bc -o - | FileCheck %s --check-prefix=CHECK-IR
+
+// CHECK:  V _ZTI1A
+// CHECK-NEXT: V _ZTI1B
+// CHECK-NEXT: V _ZTS1A
+// CHECK-NEXT: V _ZTS1B
+// CHECK-NEXT: V _ZTV1A
+// CHECK-NEXT: V _ZTV1B
+
+// CHECK-IR-DAG: _ZTS1B = linkonce_odr constant
+// CHECK-IR-DAG: _ZTS1A = linkonce_odr constant
+// CHECK-IR-DAG: _ZTV1B = linkonce_odr unnamed_addr constant
+// CHECK-IR-DAG: _ZTI1A = linkonce_odr constant
+// CHECK-IR-DAG: _ZTI1B = linkonce_odr constant
+// CHECK-IR-DAG: _ZTV1A = linkonce_odr unnamed_addr constant
+
+struct A {
+  virtual int c(int i) = 0;
+};
+
+struct B : A {
+  virtual int c(int i) { return i; }
+};
+
+int use() {
+  return (new B)->c(0);
+}
Index: clang/lib/CodeGen/CodeGenAction.cpp
===
--- clang/lib/CodeGen/CodeGenAction.cpp
+++ clang/lib/CodeGen/CodeGenAction.cpp
@@ -1112,21 +1112,21 @@
   CompilerInstance  = getCompilerInstance();
   SourceManager  = CI.getSourceManager();
 
+  auto DiagErrors = [&](Error E) -> std::unique_ptr {
+unsigned DiagID =
+CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
+handleAllErrors(std::move(E), [&](ErrorInfoBase ) {
+  CI.getDiagnostics().Report(DiagID) << EIB.message();
+});
+return {};
+  };
+
   // For ThinLTO backend invocations, ensure that the context
   // merges types based on ODR identifiers. We also need to read
   // the correct module out of a multi-module bitcode file.
   if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) {
 VMContext->enableDebugTypeODRUniquing();
 
-auto DiagErrors = [&](Error E) -> std::unique_ptr {
-  unsigned DiagID =
-  CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
-  handleAllErrors(std::move(E), [&](ErrorInfoBase ) {
-CI.getDiagnostics().Report(DiagID) << EIB.message();
-  });
-  return {};
-};
-
 Expected> BMsOrErr = getBitcodeModuleList(MBRef);
 if (!BMsOrErr)
   return DiagErrors(BMsOrErr.takeError());
@@ -1151,10 +1151,35 @@
   if (loadLinkModules(CI))
 return nullptr;
 
+  // Handle textual IR and bitcode file with one single module.
   llvm::SMDiagnostic Err;
   if (std::unique_ptr M = parseIR(MBRef, Err, *VMContext))
 return M;
 
+  // If MBRef is a bitcode with multiple modules (e.g., -fsplit-lto-unit
+  // output), place the extra modules (actually only one, a regular LTO module)
+  // into LinkModules as if we are using -mlink-bitcode-file.
+  Expected> BMsOrErr = getBitcodeModuleList(MBRef);
+  if (BMsOrErr && BMsOrErr->size()) {
+std::unique_ptr FirstM;
+for (auto  : *BMsOrErr) {
+  Expected> MOrErr =
+  BM.parseModule(*VMContext);
+  if (!MOrErr)
+return DiagErrors(MOrErr.takeError());
+  if (FirstM)
+LinkModules.push_back({std::move(*MOrErr), /*PropagateAttrs=*/false,
+   /*Internalize=*/false, /*LinkFlags=*/{}});
+  else
+FirstM = std::move(*MOrErr);
+}
+if (FirstM)
+  return FirstM;
+  }
+  // If BMsOrErr fails, consume the error and use the error message from
+  // parseIR.
+  consumeError(BMsOrErr.takeError());
+
   // Translate from the diagnostic info to the SourceManager location if
   // available.
   // TODO: Unify this with ConvertBackendLocation()
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154923: [CodeGen] Support bitcode input containing multiple modules

2023-07-21 Thread Matthew Voss via Phabricator via cfe-commits
ormris accepted this revision.
ormris added a comment.
This revision is now accepted and ready to land.

LGTM


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154923/new/

https://reviews.llvm.org/D154923

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154923: [CodeGen] Support bitcode input containing multiple modules

2023-07-21 Thread Fangrui Song via Phabricator via cfe-commits
MaskRay updated this revision to Diff 543084.
MaskRay added a comment.

rename a variable


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154923/new/

https://reviews.llvm.org/D154923

Files:
  clang/lib/CodeGen/CodeGenAction.cpp
  clang/test/CodeGen/split-lto-unit-input.cpp

Index: clang/test/CodeGen/split-lto-unit-input.cpp
===
--- /dev/null
+++ clang/test/CodeGen/split-lto-unit-input.cpp
@@ -0,0 +1,32 @@
+// REQUIRES: x86-registered-target
+/// When the input is a -fsplit-lto-unit bitcode file, link the regular LTO file like -mlink-bitcode-file.
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm-bc -flto=thin -flto-unit -fsplit-lto-unit %s -o %t.bc
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-obj %t.bc -o %t.o
+// RUN: llvm-nm %t.o | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %t.bc -o - | FileCheck %s --check-prefix=CHECK-IR
+
+// CHECK:  V _ZTI1A
+// CHECK-NEXT: V _ZTI1B
+// CHECK-NEXT: V _ZTS1A
+// CHECK-NEXT: V _ZTS1B
+// CHECK-NEXT: V _ZTV1A
+// CHECK-NEXT: V _ZTV1B
+
+// CHECK-IR-DAG: _ZTS1B = linkonce_odr constant
+// CHECK-IR-DAG: _ZTS1A = linkonce_odr constant
+// CHECK-IR-DAG: _ZTV1B = linkonce_odr unnamed_addr constant
+// CHECK-IR-DAG: _ZTI1A = linkonce_odr constant
+// CHECK-IR-DAG: _ZTI1B = linkonce_odr constant
+// CHECK-IR-DAG: _ZTV1A = linkonce_odr unnamed_addr constant
+
+struct A {
+  virtual int c(int i) = 0;
+};
+
+struct B : A {
+  virtual int c(int i) { return i; }
+};
+
+int use() {
+  return (new B)->c(0);
+}
Index: clang/lib/CodeGen/CodeGenAction.cpp
===
--- clang/lib/CodeGen/CodeGenAction.cpp
+++ clang/lib/CodeGen/CodeGenAction.cpp
@@ -1112,21 +1112,21 @@
   CompilerInstance  = getCompilerInstance();
   SourceManager  = CI.getSourceManager();
 
+  auto DiagErrors = [&](Error E) -> std::unique_ptr {
+unsigned DiagID =
+CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
+handleAllErrors(std::move(E), [&](ErrorInfoBase ) {
+  CI.getDiagnostics().Report(DiagID) << EIB.message();
+});
+return {};
+  };
+
   // For ThinLTO backend invocations, ensure that the context
   // merges types based on ODR identifiers. We also need to read
   // the correct module out of a multi-module bitcode file.
   if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) {
 VMContext->enableDebugTypeODRUniquing();
 
-auto DiagErrors = [&](Error E) -> std::unique_ptr {
-  unsigned DiagID =
-  CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
-  handleAllErrors(std::move(E), [&](ErrorInfoBase ) {
-CI.getDiagnostics().Report(DiagID) << EIB.message();
-  });
-  return {};
-};
-
 Expected> BMsOrErr = getBitcodeModuleList(MBRef);
 if (!BMsOrErr)
   return DiagErrors(BMsOrErr.takeError());
@@ -1151,10 +1151,35 @@
   if (loadLinkModules(CI))
 return nullptr;
 
+  // Handle textual IR and bitcode file with one single module.
   llvm::SMDiagnostic Err;
   if (std::unique_ptr M = parseIR(MBRef, Err, *VMContext))
 return M;
 
+  // If MBRef is a bitcode with multiple modules (e.g., -fsplit-lto-unit
+  // output), place the extra modules (actually only one, a regular LTO module)
+  // into LinkModules as if we are using -mlink-bitcode-file.
+  Expected> BMsOrErr = getBitcodeModuleList(MBRef);
+  if (BMsOrErr && BMsOrErr->size()) {
+std::unique_ptr FirstM;
+for (auto  : *BMsOrErr) {
+  Expected> MOrErr =
+  BM.parseModule(*VMContext);
+  if (!MOrErr)
+return DiagErrors(MOrErr.takeError());
+  if (FirstM)
+LinkModules.push_back({std::move(*MOrErr), /*PropagateAttrs=*/false,
+   /*Internalize=*/false, /*LinkFlags=*/{}});
+  else
+FirstM = std::move(*MOrErr);
+}
+if (FirstM)
+  return FirstM;
+  }
+  // If BMsOrErr fails, consume the error and use the error message from
+  // parseIR.
+  consumeError(BMsOrErr.takeError());
+
   // Translate from the diagnostic info to the SourceManager location if
   // available.
   // TODO: Unify this with ConvertBackendLocation()
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154923: [CodeGen] Support bitcode input containing multiple modules

2023-07-21 Thread Fangrui Song via Phabricator via cfe-commits
MaskRay updated this revision to Diff 543083.
MaskRay edited the summary of this revision.
MaskRay added a comment.

rename a variable


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154923/new/

https://reviews.llvm.org/D154923

Files:
  clang/lib/CodeGen/CodeGenAction.cpp
  clang/test/CodeGen/split-lto-unit-input.cpp

Index: clang/test/CodeGen/split-lto-unit-input.cpp
===
--- /dev/null
+++ clang/test/CodeGen/split-lto-unit-input.cpp
@@ -0,0 +1,32 @@
+// REQUIRES: x86-registered-target
+/// When the input is a -fsplit-lto-unit bitcode file, link the regular LTO file like -mlink-bitcode-file.
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm-bc -flto=thin -flto-unit -fsplit-lto-unit %s -o %t.bc
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-obj %t.bc -o %t.o
+// RUN: llvm-nm %t.o | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %t.bc -o - | FileCheck %s --check-prefix=CHECK-IR
+
+// CHECK:  V _ZTI1A
+// CHECK-NEXT: V _ZTI1B
+// CHECK-NEXT: V _ZTS1A
+// CHECK-NEXT: V _ZTS1B
+// CHECK-NEXT: V _ZTV1A
+// CHECK-NEXT: V _ZTV1B
+
+// CHECK-IR-DAG: _ZTS1B = linkonce_odr constant
+// CHECK-IR-DAG: _ZTS1A = linkonce_odr constant
+// CHECK-IR-DAG: _ZTV1B = linkonce_odr unnamed_addr constant
+// CHECK-IR-DAG: _ZTI1A = linkonce_odr constant
+// CHECK-IR-DAG: _ZTI1B = linkonce_odr constant
+// CHECK-IR-DAG: _ZTV1A = linkonce_odr unnamed_addr constant
+
+struct A {
+  virtual int c(int i) = 0;
+};
+
+struct B : A {
+  virtual int c(int i) { return i; }
+};
+
+int use() {
+  return (new B)->c(0);
+}
Index: clang/lib/CodeGen/CodeGenAction.cpp
===
--- clang/lib/CodeGen/CodeGenAction.cpp
+++ clang/lib/CodeGen/CodeGenAction.cpp
@@ -1112,21 +1112,21 @@
   CompilerInstance  = getCompilerInstance();
   SourceManager  = CI.getSourceManager();
 
+  auto DiagErrors = [&](Error E) -> std::unique_ptr {
+unsigned DiagID =
+CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
+handleAllErrors(std::move(E), [&](ErrorInfoBase ) {
+  CI.getDiagnostics().Report(DiagID) << EIB.message();
+});
+return {};
+  };
+
   // For ThinLTO backend invocations, ensure that the context
   // merges types based on ODR identifiers. We also need to read
   // the correct module out of a multi-module bitcode file.
   if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) {
 VMContext->enableDebugTypeODRUniquing();
 
-auto DiagErrors = [&](Error E) -> std::unique_ptr {
-  unsigned DiagID =
-  CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
-  handleAllErrors(std::move(E), [&](ErrorInfoBase ) {
-CI.getDiagnostics().Report(DiagID) << EIB.message();
-  });
-  return {};
-};
-
 Expected> BMsOrErr = getBitcodeModuleList(MBRef);
 if (!BMsOrErr)
   return DiagErrors(BMsOrErr.takeError());
@@ -1151,10 +1151,35 @@
   if (loadLinkModules(CI))
 return nullptr;
 
+  // Handle textual IR and bitcode file with one single module.
   llvm::SMDiagnostic Err;
   if (std::unique_ptr M = parseIR(MBRef, Err, *VMContext))
 return M;
 
+  // If MBRef is a bitcode with multiple modules (e.g., -fsplit-lto-unit
+  // output), place the extra modules (actually only one, a regular LTO module)
+  // into LinkModules as if we are using -mlink-bitcode-file.
+  Expected> BMsOrErr = getBitcodeModuleList(MBRef);
+  if (BMsOrErr && BMsOrErr->size()) {
+std::unique_ptr M;
+for (auto  : *BMsOrErr) {
+  Expected> MOrErr =
+  BM.parseModule(*VMContext);
+  if (!MOrErr)
+return DiagErrors(MOrErr.takeError());
+  if (M)
+LinkModules.push_back({std::move(*MOrErr), /*PropagateAttrs=*/false,
+   /*Internalize=*/false, /*LinkFlags=*/{}});
+  else
+M = std::move(*MOrErr);
+}
+if (M)
+  return M;
+  }
+  // If BMsOrErr fails, consume the error and use the error message from
+  // parseIR.
+  consumeError(BMsOrErr.takeError());
+
   // Translate from the diagnostic info to the SourceManager location if
   // available.
   // TODO: Unify this with ConvertBackendLocation()
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154923: [CodeGen] Support bitcode input containing multiple modules

2023-07-21 Thread Matthew Voss via Phabricator via cfe-commits
ormris added a comment.

This is a good way to resolve the inconsistencies I was looking at in my own 
review.

> I think whether a bitcode input file contains 2 modules (internal 
> implementation strategy) should not be a criterion to require an additional 
> driver option

Agreed. Most users don't know about the internal structure of bitcode modules, 
so I think it's best to use a consistent interface for all bitcode files.




Comment at: clang/lib/CodeGen/CodeGenAction.cpp:1174
+  else
+M = std::move(*MOrErr);
+}

Perhaps this variable name could be more descriptive. Maybe "FirstM" or 
something like that?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154923/new/

https://reviews.llvm.org/D154923

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154923: [CodeGen] Support bitcode input containing multiple modules

2023-07-14 Thread Fangrui Song via Phabricator via cfe-commits
MaskRay added a comment.

In D154923#4491673 , @MaskRay wrote:

> In D154923#4491411 , @efriedma 
> wrote:
>
>> If I follow correctly, this is basically undoing the splitting that was done 
>> by the command that produced the bitcode file?
>
> Yes, undoing `llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp` change that 
> would make the output bitcode file not usable as an input for non-LTO use 
> cases.
>
>> I guess that could be useful.  But it requires either renaming your object 
>> files from the default ".o" to ".bc", or explicitly passing "-x ir"?  That 
>> seems unintuitive.  Maybe it's better to put this behind some explicit flag?
>
> Yes, specify `-x ir` or let the driver deduce the file type with the 
> predefined extension `.bc`.
>
> I think this is a less common operation (compiling with LTO but then using as 
> non-LTO), so I think adding another option seems not necessary.

Perhaps rephrase my argument:

There are multiple ways to have just one module in a bitcode file output: 
`-Xclang -fno-lto-unit`, not using features like -fsanitize=cfi, using 
-fsanitize=cfi with `-fno-split-lto-unit`.
I think whether a bitcode input file contains 2 modules (internal 
implementation strategy) should not be a criterion to require an additional 
driver option when the user seek for a non-LTO compile action.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154923/new/

https://reviews.llvm.org/D154923

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154923: [CodeGen] Support bitcode input containing multiple modules

2023-07-11 Thread Fangrui Song via Phabricator via cfe-commits
MaskRay added a comment.

In D154923#4491411 , @efriedma wrote:

> If I follow correctly, this is basically undoing the splitting that was done 
> by the command that produced the bitcode file?

Yes, undoing `llvm/lib/Transforms/IPO/ThinLTOBitcodeWriter.cpp` change that 
would make the output bitcode file not usable as an input for non-LTO use cases.

> I guess that could be useful.  But it requires either renaming your object 
> files from the default ".o" to ".bc", or explicitly passing "-x ir"?  That 
> seems unintuitive.  Maybe it's better to put this behind some explicit flag?

Yes, specify `-x ir` or let the driver deduce the file type with the predefined 
extension `.bc`.

I think this is a less common operation (compiling with LTO but then using as 
non-LTO), so I think adding another option seems not necessary.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154923/new/

https://reviews.llvm.org/D154923

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154923: [CodeGen] Support bitcode input containing multiple modules

2023-07-11 Thread Eli Friedman via Phabricator via cfe-commits
efriedma added a comment.

If I follow correctly, this is basically undoing the splitting that was done by 
the command that produced the bitcode file?  I guess that could be useful.  But 
it requires either renaming your object files from the default ".o" to ".bc", 
or explicitly passing "-x ir"?  That seems unintuitive.  Maybe it's better to 
put this behind some explicit flag?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D154923/new/

https://reviews.llvm.org/D154923

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154923: [CodeGen] Support bitcode input containing multiple modules

2023-07-11 Thread Fangrui Song via Phabricator via cfe-commits
MaskRay created this revision.
MaskRay added reviewers: ormris, efriedma, rjmccall, aaron.ballman.
Herald added subscribers: steven_wu, hiraditya.
Herald added a project: All.
MaskRay requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

When using -fsplit-lto-unit (explicitly specified or due to using
-fsanitize=cfi/-fwhole-program-vtables), the emitted LLVM IR contains a module
flag metadata `"EnableSplitLTOUnit"`. If a module contains both type metadata 
and
`"EnableSplitLTOUnit"`, `ThinLTOBitcodeWriter.cpp` will write two modules into
the bitcode file. Compiling the bitcode will lead to an error due to `parseIR`
requiring a single module.

  % clang -flto=thin a.cc -c -o a.bc
  % clang -c a.bc
  % clang -fsplit-lto-unit -flto=thin a.cc -c -o a.bc
  % clang -c a.bc
  error: Expected a single module
  1 error generated.

Let's place the extra module (if present) into CodeGenOptions::LinkBitcodeFiles
(originally for -cc1 -mlink-bitcode-file). Linker::linkModules will link the two
modules together. This patch makes the following commands work:

  clang -S -emit-llvm a.bc
  clang -S a.bc
  clang -c a.bc


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D154923

Files:
  clang/lib/CodeGen/CodeGenAction.cpp
  clang/test/CodeGen/split-lto-unit-input.cpp

Index: clang/test/CodeGen/split-lto-unit-input.cpp
===
--- /dev/null
+++ clang/test/CodeGen/split-lto-unit-input.cpp
@@ -0,0 +1,32 @@
+// REQUIRES: x86-registered-target
+/// When the input is a -fsplit-lto-unit bitcode file, link the regular LTO file like -mlink-bitcode-file.
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm-bc -flto=thin -flto-unit -fsplit-lto-unit %s -o %t.bc
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-obj %t.bc -o %t.o
+// RUN: llvm-nm %t.o | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm %t.bc -o - | FileCheck %s --check-prefix=CHECK-IR
+
+// CHECK:  V _ZTI1A
+// CHECK-NEXT: V _ZTI1B
+// CHECK-NEXT: V _ZTS1A
+// CHECK-NEXT: V _ZTS1B
+// CHECK-NEXT: V _ZTV1A
+// CHECK-NEXT: V _ZTV1B
+
+// CHECK-IR-DAG: _ZTS1B = linkonce_odr constant
+// CHECK-IR-DAG: _ZTS1A = linkonce_odr constant
+// CHECK-IR-DAG: _ZTV1B = linkonce_odr unnamed_addr constant
+// CHECK-IR-DAG: _ZTI1A = linkonce_odr constant
+// CHECK-IR-DAG: _ZTI1B = linkonce_odr constant
+// CHECK-IR-DAG: _ZTV1A = linkonce_odr unnamed_addr constant
+
+struct A {
+  virtual int c(int i) = 0;
+};
+
+struct B : A {
+  virtual int c(int i) { return i; }
+};
+
+int use() {
+  return (new B)->c(0);
+}
Index: clang/lib/CodeGen/CodeGenAction.cpp
===
--- clang/lib/CodeGen/CodeGenAction.cpp
+++ clang/lib/CodeGen/CodeGenAction.cpp
@@ -1112,21 +1112,21 @@
   CompilerInstance  = getCompilerInstance();
   SourceManager  = CI.getSourceManager();
 
+  auto DiagErrors = [&](Error E) -> std::unique_ptr {
+unsigned DiagID =
+CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
+handleAllErrors(std::move(E), [&](ErrorInfoBase ) {
+  CI.getDiagnostics().Report(DiagID) << EIB.message();
+});
+return {};
+  };
+
   // For ThinLTO backend invocations, ensure that the context
   // merges types based on ODR identifiers. We also need to read
   // the correct module out of a multi-module bitcode file.
   if (!CI.getCodeGenOpts().ThinLTOIndexFile.empty()) {
 VMContext->enableDebugTypeODRUniquing();
 
-auto DiagErrors = [&](Error E) -> std::unique_ptr {
-  unsigned DiagID =
-  CI.getDiagnostics().getCustomDiagID(DiagnosticsEngine::Error, "%0");
-  handleAllErrors(std::move(E), [&](ErrorInfoBase ) {
-CI.getDiagnostics().Report(DiagID) << EIB.message();
-  });
-  return {};
-};
-
 Expected> BMsOrErr = getBitcodeModuleList(MBRef);
 if (!BMsOrErr)
   return DiagErrors(BMsOrErr.takeError());
@@ -1151,10 +1151,35 @@
   if (loadLinkModules(CI))
 return nullptr;
 
+  // Handle textual IR and bitcode file with one single module.
   llvm::SMDiagnostic Err;
   if (std::unique_ptr M = parseIR(MBRef, Err, *VMContext))
 return M;
 
+  // If MBRef is a bitcode with multiple modules (e.g., -fsplit-lto-unit
+  // output), place the extra modules (actually only one, a regular LTO module)
+  // into LinkModules as if we are using -mlink-bitcode-file.
+  Expected> BMsOrErr = getBitcodeModuleList(MBRef);
+  if (BMsOrErr && BMsOrErr->size()) {
+std::unique_ptr M;
+for (auto  : *BMsOrErr) {
+  Expected> MOrErr =
+  BM.parseModule(*VMContext);
+  if (!MOrErr)
+return DiagErrors(MOrErr.takeError());
+  if (M)
+LinkModules.push_back({std::move(*MOrErr), /*PropagateAttrs=*/false,
+   /*Internalize=*/false, /*LinkFlags=*/{}});
+  else
+M = std::move(*MOrErr);
+}
+if (M)
+  return M;
+  }
+  // If BMsOrErr fails,