[llvm] 3c436ab - llvm-reduce: Support emitting bitcode for final result

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 31 20:35:14 PDT 2022


Author: Matt Arsenault
Date: 2022-10-31T20:35:08-07:00
New Revision: 3c436ab0d457a83e8efaf74745a7672a09d6f3a3

URL: https://github.com/llvm/llvm-project/commit/3c436ab0d457a83e8efaf74745a7672a09d6f3a3
DIFF: https://github.com/llvm/llvm-project/commit/3c436ab0d457a83e8efaf74745a7672a09d6f3a3.diff

LOG: llvm-reduce: Support emitting bitcode for final result

Previously, this unconditionally emitted text IR. I ran
into a bug that manifested in broken disassembly, so the
desired output was the bitcode format. If the input format
was binary bitcode, the requested output file ends in .bc,
or an explicit -output-bitcode option was used, emit bitcode.

Added: 
    llvm/test/tools/llvm-reduce/Inputs/test-output-format.ll
    llvm/test/tools/llvm-reduce/Inputs/test-output-format.mir
    llvm/test/tools/llvm-reduce/file-output-type.test

Modified: 
    llvm/tools/llvm-reduce/ReducerWorkItem.cpp
    llvm/tools/llvm-reduce/ReducerWorkItem.h
    llvm/tools/llvm-reduce/TestRunner.cpp
    llvm/tools/llvm-reduce/TestRunner.h
    llvm/tools/llvm-reduce/deltas/Delta.cpp
    llvm/tools/llvm-reduce/llvm-reduce.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-reduce/Inputs/test-output-format.ll b/llvm/test/tools/llvm-reduce/Inputs/test-output-format.ll
new file mode 100644
index 0000000000000..d42433556a0da
--- /dev/null
+++ b/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
+}

diff  --git a/llvm/test/tools/llvm-reduce/Inputs/test-output-format.mir b/llvm/test/tools/llvm-reduce/Inputs/test-output-format.mir
new file mode 100644
index 0000000000000..0f8d5184a2d25
--- /dev/null
+++ b/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)
+...

diff  --git a/llvm/test/tools/llvm-reduce/file-output-type.test b/llvm/test/tools/llvm-reduce/file-output-type.test
new file mode 100644
index 0000000000000..e81a9ddbb8931
--- /dev/null
+++ b/llvm/test/tools/llvm-reduce/file-output-type.test
@@ -0,0 +1,48 @@
+# RUN: rm -f reduced.ll reduced.bc
+
+# RUN: llvm-as -o test-output-format.bc %p/Inputs/test-output-format.ll
+
+# 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 test-output-format.bc
+# RUN: llvm-dis -disable-output reduced.bc
+
+
+# A .bc input file with a requested .bc output should produce bitcode
+# RUN: llvm-reduce --delta-passes=instructions -o %t.0.bc --test FileCheck --test-arg %s --test-arg --input-file test-output-format.bc
+# RUN: llvm-dis -disable-output %t.0.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 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-dis -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

diff  --git a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
index aac150ba9c00a..1126fdecff15e 100644
--- a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
+++ b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp
@@ -385,10 +385,11 @@ static void initializeTargetInfo() {
   InitializeAllAsmParsers();
 }
 
-std::unique_ptr<ReducerWorkItem>
+std::pair<std::unique_ptr<ReducerWorkItem>, bool>
 parseReducerWorkItem(const char *ToolName, StringRef Filename,
                      LLVMContext &Ctxt, std::unique_ptr<TargetMachine> &TM,
                      bool IsMIR) {
+  bool IsBitcode = false;
   Triple TheTriple;
 
   auto MMM = std::make_unique<ReducerWorkItem>();
@@ -399,7 +400,7 @@ parseReducerWorkItem(const char *ToolName, StringRef Filename,
     auto FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true);
     if (std::error_code EC = FileOrErr.getError()) {
       WithColor::error(errs(), ToolName) << EC.message() << '\n';
-      return nullptr;
+      return {nullptr, false};
     }
 
     std::unique_ptr<MIRParser> MParser =
@@ -447,7 +448,7 @@ parseReducerWorkItem(const char *ToolName, StringRef Filename,
     ErrorOr<std::unique_ptr<MemoryBuffer>> MB = MemoryBuffer::getFileOrSTDIN(Filename);
     if (std::error_code EC = MB.getError()) {
       WithColor::error(errs(), ToolName) << Filename << ": " << EC.message() << "\n";
-      return nullptr;
+      return {nullptr, false};
     }
 
     if (!isBitcode((const unsigned char *)(*MB)->getBufferStart(),
@@ -455,10 +456,11 @@ parseReducerWorkItem(const char *ToolName, StringRef Filename,
       std::unique_ptr<Module> Result = parseIRFile(Filename, Err, Ctxt);
       if (!Result) {
         Err.print(ToolName, errs());
-        return nullptr;
+        return {nullptr, false};
       }
       MMM->M = std::move(Result);
     } else {
+      IsBitcode = true;
       readBitcode(*MMM, MemoryBufferRef(**MB), Ctxt, ToolName);
 
       if (MMM->LTOInfo->IsThinLTO && MMM->LTOInfo->EnableSplitLTOUnit)
@@ -468,9 +470,9 @@ parseReducerWorkItem(const char *ToolName, StringRef Filename,
   if (verifyReducerWorkItem(*MMM, &errs())) {
     WithColor::error(errs(), ToolName)
         << Filename << " - input module is broken!\n";
-    return nullptr;
+    return {nullptr, false};
   }
-  return MMM;
+  return {std::move(MMM), IsBitcode};
 }
 
 std::unique_ptr<ReducerWorkItem>

diff  --git a/llvm/tools/llvm-reduce/ReducerWorkItem.h b/llvm/tools/llvm-reduce/ReducerWorkItem.h
index 55d1f562a3835..e0e3d9fac920a 100644
--- a/llvm/tools/llvm-reduce/ReducerWorkItem.h
+++ b/llvm/tools/llvm-reduce/ReducerWorkItem.h
@@ -41,7 +41,7 @@ class ReducerWorkItem {
   uint64_t computeMIRComplexityScore() const;
 };
 
-std::unique_ptr<ReducerWorkItem>
+std::pair<std::unique_ptr<ReducerWorkItem>, bool>
 parseReducerWorkItem(const char *ToolName, StringRef Filename,
                      LLVMContext &Ctxt, std::unique_ptr<TargetMachine> &TM,
                      bool IsMIR);

diff  --git a/llvm/tools/llvm-reduce/TestRunner.cpp b/llvm/tools/llvm-reduce/TestRunner.cpp
index 63de850de5b23..da999e452b9e3 100644
--- a/llvm/tools/llvm-reduce/TestRunner.cpp
+++ b/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<std::string> &TestArgs,
                        std::unique_ptr<ReducerWorkItem> Program,
-                       std::unique_ptr<TargetMachine> TM, const char *ToolName)
+                       std::unique_ptr<TargetMachine> 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 @@ void TestRunner::setProgram(std::unique_ptr<ReducerWorkItem> P) {
   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<ModuleSummaryIndex> Index;
+    if (M.LTOInfo && M.LTOInfo->HasSummary) {
+      ProfileSummaryInfo PSI(M);
+      Index = std::make_unique<ModuleSummaryIndex>(
+          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';
+}

diff  --git a/llvm/tools/llvm-reduce/TestRunner.h b/llvm/tools/llvm-reduce/TestRunner.h
index 6d7dd7a51ceba..f98628d511ddf 100644
--- a/llvm/tools/llvm-reduce/TestRunner.h
+++ b/llvm/tools/llvm-reduce/TestRunner.h
@@ -28,7 +28,8 @@ class TestRunner {
 public:
   TestRunner(StringRef TestName, const std::vector<std::string> &TestArgs,
              std::unique_ptr<ReducerWorkItem> Program,
-             std::unique_ptr<TargetMachine> TM, const char *ToolName);
+             std::unique_ptr<TargetMachine> 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 @@ class TestRunner {
 
   const char *getToolName() const { return ToolName; }
 
+  void writeOutput(StringRef Message);
+
 private:
   StringRef TestName;
   const char *ToolName;
   const std::vector<std::string> &TestArgs;
   std::unique_ptr<ReducerWorkItem> Program;
   std::unique_ptr<TargetMachine> TM;
+  StringRef OutputFilename;
+  bool EmitBitcode;
 };
 
 } // namespace llvm

diff  --git a/llvm/tools/llvm-reduce/deltas/Delta.cpp b/llvm/tools/llvm-reduce/deltas/Delta.cpp
index 26feca6b99248..28b4cee521867 100644
--- a/llvm/tools/llvm-reduce/deltas/Delta.cpp
+++ b/llvm/tools/llvm-reduce/deltas/Delta.cpp
@@ -60,8 +60,6 @@ static cl::opt<unsigned> NumJobs(
 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,
@@ -369,7 +367,7 @@ void llvm::runDeltaPass(TestRunner &Test, ReductionFunc ExtractChunksFromModule,
       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,

diff  --git a/llvm/tools/llvm-reduce/llvm-reduce.cpp b/llvm/tools/llvm-reduce/llvm-reduce.cpp
index 5cadaa73a682d..627d30b81ed9e 100644
--- a/llvm/tools/llvm-reduce/llvm-reduce.cpp
+++ b/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 <system_error>
 #include <vector>
 
@@ -63,7 +56,8 @@ static cl::list<std::string>
                   cl::cat(LLVMReduceOptions));
 
 static cl::opt<std::string> 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 @@ static cl::opt<InputLanguages>
                              clEnumValN(InputLanguages::MIR, "mir", "")),
                   cl::cat(LLVMReduceOptions));
 
+static cl::opt<bool> ForceOutputBitcode(
+    "output-bitcode",
+    cl::desc("Emit final result as bitcode instead of text IR"), cl::Hidden,
+    cl::cat(LLVMReduceOptions));
+
 static cl::opt<int>
     MaxPassIterations("max-pass-iterations",
                       cl::desc("Maximum number of times to run the full set "
@@ -94,45 +93,24 @@ static codegen::RegisterCodeGenFlags CGF;
 
 bool isReduced(ReducerWorkItem &M, TestRunner &Test);
 
-void writeOutput(ReducerWorkItem &M, StringRef Message) {
-  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);
-  }
-  M.print(Out, /*AnnotationWriter=*/nullptr);
-  errs() << Message << OutputFilename << "\n";
-}
+static std::pair<StringRef, bool> determineOutputType(bool IsMIR,
+                                                      bool InputIsBitcode) {
+  bool OutputBitcode = ForceOutputBitcode;
 
-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<ModuleSummaryIndex> Index;
-    if (M.LTOInfo && M.LTOInfo->HasSummary) {
-      ProfileSummaryInfo PSI(M);
-      Index = std::make_unique<ModuleSummaryIndex>(
-          buildModuleSummaryIndex(M, nullptr, &PSI));
-    }
-    WriteBitcodeToFile(M, OutStream, Index.get());
-  }
+  if (ReplaceInput) { // In-place
+    OutputFilename = InputFilename.c_str();
+    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");
+  } else
+    OutputBitcode |= StringRef(OutputFilename).endswith(".bc");
+
+  return {OutputFilename, OutputBitcode};
 }
 
 void readBitcode(ReducerWorkItem &M, MemoryBufferRef Data, LLVMContext &Ctx, const char *ToolName) {
@@ -174,15 +152,20 @@ int main(int Argc, char **Argv) {
   LLVMContext Context;
   std::unique_ptr<TargetMachine> TM;
 
-  std::unique_ptr<ReducerWorkItem> OriginalProgram =
+  auto [OriginalProgram, InputIsBitcode] =
       parseReducerWorkItem(Argv[0], InputFilename, Context, TM, ReduceModeMIR);
   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 @@ int main(int Argc, char **Argv) {
   if (OutputFilename == "-")
     Tester.getProgram().print(outs(), nullptr);
   else
-    writeOutput(Tester.getProgram(), "Done reducing! Reduced testcase: ");
+    Tester.writeOutput("Done reducing! Reduced testcase: ");
 
   return 0;
 }


        


More information about the llvm-commits mailing list