Index: llvm/test/tools/llvm-reduce/Inputs/llvm-dis-and-filecheck.py =================================================================== --- llvm/test/tools/llvm-reduce/Inputs/llvm-dis-and-filecheck.py +++ llvm/test/tools/llvm-reduce/Inputs/llvm-dis-and-filecheck.py @@ -13,6 +13,7 @@ import sys +import os import subprocess llvm_dis = sys.argv[1] @@ -20,10 +21,23 @@ filecheck_args = [filecheck, ] filecheck_args.extend(sys.argv[3:-1]) bitcode_file = sys.argv[-1] +ir_file = bitcode_file + ".ll" -disassemble = subprocess.Popen([llvm_dis, "-o", "-", bitcode_file], - stdout=subprocess.PIPE) -check = subprocess.Popen(filecheck_args, stdin=disassemble.stdout) -disassemble.stdout.close() +disassemble = subprocess.Popen([llvm_dis, "-o", ir_file, bitcode_file]) +if os.path.exists(ir_file + ".0"): + ir_file = ir_file + ".0" + +disassemble.communicate() + +if disassemble.returncode != 0: + print("stderr:") + print(disassemble.stderr) + print("stdout:") + print(disassemble.stdout) + sys.exit(1) + +check=None +with open(ir_file, "r") as ir: + check = subprocess.Popen(filecheck_args, stdin=ir, stdout=sys.stdout) check.communicate() sys.exit(check.returncode) Index: llvm/test/tools/llvm-reduce/fail-file-open.test =================================================================== --- llvm/test/tools/llvm-reduce/fail-file-open.test +++ llvm/test/tools/llvm-reduce/fail-file-open.test @@ -2,4 +2,4 @@ This file will not be read. An invalid file path is fed to llvm-reduce. -# CHECK: llvm-reduce{{.*}}: {{.*}}.NotAFileInTestingDir: error: \ No newline at end of file +# CHECK: llvm-reduce{{.*}}: error: {{.*}}.NotAFileInTestingDir: Index: llvm/test/tools/llvm-reduce/invalid-bitcode-error.ll =================================================================== --- /dev/null +++ llvm/test/tools/llvm-reduce/invalid-bitcode-error.ll @@ -0,0 +1,3 @@ +; RUN: not %python %p/Inputs/llvm-dis-and-filecheck.py llvm-dis FileCheck %s %s 2>&1 | FileCheck %s +; CHECK: stderr +; CHECK: stdout Index: llvm/test/tools/llvm-reduce/temporary-files-as-bitcode-split.ll =================================================================== --- /dev/null +++ llvm/test/tools/llvm-reduce/temporary-files-as-bitcode-split.ll @@ -0,0 +1,27 @@ +; RUN: opt --thinlto-bc --thinlto-split-lto-unit %s -o %t0 +; RUN: llvm-reduce -write-tmp-files-as-bitcode --delta-passes=basic-blocks %t0 -o %t1 \ +; RUN: --test %python --test-arg %p/Inputs/llvm-dis-and-filecheck.py --test-arg llvm-dis --test-arg FileCheck --test-arg --check-prefixes=CHECK-ALL,CHECK-INTERESTINGNESS --test-arg %s +; RUN: cat %t1* | FileCheck --check-prefixes=CHECK-ALL,CHECK-FINAL %s + +@g = internal global i8 42, !type !0 + +; CHECK-INTERESTINGNESS: @callee( +; CHECK-FINAL: declare void @callee() +define void @callee() { + ret void +} + +; CHECK-ALL: define void @caller() +define void @caller() { +entry: +; CHECK-ALL: call void @callee() +; CHECK-ALL: ret void + call void @callee() + ret void +} +define i8* @f() { + ; CHECK-ALL: ret i8* @g.{{([0-9a-f]{32})}} + ret i8* @g +} + +!0 = !{i32 0, !"typeid"} Index: llvm/tools/llvm-reduce/CMakeLists.txt =================================================================== --- llvm/tools/llvm-reduce/CMakeLists.txt +++ llvm/tools/llvm-reduce/CMakeLists.txt @@ -13,6 +13,7 @@ Support Target TransformUtils + IPO ) add_llvm_tool(llvm-reduce Index: llvm/tools/llvm-reduce/ReducerWorkItem.h =================================================================== --- llvm/tools/llvm-reduce/ReducerWorkItem.h +++ llvm/tools/llvm-reduce/ReducerWorkItem.h @@ -9,9 +9,11 @@ #ifndef LLVM_TOOLS_LLVM_REDUCE_REDUCERWORKITEM_H #define LLVM_TOOLS_LLVM_REDUCE_REDUCERWORKITEM_H +#include "llvm/Bitcode/BitcodeReader.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/IR/Module.h" +#include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/Target/TargetMachine.h" using namespace llvm; @@ -19,6 +21,7 @@ class ReducerWorkItem { public: std::shared_ptr M; + std::unique_ptr LTOInfo; std::unique_ptr MMI; bool isMIR() const { return MMI != nullptr; } Index: llvm/tools/llvm-reduce/ReducerWorkItem.cpp =================================================================== --- llvm/tools/llvm-reduce/ReducerWorkItem.cpp +++ llvm/tools/llvm-reduce/ReducerWorkItem.cpp @@ -7,6 +7,7 @@ //===----------------------------------------------------------------------===// #include "ReducerWorkItem.h" +#include "llvm/Bitcode/BitcodeReader.h" #include "llvm/CodeGen/CommandFlags.h" #include "llvm/CodeGen/MIRParser/MIRParser.h" #include "llvm/CodeGen/MIRPrinter.h" @@ -17,11 +18,14 @@ #include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/IR/ModuleSummaryIndex.h" #include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/Host.h" +#include "llvm/Support/MemoryBufferRef.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetSelect.h" #include "llvm/Support/WithColor.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Transforms/Utils/Cloning.h" @@ -31,6 +35,8 @@ cl::desc("Set the target triple"), cl::cat(LLVMReduceOptions)); +void readBitcode(ReducerWorkItem &M, MemoryBufferRef Data, LLVMContext &Ctx); + static void cloneFrameInfo( MachineFrameInfo &DstMFI, const MachineFrameInfo &SrcMFI, const DenseMap &Src2DstMBB) { @@ -348,6 +354,13 @@ return DstMF; } +static void initializeTargetInfo() { + InitializeAllTargets(); + InitializeAllTargetMCs(); + InitializeAllAsmPrinters(); + InitializeAllAsmParsers(); +} + std::unique_ptr parseReducerWorkItem(const char *ToolName, StringRef Filename, LLVMContext &Ctxt, std::unique_ptr &TM, @@ -357,6 +370,8 @@ auto MMM = std::make_unique(); if (IsMIR) { + initializeTargetInfo(); + auto FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true); if (std::error_code EC = FileOrErr.getError()) { WithColor::error(errs(), ToolName) << EC.message() << '\n'; @@ -405,12 +420,26 @@ MMM->M = std::move(M); } else { SMDiagnostic Err; - std::unique_ptr Result = parseIRFile(Filename, Err, Ctxt); - if (!Result) { - Err.print(ToolName, errs()); + ErrorOr> MB = MemoryBuffer::getFileOrSTDIN(Filename); + if (std::error_code EC = MB.getError()) { + WithColor::error(errs(), ToolName) << Filename << ": " << EC.message() << "\n"; return std::unique_ptr(); } - MMM->M = std::move(Result); + + if (!isBitcode((const unsigned char *)(*MB)->getBufferStart(), + (const unsigned char *)(*MB)->getBufferEnd())) { + std::unique_ptr Result = parseIRFile(Filename, Err, Ctxt); + if (!Result) { + Err.print(ToolName, errs()); + return std::unique_ptr(); + } + MMM->M = std::move(Result); + } else { + readBitcode(*MMM, MemoryBufferRef(**MB), Ctxt); + + if (MMM->LTOInfo->IsThinLTO && MMM->LTOInfo->EnableSplitLTOUnit) + initializeTargetInfo(); + } } if (verifyReducerWorkItem(*MMM, &errs())) { WithColor::error(errs(), ToolName) @@ -423,7 +452,7 @@ std::unique_ptr cloneReducerWorkItem(const ReducerWorkItem &MMM, const TargetMachine *TM) { auto CloneMMM = std::make_unique(); - if (TM) { + if (MMM.MMI) { // We're assuming the Module IR contents are always unchanged by MIR // reductions, and can share it as a constant. CloneMMM->M = MMM.M; Index: llvm/tools/llvm-reduce/deltas/Delta.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/Delta.cpp +++ llvm/tools/llvm-reduce/deltas/Delta.cpp @@ -15,11 +15,16 @@ #include "Delta.h" #include "ReducerWorkItem.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/Analysis/ProfileSummaryInfo.h" +#include "llvm/Analysis/ModuleSummaryAnalysis.h" #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/CodeGen/MachineFunction.h" +#include "llvm/IR/Module.h" #include "llvm/IR/Verifier.h" +#include "llvm/MC/TargetRegistry.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/MemoryBufferRef.h" #include "llvm/Support/ThreadPool.h" #include "llvm/Support/ToolOutputFile.h" #include @@ -56,6 +61,10 @@ void writeOutput(ReducerWorkItem &M, llvm::StringRef Message); +void writeBitcode(ReducerWorkItem &M, llvm::raw_ostream &OutStream); + +void readBitcode(ReducerWorkItem &M, MemoryBufferRef Data, LLVMContext &Ctx); + bool isReduced(ReducerWorkItem &M, TestRunner &Test, SmallString<128> &CurrentFilepath) { // Write ReducerWorkItem to tmp file @@ -70,7 +79,7 @@ if (TmpFilesAsBitcode) { llvm::raw_fd_ostream OutStream(FD, true); - WriteBitcodeToFile(M, OutStream); + writeBitcode(M, OutStream); OutStream.close(); if (OutStream.has_error()) { errs() << "Error emitting bitcode to file '" << CurrentFilepath << "'!\n"; @@ -192,14 +201,10 @@ std::vector &ChunksStillConsideredInteresting, SmallString<0> &OriginalBC, std::atomic &AnyReduced) { LLVMContext Ctx; - Expected> MOrErr = parseBitcodeFile( - MemoryBufferRef(StringRef(OriginalBC.data(), OriginalBC.size()), - ""), - Ctx); - if (!MOrErr) - report_fatal_error("Failed to read bitcode"); auto CloneMMM = std::make_unique(); - CloneMMM->M = std::move(MOrErr.get()); + auto Data = MemoryBufferRef(StringRef(OriginalBC.data(), OriginalBC.size()), + ""); + readBitcode(*CloneMMM, Data, Ctx); SmallString<0> Result; if (std::unique_ptr ChunkResult = @@ -207,7 +212,7 @@ Test, ExtractChunksFromModule, UninterestingChunks, ChunksStillConsideredInteresting)) { raw_svector_ostream BCOS(Result); - WriteBitcodeToFile(*ChunkResult->M, BCOS); + writeBitcode(*ChunkResult, BCOS); // Communicate that the task reduced a chunk. AnyReduced = true; } @@ -284,7 +289,7 @@ SmallString<0> OriginalBC; if (NumJobs > 1) { raw_svector_ostream BCOS(OriginalBC); - WriteBitcodeToFile(*Test.getProgram().M, BCOS); + writeBitcode(Test.getProgram(), BCOS); } std::deque>> TaskQueue; @@ -351,14 +356,10 @@ continue; } - Expected> MOrErr = parseBitcodeFile( - MemoryBufferRef(StringRef(Res.data(), Res.size()), - ""), - Test.getProgram().M->getContext()); - if (!MOrErr) - report_fatal_error("Failed to read bitcode"); Result = std::make_unique(); - Result->M = std::move(MOrErr.get()); + auto Data = MemoryBufferRef(StringRef(Res.data(), Res.size()), + ""); + readBitcode(*Result, Data, Test.getProgram().M->getContext()); break; } // Forward I to the last chunk processed in parallel. Index: llvm/tools/llvm-reduce/llvm-reduce.cpp =================================================================== --- llvm/tools/llvm-reduce/llvm-reduce.cpp +++ llvm/tools/llvm-reduce/llvm-reduce.cpp @@ -17,10 +17,15 @@ #include "DeltaManager.h" #include "ReducerWorkItem.h" #include "TestRunner.h" +#include "llvm/Analysis/ProfileSummaryInfo.h" +#include "llvm/Analysis/ModuleSummaryAnalysis.h" #include "llvm/ADT/SmallString.h" +#include "llvm/Bitcode/BitcodeReader.h" +#include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/CodeGen/CommandFlags.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" @@ -32,6 +37,7 @@ #include "llvm/Support/TargetSelect.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/IPO.h" #include #include @@ -94,13 +100,6 @@ static codegen::RegisterCodeGenFlags CGF; -static void initializeTargetInfo() { - InitializeAllTargets(); - InitializeAllTargetMCs(); - InitializeAllAsmPrinters(); - InitializeAllAsmParsers(); -} - void writeOutput(ReducerWorkItem &M, StringRef Message) { if (ReplaceInput) // In-place OutputFilename = InputFilename.c_str(); @@ -116,6 +115,39 @@ errs() << Message << OutputFilename << "\n"; } +void writeBitcode(ReducerWorkItem &M, llvm::raw_ostream &OutStream) { + if (M.LTOInfo && M.LTOInfo->IsThinLTO && M.LTOInfo->EnableSplitLTOUnit) { + legacy::PassManager PM; + PM.add(llvm::createWriteThinLTOBitcodePass(OutStream)); + PM.run(*(M.M)); + } else { + std::unique_ptr Index; + if (M.LTOInfo && M.LTOInfo->HasSummary) { + ProfileSummaryInfo PSI(M); + Index = std::make_unique( + buildModuleSummaryIndex(M, nullptr, &PSI)); + } + WriteBitcodeToFile(M, OutStream, Index.get()); + } +} + +void readBitcode(ReducerWorkItem &M, MemoryBufferRef Data, LLVMContext &Ctx) { + Expected IF = llvm::getBitcodeFileContents(Data); + if (!IF) { + WithColor::error(errs()) << IF.takeError(); + exit(1); + } + BitcodeModule BM = IF->Mods[0]; + Expected LI = BM.getLTOInfo(); + Expected> MOrErr = BM.parseModule(Ctx); + if (!LI || !MOrErr) { + WithColor::error(errs()) << IF.takeError(); + exit(1); + } + M.LTOInfo = std::make_unique(*LI); + M.M = std::move(MOrErr.get()); +} + int main(int Argc, char **Argv) { InitLLVM X(Argc, Argv); @@ -135,9 +167,6 @@ return 0; } - if (ReduceModeMIR) - initializeTargetInfo(); - LLVMContext Context; std::unique_ptr TM;