diff options
-rw-r--r-- | llvm/lib/CodeGen/MachineOutliner.cpp | 111 | ||||
-rw-r--r-- | llvm/test/CodeGen/AArch64/machine-outliner-remarks.ll | 68 |
2 files changed, 134 insertions, 45 deletions
diff --git a/llvm/lib/CodeGen/MachineOutliner.cpp b/llvm/lib/CodeGen/MachineOutliner.cpp index cf919a0928c..1bc869e02e6 100644 --- a/llvm/lib/CodeGen/MachineOutliner.cpp +++ b/llvm/lib/CodeGen/MachineOutliner.cpp @@ -149,6 +149,8 @@ private: unsigned OccurrenceCount = 0; public: + std::vector<std::shared_ptr<Candidate>> Candidates; + /// The actual outlined function created. /// This is initialized after we go through and create the actual function. MachineFunction *MF = nullptr; @@ -807,10 +809,11 @@ struct MachineOutliner : public ModulePass { /// type of candidate. /// /// \returns The length of the longest candidate found. - unsigned findCandidates(SuffixTree &ST, const TargetInstrInfo &TII, - InstructionMapper &Mapper, - std::vector<Candidate> &CandidateList, - std::vector<OutlinedFunction> &FunctionList); + unsigned + findCandidates(SuffixTree &ST, const TargetInstrInfo &TII, + InstructionMapper &Mapper, + std::vector<std::shared_ptr<Candidate>> &CandidateList, + std::vector<OutlinedFunction> &FunctionList); /// \brief Replace the sequences of instructions represented by the /// \p Candidates in \p CandidateList with calls to \p MachineFunctions @@ -820,7 +823,8 @@ struct MachineOutliner : public ModulePass { /// \param CandidateList A list of candidates to be outlined. /// \param FunctionList A list of functions to be inserted into the module. /// \param Mapper Contains the instruction mappings for the module. - bool outline(Module &M, const ArrayRef<Candidate> &CandidateList, + bool outline(Module &M, + const ArrayRef<std::shared_ptr<Candidate>> &CandidateList, std::vector<OutlinedFunction> &FunctionList, InstructionMapper &Mapper); @@ -841,10 +845,11 @@ struct MachineOutliner : public ModulePass { /// \param TII TargetInstrInfo for the module. /// /// \returns The length of the longest candidate found. 0 if there are none. - unsigned buildCandidateList(std::vector<Candidate> &CandidateList, - std::vector<OutlinedFunction> &FunctionList, - SuffixTree &ST, InstructionMapper &Mapper, - const TargetInstrInfo &TII); + unsigned + buildCandidateList(std::vector<std::shared_ptr<Candidate>> &CandidateList, + std::vector<OutlinedFunction> &FunctionList, + SuffixTree &ST, InstructionMapper &Mapper, + const TargetInstrInfo &TII); /// Helper function for pruneOverlaps. /// Removes \p C from the candidate list, and updates its \p OutlinedFunction. @@ -863,7 +868,7 @@ struct MachineOutliner : public ModulePass { /// \param Mapper Contains instruction mapping info for outlining. /// \param MaxCandidateLen The length of the longest candidate. /// \param TII TargetInstrInfo for the module. - void pruneOverlaps(std::vector<Candidate> &CandidateList, + void pruneOverlaps(std::vector<std::shared_ptr<Candidate>> &CandidateList, std::vector<OutlinedFunction> &FunctionList, InstructionMapper &Mapper, unsigned MaxCandidateLen, const TargetInstrInfo &TII); @@ -887,11 +892,10 @@ ModulePass *createMachineOutlinerPass(bool OutlineFromLinkOnceODRs) { INITIALIZE_PASS(MachineOutliner, DEBUG_TYPE, "Machine Function Outliner", false, false) -unsigned -MachineOutliner::findCandidates(SuffixTree &ST, const TargetInstrInfo &TII, - InstructionMapper &Mapper, - std::vector<Candidate> &CandidateList, - std::vector<OutlinedFunction> &FunctionList) { +unsigned MachineOutliner::findCandidates( + SuffixTree &ST, const TargetInstrInfo &TII, InstructionMapper &Mapper, + std::vector<std::shared_ptr<Candidate>> &CandidateList, + std::vector<OutlinedFunction> &FunctionList) { CandidateList.clear(); FunctionList.clear(); unsigned MaxLen = 0; @@ -1004,13 +1008,17 @@ MachineOutliner::findCandidates(SuffixTree &ST, const TargetInstrInfo &TII, // At this point, the candidate class is seen as beneficial. Set their // benefit values and save them in the candidate list. + std::vector<std::shared_ptr<Candidate>> CandidatesForFn; for (Candidate &C : CandidatesForRepeatedSeq) { C.Benefit = Benefit; C.MInfo = MInfo; - CandidateList.push_back(C); + std::shared_ptr<Candidate> Cptr = std::make_shared<Candidate>(C); + CandidateList.push_back(Cptr); + CandidatesForFn.push_back(Cptr); } FunctionList.push_back(OF); + FunctionList.back().Candidates = CandidatesForFn; // Move to the next function. Parent.IsInTree = false; @@ -1038,11 +1046,10 @@ void MachineOutliner::prune(Candidate &C, << "\n";); } -void MachineOutliner::pruneOverlaps(std::vector<Candidate> &CandidateList, - std::vector<OutlinedFunction> &FunctionList, - InstructionMapper &Mapper, - unsigned MaxCandidateLen, - const TargetInstrInfo &TII) { +void MachineOutliner::pruneOverlaps( + std::vector<std::shared_ptr<Candidate>> &CandidateList, + std::vector<OutlinedFunction> &FunctionList, InstructionMapper &Mapper, + unsigned MaxCandidateLen, const TargetInstrInfo &TII) { // Return true if this candidate became unbeneficial for outlining in a // previous step. @@ -1069,7 +1076,7 @@ void MachineOutliner::pruneOverlaps(std::vector<Candidate> &CandidateList, // This is O(MaxCandidateLen * CandidateList.size()). for (auto It = CandidateList.begin(), Et = CandidateList.end(); It != Et; It++) { - Candidate &C1 = *It; + Candidate &C1 = **It; // If C1 was already pruned, or its function is no longer beneficial for // outlining, move to the next candidate. @@ -1088,7 +1095,7 @@ void MachineOutliner::pruneOverlaps(std::vector<Candidate> &CandidateList, // FarthestPossibleIdx indices away from C1. There are at most // MaxCandidateLen of these. for (auto Sit = It + 1; Sit != Et; Sit++) { - Candidate &C2 = *Sit; + Candidate &C2 = **Sit; // Is this candidate too far away to overlap? if (C2.getStartIdx() < FarthestPossibleIdx) @@ -1130,11 +1137,10 @@ void MachineOutliner::pruneOverlaps(std::vector<Candidate> &CandidateList, } } -unsigned -MachineOutliner::buildCandidateList(std::vector<Candidate> &CandidateList, - std::vector<OutlinedFunction> &FunctionList, - SuffixTree &ST, InstructionMapper &Mapper, - const TargetInstrInfo &TII) { +unsigned MachineOutliner::buildCandidateList( + std::vector<std::shared_ptr<Candidate>> &CandidateList, + std::vector<OutlinedFunction> &FunctionList, SuffixTree &ST, + InstructionMapper &Mapper, const TargetInstrInfo &TII) { std::vector<unsigned> CandidateSequence; // Current outlining candidate. unsigned MaxCandidateLen = 0; // Length of the longest candidate. @@ -1145,7 +1151,10 @@ MachineOutliner::buildCandidateList(std::vector<Candidate> &CandidateList, // Sort the candidates in decending order. This will simplify the outlining // process when we have to remove the candidates from the mapping by // allowing us to cut them out without keeping track of an offset. - std::stable_sort(CandidateList.begin(), CandidateList.end()); + std::stable_sort( + CandidateList.begin(), CandidateList.end(), + [](const std::shared_ptr<Candidate> &LHS, + const std::shared_ptr<Candidate> &RHS) { return *LHS < *RHS; }); return MaxCandidateLen; } @@ -1204,15 +1213,14 @@ MachineOutliner::createOutlinedFunction(Module &M, const OutlinedFunction &OF, return &MF; } -bool MachineOutliner::outline(Module &M, - const ArrayRef<Candidate> &CandidateList, - std::vector<OutlinedFunction> &FunctionList, - InstructionMapper &Mapper) { +bool MachineOutliner::outline( + Module &M, const ArrayRef<std::shared_ptr<Candidate>> &CandidateList, + std::vector<OutlinedFunction> &FunctionList, InstructionMapper &Mapper) { bool OutlinedSomething = false; // Replace the candidates with calls to their respective outlined functions. - for (const Candidate &C : CandidateList) { - + for (const std::shared_ptr<Candidate> &Cptr : CandidateList) { + Candidate &C = *Cptr; // Was the candidate removed during pruneOverlaps? if (!C.InCandidateList) continue; @@ -1240,6 +1248,37 @@ bool MachineOutliner::outline(Module &M, // Does this candidate have a function yet? if (!OF.MF) { OF.MF = createOutlinedFunction(M, OF, Mapper); + MachineBasicBlock *MBB = &*OF.MF->begin(); + + // Output a remark telling the user that an outlined function was created, + // and explaining where it came from. + MachineOptimizationRemarkEmitter MORE(*OF.MF, nullptr); + MachineOptimizationRemark R(DEBUG_TYPE, "OutlinedFunction", + MBB->findDebugLoc(MBB->begin()), MBB); + R << "Saved " << NV("OutliningBenefit", OF.getBenefit()) + << " instructions by " + << "outlining " << NV("Length", OF.Sequence.size()) << " instructions " + << "from " << NV("NumOccurrences", OF.getOccurrenceCount()) + << " locations. " + << "(Found at: "; + + // Tell the user the other places the candidate was found. + for (size_t i = 0, e = OF.Candidates.size(); i < e; i++) { + + // Skip over things that were pruned. + if (!OF.Candidates[i]->InCandidateList) + continue; + + R << NV( + (Twine("StartLoc") + Twine(i)).str(), + Mapper.InstrList[OF.Candidates[i]->getStartIdx()]->getDebugLoc()); + if (i != e - 1) + R << ", "; + } + + R << ")"; + + MORE.emit(R); FunctionsCreated++; } @@ -1300,7 +1339,7 @@ bool MachineOutliner::runOnModule(Module &M) { // Construct a suffix tree, use it to find candidates, and then outline them. SuffixTree ST(Mapper.UnsignedVec); - std::vector<Candidate> CandidateList; + std::vector<std::shared_ptr<Candidate>> CandidateList; std::vector<OutlinedFunction> FunctionList; // Find all of the outlining candidates. diff --git a/llvm/test/CodeGen/AArch64/machine-outliner-remarks.ll b/llvm/test/CodeGen/AArch64/machine-outliner-remarks.ll index 113f3431101..1a237a2403e 100644 --- a/llvm/test/CodeGen/AArch64/machine-outliner-remarks.ll +++ b/llvm/test/CodeGen/AArch64/machine-outliner-remarks.ll @@ -1,9 +1,12 @@ -; RUN: llc %s -enable-machine-outliner -mtriple=aarch64-unknown-unknown -pass-remarks-missed=machine-outliner -o /dev/null 2>&1 | FileCheck %s +; RUN: llc %s -enable-machine-outliner -mtriple=aarch64-unknown-unknown -pass-remarks=machine-outliner -pass-remarks-missed=machine-outliner -o /dev/null 2>&1 | FileCheck %s ; CHECK: machine-outliner-remarks.ll:5:9: ; CHECK-SAME: Did not outline 2 instructions from 2 locations. ; CHECK-SAME: Instructions from outlining all occurrences (9) >= ; CHECK-SAME: Unoutlined instruction count (4) ; CHECK-SAME: (Also found at: machine-outliner-remarks.ll:13:9) +; CHECK: remark: <unknown>:0:0: Saved 5 instructions by outlining 7 instructions +; CHECK-SAME: from 2 locations. (Found at: machine-outliner-remarks.ll:27:9, +; CHECK-SAME: machine-outliner-remarks.ll:36:1) ; RUN: llc %s -enable-machine-outliner -mtriple=aarch64-unknown-unknown -o /dev/null -pass-remarks-missed=machine-outliner -pass-remarks-output=%t.yaml ; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML ; YAML: --- !Missed @@ -28,23 +31,68 @@ ; YAML-NEXT: - OtherStartLoc1: 'machine-outliner-remarks.ll:13:9' ; YAML-NEXT: DebugLoc: { File: machine-outliner-remarks.ll, Line: 13, Column: 9 } ; YAML-NEXT: - String: ')' +; YAML: --- !Passed +; YAML-NEXT: Pass: machine-outliner +; YAML-NEXT: Name: OutlinedFunction +; YAML-NEXT: Function: OUTLINED_FUNCTION_0 +; YAML-NEXT: Args: +; YAML-NEXT: - String: 'Saved ' +; YAML-NEXT: - OutliningBenefit: '5' +; YAML-NEXT: - String: ' instructions by ' +; YAML-NEXT: - String: 'outlining ' +; YAML-NEXT: - Length: '7' +; YAML-NEXT: - String: ' instructions ' +; YAML-NEXT: - String: 'from ' +; YAML-NEXT: - NumOccurrences: '2' +; YAML-NEXT: - String: ' locations. ' +; YAML-NEXT: - String: '(Found at: ' +; YAML-NEXT: - StartLoc0: 'machine-outliner-remarks.ll:27:9' +; YAML-NEXT: DebugLoc: { File: machine-outliner-remarks.ll, Line: 27, Column: 9 } +; YAML-NEXT: - String: ', ' +; YAML-NEXT: - StartLoc1: 'machine-outliner-remarks.ll:36:1' +; YAML-NEXT: DebugLoc: { File: machine-outliner-remarks.ll, Line: 36, Column: 1 } +; YAML-NEXT: - String: ')' define void @dog() #0 !dbg !8 { entry: %x = alloca i32, align 4 %y = alloca i32, align 4 - store i32 0, i32* %x, align 4, !dbg !11 + store i32 0, i32* %x, align 4 store i32 1, i32* %y, align 4, !dbg !12 - ret void, !dbg !13 + ret void } define void @cat() #0 !dbg !14 { entry: %x = alloca i32, align 4 %y = alloca i32, align 4 - store i32 0, i32* %x, align 4, !dbg !15 + store i32 0, i32* %x, align 4 store i32 1, i32* %y, align 4, !dbg !16 - ret void, !dbg !17 + ret void +} + +define void @foo() #0 !dbg !18 { + %1 = alloca i32, align 4 + %2 = alloca i32, align 4 + %3 = alloca i32, align 4 + %4 = alloca i32, align 4 + store i32 0, i32* %1, align 4 + store i32 1, i32* %2, align 4, !dbg !24 + store i32 2, i32* %3, align 4 + store i32 3, i32* %4, align 4, !dbg !26 + ret void +} + +define void @bar() #0 !dbg !27 { + %1 = alloca i32, align 4 + %2 = alloca i32, align 4 + %3 = alloca i32, align 4 + %4 = alloca i32, align 4 + store i32 0, i32* %1, align 4 + store i32 1, i32* %2, align 4, !dbg !33 + store i32 2, i32* %3, align 4 + store i32 3, i32* %4, align 4, !dbg !35 + ret void } attributes #0 = { noredzone nounwind ssp uwtable "no-frame-pointer-elim"="false" "target-cpu"="cyclone" } @@ -64,10 +112,12 @@ attributes #0 = { noredzone nounwind ssp uwtable "no-frame-pointer-elim"="false" !8 = distinct !DISubprogram(name: "dog", scope: !1, file: !1, line: 2, type: !9, isLocal: false, isDefinition: true, scopeLine: 3, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) !9 = !DISubroutineType(types: !10) !10 = !{null} -!11 = !DILocation(line: 4, column: 9, scope: !8) !12 = !DILocation(line: 5, column: 9, scope: !8) -!13 = !DILocation(line: 6, column: 1, scope: !8) !14 = distinct !DISubprogram(name: "cat", scope: !1, file: !1, line: 10, type: !9, isLocal: false, isDefinition: true, scopeLine: 11, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) -!15 = !DILocation(line: 12, column: 9, scope: !14) !16 = !DILocation(line: 13, column: 9, scope: !14) -!17 = !DILocation(line: 14, column: 1, scope: !14) +!18 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 26, type: !9, isLocal: false, isDefinition: true, scopeLine: 26, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!24 = !DILocation(line: 27, column: 9, scope: !18) +!26 = !DILocation(line: 29, column: 9, scope: !18) +!27 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 35, type: !9, isLocal: false, isDefinition: true, scopeLine: 35, flags: DIFlagPrototyped, isOptimized: false, unit: !0, variables: !2) +!33 = !DILocation(line: 36, column: 1, scope: !27) +!35 = !DILocation(line: 38, column: 1, scope: !27)
\ No newline at end of file |