Index: llvm/test/tools/llvm-reduce/mir/instr-reduce.mir =================================================================== --- /dev/null +++ llvm/test/tools/llvm-reduce/mir/instr-reduce.mir @@ -0,0 +1,31 @@ +# RUN: llvm-reduce -mir -mtriple=riscv32 --test %python --test-arg %p/instr-reduce.py %s -o %t +# RUN: cat %t | FileCheck --match-full-lines %s + +# REQUIRES: plugins +# REQUIRES: riscv-registered-target + +# Verify that after reduction the following instruction sequence remains. The +# interestingness-test 'instr-reduce.py' matches a '%[0-9]+:gpr = ADDI %[0-9]+, 5' +# pattern in the output and that combined with that the MIR has to be valid +# (pass verify) results in the given sequence. + +# CHECK: %0:gpr = COPY $x10 +# CHECK-NEXT: %2:gpr = ADDI %0, 5 +# CHECK-NEXT: PseudoRET implicit $x10 + +... +--- +name: f +tracksRegLiveness: true +body: | + bb.0: + liveins: $x10 + + %10:gpr = COPY $x10 + %20:gpr = ADDI %10, 1 + %30:gpr = ADDI %20, 5 + %40:gpr = ADDI %30, 9 + $x10 = COPY %40 + PseudoRET implicit $x10 +... +--- Index: llvm/test/tools/llvm-reduce/mir/instr-reduce.py =================================================================== --- /dev/null +++ llvm/test/tools/llvm-reduce/mir/instr-reduce.py @@ -0,0 +1,16 @@ +from subprocess import run, PIPE +import re +import sys + +llc = run( [ 'llc', '-disable-symbolication','-verify-machineinstrs', '-mtriple=riscv32', '-run-pass=none', '-o', '-', sys.argv[1]], stdout=PIPE, stderr=PIPE ) + +stdout = llc.stdout.decode() + +p = re.compile(r'^\s*%[0-9]+:gpr = ADDI %[0-9]+, 5$', flags=re.MULTILINE) + +if (llc.returncode == 0 and p.search(stdout)): + print('This is interesting!') + sys.exit(0) +else: + print('This is NOT interesting!') + sys.exit(1) Index: llvm/tools/llvm-reduce/CMakeLists.txt =================================================================== --- llvm/tools/llvm-reduce/CMakeLists.txt +++ llvm/tools/llvm-reduce/CMakeLists.txt @@ -5,6 +5,7 @@ AllTargetsInfos Core IRReader + MIRParser Support Target TransformUtils @@ -29,6 +30,8 @@ deltas/ReduceOperandBundles.cpp deltas/ReduceSpecialGlobals.cpp deltas/ReduceOperands.cpp + deltas/ReduceInstructionsMIR.cpp + MyMachineModule.cpp llvm-reduce.cpp DEPENDS Index: llvm/tools/llvm-reduce/DeltaManager.cpp =================================================================== --- llvm/tools/llvm-reduce/DeltaManager.cpp +++ llvm/tools/llvm-reduce/DeltaManager.cpp @@ -24,6 +24,7 @@ #include "deltas/ReduceGlobalVarInitializers.h" #include "deltas/ReduceGlobalVars.h" #include "deltas/ReduceInstructions.h" +#include "deltas/ReduceInstructionsMIR.h" #include "deltas/ReduceMetadata.h" #include "deltas/ReduceModuleData.h" #include "deltas/ReduceOperandBundles.h" @@ -37,6 +38,7 @@ DeltaPasses("delta-passes", cl::desc("Delta passes to run, separated by commas. By " "default, run all delta passes.")); +extern cl::opt EnableMIR; #define DELTA_PASSES \ DELTA_PASS("special-globals", reduceSpecialGlobalsDeltaPass) \ @@ -55,9 +57,16 @@ DELTA_PASS("attributes", reduceAttributesDeltaPass) \ DELTA_PASS("module-data", reduceModuleDataDeltaPass) +#define DELTA_PASSES_MIR \ + DELTA_PASS("instructions", reduceInstructionsMIRDeltaPass) + static void runAllDeltaPasses(TestRunner &Tester) { #define DELTA_PASS(NAME, FUNC) FUNC(Tester); - DELTA_PASSES + if (EnableMIR) { + DELTA_PASSES_MIR + } else { + DELTA_PASSES + } #undef DELTA_PASS } @@ -67,7 +76,11 @@ FUNC(Tester); \ return; \ } - DELTA_PASSES + if (EnableMIR) { + DELTA_PASSES_MIR + } else { + DELTA_PASSES + } #undef DELTA_PASS errs() << "unknown pass \"" << PassName << "\""; exit(1); @@ -76,7 +89,11 @@ void llvm::printDeltaPasses(raw_ostream &OS) { OS << "Delta passes (pass to `--delta-passes=` as a comma separated list):\n"; #define DELTA_PASS(NAME, FUNC) OS << " " << NAME << "\n"; - DELTA_PASSES + if (EnableMIR) { + DELTA_PASSES_MIR + } else { + DELTA_PASSES + } #undef DELTA_PASS } Index: llvm/tools/llvm-reduce/MyMachineModule.h =================================================================== --- /dev/null +++ llvm/tools/llvm-reduce/MyMachineModule.h @@ -0,0 +1,38 @@ +//===- MyMachineModule.h - Wrapper for Module and MachineFunction ---------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_REDUCE_MYMACHINEMODULE_H +#define LLVM_TOOLS_LLVM_REDUCE_MYMACHINEMODULE_H + +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/Module.h" + +using namespace llvm; + +class MyMachineModule { +public: + std::shared_ptr M; + std::unique_ptr MF; + void print(raw_ostream &ROS, void *p); +}; + +std::unique_ptr parseMyMachineModule(StringRef Filename, + LLVMContext &Ctxt, + MachineModuleInfo &MMI); + +std::unique_ptr +cloneMyMachineModule(const MyMachineModule &MMM); + +bool verifyMyMachineModule(const MyMachineModule &MMM, raw_fd_ostream *OS); + +void writeMyMachineModule(const MyMachineModule *MMM, StringRef FileName); + +bool runMyMachineModule(const std::unique_ptr &MMM); + +#endif Index: llvm/tools/llvm-reduce/MyMachineModule.cpp =================================================================== --- /dev/null +++ llvm/tools/llvm-reduce/MyMachineModule.cpp @@ -0,0 +1,155 @@ +//===- MyMachineModule.cpp - Wrapper for Module and MachineFunction -------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "MyMachineModule.h" +#include "llvm/CodeGen/MIRParser/MIRParser.h" +#include "llvm/CodeGen/MIRPrinter.h" +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/IRReader/IRReader.h" +#include "llvm/Target/TargetMachine.h" + +static std::unique_ptr cloneMF(MachineFunction *SrcMF) { + auto DstMF = std::make_unique( + SrcMF->getFunction(), SrcMF->getTarget(), SrcMF->getSubtarget(), + SrcMF->getFunctionNumber(), SrcMF->getMMI()); + DenseMap Src2DstMBB; + DenseMap Src2DstReg; + + auto *SrcMRI = &SrcMF->getRegInfo(); + auto *DstMRI = &DstMF->getRegInfo(); + + // Create vregs. + for (auto &SrcMBB : *SrcMF) { + for (auto &SrcMI : SrcMBB) { + for (unsigned I = 0, E = SrcMI.getNumOperands(); I < E; ++I) { + auto &DMO = SrcMI.getOperand(I); + if (!DMO.isReg() || !DMO.isDef()) + continue; + Register SrcReg = DMO.getReg(); + if (Register::isPhysicalRegister(SrcReg)) + continue; + auto SrcRC = SrcMRI->getRegClass(SrcReg); + auto DstReg = DstMRI->createVirtualRegister(SrcRC); + Src2DstReg[SrcReg] = DstReg; + } + } + } + + // Clone blocks. + for (auto &SrcMBB : *SrcMF) + Src2DstMBB[&SrcMBB] = DstMF->CreateMachineBasicBlock(); + // Link blocks. + for (auto &SrcMBB : *SrcMF) { + auto *DstMBB = Src2DstMBB[&SrcMBB]; + DstMF->push_back(DstMBB); + for (auto It = SrcMBB.succ_begin(), IterEnd = SrcMBB.succ_end(); + It != IterEnd; ++It) { + auto *SrcSuccMBB = *It; + auto *DstSuccMBB = Src2DstMBB[SrcSuccMBB]; + DstMBB->addSuccessor(DstSuccMBB); + } + for (auto &LI : SrcMBB.liveins()) + DstMBB->addLiveIn(LI); + } + // Clone instructions. + for (auto &SrcMBB : *SrcMF) { + auto *DstMBB = Src2DstMBB[&SrcMBB]; + for (auto &SrcMI : SrcMBB) { + const auto &MCID = + DstMF->getSubtarget().getInstrInfo()->get(SrcMI.getOpcode()); + auto *DstMI = DstMF->CreateMachineInstr(MCID, SrcMI.getDebugLoc(), + /*NoImplicit=*/true); + DstMBB->push_back(DstMI); + for (auto &SrcMO : SrcMI.operands()) { + MachineOperand DstMO(SrcMO); + DstMO.clearParent(); + // Update vreg. + if (DstMO.isReg() && Src2DstReg.count(DstMO.getReg())) { + DstMO.setReg(Src2DstReg[DstMO.getReg()]); + } + // Update MBB. + if (DstMO.isMBB()) { + DstMO.setMBB(Src2DstMBB[DstMO.getMBB()]); + } + DstMI->addOperand(DstMO); + } + DstMI->setMemRefs(*DstMF, SrcMI.memoperands()); + } + } + + DstMF->verify(nullptr, "", /*AbortOnErrors=*/true); + return DstMF; +} + +std::unique_ptr parseMyMachineModule(StringRef Filename, + LLVMContext &Ctxt, + MachineModuleInfo &MMI) { + auto FileOrErr = MemoryBuffer::getFileOrSTDIN(Filename, /*IsText=*/true); + std::unique_ptr MParser = + createMIRParser(std::move(FileOrErr.get()), Ctxt); + + auto SetDataLayout = + [&](StringRef DataLayoutTargetTriple) -> Optional { + return MMI.getTarget().createDataLayout().getStringRepresentation(); + }; + + std::unique_ptr M = MParser->parseIRModule(SetDataLayout); + MParser->parseMachineFunctions(*M, MMI); + MachineFunction *MF = nullptr; + for (auto &F : *M) { + if (auto *MF4F = MMI.getMachineFunction(F)) { + // XXX: Maybe it would not be a lot of effort to handle multiple MFs by + // simply storing them in a MyMachineModule::SmallVector or similar. The + // single MF use-case seems a lot more common though so that will do for + // now. + assert(!MF && "Only single MF supported!"); + MF = MF4F; + } + } + assert(MF && "No MF found!"); + + auto MMM = std::make_unique(); + MMM->M = std::move(M); + MMM->MF = cloneMF(MF); + return MMM; +} + +std::unique_ptr +cloneMyMachineModule(const MyMachineModule &MMM) { + auto CloneMMM = std::make_unique(); + // Note that we cannot clone the Module as then we would need a way to + // updated the cloned MachineFunction's IR references. + CloneMMM->M = MMM.M; + CloneMMM->MF = cloneMF(MMM.MF.get()); + return CloneMMM; +} + +bool verifyMyMachineModule(const MyMachineModule &MMM, raw_fd_ostream *OS) { + return !MMM.MF->verify(nullptr, "", /*AbortOnErrors=*/false); +} + +void writeMyMachineModule(const MyMachineModule *MMM, StringRef FileName) { + std::error_code EC; + raw_fd_ostream OS(FileName, EC); + if (EC) { + errs() << "Error opening output file: " << EC.message() << "!\n"; + exit(1); + } + printMIR(OS, *MMM->M.get()); + printMIR(OS, *MMM->MF); + OS.close(); +} + +void MyMachineModule::print(raw_ostream &ROS, void *p) { + printMIR(ROS, *M.get()); + printMIR(ROS, *MF); +} Index: llvm/tools/llvm-reduce/TestRunner.h =================================================================== --- llvm/tools/llvm-reduce/TestRunner.h +++ llvm/tools/llvm-reduce/TestRunner.h @@ -9,6 +9,7 @@ #ifndef LLVM_TOOLS_LLVM_REDUCE_TESTRUNNER_H #define LLVM_TOOLS_LLVM_REDUCE_TESTRUNNER_H +#include "MyMachineModule.h" #include "llvm/ADT/SmallString.h" #include "llvm/IR/Module.h" #include "llvm/Support/Error.h" @@ -31,14 +32,16 @@ int run(StringRef Filename); /// Returns the most reduced version of the original testcase - Module *getProgram() const { return Program.get(); } + MyMachineModule *getProgram() const { return Program.get(); } - void setProgram(std::unique_ptr P) { Program = std::move(P); } + void setProgram(std::unique_ptr P) { + Program = std::move(P); + } private: StringRef TestName; const std::vector &TestArgs; - std::unique_ptr Program; + std::unique_ptr Program; }; } // namespace llvm Index: llvm/tools/llvm-reduce/deltas/Delta.h =================================================================== --- llvm/tools/llvm-reduce/deltas/Delta.h +++ llvm/tools/llvm-reduce/deltas/Delta.h @@ -101,9 +101,10 @@ /// /// Other implementations of the Delta Debugging algorithm can also be found in /// the CReduce, Delta, and Lithium projects. -void runDeltaPass(TestRunner &Test, int Targets, - std::function &, Module *)> - ExtractChunksFromModule); +void runDeltaPass( + TestRunner &Test, int Targets, + std::function &, MyMachineModule *)> + ExtractChunksFromModule); } // namespace llvm #endif Index: llvm/tools/llvm-reduce/deltas/Delta.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/Delta.cpp +++ llvm/tools/llvm-reduce/deltas/Delta.cpp @@ -13,6 +13,7 @@ //===----------------------------------------------------------------------===// #include "Delta.h" +#include "MyMachineModule.h" #include "llvm/ADT/STLExtras.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/CommandLine.h" @@ -27,20 +28,26 @@ "abort-on-invalid-reduction", cl::desc("Abort if any reduction results in invalid IR")); -void writeOutput(llvm::Module *M, llvm::StringRef Message); +extern cl::opt EnableMIR; -bool isReduced(Module &M, TestRunner &Test, SmallString<128> &CurrentFilepath) { - // Write Module to tmp file +void writeOutput(MyMachineModule *M, llvm::StringRef Message); + +bool isReduced(MyMachineModule &M, TestRunner &Test, + SmallString<128> &CurrentFilepath) { + // Write MyMachineModule to tmp file int FD; - std::error_code EC = - sys::fs::createTemporaryFile("llvm-reduce", "ll", FD, CurrentFilepath); + std::error_code EC = sys::fs::createTemporaryFile( + "llvm-reduce", EnableMIR ? "mir" : "ll", FD, CurrentFilepath); if (EC) { errs() << "Error making unique filename: " << EC.message() << "!\n"; exit(1); } ToolOutputFile Out(CurrentFilepath, FD); - M.print(Out.os(), /*AnnotationWriter=*/nullptr); + if (EnableMIR) + M.print(Out.os(), /*AnnotationWriter=*/nullptr); + else + M.M->print(Out.os(), /*AnnotationWriter=*/nullptr); Out.os().close(); if (Out.os().has_error()) { errs() << "Error emitting bitcode to file '" << CurrentFilepath << "'!\n"; @@ -97,7 +104,7 @@ /// given test. void llvm::runDeltaPass( TestRunner &Test, int Targets, - std::function &, Module *)> + std::function &, MyMachineModule *)> ExtractChunksFromModule) { assert(Targets >= 0); if (!Targets) { @@ -105,19 +112,20 @@ return; } - if (Module *Program = Test.getProgram()) { + if (MyMachineModule *Program = Test.getProgram()) { SmallString<128> CurrentFilepath; if (!isReduced(*Program, Test, CurrentFilepath)) { errs() << "\nInput isn't interesting! Verify interesting-ness test\n"; exit(1); } - assert(!verifyModule(*Program, &errs()) && + assert(!(EnableMIR ? verifyMyMachineModule(*Program, &errs()) + : verifyModule(*Program->M, &errs())) && "input module is broken before making changes"); } std::vector ChunksStillConsideredInteresting = {{1, Targets}}; - std::unique_ptr ReducedProgram; + std::unique_ptr ReducedProgram; bool FoundAtLeastOneNewUninterestingChunkWithCurrentGranularity; do { @@ -140,12 +148,18 @@ }); // Clone module before hacking it up.. - std::unique_ptr Clone = CloneModule(*Test.getProgram()); + auto Clone = std::make_unique(); + if (EnableMIR) { + Clone = cloneMyMachineModule(*Test.getProgram()); + } else { + Clone->M = CloneModule(*Test.getProgram()->M); + } // Generate Module with only Targets inside Current Chunks ExtractChunksFromModule(CurrentChunks, Clone.get()); // Some reductions may result in invalid IR. Skip such reductions. - if (verifyModule(*Clone.get(), &errs())) { + if (EnableMIR ? verifyMyMachineModule(*Clone.get(), &errs()) + : verifyModule(*Clone->M.get(), &errs())) { if (AbortOnInvalidReduction) { errs() << "Invalid reduction\n"; exit(1); Index: llvm/tools/llvm-reduce/deltas/ReduceAliases.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceAliases.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceAliases.cpp @@ -21,10 +21,10 @@ /// Removes all aliases aren't inside any of the /// desired Chunks. static void extractAliasesFromModule(const std::vector &ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { Oracle O(ChunksToKeep); - for (auto &GA : make_early_inc_range(Program->aliases())) { + for (auto &GA : make_early_inc_range(Program->M->aliases())) { if (!O.shouldKeep()) { GA.replaceAllUsesWith(GA.getAliasee()); GA.eraseFromParent(); @@ -33,12 +33,12 @@ } /// Counts the amount of aliases and prints their respective name & index. -static int countAliases(Module *Program) { +static int countAliases(MyMachineModule *Program) { // TODO: Silence index with --quiet flag errs() << "----------------------------\n"; errs() << "Aliases Index Reference:\n"; int Count = 0; - for (auto &GA : Program->aliases()) + for (auto &GA : Program->M->aliases()) errs() << "\t" << ++Count << ": " << GA.getName() << "\n"; errs() << "----------------------------\n"; Index: llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceArguments.cpp @@ -50,13 +50,13 @@ /// Removes out-of-chunk arguments from functions, and modifies their calls /// accordingly. It also removes allocations of out-of-chunk arguments. static void extractArgumentsFromModule(std::vector ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { Oracle O(ChunksToKeep); std::set ArgsToKeep; std::vector Funcs; // Get inside-chunk arguments, as well as their parent function - for (auto &F : *Program) + for (auto &F : *Program->M) if (shouldRemoveArguments(F)) { Funcs.push_back(&F); for (auto &A : F.args()) @@ -98,7 +98,7 @@ auto *ClonedFunc = CloneFunction(F, VMap); // In order to preserve function order, we move Clone after old Function ClonedFunc->removeFromParent(); - Program->getFunctionList().insertAfter(F->getIterator(), ClonedFunc); + Program->M->getFunctionList().insertAfter(F->getIterator(), ClonedFunc); replaceFunctionCalls(*F, *ClonedFunc, ArgIndexesToKeep); // Rename Cloned Function to Old's name @@ -111,12 +111,12 @@ /// Counts the amount of arguments in functions and prints their respective /// name, index, and parent function name -static int countArguments(Module *Program) { +static int countArguments(MyMachineModule *Program) { // TODO: Silence index with --quiet flag outs() << "----------------------------\n"; outs() << "Param Index Reference:\n"; int ArgsCount = 0; - for (auto &F : *Program) + for (auto &F : *Program->M) if (shouldRemoveArguments(F)) { outs() << " " << F.getName() << "\n"; for (auto &A : F.args()) Index: llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceAttributes.cpp @@ -169,11 +169,11 @@ /// Removes out-of-chunk attributes from module. static void extractAttributesFromModule(std::vector ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { AttributeRemapper R(ChunksToKeep); - R.visit(Program); + R.visit(*Program->M); - LLVMContext &C = Program->getContext(); + LLVMContext &C = Program->M->getContext(); for (const auto &I : R.GlobalVariablesToRefine) I.first->setAttributes(convertAttributeRefToAttributeSet(C, I.second)); for (const auto &I : R.FunctionsToRefine) @@ -183,12 +183,12 @@ } /// Counts the amount of attributes. -static int countAttributes(Module *Program) { +static int countAttributes(MyMachineModule *Program) { AttributeCounter C; // TODO: Silence index with --quiet flag outs() << "----------------------------\n"; - C.visit(Program); + C.visit(*Program->M); outs() << "Number of attributes: " << C.AttributeCount << "\n"; return C.AttributeCount; Index: llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceBasicBlocks.cpp @@ -88,18 +88,18 @@ /// Removes out-of-chunk arguments from functions, and modifies their calls /// accordingly. It also removes allocations of out-of-chunk arguments. static void extractBasicBlocksFromModule(std::vector ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { Oracle O(ChunksToKeep); std::set BBsToKeep; - for (auto &F : *Program) + for (auto &F : *Program->M) for (auto &BB : F) if (O.shouldKeep()) BBsToKeep.insert(&BB); std::vector BBsToDelete; - for (auto &F : *Program) + for (auto &F : *Program->M) for (auto &BB : F) { if (!BBsToKeep.count(&BB)) { BBsToDelete.push_back(&BB); @@ -110,7 +110,7 @@ } // Replace terminators that reference out-of-chunk BBs - for (auto &F : *Program) + for (auto &F : *Program->M) for (auto &BB : F) { if (auto *SwInst = dyn_cast(BB.getTerminator())) removeUninterestingBBsFromSwitch(*SwInst, BBsToKeep); @@ -128,11 +128,11 @@ } /// Counts the amount of basic blocks and prints their name & respective index -static int countBasicBlocks(Module *Program) { +static int countBasicBlocks(MyMachineModule *Program) { // TODO: Silence index with --quiet flag outs() << "----------------------------\n"; int BBCount = 0; - for (auto &F : *Program) + for (auto &F : *Program->M) for (auto &BB : F) { if (BB.hasName()) outs() << "\t" << ++BBCount << ": " << BB.getName() << "\n"; Index: llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceFunctionBodies.cpp @@ -21,12 +21,12 @@ /// desired Chunks. static void extractFunctionBodiesFromModule(const std::vector &ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { Oracle O(ChunksToKeep); // Delete out-of-chunk function bodies std::vector FuncDefsToReduce; - for (auto &F : *Program) + for (auto &F : *Program->M) if (!F.isDeclaration() && !O.shouldKeep()) { F.deleteBody(); F.setComdat(nullptr); @@ -35,12 +35,12 @@ /// Counts the amount of non-declaration functions and prints their /// respective name & index -static int countFunctionDefinitions(Module *Program) { +static int countFunctionDefinitions(MyMachineModule *Program) { // TODO: Silence index with --quiet flag errs() << "----------------------------\n"; errs() << "Function Definition Index Reference:\n"; int FunctionDefinitionCount = 0; - for (auto &F : *Program) + for (auto &F : *Program->M) if (!F.isDeclaration()) errs() << "\t" << ++FunctionDefinitionCount << ": " << F.getName() << "\n"; Index: llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceFunctions.cpp @@ -24,12 +24,12 @@ /// Removes all the Defined Functions /// that aren't inside any of the desired Chunks. static void extractFunctionsFromModule(const std::vector &ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { Oracle O(ChunksToKeep); // Record all out-of-chunk functions. std::vector> FuncsToRemove; - copy_if(Program->functions(), std::back_inserter(FuncsToRemove), + copy_if(Program->M->functions(), std::back_inserter(FuncsToRemove), [&O](Function &F) { // Intrinsics don't have function bodies that are useful to // reduce. Additionally, intrinsics may have additional operand @@ -53,12 +53,12 @@ /// Counts the amount of functions and prints their /// respective name & index -static int countFunctions(Module *Program) { +static int countFunctions(MyMachineModule *Program) { // TODO: Silence index with --quiet flag errs() << "----------------------------\n"; errs() << "Function Index Reference:\n"; int FunctionCount = 0; - for (auto &F : *Program) { + for (auto &F : *Program->M) { if (F.isIntrinsic() && !F.use_empty()) continue; Index: llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceGlobalValues.cpp @@ -23,11 +23,11 @@ /// Sets dso_local to false for all global values. static void extractGVsFromModule(std::vector ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { Oracle O(ChunksToKeep); // remove dso_local from global values - for (auto &GV : Program->global_values()) + for (auto &GV : Program->M->global_values()) if (isValidDSOLocalReductionGV(GV) && !O.shouldKeep()) { GV.setDSOLocal(false); } @@ -35,12 +35,12 @@ /// Counts the amount of global values with dso_local and displays their /// respective name & index -static int countGVs(Module *Program) { +static int countGVs(MyMachineModule *Program) { // TODO: Silence index with --quiet flag outs() << "----------------------------\n"; outs() << "GlobalValue Index Reference:\n"; int GVCount = 0; - for (auto &GV : Program->global_values()) + for (auto &GV : Program->M->global_values()) if (isValidDSOLocalReductionGV(GV)) outs() << "\t" << ++GVCount << ": " << GV.getName() << "\n"; outs() << "----------------------------\n"; Index: llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceGlobalVarInitializers.cpp @@ -19,11 +19,11 @@ /// Removes all the Initialized GVs that aren't inside the desired Chunks. static void extractGVsFromModule(std::vector ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { Oracle O(ChunksToKeep); // Drop initializers of out-of-chunk GVs - for (auto &GV : Program->globals()) + for (auto &GV : Program->M->globals()) if (GV.hasInitializer() && !O.shouldKeep()) { GV.setInitializer(nullptr); GV.setLinkage(GlobalValue::LinkageTypes::ExternalLinkage); @@ -33,12 +33,12 @@ /// Counts the amount of initialized GVs and displays their /// respective name & index -static int countGVs(Module *Program) { +static int countGVs(MyMachineModule *Program) { // TODO: Silence index with --quiet flag outs() << "----------------------------\n"; outs() << "GlobalVariable Index Reference:\n"; int GVCount = 0; - for (auto &GV : Program->globals()) + for (auto &GV : Program->M->globals()) if (GV.hasInitializer()) outs() << "\t" << ++GVCount << ": " << GV.getName() << "\n"; outs() << "----------------------------\n"; Index: llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceGlobalVars.cpp @@ -19,19 +19,19 @@ /// Removes all the GVs that aren't inside the desired Chunks. static void extractGVsFromModule(std::vector ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { Oracle O(ChunksToKeep); // Get GVs inside desired chunks std::set GVsToKeep; - for (auto &GV : Program->globals()) + for (auto &GV : Program->M->globals()) if (O.shouldKeep()) GVsToKeep.insert(&GV); // Delete out-of-chunk GVs and their uses std::vector ToRemove; std::vector InstToRemove; - for (auto &GV : Program->globals()) + for (auto &GV : Program->M->globals()) if (!GVsToKeep.count(&GV)) { for (auto *U : GV.users()) if (auto *Inst = dyn_cast(U)) @@ -56,12 +56,12 @@ /// Counts the amount of GVs and displays their /// respective name & index -static int countGVs(Module *Program) { +static int countGVs(MyMachineModule *Program) { // TODO: Silence index with --quiet flag outs() << "----------------------------\n"; outs() << "GlobalVariable Index Reference:\n"; int GVCount = 0; - for (auto &GV : Program->globals()) + for (auto &GV : Program->M->globals()) outs() << "\t" << ++GVCount << ": " << GV.getName() << "\n"; outs() << "----------------------------\n"; return GVCount; Index: llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceInstructions.cpp @@ -18,12 +18,12 @@ /// Removes out-of-chunk arguments from functions, and modifies their calls /// accordingly. It also removes allocations of out-of-chunk arguments. static void extractInstrFromModule(std::vector ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { Oracle O(ChunksToKeep); std::set InstToKeep; - for (auto &F : *Program) + for (auto &F : *Program->M) for (auto &BB : F) { // Removing the terminator would make the block invalid. Only iterate over // instructions before the terminator. @@ -34,7 +34,7 @@ } std::vector InstToDelete; - for (auto &F : *Program) + for (auto &F : *Program->M) for (auto &BB : F) for (auto &Inst : BB) if (!InstToKeep.count(&Inst)) { @@ -47,11 +47,11 @@ } /// Counts the amount of basic blocks and prints their name & respective index -static unsigned countInstructions(Module *Program) { +static unsigned countInstructions(MyMachineModule *Program) { // TODO: Silence index with --quiet flag outs() << "----------------------------\n"; int InstCount = 0; - for (auto &F : *Program) + for (auto &F : *Program->M) for (auto &BB : F) // Well-formed blocks have terminators, which we cannot remove. InstCount += BB.getInstList().size() - 1; Index: llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.h =================================================================== --- /dev/null +++ llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.h @@ -0,0 +1,23 @@ +//===- ReduceArguments.h - Specialized Delta Pass -------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a function which calls the Generic Delta pass in order +// to reduce uninteresting Arguments from defined functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEINSTRUCTIONS_MIR_H +#define LLVM_TOOLS_LLVM_REDUCE_DELTAS_REDUCEINSTRUCTIONS_MIR_H + +#include "Delta.h" + +namespace llvm { +void reduceInstructionsMIRDeltaPass(TestRunner &Test); +} // namespace llvm + +#endif Index: llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp =================================================================== --- /dev/null +++ llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp @@ -0,0 +1,150 @@ +//===- ReduceArguments.cpp - Specialized Delta Pass -----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements a function which calls the Generic Delta pass in order +// to reduce uninteresting Arguments from defined functions. +// +//===----------------------------------------------------------------------===// + +#include "ReduceInstructionsMIR.h" + +#include "llvm/CodeGen/MachineDominators.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/CodeGen/TargetInstrInfo.h" +#include "llvm/Support/Debug.h" + +using namespace llvm; + +static Register getPrevDefOfRCInMBB(MachineBasicBlock &MBB, + MachineBasicBlock::reverse_iterator &RI, + const TargetRegisterClass *RC, + SetVector &ExcludeMIs) { + auto MRI = &MBB.getParent()->getRegInfo(); + for (MachineBasicBlock::reverse_instr_iterator E = MBB.instr_rend(); RI != E; + ++RI) { + auto &MI = *RI; + // All Def operands explicit and implicit. + for (auto &MO : MI.operands()) { + if (!MO.isReg() || !MO.isDef()) + continue; + auto Reg = MO.getReg(); + if (Register::isPhysicalRegister(Reg)) + continue; + + if (MRI->getRegClass(Reg) == RC && !ExcludeMIs.count(MO.getParent())) + return Reg; + } + } + return 0; +} + +static unsigned countInstructions(MyMachineModule *Program) { + unsigned Count = 0; + MachineInstr *TopMI = nullptr; + for (auto &MBB : *Program->MF) { + for (auto &MI : MBB) { + if (MI.isTerminator()) + continue; + if (MBB.isEntryBlock() && !TopMI) { + TopMI = &MI; + continue; + } + Count++; + } + } + return Count; +} + +static void extractInstrFromModule(std::vector ChunksToKeep, + MyMachineModule *Program) { + auto &MF = *Program->MF; + MachineDominatorTree MDT; + MDT.runOnMachineFunction(MF); + + Oracle O(ChunksToKeep); + + auto MRI = &MF.getRegInfo(); + SetVector ToDelete; + + MachineInstr *TopMI = nullptr; + + // Mark MIs for deletion according to some criteria. + for (auto &MBB : MF) { + for (auto &MI : MBB) { + if (MI.isTerminator()) + continue; + if (MBB.isEntryBlock() && !TopMI) { + TopMI = &MI; + continue; + } + if (!O.shouldKeep()) { + ToDelete.insert(&MI); + // errs() << "Deleting: " << MI; + } + } + } + + // For each MI to be deleted update users of regs defined by that MI to use + // some other dominating definition (that is not to be deleted). + for (auto *MI : ToDelete) { + for (auto &MO : MI->operands()) { + if (!MO.isReg() || !MO.isDef()) + continue; + auto Reg = MO.getReg(); + if (Register::isPhysicalRegister(Reg)) + continue; + auto UI = MRI->use_begin(Reg); + auto UE = MRI->use_end(); + + auto RegRC = MRI->getRegClass(Reg); + Register NewReg = 0; + // If this is not a physical register and there are some uses. + if (UI != UE) { + MachineBasicBlock::reverse_iterator RI(*MI); + MachineBasicBlock *BB = MI->getParent(); + ++RI; + while (NewReg == 0 && BB) { + NewReg = getPrevDefOfRCInMBB(*BB, RI, RegRC, ToDelete); + // Prepare for idom(BB). + if (auto *IDM = MDT.getNode(BB)->getIDom()) { + BB = IDM->getBlock(); + RI = BB->rbegin(); + } else { + BB = nullptr; + } + } + } + + // If no dominating definition was found then add an implicit one to the + // first instruction in the entry block. + if (!NewReg && TopMI) { + NewReg = MRI->createVirtualRegister(RegRC); + TopMI->addOperand(MachineOperand::CreateReg( + NewReg, true /*IsDef*/, true /*IsImp*/, false /*IsKill*/)); + } + + // Update all uses. + while (UI != UE) { + auto &UMO = *UI++; + UMO.setReg(NewReg); + } + } + } + + // Finally delete the MIs. + for (auto *MI : ToDelete) + MI->eraseFromParent(); +} + +void llvm::reduceInstructionsMIRDeltaPass(TestRunner &Test) { + outs() << "*** Reducing Instructions...\n"; + unsigned InstCount = countInstructions(Test.getProgram()); + runDeltaPass(Test, InstCount, extractInstrFromModule); +} Index: llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceMetadata.cpp @@ -23,12 +23,12 @@ /// Removes all the Named and Unnamed Metadata Nodes, as well as any debug /// functions that aren't inside the desired Chunks. static void extractMetadataFromModule(const std::vector &ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { Oracle O(ChunksToKeep); // Get out-of-chunk Named metadata nodes SmallVector NamedNodesToDelete; - for (NamedMDNode &MD : Program->named_metadata()) + for (NamedMDNode &MD : Program->M->named_metadata()) if (!O.shouldKeep()) NamedNodesToDelete.push_back(&MD); @@ -40,14 +40,14 @@ // Delete out-of-chunk metadata attached to globals. SmallVector> MDs; - for (GlobalVariable &GV : Program->globals()) { + for (GlobalVariable &GV : Program->M->globals()) { GV.getAllMetadata(MDs); for (std::pair &MD : MDs) if (!O.shouldKeep()) GV.setMetadata(MD.first, NULL); } - for (Function &F : *Program) { + for (Function &F : *Program->M) { // Delete out-of-chunk metadata attached to functions. F.getAllMetadata(MDs); for (std::pair &MD : MDs) @@ -64,13 +64,13 @@ } } -static int countMetadataTargets(Module *Program) { - int NamedMetadataNodes = Program->named_metadata_size(); +static int countMetadataTargets(MyMachineModule *Program) { + int NamedMetadataNodes = Program->M->named_metadata_size(); // Get metadata attached to globals. int GlobalMetadataArgs = 0; SmallVector> MDs; - for (GlobalVariable &GV : Program->globals()) { + for (GlobalVariable &GV : Program->M->globals()) { GV.getAllMetadata(MDs); GlobalMetadataArgs += MDs.size(); } @@ -78,7 +78,7 @@ // Get metadata attached to functions & instructions. int FunctionMetadataArgs = 0; int InstructionMetadataArgs = 0; - for (Function &F : *Program) { + for (Function &F : *Program->M) { F.getAllMetadata(MDs); FunctionMetadataArgs += MDs.size(); Index: llvm/tools/llvm-reduce/deltas/ReduceModuleData.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceModuleData.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceModuleData.cpp @@ -14,33 +14,34 @@ using namespace llvm; -static void clearModuleData(std::vector ChunksToKeep, Module *Program) { +static void clearModuleData(std::vector ChunksToKeep, + MyMachineModule *Program) { Oracle O(ChunksToKeep); - if (!Program->getModuleIdentifier().empty() && !O.shouldKeep()) - Program->setModuleIdentifier(""); - if (!Program->getSourceFileName().empty() && !O.shouldKeep()) - Program->setSourceFileName(""); - if (!Program->getDataLayoutStr().empty() && !O.shouldKeep()) - Program->setDataLayout(""); - if (!Program->getTargetTriple().empty() && !O.shouldKeep()) - Program->setTargetTriple(""); + if (!Program->M->getModuleIdentifier().empty() && !O.shouldKeep()) + Program->M->setModuleIdentifier(""); + if (!Program->M->getSourceFileName().empty() && !O.shouldKeep()) + Program->M->setSourceFileName(""); + if (!Program->M->getDataLayoutStr().empty() && !O.shouldKeep()) + Program->M->setDataLayout(""); + if (!Program->M->getTargetTriple().empty() && !O.shouldKeep()) + Program->M->setTargetTriple(""); // TODO: clear line by line rather than all at once - if (!Program->getModuleInlineAsm().empty() && !O.shouldKeep()) - Program->setModuleInlineAsm(""); + if (!Program->M->getModuleInlineAsm().empty() && !O.shouldKeep()) + Program->M->setModuleInlineAsm(""); } -static int countModuleData(Module *M) { +static int countModuleData(MyMachineModule *M) { int Count = 0; - if (!M->getModuleIdentifier().empty()) + if (!M->M->getModuleIdentifier().empty()) ++Count; - if (!M->getSourceFileName().empty()) + if (!M->M->getSourceFileName().empty()) ++Count; - if (!M->getDataLayoutStr().empty()) + if (!M->M->getDataLayoutStr().empty()) ++Count; - if (!M->getTargetTriple().empty()) + if (!M->M->getTargetTriple().empty()) ++Count; - if (!M->getModuleInlineAsm().empty()) + if (!M->M->getModuleInlineAsm().empty()) ++Count; return Count; } Index: llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceOperandBundles.cpp @@ -97,21 +97,21 @@ /// Removes out-of-chunk operand bundles from calls. static void extractOperandBundesFromModule(std::vector ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { OperandBundleRemapper R(ChunksToKeep); - R.visit(Program); + R.visit(*Program->M); for (const auto &I : R.CallsToRefine) maybeRewriteCallWithDifferentBundles(I.first, I.second); } /// Counts the amount of operand bundles. -static int countOperandBundes(Module *Program) { +static int countOperandBundes(MyMachineModule *Program) { OperandBundleCounter C; // TODO: Silence index with --quiet flag outs() << "----------------------------\n"; - C.visit(Program); + C.visit(*Program->M); outs() << "Number of operand bundles: " << C.OperandBundeCount << "\n"; return C.OperandBundeCount; Index: llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceOperands.cpp @@ -35,11 +35,11 @@ /// Sets Operands to undef. static void extractOperandsFromModule(std::vector ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { Oracle O(ChunksToKeep); // Extract Operands from the module. - for (auto &F : Program->functions()) { + for (auto &F : Program->M->functions()) { for (auto &I : instructions(&F)) { for (auto &Op : I.operands()) { // Filter Operands then set to undef. @@ -53,9 +53,9 @@ } /// Counts the amount of operands in the module that can be reduced. -static int countOperands(Module *Program) { +static int countOperands(MyMachineModule *Program) { int Count = 0; - for (auto &F : Program->functions()) { + for (auto &F : Program->M->functions()) { for (auto &I : instructions(&F)) { for (auto &Op : I.operands()) { if (canReduceOperand(Op)) { Index: llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.cpp =================================================================== --- llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.cpp +++ llvm/tools/llvm-reduce/deltas/ReduceSpecialGlobals.cpp @@ -28,11 +28,11 @@ /// desired Chunks. static void extractSpecialGlobalsFromModule(const std::vector &ChunksToKeep, - Module *Program) { + MyMachineModule *Program) { Oracle O(ChunksToKeep); for (StringRef Name : SpecialGlobalNames) { - if (auto *Used = Program->getNamedGlobal(Name)) { + if (auto *Used = Program->M->getNamedGlobal(Name)) { Used->replaceAllUsesWith(UndefValue::get(Used->getType())); Used->eraseFromParent(); } @@ -41,13 +41,13 @@ /// Counts the amount of special globals and prints their /// respective name & index -static int countSpecialGlobals(Module *Program) { +static int countSpecialGlobals(MyMachineModule *Program) { // TODO: Silence index with --quiet flag errs() << "----------------------------\n"; errs() << "Special Globals Index Reference:\n"; int Count = 0; for (StringRef Name : SpecialGlobalNames) { - if (auto *Used = Program->getNamedGlobal(Name)) + if (auto *Used = Program->M->getNamedGlobal(Name)) errs() << "\t" << ++Count << ": " << Used->getName() << "\n"; } errs() << "----------------------------\n"; Index: llvm/tools/llvm-reduce/llvm-reduce.cpp =================================================================== --- llvm/tools/llvm-reduce/llvm-reduce.cpp +++ llvm/tools/llvm-reduce/llvm-reduce.cpp @@ -15,15 +15,20 @@ //===----------------------------------------------------------------------===// #include "DeltaManager.h" +#include "MyMachineModule.h" #include "TestRunner.h" #include "llvm/ADT/SmallString.h" +#include "llvm/CodeGen/CommandFlags.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Verifier.h" #include "llvm/IRReader/IRReader.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Target/TargetMachine.h" #include #include @@ -57,7 +62,7 @@ static cl::opt OutputFilename("output", - cl::desc("Specify the output file. default: reduced.ll")); + cl::desc("Specify the output file. default: reduced.mir")); static cl::alias OutputFileAlias("o", cl::desc("Alias for -output"), cl::aliasopt(OutputFilename), cl::cat(Options)); @@ -68,6 +73,12 @@ "with the reduced version!"), cl::cat(Options)); +static cl::opt TargetTriple("mtriple", + cl::desc("Set the target triple")); +cl::opt EnableMIR("mir", cl::desc("MIR mode")); + +static codegen::RegisterCodeGenFlags CGF; + // Parses IR into a Module and verifies it static std::unique_ptr parseInputFile(StringRef Filename, LLVMContext &Ctxt) { @@ -86,22 +97,43 @@ return Result; } -void writeOutput(Module *M, StringRef Message) { +void writeOutput(MyMachineModule *M, StringRef Message) { if (ReplaceInput) // In-place OutputFilename = InputFilename.c_str(); else if (OutputFilename.empty() || OutputFilename == "-") - OutputFilename = "reduced.ll"; - - std::error_code EC; - raw_fd_ostream Out(OutputFilename, EC); - if (EC) { - errs() << "Error opening output file: " << EC.message() << "!\n"; - exit(1); + OutputFilename = EnableMIR ? "reduced.mir" : "reduced.ll"; + if (!EnableMIR) { + std::error_code EC; + raw_fd_ostream Out(OutputFilename, EC); + if (EC) { + errs() << "Error opening output file: " << EC.message() << "!\n"; + exit(1); + } + M->M->print(Out, /*AnnotationWriter=*/nullptr); + } else { + writeMyMachineModule(M, OutputFilename); } - M->print(Out, /*AnnotationWriter=*/nullptr); errs() << Message << OutputFilename << "\n"; } +static std::unique_ptr createTargetMachine() { + InitializeAllTargets(); + InitializeAllTargetMCs(); + InitializeAllAsmPrinters(); + InitializeAllAsmParsers(); + + auto TT(Triple::normalize(TargetTriple)); + std::string CPU(codegen::getCPUStr()); + std::string FS(codegen::getFeaturesStr()); + + std::string Error; + const Target *TheTarget = TargetRegistry::lookupTarget(TT, Error); + + return std::unique_ptr( + static_cast(TheTarget->createTargetMachine( + TT, CPU, FS, TargetOptions(), None, None, CodeGenOpt::Default))); +} + int main(int Argc, char **Argv) { InitLLVM X(Argc, Argv); @@ -114,8 +146,20 @@ } LLVMContext Context; - std::unique_ptr OriginalProgram = - parseInputFile(InputFilename, Context); + std::unique_ptr TM; + std::unique_ptr MMI; + std::unique_ptr OriginalProgram; + if (EnableMIR) { + TM = createTargetMachine(); + MMI = std::make_unique(TM.get()); + OriginalProgram = parseMyMachineModule(InputFilename, Context, *MMI); + } else { + OriginalProgram = std::make_unique(); + OriginalProgram->M = parseInputFile(InputFilename, Context); + if (!OriginalProgram->M) { + return 1; + } + } if (!OriginalProgram) { return 1;