Index: clang/include/clang/Driver/Driver.h =================================================================== --- clang/include/clang/Driver/Driver.h +++ clang/include/clang/Driver/Driver.h @@ -578,6 +578,10 @@ /// compilation based on which -f(no-)?lto(=.*)? option occurs last. void setLTOMode(const llvm::opt::ArgList &Args); + /// Parse the \p Inputs list for LTO inputs. LTO inputs are object files + /// that contain LLVM bitcode + void setLTOModeFromInputFiles(const InputList *Inputs); + /// Retrieves a ToolChain for a particular \p Target triple. /// /// Will cache ToolChains for the life of the driver object, and create them Index: clang/lib/Driver/CMakeLists.txt =================================================================== --- clang/lib/Driver/CMakeLists.txt +++ clang/lib/Driver/CMakeLists.txt @@ -3,6 +3,7 @@ Option ProfileData Support + BitReader ) if(WIN32) Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -64,6 +64,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Config/llvm-config.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" @@ -586,6 +587,43 @@ return Target; } +static LTOKind +getInputLTOMode(const std::pair Input) { + // Must be an object file + if (Input.first != types::TY_Object) + return LTOK_None; + + // ... and contain LLVM bitcode + for (const char *Filename : Input.second->getValues()) { + auto Buff = llvm::MemoryBuffer::getFile(Filename); + if (Buff) { + auto R = (*Buff)->getMemBufferRef(); + Expected LTOInfo = llvm::getBitcodeLTOInfo(R); + + if (LTOInfo) + return LTOInfo->IsThinLTO ? LTOK_Thin : LTOK_Full; + + llvm::consumeError(LTOInfo.takeError()); + } + } + + return LTOK_None; +} + +void Driver::setLTOModeFromInputFiles(const InputList *Inputs) { + if (LTOMode != LTOK_None) + return; + + for (auto Input : *Inputs) { + auto InputLTOMode = getInputLTOMode(Input); + + if (InputLTOMode != LTOK_None) { + LTOMode = InputLTOMode; + break; + } + } +} + // Parse the LTO options and record the type of LTO compilation // based on which -f(no-)?lto(=.*)? option occurs last. void Driver::setLTOMode(const llvm::opt::ArgList &Args) { @@ -1164,6 +1202,8 @@ InputList Inputs; BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs); + setLTOModeFromInputFiles(&Inputs); + // Populate the tool chains for the offloading devices, if any. CreateOffloadingDeviceToolChains(*C, Inputs); Index: clang/test/Driver/thinlto_backend.c =================================================================== --- clang/test/Driver/thinlto_backend.c +++ clang/test/Driver/thinlto_backend.c @@ -24,3 +24,13 @@ // RUN: not %clang -O2 -o %t1.o %s -c -fthinlto-index=%t.thinlto.bc 2>&1 \ // RUN: | FileCheck %s -check-prefix=CHECK-WARNING // CHECK-WARNING: error: option '-fthinlto-index={{.*}}' requires input to be LLVM bitcode + +// thinlto enabled without -flto=thin explicitly passed +// RUN: %clang -O2 %s -c -flto=thin -o %r.o +// RUN: %clang %r.o -### 2>&1 | FileCheck %s -check-prefix=CHECK-THIN-LTO-ENABLED +// CHECK-THIN-LTO-ENABLED: -plugin-opt=thinlto + +// Same for full LTO +// RUN: %clang -O2 %s -target x86_64-unknown-linux-gnu -c -flto=full -o %r.o +// RUN: %clang %r.o -### 2>&1 | FileCheck %s -check-prefix=CHECK-FULL-LTO-ENABLED +// CHECK-FULL-LTO-ENABLED: LLVMgold