[llvm] r316396 - [MachineOutliner] Add optimisation remarks for successful outlining

Jessica Paquette via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 23 16:36:46 PDT 2017


Author: paquette
Date: Mon Oct 23 16:36:46 2017
New Revision: 316396

URL: http://llvm.org/viewvc/llvm-project?rev=316396&view=rev
Log:
[MachineOutliner] Add optimisation remarks for successful outlining

This commit adds optimisation remarks for outlining which fire when a function
is successfully outlined.

To do this, OutlinedFunctions must now contain references to their Candidates.
Since the Candidates must still be sorted and worked on separately, this is
done by working on everything in terms of shared_ptrs to Candidates. This is
good; it means that we can easily move everything to outlining in terms of
the OutlinedFunctions rather than the individual Candidates. This is far more
intuitive than what's currently there!

(Remarks are output when a function is created for some group of Candidates.
In a later commit, all of the outlining logic should be rewritten so that we
loop over OutlinedFunctions rather than over Candidates.)
 

Modified:
    llvm/trunk/lib/CodeGen/MachineOutliner.cpp
    llvm/trunk/test/CodeGen/AArch64/machine-outliner-remarks.ll

Modified: llvm/trunk/lib/CodeGen/MachineOutliner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineOutliner.cpp?rev=316396&r1=316395&r2=316396&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineOutliner.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineOutliner.cpp Mon Oct 23 16:36:46 2017
@@ -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 ModulePa
   /// 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 ModulePa
   /// \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 ModulePa
   /// \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 ModulePa
   /// \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(bo
 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(SuffixTr
 
     // 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:
   // 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:
     // 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:
   }
 }
 
-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:
   // 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(
   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
 
   // 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.

Modified: llvm/trunk/test/CodeGen/AArch64/machine-outliner-remarks.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/machine-outliner-remarks.ll?rev=316396&r1=316395&r2=316396&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/machine-outliner-remarks.ll (original)
+++ llvm/trunk/test/CodeGen/AArch64/machine-outliner-remarks.ll Mon Oct 23 16:36:46 2017
@@ -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
 !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




More information about the llvm-commits mailing list