Index: llvm/test/tools/llvm-reduce/Inputs/test-output-format.ll =================================================================== --- /dev/null +++ llvm/test/tools/llvm-reduce/Inputs/test-output-format.ll @@ -0,0 +1,6 @@ + +define void @foo(ptr %ptr) { + store i32 0, ptr %ptr + store i32 1, ptr %ptr + ret void +} Index: llvm/test/tools/llvm-reduce/Inputs/test-output-format.mir =================================================================== --- /dev/null +++ llvm/test/tools/llvm-reduce/Inputs/test-output-format.mir @@ -0,0 +1,12 @@ +--- +name: func +tracksRegLiveness: true +body: | + bb.0: + + %ptr:_(p0) = G_IMPLICIT_DEF + %const0:_(s32) = G_CONSTANT i32 0 + G_STORE %const0, %ptr :: (store 4, addrspace 1) + %const1:_(s32) = G_CONSTANT i32 1 + G_STORE %const1, %ptr :: (store 4, addrspace 1) +... Index: llvm/test/tools/llvm-reduce/file-output-type.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-reduce/file-output-type.test @@ -0,0 +1,40 @@ +# RUN: rm -f reduced.ll reduced.bc + +# A .ll input file should default to text output in reduced.ll +# RUN: llvm-reduce --delta-passes=instructions --test FileCheck --test-arg %s --test-arg --input-file %p/Inputs/test-output-format.ll +# RUN: llvm-as -disable-output reduced.ll + + +# A .bc input file should default to bitcode output, in reduced.bc +# RUN: rm -f reduced.ll reduced.bc +# RUN: llvm-reduce --delta-passes=instructions --test FileCheck --test-arg %s --test-arg --input-file %p/Inputs/test-output-format.bc +# RUN: llvm-dis -disable-output reduced.bc + +# A .bc input file with a requested .ll output should produce text +# RUN: rm -f reduced.ll reduced.bc +# RUN: llvm-reduce --delta-passes=instructions -o %t.0.ll --test FileCheck --test-arg %s --test-arg --input-file %p/Inputs/test-output-format.bc +# RUN: llvm-as -disable-output %t.0.ll + + +# A file name ending in .bc should default to bitcode output +# RUN: llvm-reduce -o %t.1.bc --delta-passes=instructions --test FileCheck --test-arg %s --test-arg --input-file %p/Inputs/test-output-format.ll +# RUN: llvm-as -disable-output %t.1.bc + + +# Make sure an explicit -output-bitcode produces bitcode output regardless of suffix +# RUN: llvm-reduce -output-bitcode -o %t.2_no_suffix --delta-passes=instructions --test FileCheck --test-arg %s --test-arg --input-file %p/Inputs/test-output-format.ll +# RUN: llvm-dis -disable-output %t.2_no_suffix + + +# Make sure an explicit -output-bitcode overrides .ll suffix +# RUN: llvm-reduce -output-bitcode -o %t.2.ll --delta-passes=instructions --test FileCheck --test-arg %s --test-arg --input-file %p/Inputs/test-output-format.ll +# RUN: llvm-dis -disable-output %t.2.ll + + +# Make sure MIR ignores requests for bitcode +# RUN: llvm-reduce -output-bitcode --delta-passes=instructions -o %t.3 --test FileCheck --test-arg --check-prefix=MIR --test-arg %s --test-arg --input-file %p/Inputs/test-output-format.mir +# RUN: llc -x mir -run-pass=none -o /dev/null %t.3 + + +# CHECK: store i32 0 +# MIR: G_CONSTANT i32 0 Index: llvm/tools/llvm-reduce/ReducerWorkItem.h =================================================================== --- llvm/tools/llvm-reduce/ReducerWorkItem.h +++ llvm/tools/llvm-reduce/ReducerWorkItem.h @@ -44,7 +44,7 @@ std::unique_ptr parseReducerWorkItem(const char *ToolName, StringRef Filename, LLVMContext &Ctxt, std::unique_ptr &TM, - bool IsMIR); + bool IsMIR, bool &IsBitcode); std::unique_ptr cloneReducerWorkItem(const ReducerWorkItem &MMM, const TargetMachine *TM); Index: llvm/tools/llvm-reduce/ReducerWorkItem.cpp =================================================================== --- llvm/tools/llvm-reduce/ReducerWorkItem.cpp +++ llvm/tools/llvm-reduce/ReducerWorkItem.cpp @@ -388,7 +388,7 @@ std::unique_ptr parseReducerWorkItem(const char *ToolName, StringRef Filename, LLVMContext &Ctxt, std::unique_ptr &TM, - bool IsMIR) { + bool IsMIR, bool &IsBitcode) { Triple TheTriple; auto MMM = std::make_unique(); @@ -459,6 +459,7 @@ } MMM->M = std::move(Result); } else { + IsBitcode = true; readBitcode(*MMM, MemoryBufferRef(**MB), Ctxt, ToolName); if (MMM->LTOInfo->IsThinLTO && MMM->LTOInfo->EnableSplitLTOUnit) Index: llvm/tools/llvm-reduce/TestRunner.h =================================================================== --- llvm/tools/llvm-reduce/TestRunner.h +++ llvm/tools/llvm-reduce/TestRunner.h @@ -28,7 +28,8 @@ public: TestRunner(StringRef TestName, const std::vector &TestArgs, std::unique_ptr Program, - std::unique_ptr TM, const char *ToolName); + std::unique_ptr TM, const char *ToolName, + StringRef OutputFilename, bool OutputBitcode); /// Runs the interesting-ness test for the specified file /// @returns 0 if test was successful, 1 if otherwise @@ -43,12 +44,16 @@ const char *getToolName() const { return ToolName; } + void writeOutput(StringRef Message); + private: StringRef TestName; const char *ToolName; const std::vector &TestArgs; std::unique_ptr Program; std::unique_ptr TM; + StringRef OutputFilename; + bool EmitBitcode; }; } // namespace llvm Index: llvm/tools/llvm-reduce/TestRunner.cpp =================================================================== --- llvm/tools/llvm-reduce/TestRunner.cpp +++ llvm/tools/llvm-reduce/TestRunner.cpp @@ -9,15 +9,23 @@ #include "TestRunner.h" #include "ReducerWorkItem.h" #include "deltas/Utils.h" +#include "llvm/Analysis/ModuleSummaryAnalysis.h" +#include "llvm/Analysis/ProfileSummaryInfo.h" +#include "llvm/Bitcode/BitcodeReader.h" +#include "llvm/Bitcode/BitcodeWriter.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" using namespace llvm; TestRunner::TestRunner(StringRef TestName, const std::vector &TestArgs, std::unique_ptr Program, - std::unique_ptr TM, const char *ToolName) + std::unique_ptr TM, const char *ToolName, + StringRef OutputName, bool OutputBitcode) : TestName(TestName), ToolName(ToolName), TestArgs(TestArgs), - Program(std::move(Program)), TM(std::move(TM)) { + Program(std::move(Program)), TM(std::move(TM)), + OutputFilename(OutputName), EmitBitcode(OutputBitcode) { assert(this->Program && "Initialized with null program?"); } @@ -58,3 +66,46 @@ assert(P && "Setting null program?"); Program = std::move(P); } + +void writeBitcode(ReducerWorkItem &M, raw_ostream &OutStream) { + if (M.LTOInfo && M.LTOInfo->IsThinLTO && M.LTOInfo->EnableSplitLTOUnit) { + PassBuilder PB; + LoopAnalysisManager LAM; + FunctionAnalysisManager FAM; + CGSCCAnalysisManager CGAM; + ModuleAnalysisManager MAM; + PB.registerModuleAnalyses(MAM); + PB.registerCGSCCAnalyses(CGAM); + PB.registerFunctionAnalyses(FAM); + PB.registerLoopAnalyses(LAM); + PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); + ModulePassManager MPM; + MPM.addPass(ThinLTOBitcodeWriterPass(OutStream, nullptr)); + MPM.run(*M.M, MAM); + } 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 TestRunner::writeOutput(StringRef Message) { + std::error_code EC; + raw_fd_ostream Out(OutputFilename, EC); + if (EC) { + errs() << "Error opening output file: " << EC.message() << "!\n"; + exit(1); + } + + // Requesting bitcode emission with mir is nonsense, so just ignore it. + if (EmitBitcode && !Program->isMIR()) + writeBitcode(*Program, Out); + else + Program->print(Out, /*AnnotationWriter=*/nullptr); + + errs() << Message << OutputFilename << '\n'; +} Index: llvm/tools/llvm-reduce/deltas/Delta.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/Delta.cpp +++ llvm/tools/llvm-reduce/deltas/Delta.cpp @@ -60,8 +60,6 @@ unsigned NumJobs = 1; #endif -void writeOutput(ReducerWorkItem &M, llvm::StringRef Message); - void writeBitcode(ReducerWorkItem &M, raw_ostream &OutStream); void readBitcode(ReducerWorkItem &M, MemoryBufferRef Data, LLVMContext &Ctx, @@ -383,7 +381,7 @@ ReducedProgram = std::move(Result); // FIXME: Report meaningful progress info - writeOutput(*ReducedProgram, " **** SUCCESS | Saved new best reduction to "); + Test.writeOutput(" **** SUCCESS | Saved new best reduction to "); } // Delete uninteresting chunks erase_if(ChunksStillConsideredInteresting, Index: llvm/tools/llvm-reduce/llvm-reduce.cpp =================================================================== --- llvm/tools/llvm-reduce/llvm-reduce.cpp +++ llvm/tools/llvm-reduce/llvm-reduce.cpp @@ -17,19 +17,12 @@ #include "DeltaManager.h" #include "ReducerWorkItem.h" #include "TestRunner.h" -#include "llvm/Analysis/ModuleSummaryAnalysis.h" -#include "llvm/Analysis/ProfileSummaryInfo.h" -#include "llvm/Bitcode/BitcodeReader.h" -#include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/CodeGen/CommandFlags.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IRReader/IRReader.h" -#include "llvm/Passes/PassBuilder.h" + #include "llvm/Support/CommandLine.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/WithColor.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h" #include #include @@ -63,7 +56,8 @@ cl::cat(LLVMReduceOptions)); static cl::opt OutputFilename( - "output", cl::desc("Specify the output file. default: reduced.ll|mir")); + "output", + cl::desc("Specify the output file. default: reduced.ll|.bc|.mir")); static cl::alias OutputFileAlias("o", cl::desc("Alias for -output"), cl::aliasopt(OutputFilename), cl::cat(LLVMReduceOptions)); @@ -84,6 +78,11 @@ clEnumValN(InputLanguages::MIR, "mir", "")), cl::cat(LLVMReduceOptions)); +static cl::opt ForceOutputBitcode( + "output-bitcode", + cl::desc("Emit final result as bitcode instead of text IR"), cl::Hidden, + cl::cat(LLVMReduceOptions)); + static cl::opt MaxPassIterations("max-pass-iterations", cl::desc("Maximum number of times to run the full set " @@ -94,45 +93,23 @@ bool isReduced(ReducerWorkItem &M, TestRunner &Test); -void writeOutput(ReducerWorkItem &M, StringRef Message) { - if (ReplaceInput) // In-place +static std::pair determineOutputType(bool IsMIR, + bool InputIsBitcode) { + bool OutputBitcode = ForceOutputBitcode; + + if (ReplaceInput) { // In-place OutputFilename = InputFilename.c_str(); - else if (OutputFilename.empty() || OutputFilename == "-") - OutputFilename = M.isMIR() ? "reduced.mir" : "reduced.ll"; - std::error_code EC; - raw_fd_ostream Out(OutputFilename, EC); - if (EC) { - errs() << "Error opening output file: " << EC.message() << "!\n"; - exit(1); + OutputBitcode |= StringRef(OutputFilename).endswith(".bc"); + } else if (OutputFilename.empty() || OutputFilename == "-") { + // Default to producing bitcode if the input was bitcode, if not explicitly + // requested. + + OutputBitcode |= InputIsBitcode; + OutputFilename = + IsMIR ? "reduced.mir" : (OutputBitcode ? "reduced.bc" : "reduced.ll"); } - M.print(Out, /*AnnotationWriter=*/nullptr); - errs() << Message << OutputFilename << "\n"; -} -void writeBitcode(ReducerWorkItem &M, llvm::raw_ostream &OutStream) { - if (M.LTOInfo && M.LTOInfo->IsThinLTO && M.LTOInfo->EnableSplitLTOUnit) { - PassBuilder PB; - LoopAnalysisManager LAM; - FunctionAnalysisManager FAM; - CGSCCAnalysisManager CGAM; - ModuleAnalysisManager MAM; - PB.registerModuleAnalyses(MAM); - PB.registerCGSCCAnalyses(CGAM); - PB.registerFunctionAnalyses(FAM); - PB.registerLoopAnalyses(LAM); - PB.crossRegisterProxies(LAM, FAM, CGAM, MAM); - ModulePassManager MPM; - MPM.addPass(ThinLTOBitcodeWriterPass(OutStream, nullptr)); - MPM.run(*M.M, MAM); - } 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()); - } + return {OutputFilename, OutputBitcode}; } void readBitcode(ReducerWorkItem &M, MemoryBufferRef Data, LLVMContext &Ctx, const char *ToolName) { @@ -173,16 +150,22 @@ LLVMContext Context; std::unique_ptr TM; + bool InputIsBitcode = false; - std::unique_ptr OriginalProgram = - parseReducerWorkItem(Argv[0], InputFilename, Context, TM, ReduceModeMIR); + std::unique_ptr OriginalProgram = parseReducerWorkItem( + Argv[0], InputFilename, Context, TM, ReduceModeMIR, InputIsBitcode); if (!OriginalProgram) { return 1; } + StringRef OutputFilename; + bool OutputBitcode; + std::tie(OutputFilename, OutputBitcode) = + determineOutputType(ReduceModeMIR, InputIsBitcode); + // Initialize test environment TestRunner Tester(TestFilename, TestArguments, std::move(OriginalProgram), - std::move(TM), Argv[0]); + std::move(TM), Argv[0], OutputFilename, OutputBitcode); // This parses and writes out the testcase into a temporary file copy for the // test, rather than evaluating the source IR directly. This is for the @@ -200,7 +183,7 @@ if (OutputFilename == "-") Tester.getProgram().print(outs(), nullptr); else - writeOutput(Tester.getProgram(), "Done reducing! Reduced testcase: "); + Tester.writeOutput("Done reducing! Reduced testcase: "); return 0; }