[PATCH] Machine Level IR Serialization: print and parse LLVM IR.
Duncan P. N. Exon Smith
dexonsmith at apple.com
Thu May 14 17:44:40 PDT 2015
> On 2015-May-13, at 13:08, Alex Lorenz <arphaman at gmail.com> wrote:
>
> REPOSITORY
> rL LLVM
>
> ================
> Comment at: lib/CodeGen/Serialization/MIRPrintingPass.cpp:28
> @@ +27,3 @@
> +/// an output stream.
> +struct MachineLevelIRPrintingPass : public MachineFunctionPass {
> + static char ID;
> ----------------
> reames wrote:
>> Is there a MachineModulePass? The use of the HaveToPrintModule flag feels very dirty.
> There's no machine module pass, but I decided to use a module pass and to get rid of this flag.
> This means I will have to add a new pass that prints out machine functions in later patches. It will have to run right after the module printing pass.
>
> http://reviews.llvm.org/D9616
I'm not sure this is the right end point. Coordinating printing
out the .mir from separate passes is indirect and likely bugprone.
I wonder if we should just be inventing a MachineModulePass.
What you have is fine as a starting point though.
> I rebased this patch and reflowed a long line in lib/CodeGen/LLVMBuild.txt based on
> r237367 (it reflows long lines of LLVMBuild files).
Regarding the rest of the patch:
> Index: include/llvm/CodeGen/Passes.h
> ===================================================================
> --- include/llvm/CodeGen/Passes.h
> +++ include/llvm/CodeGen/Passes.h
> @@ -374,6 +374,10 @@
> createMachineFunctionPrinterPass(raw_ostream &OS,
> const std::string &Banner ="");
>
> + /// MIRModulePrinting pass - this pass prints out the LLVM IR into the given
> + /// stream using the MIR serialization format.
> + ModulePass *createMIRModulePrintingPass(raw_ostream &OS);
`createPrintMIRPass()`?
> +
> /// createCodeGenPreparePass - Transform the code to expose more pattern
> /// matching during instruction selection.
> FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = nullptr);
> @@ -488,6 +492,10 @@
> /// MachineFunctionPrinterPass - This pass prints out MachineInstr's.
> extern char &MachineFunctionPrinterPassID;
>
> + /// MIRModulePrintingPass - this pass prints out the LLVM IR using the MIR
> + /// serialization format.
> + extern char &MIRModulePrintingPassID;
> +
> /// TailDuplicate - Duplicate blocks with unconditional branches
> /// into tails of their predecessors.
> extern char &TailDuplicateID;
> Index: include/llvm/CodeGen/Serialization/Parser.h
> ===================================================================
> --- /dev/null
> +++ include/llvm/CodeGen/Serialization/Parser.h
Why not CodeGen/MIR/Parser.h?
> @@ -0,0 +1,57 @@
> +//===- Parser.h - MIR serialization format parser -------------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This MIR serialization library is currently a work in progress. It can't
> +// serialize machine functions at this time.
> +//
> +// This file declares the functions that parse the MIR serialization format
> +// files.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_CODEGEN_SERIALIZATION_PARSER_H
> +#define LLVM_CODEGEN_SERIALIZATION_PARSER_H
s/SERIALIZATION/MIR/
s/Serialization/MIR/
s/CodeGenSerialization/MIR/
(etc., throughout the patch)
> +
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/IR/Module.h"
> +#include "llvm/Support/SMLoc.h"
> +#include "llvm/Support/MemoryBuffer.h"
> +#include "llvm/Support/ErrorOr.h"
> +#include <vector>
> +#include <memory>
> +
> +namespace llvm {
> +
> +class SMDiagnostic;
> +
> +/// \brief This function is the main interface to the MIR serialization format
> +/// parser.
> +/// It reads a YAML file that has an optional LLVM IR and returns an LLVM
> +/// module.
> +/// \param Filename - The name of the file to parse.
> +/// \param Errs - The array into which the parsing errors are placed.
> +/// \param Context - Context in which to allocate globals info.
> +std::unique_ptr<Module> parseMIRFile(StringRef Filename,
> + std::vector<SMDiagnostic> &Errs,
> + LLVMContext &Context);
Do you really need multiple errors here? Why not just exit on the first
failure? That'd simplify this API a fair bit.
> +
> +/// \brief This function is another interface to the MIR serialization format
> +/// parser.
> +/// It parses the optional LLVM IR in the given buffer, and returns an LLVM
> +/// module.
> +/// \param Contents - The MemoryBuffer containing the machine level IR.
> +/// \param Errs - The array into which the parsing errors are placed.
> +/// \param Context - Context in which to allocate globals info.
> +std::unique_ptr<Module> parseMIR(std::unique_ptr<MemoryBuffer> Contents,
> + std::vector<SMDiagnostic> &Errs,
> + LLVMContext &Context);
> +
> +} // End llvm namespace
> +
> +#endif
> Index: include/llvm/InitializePasses.h
> ===================================================================
> --- include/llvm/InitializePasses.h
> +++ include/llvm/InitializePasses.h
> @@ -288,6 +288,7 @@
> void initializeSLPVectorizerPass(PassRegistry&);
> void initializeBBVectorizePass(PassRegistry&);
> void initializeMachineFunctionPrinterPassPass(PassRegistry&);
> +void initializeMIRModulePrintingPassPass(PassRegistry &);
> void initializeStackMapLivenessPass(PassRegistry&);
> void initializeMachineCombinerPass(PassRegistry &);
> void initializeLoadCombinePass(PassRegistry&);
> Index: include/llvm/Support/YAMLTraits.h
> ===================================================================
> --- include/llvm/Support/YAMLTraits.h
> +++ include/llvm/Support/YAMLTraits.h
> @@ -1090,6 +1090,9 @@
> bool setCurrentDocument();
> bool nextDocument();
>
> + /// \brief Returns the current node that's being parsed by the YAML Parser.
> + const Node *getCurrentNode();
> +
> private:
> llvm::SourceMgr SrcMgr; // must be before Strm
> std::unique_ptr<llvm::yaml::Stream> Strm;
> Index: lib/CodeGen/CMakeLists.txt
> ===================================================================
> --- lib/CodeGen/CMakeLists.txt
> +++ lib/CodeGen/CMakeLists.txt
> @@ -128,3 +128,4 @@
>
> add_subdirectory(SelectionDAG)
> add_subdirectory(AsmPrinter)
> +add_subdirectory(Serialization)
> Index: lib/CodeGen/LLVMBuild.txt
> ===================================================================
> --- lib/CodeGen/LLVMBuild.txt
> +++ lib/CodeGen/LLVMBuild.txt
> @@ -16,10 +16,11 @@
> ;===------------------------------------------------------------------------===;
>
> [common]
> -subdirectories = AsmPrinter SelectionDAG
> +subdirectories = AsmPrinter SelectionDAG Serialization
>
> [component_0]
> type = Library
> name = CodeGen
> parent = Libraries
> required_libraries = Analysis Core MC Scalar Support Target TransformUtils
> + CodeGenSerialization
> Index: lib/CodeGen/LLVMTargetMachine.cpp
> ===================================================================
> --- lib/CodeGen/LLVMTargetMachine.cpp
> +++ lib/CodeGen/LLVMTargetMachine.cpp
> @@ -150,12 +150,8 @@
> return true;
>
> if (StopAfter) {
> - // FIXME: The intent is that this should eventually write out a YAML file,
> - // containing the LLVM IR, the machine-level IR (when stopping after a
> - // machine-level pass), and whatever other information is needed to
> - // deserialize the code and resume compilation. For now, just write the
> - // LLVM IR.
> - PM.add(createPrintModulePass(Out));
> + PM.add(createMIRModulePrintingPass(outs()));
> + // TODO: Print out the machine functions.
> return false;
> }
>
> Index: lib/CodeGen/Makefile
> ===================================================================
> --- lib/CodeGen/Makefile
> +++ lib/CodeGen/Makefile
> @@ -9,7 +9,7 @@
>
> LEVEL = ../..
> LIBRARYNAME = LLVMCodeGen
> -PARALLEL_DIRS = SelectionDAG AsmPrinter
> +PARALLEL_DIRS = SelectionDAG AsmPrinter Serialization
> BUILD_ARCHIVE = 1
>
> include $(LEVEL)/Makefile.common
> Index: lib/CodeGen/Serialization/CMakeLists.txt
> ===================================================================
> --- /dev/null
> +++ lib/CodeGen/Serialization/CMakeLists.txt
> @@ -0,0 +1,8 @@
> +add_llvm_library(LLVMCodeGenSerialization
> + YAMLMapping.cpp
> + MIRPrintingPasses.cpp
> + Parser.cpp
> + MIRParser.cpp
> + )
> +
> +add_dependencies(LLVMCodeGenSerialization intrinsics_gen)
> Index: lib/CodeGen/Serialization/LLVMBuild.txt
> ===================================================================
> --- /dev/null
> +++ lib/CodeGen/Serialization/LLVMBuild.txt
> @@ -0,0 +1,22 @@
> +;===- ./lib/CodeGen/Serialization/LLVMBuild.txt ----------------*- Conf -*--===;
> +;
> +; The LLVM Compiler Infrastructure
> +;
> +; This file is distributed under the University of Illinois Open Source
> +; License. See LICENSE.TXT for details.
> +;
> +;===------------------------------------------------------------------------===;
> +;
> +; This is an LLVMBuild description file for the components in this subdirectory.
> +;
> +; For more information on the LLVMBuild system, please see:
> +;
> +; http://llvm.org/docs/LLVMBuild.html
> +;
> +;===------------------------------------------------------------------------===;
> +
> +[component_0]
> +type = Library
> +name = CodeGenSerialization
> +parent = CodeGen
> +required_libraries = Core Support Target AsmParser
> Index: lib/CodeGen/Serialization/MIRParser.cpp
> ===================================================================
> --- /dev/null
> +++ lib/CodeGen/Serialization/MIRParser.cpp
> @@ -0,0 +1,36 @@
> +//===- MIRParser.cpp - MIR serialization format parser implementation -----===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file implements the class that parses the optional LLVM IR and machine
> +// functions that are stored in MIR files.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "MIRParser.h"
> +#include "llvm/AsmParser/Parser.h"
> +#include "llvm/Support/LineIterator.h"
> +#include "llvm/Support/SourceMgr.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +using namespace llvm;
> +
> +MIRParserImpl::MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents,
> + StringRef Filename, LLVMContext &Context)
> + : SM(), Filename(Filename), Context(Context) {
> + SM.AddNewSourceBuffer(std::move(Contents), SMLoc());
> +}
> +
> +std::unique_ptr<Module>
> +MIRParserImpl::parseLLVMModule(StringRef Str, std::vector<SMDiagnostic> &Errs) {
> + SMDiagnostic LLErr;
> + auto Mod = parseAssembly(MemoryBufferRef(Str, Filename), LLErr, Context);
> + if (LLErr.getLineNo())
> + Errs.push_back(LLErr);
> + return Mod;
> +}
> Index: lib/CodeGen/Serialization/MIRParser.h
> ===================================================================
> --- /dev/null
> +++ lib/CodeGen/Serialization/MIRParser.h
> @@ -0,0 +1,52 @@
> +//===- MIRParser.h - MIR serialization format parser ----------------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file declares the class that parses the optional LLVM IR and machine
> +// functions that are stored in MIR files.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_LIB_CODEGEN_SERIALIZATION_MIRPARSER_H
> +#define LLVM_LIB_CODEGEN_SERIALIZATION_MIRPARSER_H
> +
> +#include "llvm/ADT/StringRef.h"
> +#include "llvm/IR/Module.h"
> +#include "llvm/Support/SMLoc.h"
> +#include "llvm/Support/SourceMgr.h"
> +#include "llvm/Support/MemoryBuffer.h"
> +#include <vector>
> +
> +namespace llvm {
> +
> +class SMDiagnostic;
> +
> +/// \brief This class implements the parsing of LLVM IR that's embedded inside
> +/// of a MIR file.
> +class MIRParserImpl {
> + SourceMgr SM;
> + StringRef Filename;
> + LLVMContext &Context;
> +
> +public:
> + MIRParserImpl(std::unique_ptr<MemoryBuffer> Contents, StringRef Filename,
> + LLVMContext &Context);
> +
> + /// \brief Try to parse the optional LLVM module in the MIR file. Return null
> + /// if an error occurred while parsing the LLVM module.
> + std::unique_ptr<Module> parseLLVMModule(std::vector<SMDiagnostic> &Errs);
> +
> +private:
> + /// \brief Parse the LLVM module in the given string.
> + std::unique_ptr<Module> parseLLVMModule(StringRef Str,
> + std::vector<SMDiagnostic> &Errs);
> +};
> +
> +} // End llvm namespace
> +
> +#endif
> Index: lib/CodeGen/Serialization/MIRPrintingPasses.cpp
> ===================================================================
> --- /dev/null
> +++ lib/CodeGen/Serialization/MIRPrintingPasses.cpp
> @@ -0,0 +1,65 @@
> +//===- MIRPrintingPasses.cpp - Passes that print out using the MIR format -===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file implements a pass that prints out the LLVM module using the MIR
> +// serialization format.
> +// TODO: Implement a pass the prints out the machine functions.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "YAMLMapping.h"
> +#include "llvm/CodeGen/Passes.h"
> +#include "llvm/CodeGen/MachineFunction.h"
> +#include "llvm/CodeGen/MachineModuleInfo.h"
> +#include "llvm/CodeGen/MachineFunctionPass.h"
> +#include "llvm/Support/Debug.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +using namespace llvm;
> +
> +namespace {
> +
> +/// MIRModulePrintingPass - This pass prints out the LLVM IR to an output stream
> +/// using the MIR serialization format.
> +struct MIRModulePrintingPass : public ModulePass {
> + static char ID;
> + raw_ostream &OS;
> +
> + MIRModulePrintingPass() : ModulePass(ID), OS(dbgs()) {}
> + MIRModulePrintingPass(raw_ostream &OS) : ModulePass(ID), OS(OS) {}
> +
> + const char *getPassName() const override {
> + return "MIR Module Printing Pass";
> + }
> +
> + void getAnalysisUsage(AnalysisUsage &AU) const override {
> + AU.setPreservesAll();
> + ModulePass::getAnalysisUsage(AU);
> + }
> +
> + virtual bool runOnModule(Module &M) override {
> + MIRPrinter Printer(OS);
> + Printer.printModule(&M);
> + return false;
> + }
> +};
> +
> +char MIRModulePrintingPass::ID = 0;
> +}
> +
> +char &llvm::MIRModulePrintingPassID = MIRModulePrintingPass::ID;
> +INITIALIZE_PASS(MIRModulePrintingPass, "mir-module-printer",
> + "MIR Module Printer", false, false)
> +
> +namespace llvm {
> +
> +ModulePass *createMIRModulePrintingPass(raw_ostream &OS) {
> + return new MIRModulePrintingPass(OS);
> +}
> +}
> Index: lib/CodeGen/Serialization/Makefile
> ===================================================================
> --- /dev/null
> +++ lib/CodeGen/Serialization/Makefile
> @@ -0,0 +1,13 @@
> +##===- lib/CodeGen/Serialization/Makefile ------------------*- Makefile -*-===##
> +#
> +# The LLVM Compiler Infrastructure
> +#
> +# This file is distributed under the University of Illinois Open Source
> +# License. See LICENSE.TXT for details.
> +#
> +##===----------------------------------------------------------------------===##
> +
> +LEVEL = ../../..
> +LIBRARYNAME = LLVMCodeGenSerialization
> +
> +include $(LEVEL)/Makefile.common
> Index: lib/CodeGen/Serialization/Parser.cpp
> ===================================================================
> --- /dev/null
> +++ lib/CodeGen/Serialization/Parser.cpp
> @@ -0,0 +1,42 @@
> +//===- Parser.cpp - MIR serialization format parser implementation --------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file implements the functions that parse the MIR serialization format.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "llvm/CodeGen/Serialization/Parser.h"
> +#include "MIRParser.h"
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/AsmParser/Parser.h"
> +#include "llvm/Support/LineIterator.h"
> +#include "llvm/Support/SourceMgr.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +using namespace llvm;
> +
> +std::unique_ptr<Module> llvm::parseMIRFile(StringRef Filename,
> + std::vector<SMDiagnostic> &Errs,
> + LLVMContext &Context) {
> + auto FileOrErr = MemoryBuffer::getFile(Filename);
> + if (auto EC = FileOrErr.getError()) {
> + Errs.push_back(SMDiagnostic(Filename, SourceMgr::DK_Error,
> + "Could not open input file: " + EC.message()));
> + return std::unique_ptr<Module>();
> + }
> + return parseMIR(std::move(FileOrErr.get()), Errs, Context);
> +}
> +
> +std::unique_ptr<Module> llvm::parseMIR(std::unique_ptr<MemoryBuffer> Contents,
> + std::vector<SMDiagnostic> &Errs,
> + LLVMContext &Context) {
> + auto Filename = Contents->getBufferIdentifier();
> + MIRParserImpl Parser(std::move(Contents), Filename, Context);
> + return Parser.parseLLVMModule(Errs);
> +}
> Index: lib/CodeGen/Serialization/YAMLMapping.cpp
> ===================================================================
> --- /dev/null
> +++ lib/CodeGen/Serialization/YAMLMapping.cpp
> @@ -0,0 +1,65 @@
> +//===- YAMLMapping.cpp - Describes the mapping between MIR and YAML -------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file implements the mapping between various MIR data structures and
> +// their corresponding YAML representation.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#include "YAMLMapping.h"
> +#include "MIRParser.h"
> +#include "llvm/ADT/StringExtras.h"
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/IR/Module.h"
> +#include "llvm/Support/MemoryBuffer.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +using namespace llvm;
> +
> +typedef const Module *ModuleRef;
Is this really valuable? I find it obscures the code myself.
In fact, in a number of places, I'm not sure why you're not using
`Module&` instead of `Module*`.
> +
> +namespace llvm {
> +namespace yaml {
> +
> +/// \brief This struct serializes the LLVM IR module.
> +template <> struct BlockScalarTraits<ModuleRef> {
> + static void output(const ModuleRef &Mod, void *Ctxt, raw_ostream &OS) {
> + Mod->print(OS, nullptr);
> + }
> + static StringRef input(StringRef Str, void *Ctxt, ModuleRef &Mod) {
> + assert(false && "LLVM Module is supposed to be parsed separately");
> + return StringRef();
Just return `""`.
> + }
> +};
> +}
> +}
It's inconsistent the way you have a blank line at the beginning of the
namespace and not at the end. This is likely clang-format messing with
you. If you add comments to the end of the namespace, it'll leave them
alone.
namespace llvm {
void foo();
void bar();
void baz();
void foo(int);
void bar(int);
void baz(int);
} // end namespace llvm
> +
> +MIRPrinter::MIRPrinter(raw_ostream &OS) : OS(OS) {}
> +
> +void MIRPrinter::printModule(const Module *Mod) {
> + yaml::Output Out(OS);
> + Out << Mod;
> +}
> +
> +std::unique_ptr<Module>
> +MIRParserImpl::parseLLVMModule(std::vector<SMDiagnostic> &Errs) {
> + yaml::Input In(SM.getMemoryBuffer(SM.getMainFileID())->getBuffer());
> +
> + // Parse the block scalar manually so that we can return unique pointer
> + // without having to go trough YAML traits.
> + if (In.setCurrentDocument()) {
> + if (const auto *BSN =
> + dyn_cast_or_null<yaml::BlockScalarNode>(In.getCurrentNode())) {
> + return parseLLVMModule(BSN->getValue(), Errs);
> + }
> + }
> +
> + // Create an new, empty module.
> + return llvm::make_unique<Module>(Filename, Context);
> +}
> Index: lib/CodeGen/Serialization/YAMLMapping.h
> ===================================================================
> --- /dev/null
> +++ lib/CodeGen/Serialization/YAMLMapping.h
> @@ -0,0 +1,37 @@
> +//===- YAMLMapping.h - Describes the mapping between MIR and YAML ---------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
> +//===----------------------------------------------------------------------===//
> +//
> +// This file declares some of the utility classes for handling the YAML
> +// representation of MIR data structures.
> +//
> +//===----------------------------------------------------------------------===//
> +
> +#ifndef LLVM_LIB_CODEGEN_SERIALIZATION_YAMLMAPPING_H
> +#define LLVM_LIB_CODEGEN_SERIALIZATION_YAMLMAPPING_H
> +
> +#include "llvm/Support/YAMLTraits.h"
> +
> +namespace llvm {
> +
> +class Module;
> +
> +/// \brief This class prints out the LLVM IR using the MIR serialization format
> +/// and YAML I/O.
> +class MIRPrinter {
> + raw_ostream &OS;
> +
> +public:
> + MIRPrinter(raw_ostream &OS);
> +
> + void printModule(const Module *Mod);
> +};
> +
> +} // End llvm namespace
This isn't really a sentence -- it's mainly a way to convince
clang-format not to move your closing brace -- so IMO
} // end llvm namespace
reads better.
> +
> +#endif
> Index: lib/Support/YAMLTraits.cpp
> ===================================================================
> --- lib/Support/YAMLTraits.cpp
> +++ lib/Support/YAMLTraits.cpp
> @@ -97,6 +97,10 @@
> return ++DocIterator != Strm->end();
> }
>
> +const Node *Input::getCurrentNode() {
> + return CurrentNode ? CurrentNode->_node : nullptr;
> +}
> +
> bool Input::mapTag(StringRef Tag, bool Default) {
> std::string foundTag = CurrentNode->_node->getVerbatimTag();
> if (foundTag.empty()) {
> Index: test/CodeGen/Generic/stop-after.ll
> ===================================================================
> --- test/CodeGen/Generic/stop-after.ll
> +++ test/CodeGen/Generic/stop-after.ll
> @@ -1,9 +1,10 @@
> ; RUN: llc < %s -debug-pass=Structure -stop-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=STOP
> ; RUN: llc < %s -debug-pass=Structure -start-after=loop-reduce -o /dev/null 2>&1 | FileCheck %s -check-prefix=START
>
> -; STOP: -loop-reduce -print-module
> +; STOP: -loop-reduce
> ; STOP: Loop Strength Reduction
> ; STOP-NEXT: Machine Function Analysis
> +; STOP-NEXT: MIR Module Printing Pass
>
> ; START: -machine-branch-prob -gc-lowering
> ; START: FunctionPass Manager
> Index: test/CodeGen/Serialization/lit.local.cfg
> ===================================================================
> --- /dev/null
> +++ test/CodeGen/Serialization/lit.local.cfg
> @@ -0,0 +1,2 @@
> +config.suffixes = ['.mir']
> +
> Index: test/CodeGen/Serialization/llvmIR.mir
> ===================================================================
> --- /dev/null
> +++ test/CodeGen/Serialization/llvmIR.mir
> @@ -0,0 +1,35 @@
> +# RUN: ~/build/llvm/bin/llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s | FileCheck %s
> +# This test ensures that the LLVM IR that's embedded with machine level IR is
> +# parsed correctly.
> +
> +--- |
> + target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
> + target triple = "x86_64-apple-darwin14.3.0"
> +
> + ; CHECK: define i32 @foo(i32 %x, i32 %y)
> + ; CHECK: %z = alloca i32, align 4
> + ; CHECK: store i32 %x, i32* %z, align 4
> + ; CHECK: br label %Test
> + ; CHECK: Test:
> + ; CHECK: %m = load i32, i32* %z, align 4
> + ; CHECK: %cond = icmp eq i32 %y, %m
> + ; CHECK: br i1 %cond, label %IfEqual, label %IfUnequal
> + ; CHECK: IfEqual:
> + ; CHECK: ret i32 1
> + ; CHECK: IfUnequal:
> + ; CHECK: ret i32 0
> + define i32 @foo(i32 %x, i32 %y) {
> + %z = alloca i32, align 4
> + store i32 %x, i32* %z, align 4
> + br label %Test
> + Test:
> + %m = load i32, i32* %z, align 4
> + %cond = icmp eq i32 %y, %m
> + br i1 %cond, label %IfEqual, label %IfUnequal
> + IfEqual:
> + ret i32 1
> + IfUnequal:
> + ret i32 0
> + }
> +
> +...
> Index: test/CodeGen/Serialization/llvmIRMissing.mir
> ===================================================================
> --- /dev/null
> +++ test/CodeGen/Serialization/llvmIRMissing.mir
> @@ -0,0 +1,5 @@
> +# RUN: ~/build/llvm/bin/llc -start-after branch-folder -stop-after branch-folder -o /dev/null %s
> +# This test ensures that the MIR parser accepts files without the LLVM IR.
> +
> +---
> +...
> Index: tools/llc/llc.cpp
> ===================================================================
> --- tools/llc/llc.cpp
> +++ tools/llc/llc.cpp
> @@ -20,6 +20,7 @@
> #include "llvm/CodeGen/CommandFlags.h"
> #include "llvm/CodeGen/LinkAllAsmWriterComponents.h"
> #include "llvm/CodeGen/LinkAllCodegenComponents.h"
> +#include "llvm/CodeGen/Serialization/Parser.h"
> #include "llvm/IR/DataLayout.h"
> #include "llvm/IR/IRPrintingPasses.h"
> #include "llvm/IR/LLVMContext.h"
> @@ -109,6 +110,8 @@
> StringRef IFN = InputFilename;
> if (IFN.endswith(".bc") || IFN.endswith(".ll"))
> OutputFilename = IFN.drop_back(3);
> + else if (IFN.endswith(".mir"))
> + OutputFilename = IFN.drop_back(4);
> else
> OutputFilename = IFN;
>
> @@ -206,18 +209,28 @@
> static int compileModule(char **argv, LLVMContext &Context) {
> // Load the module to be compiled...
> SMDiagnostic Err;
> + std::vector<SMDiagnostic> Errs;
> std::unique_ptr<Module> M;
> Triple TheTriple;
>
> bool SkipModule = MCPU == "help" ||
> (!MAttrs.empty() && MAttrs.front() == "help");
>
> // If user just wants to list available options, skip module loading
> if (!SkipModule) {
> - M = parseIRFile(InputFilename, Err, Context);
> - if (!M) {
> - Err.print(argv[0], errs());
> - return 1;
> + if (StringRef(InputFilename).endswith_lower(".mir")) {
> + M = parseMIRFile(InputFilename, Errs, Context);
> + if (!M) {
> + for (const auto &Err : Errs)
> + Err.print(argv[0], errs());
You're shadowing the other `Err`, which is a bit awkward. Fortunately
you'll be able to refactor this nicely if you change the API to only
expect one `SMDiagnostic`.
> + return 1;
> + }
> + } else {
> + M = parseIRFile(InputFilename, Err, Context);
> + if (!M) {
> + Err.print(argv[0], errs());
> + return 1;
> + }
> }
>
> // Verify module immediately to catch problems before doInitialization() is
>
More information about the llvm-commits
mailing list