diff --git a/llvm/include/llvm/CodeGen/MachineModuleInfo.h b/llvm/include/llvm/CodeGen/MachineModuleInfo.h index e967853547a8..d4e788878f92 100644 --- a/llvm/include/llvm/CodeGen/MachineModuleInfo.h +++ b/llvm/include/llvm/CodeGen/MachineModuleInfo.h @@ -163,6 +163,9 @@ public: /// Machine Function map. void deleteMachineFunctionFor(Function &F); + /// Add an externally created MachineFunction \p MF for \p F. + void insertFunction(const Function &F, std::unique_ptr &&MF); + /// Keep track of various per-module pieces of information for backends /// that would like to do so. template diff --git a/llvm/lib/CodeGen/MachineModuleInfo.cpp b/llvm/lib/CodeGen/MachineModuleInfo.cpp index 92e73324e9c3..7dee06dfee65 100644 --- a/llvm/lib/CodeGen/MachineModuleInfo.cpp +++ b/llvm/lib/CodeGen/MachineModuleInfo.cpp @@ -141,6 +141,13 @@ void MachineModuleInfo::deleteMachineFunctionFor(Function &F) { LastResult = nullptr; } +void MachineModuleInfo::insertFunction(const Function &F, + std::unique_ptr &&MF) { + auto I = MachineFunctions.insert(std::make_pair(&F, std::move(MF))); + assert(I.second && "machine function already mapped"); + (void)I; +} + namespace { /// This pass frees the MachineFunction object associated with a Function. diff --git a/llvm/test/tools/llvm-reduce/mir/multiple-functions.mir b/llvm/test/tools/llvm-reduce/mir/multiple-functions.mir new file mode 100644 index 000000000000..e83ce844ea76 --- /dev/null +++ b/llvm/test/tools/llvm-reduce/mir/multiple-functions.mir @@ -0,0 +1,45 @@ +# REQUIRES: amdgpu-registered-target +# RUN: llvm-reduce -simplify-mir -mtriple=amdgcn-amd-amdhsa --test FileCheck --test-arg --check-prefix=CHECK-INTERESTINGNESS --test-arg %s --test-arg --input-file %s -o %t 2> %t.log +# RUN: FileCheck --check-prefix=RESULT %s < %t + +# CHECK-INTERESTINGNESS: S_NOP 0 + +# RESULT: name: func0 +# RESULT: S_NOP 0 + +# RESULT: name: func1 +# RESULT-NOT: S_NOP + +--- | + define void @func0() { + ret void + } + + define void @func1() { + ret void + } + +... +--- +name: func0 +tracksRegLiveness: true +body: | + bb.0: + S_WAITCNT 0 + S_NOP 0 + %0:vgpr_32 = V_MOV_B32_e32 0, implicit $exec + INLINEASM &"", 1 /* sideeffect attdialect */ + S_ENDPGM 0, implicit %0 +... + +--- +name: func1 +tracksRegLiveness: true +body: | + bb.0: + S_WAITCNT 0 + S_NOP 1 + %0:vgpr_32 = V_MOV_B32_e32 0, implicit $exec + INLINEASM &"", 1 /* sideeffect attdialect */ + S_ENDPGM 0, implicit %0 +... diff --git a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp index 4ea7b615e9d1..d77fe024e475 100644 --- a/llvm/tools/llvm-reduce/ReducerWorkItem.cpp +++ b/llvm/tools/llvm-reduce/ReducerWorkItem.cpp @@ -127,10 +127,11 @@ static void cloneFrameInfo( } } -static std::unique_ptr cloneMF(MachineFunction *SrcMF) { +static std::unique_ptr cloneMF(MachineFunction *SrcMF, + MachineModuleInfo &DestMMI) { auto DstMF = std::make_unique( SrcMF->getFunction(), SrcMF->getTarget(), SrcMF->getSubtarget(), - SrcMF->getFunctionNumber(), SrcMF->getMMI()); + SrcMF->getFunctionNumber(), DestMMI); DenseMap Src2DstMBB; auto *SrcMRI = &SrcMF->getRegInfo(); @@ -292,7 +293,7 @@ static std::unique_ptr cloneMF(MachineFunction *SrcMF) { std::unique_ptr parseReducerWorkItem(const char *ToolName, StringRef Filename, LLVMContext &Ctxt, std::unique_ptr &TM, - std::unique_ptr &MMI, bool IsMIR) { + bool IsMIR) { Triple TheTriple; auto MMM = std::make_unique(); @@ -336,23 +337,9 @@ parseReducerWorkItem(const char *ToolName, StringRef Filename, std::unique_ptr M = MParser->parseIRModule(SetDataLayout); LLVMTargetMachine *LLVMTM = static_cast(TM.get()); - MMI = std::make_unique(LLVMTM); - 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 ReducerWorkItem::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!"); - + MMM->MMI = std::make_unique(LLVMTM); + MParser->parseMachineFunctions(*M, *MMM->MMI); MMM->M = std::move(M); - MMM->MF = cloneMF(MF); } else { SMDiagnostic Err; std::unique_ptr Result = parseIRFile(Filename, Err, Ctxt); @@ -371,16 +358,24 @@ parseReducerWorkItem(const char *ToolName, StringRef Filename, } std::unique_ptr -cloneReducerWorkItem(const ReducerWorkItem &MMM) { +cloneReducerWorkItem(const ReducerWorkItem &MMM, const TargetMachine *TM) { auto CloneMMM = std::make_unique(); - if (MMM.MF) { - // Note that we cannot clone the Module as then we would need a way to - // updated the cloned MachineFunction's IR references. - // XXX: Actually have a look at - // std::unique_ptr CloneModule(const Module &M, ValueToValueMapTy - // &VMap); + if (TM) { + // We're assuming the Module IR contents are always unchanged by MIR + // reductions, and can share it as a constant. CloneMMM->M = MMM.M; - CloneMMM->MF = cloneMF(MMM.MF.get()); + + // MachineModuleInfo contains a lot of other state used during codegen which + // we won't be using here, but we should be able to ignore it (although this + // is pretty ugly). + const LLVMTargetMachine *LLVMTM = + static_cast(TM); + CloneMMM->MMI = std::make_unique(LLVMTM); + + for (const Function &F : MMM.getModule()) { + if (auto *MF = MMM.MMI->getMachineFunction(F)) + CloneMMM->MMI->insertFunction(F, cloneMF(MF, *CloneMMM->MMI)); + } } else { CloneMMM->M = CloneModule(*MMM.M); } @@ -390,15 +385,27 @@ cloneReducerWorkItem(const ReducerWorkItem &MMM) { bool verifyReducerWorkItem(const ReducerWorkItem &MMM, raw_fd_ostream *OS) { if (verifyModule(*MMM.M, OS)) return true; - if (MMM.MF && !MMM.MF->verify(nullptr, "", /*AbortOnError=*/false)) - return true; + + if (!MMM.MMI) + return false; + + for (const Function &F : MMM.getModule()) { + if (const MachineFunction *MF = MMM.MMI->getMachineFunction(F)) { + if (!MF->verify(nullptr, "", /*AbortOnError=*/false)) + return true; + } + } + return false; } void ReducerWorkItem::print(raw_ostream &ROS, void *p) const { - if (MF) { + if (MMI) { printMIR(ROS, *M); - printMIR(ROS, *MF); + for (Function &F : *M) { + if (auto *MF = MMI->getMachineFunction(F)) + printMIR(ROS, *MF); + } } else { M->print(ROS, /*AssemblyAnnotationWriter=*/nullptr, /*ShouldPreserveUseListOrder=*/true); diff --git a/llvm/tools/llvm-reduce/ReducerWorkItem.h b/llvm/tools/llvm-reduce/ReducerWorkItem.h index 90d64a5ea170..d20ca1834c91 100644 --- a/llvm/tools/llvm-reduce/ReducerWorkItem.h +++ b/llvm/tools/llvm-reduce/ReducerWorkItem.h @@ -19,20 +19,23 @@ using namespace llvm; class ReducerWorkItem { public: std::shared_ptr M; - std::unique_ptr MF; + std::unique_ptr MMI; + + bool isMIR() const { return MMI != nullptr; } + + const Module &getModule() const { return *M; } + void print(raw_ostream &ROS, void *p = nullptr) const; - bool isMIR() { return MF != nullptr; } operator Module &() const { return *M; } - operator MachineFunction &() const { return *MF; } }; std::unique_ptr parseReducerWorkItem(const char *ToolName, StringRef Filename, LLVMContext &Ctxt, std::unique_ptr &TM, - std::unique_ptr &MMI, bool IsMIR); + bool IsMIR); std::unique_ptr -cloneReducerWorkItem(const ReducerWorkItem &MMM); +cloneReducerWorkItem(const ReducerWorkItem &MMM, const TargetMachine *TM); bool verifyReducerWorkItem(const ReducerWorkItem &MMM, raw_fd_ostream *OS); diff --git a/llvm/tools/llvm-reduce/TestRunner.cpp b/llvm/tools/llvm-reduce/TestRunner.cpp index e8c12138936f..6c9299797b35 100644 --- a/llvm/tools/llvm-reduce/TestRunner.cpp +++ b/llvm/tools/llvm-reduce/TestRunner.cpp @@ -12,8 +12,10 @@ using namespace llvm; TestRunner::TestRunner(StringRef TestName, const std::vector &TestArgs, - std::unique_ptr Program) - : TestName(TestName), TestArgs(TestArgs), Program(std::move(Program)) { + std::unique_ptr Program, + std::unique_ptr TM) + : TestName(TestName), TestArgs(TestArgs), Program(std::move(Program)), + TM(std::move(TM)) { assert(this->Program && "Initialized with null program?"); } diff --git a/llvm/tools/llvm-reduce/TestRunner.h b/llvm/tools/llvm-reduce/TestRunner.h index c14d0459a0fb..1074902554aa 100644 --- a/llvm/tools/llvm-reduce/TestRunner.h +++ b/llvm/tools/llvm-reduce/TestRunner.h @@ -16,6 +16,7 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" #include "llvm/Support/Program.h" +#include "llvm/Target/TargetMachine.h" #include namespace llvm { @@ -26,7 +27,8 @@ namespace llvm { class TestRunner { public: TestRunner(StringRef TestName, const std::vector &TestArgs, - std::unique_ptr Program); + std::unique_ptr Program, + std::unique_ptr TM); /// Runs the interesting-ness test for the specified file /// @returns 0 if test was successful, 1 if otherwise @@ -40,10 +42,13 @@ public: Program = std::move(P); } + const TargetMachine *getTargetMachine() const { return TM.get(); } + private: StringRef TestName; const std::vector &TestArgs; std::unique_ptr Program; + std::unique_ptr TM; }; } // namespace llvm diff --git a/llvm/tools/llvm-reduce/deltas/Delta.cpp b/llvm/tools/llvm-reduce/deltas/Delta.cpp index d48052742f93..3533afac0850 100644 --- a/llvm/tools/llvm-reduce/deltas/Delta.cpp +++ b/llvm/tools/llvm-reduce/deltas/Delta.cpp @@ -132,13 +132,14 @@ static bool increaseGranularity(std::vector &Chunks) { } return SplitOne; } + // Check if \p ChunkToCheckForUninterestingness is interesting. Returns the // modified module if the chunk resulted in a reduction. -template +template static std::unique_ptr CheckChunk(Chunk &ChunkToCheckForUninterestingness, std::unique_ptr Clone, TestRunner &Test, - function_ref ExtractChunksFromModule, + FuncType ExtractChunksFromModule, std::set &UninterestingChunks, std::vector &ChunksStillConsideredInteresting) { // Take all of ChunksStillConsideredInteresting chunks, except those we've @@ -183,11 +184,10 @@ CheckChunk(Chunk &ChunkToCheckForUninterestingness, return Clone; } -template +template SmallString<0> ProcessChunkFromSerializedBitcode( Chunk &ChunkToCheckForUninterestingness, TestRunner &Test, - function_ref ExtractChunksFromModule, - std::set &UninterestingChunks, + FuncType ExtractChunksFromModule, std::set &UninterestingChunks, std::vector &ChunksStillConsideredInteresting, SmallString<0> &OriginalBC, std::atomic &AnyReduced) { LLVMContext Ctx; @@ -217,10 +217,8 @@ SmallString<0> ProcessChunkFromSerializedBitcode( /// reduces the amount of chunks that are considered interesting by the /// given test. The number of chunks is determined by a preliminary run of the /// reduction pass where no change must be made to the module. -template -void runDeltaPassInt( - TestRunner &Test, - function_ref ExtractChunksFromModule) { +void llvm::runDeltaPass(TestRunner &Test, + ReductionFunc ExtractChunksFromModule) { assert(!verifyReducerWorkItem(Test.getProgram(), &errs()) && "input module is broken before making changes"); @@ -250,7 +248,7 @@ void runDeltaPassInt( std::vector NoChunks; Oracle NoChunksCounter(NoChunks); std::unique_ptr Clone = - cloneReducerWorkItem(Test.getProgram()); + cloneReducerWorkItem(Test.getProgram(), Test.getTargetMachine()); ExtractChunksFromModule(NoChunksCounter, *Clone); assert(Targets == NoChunksCounter.count() && "number of chunks changes when reducing"); @@ -365,9 +363,11 @@ void runDeltaPassInt( // Forward I to the last chunk processed in parallel. I += NumChunksProcessed - 1; } else { - Result = CheckChunk(*I, cloneReducerWorkItem(Test.getProgram()), Test, - ExtractChunksFromModule, UninterestingChunks, - ChunksStillConsideredInteresting); + Result = CheckChunk( + *I, + cloneReducerWorkItem(Test.getProgram(), Test.getTargetMachine()), + Test, ExtractChunksFromModule, UninterestingChunks, + ChunksStillConsideredInteresting); } if (!Result) @@ -394,15 +394,3 @@ void runDeltaPassInt( Test.setProgram(std::move(ReducedProgram)); errs() << "Couldn't increase anymore.\n"; } - -void llvm::runDeltaPass( - TestRunner &Test, - function_ref ExtractChunksFromModule) { - runDeltaPassInt(Test, ExtractChunksFromModule); -} - -void llvm::runDeltaPass( - TestRunner &Test, - function_ref ExtractChunksFromModule) { - runDeltaPassInt(Test, ExtractChunksFromModule); -} diff --git a/llvm/tools/llvm-reduce/deltas/Delta.h b/llvm/tools/llvm-reduce/deltas/Delta.h index a98da41957d0..76aaf2504482 100644 --- a/llvm/tools/llvm-reduce/deltas/Delta.h +++ b/llvm/tools/llvm-reduce/deltas/Delta.h @@ -85,6 +85,8 @@ public: int count() { return Index; } }; +using ReductionFunc = function_ref; + /// This function implements the Delta Debugging algorithm, it receives a /// number of Targets (e.g. Functions, Instructions, Basic Blocks, etc.) and /// splits them in half; these chunks of targets are then tested while ignoring @@ -103,12 +105,7 @@ public: /// /// Other implementations of the Delta Debugging algorithm can also be found in /// the CReduce, Delta, and Lithium projects. -void runDeltaPass( - TestRunner &Test, - function_ref ExtractChunksFromModule); -void runDeltaPass( - TestRunner &Test, - function_ref ExtractChunksFromModule); +void runDeltaPass(TestRunner &Test, ReductionFunc ExtractChunksFromModule); } // namespace llvm #endif diff --git a/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp b/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp index 93e457edb986..3be2eae01df0 100644 --- a/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp +++ b/llvm/tools/llvm-reduce/deltas/ReduceInstructionsMIR.cpp @@ -45,7 +45,7 @@ static Register getPrevDefOfRCInMBB(MachineBasicBlock &MBB, return 0; } -static void extractInstrFromModule(Oracle &O, MachineFunction &MF) { +static void extractInstrFromFunction(Oracle &O, MachineFunction &MF) { MachineDominatorTree MDT; MDT.runOnMachineFunction(MF); @@ -129,6 +129,13 @@ static void extractInstrFromModule(Oracle &O, MachineFunction &MF) { MI->eraseFromParent(); } +static void extractInstrFromModule(Oracle &O, ReducerWorkItem &WorkItem) { + for (const Function &F : WorkItem.getModule()) { + if (MachineFunction *MF = WorkItem.MMI->getMachineFunction(F)) + extractInstrFromFunction(O, *MF); + } +} + void llvm::reduceInstructionsMIRDeltaPass(TestRunner &Test) { outs() << "*** Reducing Instructions...\n"; runDeltaPass(Test, extractInstrFromModule); diff --git a/llvm/tools/llvm-reduce/llvm-reduce.cpp b/llvm/tools/llvm-reduce/llvm-reduce.cpp index db7bfa90cd6d..5581745ff22e 100644 --- a/llvm/tools/llvm-reduce/llvm-reduce.cpp +++ b/llvm/tools/llvm-reduce/llvm-reduce.cpp @@ -138,16 +138,16 @@ int main(int Argc, char **Argv) { LLVMContext Context; std::unique_ptr TM; - std::unique_ptr MMI; - std::unique_ptr OriginalProgram = parseReducerWorkItem( - Argv[0], InputFilename, Context, TM, MMI, ReduceModeMIR); + std::unique_ptr OriginalProgram = + parseReducerWorkItem(Argv[0], InputFilename, Context, TM, ReduceModeMIR); if (!OriginalProgram) { return 1; } // Initialize test environment - TestRunner Tester(TestFilename, TestArguments, std::move(OriginalProgram)); + TestRunner Tester(TestFilename, TestArguments, std::move(OriginalProgram), + std::move(TM)); // Try to reduce code runDeltaPasses(Tester, MaxPassIterations);