[llvm] r342009 - [MachineOutliner] Add codegen size remarks to the MachineOutliner

Jessica Paquette via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 11 16:05:35 PDT 2018


Author: paquette
Date: Tue Sep 11 16:05:34 2018
New Revision: 342009

URL: http://llvm.org/viewvc/llvm-project?rev=342009&view=rev
Log:
[MachineOutliner] Add codegen size remarks to the MachineOutliner

Since the outliner is a module pass, it doesn't get codegen size remarks like
the other codegen passes do. This adds size remarks *to* the outliner.

This is kind of a workaround, so it's peppered with FIXMEs; size remarks
really ought to not ever be handled by the pass itself. However, since the
outliner is the only "MachineModulePass", this works for now. Since the
entire purpose of the MachineOutliner is to produce code size savings, it
really ought to be included in codgen size remarks.

If we ever go ahead and make a MachineModulePass (say, something similar to
MachineFunctionPass), then all of this ought to be moved there.

Added:
    llvm/trunk/test/CodeGen/AArch64/machine-outliner-size-info.mir
Modified:
    llvm/trunk/lib/CodeGen/MachineOutliner.cpp

Modified: llvm/trunk/lib/CodeGen/MachineOutliner.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineOutliner.cpp?rev=342009&r1=342008&r2=342009&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineOutliner.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineOutliner.cpp Tue Sep 11 16:05:34 2018
@@ -812,8 +812,21 @@ struct MachineOutliner : public ModulePa
   /// These are used to construct a suffix tree.
   void populateMapper(InstructionMapper &Mapper, Module &M,
                       MachineModuleInfo &MMI);
-};
 
+  /// Initialize information necessary to output a size remark.
+  /// FIXME: This should be handled by the pass manager, not the outliner.
+  /// FIXME: This is nearly identical to the initSizeRemarkInfo in the legacy
+  /// pass manager.
+  void initSizeRemarkInfo(
+      const Module &M, const MachineModuleInfo &MMI,
+      StringMap<unsigned> &FunctionToInstrCount);
+
+  /// Emit the remark.
+  // FIXME: This should be handled by the pass manager, not the outliner.
+  void emitInstrCountChangedRemark(
+      const Module &M, const MachineModuleInfo &MMI,
+      const StringMap<unsigned> &FunctionToInstrCount);
+};
 } // Anonymous namespace.
 
 char MachineOutliner::ID = 0;
@@ -1388,6 +1401,75 @@ void MachineOutliner::populateMapper(Ins
   }
 }
 
+void MachineOutliner::initSizeRemarkInfo(
+    const Module &M, const MachineModuleInfo &MMI,
+    StringMap<unsigned> &FunctionToInstrCount) {
+  // Collect instruction counts for every function. We'll use this to emit
+  // per-function size remarks later.
+  for (const Function &F : M) {
+    MachineFunction *MF = MMI.getMachineFunction(F);
+
+    // We only care about MI counts here. If there's no MachineFunction at this
+    // point, then there won't be after the outliner runs, so let's move on.
+    if (!MF)
+      continue;
+    FunctionToInstrCount[F.getName().str()] = MF->getInstructionCount();
+  }
+}
+
+void MachineOutliner::emitInstrCountChangedRemark(
+    const Module &M, const MachineModuleInfo &MMI,
+    const StringMap<unsigned> &FunctionToInstrCount) {
+  // Iterate over each function in the module and emit remarks.
+  // Note that we won't miss anything by doing this, because the outliner never
+  // deletes functions.
+  for (const Function &F : M) {
+    MachineFunction *MF = MMI.getMachineFunction(F);
+
+    // The outliner never deletes functions. If we don't have a MF here, then we
+    // didn't have one prior to outlining either.
+    if (!MF)
+      continue;
+
+    std::string Fname = F.getName();
+    unsigned FnCountAfter = MF->getInstructionCount();
+    unsigned FnCountBefore = 0;
+
+    // Check if the function was recorded before.
+    auto It = FunctionToInstrCount.find(Fname);
+
+    // Did we have a previously-recorded size? If yes, then set FnCountBefore
+    // to that.
+    if (It != FunctionToInstrCount.end())
+      FnCountBefore = It->second;
+
+    // Compute the delta and emit a remark if there was a change.
+    int64_t FnDelta = static_cast<int64_t>(FnCountAfter) -
+                      static_cast<int64_t>(FnCountBefore);
+    if (FnDelta == 0)
+      continue;
+
+    MachineOptimizationRemarkEmitter MORE(*MF, nullptr);
+    MORE.emit([&]() {
+      MachineOptimizationRemarkAnalysis R("size-info", "FunctionMISizeChange",
+                                          DiagnosticLocation(),
+                                          &MF->front());
+      R << DiagnosticInfoOptimizationBase::Argument("Pass", "Machine Outliner")
+        << ": Function: "
+        << DiagnosticInfoOptimizationBase::Argument("Function", F.getName())
+        << ": MI instruction count changed from "
+        << DiagnosticInfoOptimizationBase::Argument("MIInstrsBefore",
+                                                    FnCountBefore)
+        << " to "
+        << DiagnosticInfoOptimizationBase::Argument("MIInstrsAfter",
+                                                    FnCountAfter)
+        << "; Delta: "
+        << DiagnosticInfoOptimizationBase::Argument("Delta", FnDelta);
+      return R;
+    });
+  }
+}
+
 bool MachineOutliner::runOnModule(Module &M) {
   // Check if there's anything in the module. If it's empty, then there's
   // nothing to outline.
@@ -1430,8 +1512,28 @@ bool MachineOutliner::runOnModule(Module
   // Remove candidates that overlap with other candidates.
   pruneOverlaps(CandidateList, FunctionList, Mapper, MaxCandidateLen);
 
+  // If we've requested size remarks, then collect the MI counts of every
+  // function before outlining, and the MI counts after outlining.
+  // FIXME: This shouldn't be in the outliner at all; it should ultimately be
+  // the pass manager's responsibility.
+  // This could pretty easily be placed in outline instead, but because we
+  // really ultimately *don't* want this here, it's done like this for now
+  // instead.
+
+  // Check if we want size remarks.
+  bool ShouldEmitSizeRemarks = M.shouldEmitInstrCountChangedRemark();
+  StringMap<unsigned> FunctionToInstrCount;
+  if (ShouldEmitSizeRemarks)
+    initSizeRemarkInfo(M, MMI, FunctionToInstrCount);
+
   // Outline each of the candidates and return true if something was outlined.
   bool OutlinedSomething = outline(M, CandidateList, FunctionList, Mapper);
 
+  // If we outlined something, we definitely changed the MI count of the
+  // module. If we've asked for size remarks, then output them.
+  // FIXME: This should be in the pass manager.
+  if (ShouldEmitSizeRemarks && OutlinedSomething)
+    emitInstrCountChangedRemark(M, MMI, FunctionToInstrCount);
+
   return OutlinedSomething;
 }

Added: llvm/trunk/test/CodeGen/AArch64/machine-outliner-size-info.mir
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/AArch64/machine-outliner-size-info.mir?rev=342009&view=auto
==============================================================================
--- llvm/trunk/test/CodeGen/AArch64/machine-outliner-size-info.mir (added)
+++ llvm/trunk/test/CodeGen/AArch64/machine-outliner-size-info.mir Tue Sep 11 16:05:34 2018
@@ -0,0 +1,81 @@
+# RUN: llc -mtriple=aarch64-apple-darwin -run-pass=prologepilog \
+# RUN: -run-pass=machine-outliner %s -pass-remarks-analysis='size-info' \
+# RUN: -pass-remarks-output=%t.yaml -o /dev/null < %s 2> %t; \
+# RUN: cat %t %t.yaml | FileCheck %s
+
+# Ensure that the MachineOutliner produces codegen size remarks. Make sure...
+# - Functions that are outlined from shrink in the remark (foo)
+# - Outlined functions start with 0 instructions
+# - Outlined functions end with the same number of instructions as the delta
+
+# CHECK: remark: <unknown>:0:0: Machine Outliner: Function: foo:
+# CHECK-SAME: MI instruction count changed from
+# CHECK-SAME: [[FOO1:[1-9][0-9]*]] to [[FOO2:[1-9][0-9]*]];
+# CHECK-SAME: Delta: [[FOODELTA:-?[1-9][0-9]*]]
+# CHECK-NEXT: remark: <unknown>:0:0: Machine Outliner:
+# CHECK-SAME: Function: OUTLINED_FUNCTION_0: MI instruction count changed from
+# CHECK-SAME: 0 to [[OFUNCSIZE:[1-9][0-9]*]]; Delta: [[OFUNCSIZE]]
+# CHECK-DAG: - Pass:            Machine Outliner
+# CHECK-NEXT: - String:          ': Function: '
+# CHECK-NEXT: - Function:        foo
+# CHECK-NEXT: - String:          ': MI instruction count changed from '
+# CHECK-NEXT: - MIInstrsBefore:  '[[FOO1]]'
+# CHECK-NEXT: - String:          ' to '
+# CHECK-NEXT: - MIInstrsAfter:   '[[FOO2]]'
+# CHECK-NEXT: - String:          '; Delta: '
+# CHECK-NEXT: - Delta:           '[[FOODELTA]]'
+# CHECK-NEXT:...
+# CHECK-NEXT: --- !Analysis
+# CHECK-NEXT: Pass:            size-info
+# CHECK-NEXT: Name:            FunctionMISizeChange
+# CHECK-NEXT: Function:        OUTLINED_FUNCTION_0
+# CHECK-NEXT: Args:
+# CHECK-NEXT:  - Pass:            Machine Outliner
+# CHECK-NEXT:  - String:          ': Function: '
+# CHECK-NEXT:  - Function:        OUTLINED_FUNCTION_0
+# CHECK-NEXT:  - String:          ': MI instruction count changed from '
+# CHECK-NEXT:  - MIInstrsBefore:  '0'
+# CHECK-NEXT:  - String:          ' to '
+# CHECK-NEXT:  - MIInstrsAfter:   '[[OFUNCSIZE]]'
+# CHECK-NEXT:  - String:          '; Delta: '
+# CHECK-NEXT:  - Delta:           '[[OFUNCSIZE]]'
+...
+--- |
+
+  define void @foo() #0 {
+    ret void
+  }
+
+  attributes #0 = { minsize noinline noredzone "no-frame-pointer-elim"="true" }
+...
+---
+name:            foo
+tracksRegLiveness: true
+fixedStack:
+body:             |
+  bb.0:
+    liveins: $lr, $w9
+    $x25 = ORRXri $xzr, 1
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 2
+  bb.1:
+    liveins: $lr, $w9
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 2
+  bb.2:
+    liveins: $lr, $w9
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 1
+    $w9 = ORRWri $wzr, 2
+    RET undef $lr




More information about the llvm-commits mailing list