Index: include/llvm/IR/Function.h
===================================================================
--- include/llvm/IR/Function.h
+++ include/llvm/IR/Function.h
@@ -141,6 +141,9 @@
   // Provide fast operand accessors.
   DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value);
 
+  /// Returns the number of IR instructions contained in the \p Function.
+  int getFunctionInstrCount();
+
   /// Returns the FunctionType for me.
   FunctionType *getFunctionType() const {
     return cast<FunctionType>(getValueType());
Index: include/llvm/IR/LegacyPassManagers.h
===================================================================
--- include/llvm/IR/LegacyPassManagers.h
+++ include/llvm/IR/LegacyPassManagers.h
@@ -403,6 +403,14 @@
       InheritedAnalysis[Index++] = (*I)->getAvailableAnalysis();
   }
 
+  /// Return the total number of IR instructions in \p M.
+  int getModuleInstrCount(Module &M);
+
+  /// \brief Emit a remark signifying that the number of IR instructions in the
+  /// module changed.
+  void emitIRSizeChangedRemark(Pass *P, Module &M, const int &OriginalCount,
+                               const int &FinalCount);
+
 protected:
   // Top level manager.
   PMTopLevelManager *TPM;
Index: include/llvm/IR/Module.h
===================================================================
--- include/llvm/IR/Module.h
+++ include/llvm/IR/Module.h
@@ -207,6 +207,9 @@
   /// @returns the module identifier as a string
   const std::string &getModuleIdentifier() const { return ModuleID; }
 
+  /// Return the number of IR instructions contained in the module.
+  int getModuleInstrCount();
+
   /// Get the module's original source file name. When compiling from
   /// bitcode, this is taken from a bitcode record where it was recorded.
   /// For other compiles it is the same as the ModuleID, which would
Index: lib/Analysis/CallGraphSCCPass.cpp
===================================================================
--- lib/Analysis/CallGraphSCCPass.cpp
+++ lib/Analysis/CallGraphSCCPass.cpp
@@ -120,7 +120,7 @@
                                  bool &DevirtualizedCall) {
   bool Changed = false;
   PMDataManager *PM = P->getAsPMDataManager();
-
+  Module &M = CG.getModule();
   if (!PM) {
     CallGraphSCCPass *CGSP = (CallGraphSCCPass*)P;
     if (!CallGraphUpToDate) {
@@ -130,7 +130,13 @@
 
     {
       TimeRegion PassTimer(getPassTimer(CGSP));
+
+      // Remember the number of instructions in the module before the pass.
+      int OriginalCount = M.getModuleInstrCount();
       Changed = CGSP->runOnSCC(CurSCC);
+      // If the pass modified the size of the module, emit a remark.
+      emitIRSizeChangedRemark(P, M, OriginalCount, M.getModuleInstrCount());
+        
     }
     
     // After the CGSCCPass is done, when assertions are enabled, use
@@ -147,13 +153,26 @@
          "Invalid CGPassManager member");
   FPPassManager *FPP = (FPPassManager*)P;
   
+  // Keep track of the original module size.
+  int ModuleCount = M.getModuleInstrCount();
+
   // Run pass P on all functions in the current SCC.
   for (CallGraphNode *CGN : CurSCC) {
     if (Function *F = CGN->getFunction()) {
       dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName());
       {
         TimeRegion PassTimer(getPassTimer(FPP));
-        Changed |= FPP->runOnFunction(*F);
+        int OrigFnCount = F->getFunctionInstrCount();
+
+        // Run FPP on F and check if it changed anything.
+        if (FPP->runOnFunction(*F)) {
+          // It changed something. Keep track of it and also emit a remark if
+          // it changed the size of the module.
+          Changed = true;
+          int InstrDiff = F->getFunctionInstrCount() - OrigFnCount;
+          emitIRSizeChangedRemark(P, M, ModuleCount, ModuleCount + InstrDiff);
+          ModuleCount += InstrDiff;
+        }
       }
       F->getContext().yield();
     }
Index: lib/IR/Function.cpp
===================================================================
--- lib/IR/Function.cpp
+++ lib/IR/Function.cpp
@@ -195,6 +195,13 @@
   return getType()->getContext();
 }
 
+int Function::getFunctionInstrCount() {
+  int IRCount = 0;
+  for (BasicBlock &BB : BasicBlocks)
+    IRCount += BB.size();
+  return IRCount;
+}
+
 void Function::removeFromParent() {
   getParent()->getFunctionList().remove(getIterator());
 }
Index: lib/IR/LegacyPassManager.cpp
===================================================================
--- lib/IR/LegacyPassManager.cpp
+++ lib/IR/LegacyPassManager.cpp
@@ -13,6 +13,7 @@
 
 #include "llvm/IR/LegacyPassManager.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/IR/DiagnosticInfo.h"
 #include "llvm/IR/IRPrintingPasses.h"
 #include "llvm/IR/LLVMContext.h"
 #include "llvm/IR/LegacyPassManagers.h"
@@ -128,8 +129,33 @@
   return PassDebugging >= Executions;
 }
 
-
-
+void PMDataManager::emitIRSizeChangedRemark(Pass *P, Module &M,
+                                            const int &OriginalCount,
+                                            const int &FinalCount) {
+  // If there was no change, don't emit a remark.
+  if (OriginalCount == FinalCount)
+      return;
+
+  // If it's a pass manager, don't emit a remark. (This hinges on the assumption
+  // that the only passes that return non-null with getAsPMDataManager are
+  // pass managers.)
+  if (P->getAsPMDataManager())
+      return;
+
+  Function &F = *M.begin();
+  BasicBlock &BB = *F.begin();
+  OptimizationRemarkAnalysis R("size-info", "IRSizeChange",
+                               DiagnosticLocation(), &BB);
+  R << DiagnosticInfoOptimizationBase::Argument("Pass", P->getPassName())
+    << ": IR instruction count changed from "
+    << DiagnosticInfoOptimizationBase::Argument("IRInstrsBefore", OriginalCount)
+    << " to "
+    << DiagnosticInfoOptimizationBase::Argument("IRInstrsAfter", FinalCount)
+    << "; Delta: "
+    << DiagnosticInfoOptimizationBase::Argument("DeltaInstrCount",
+                                                FinalCount - OriginalCount);
+  F.getContext().diagnose(R);
+}
 
 void PassManagerPrettyStackEntry::print(raw_ostream &OS) const {
   if (!V && !M)
@@ -173,7 +199,7 @@
 
 public:
   static char ID;
-  explicit BBPassManager()
+  explicit BBPassManager() 
     : PMDataManager(), FunctionPass(ID) {}
 
   /// Execute all of the passes scheduled for execution.  Keep track of
@@ -322,7 +348,7 @@
 
   using llvm::Pass::doInitialization;
   using llvm::Pass::doFinalization;
-
+  
   /// Pass Manager itself does not invalidate any analysis info.
   void getAnalysisUsage(AnalysisUsage &Info) const override {
     Info.setPreservesAll();
@@ -350,7 +376,7 @@
       ModulePass *MP = getContainedPass(Index);
       MP->dumpPassStructure(Offset + 1);
       std::map<Pass *, FunctionPassManagerImpl *>::const_iterator I =
-        OnTheFlyManagers.find(MP);
+          OnTheFlyManagers.find(MP);
       if (I != OnTheFlyManagers.end())
         I->second->dumpPassStructure(Offset + 2);
       dumpLastUses(MP, Offset+1);
@@ -366,7 +392,7 @@
     return PMT_ModulePassManager;
   }
 
- private:
+private:
   /// Collection of on the fly FPPassManagers. These managers manage
   /// function passes that are required by module passes.
   std::map<Pass *, FunctionPassManagerImpl *> OnTheFlyManagers;
@@ -394,8 +420,8 @@
                               PMTopLevelManager(new MPPassManager()) {}
 
   /// \copydoc PassManager::add()
-  void add(Pass *P) {
-    schedulePass(P);
+  void add(Pass *P) { 
+    schedulePass(P); 
   }
 
   /// createPrinterPass - Get a module printer pass.
@@ -410,7 +436,7 @@
 
   using llvm::Pass::doInitialization;
   using llvm::Pass::doFinalization;
-
+  
   /// Pass Manager itself does not invalidate any analysis info.
   void getAnalysisUsage(AnalysisUsage &Info) const override {
     Info.setPreservesAll();
@@ -467,8 +493,8 @@
   static void createTheTimeInfo();
 
   // print - Prints out timing information and then resets the timers.
-  void print() {
-    TG.print(*CreateInfoOutputFile());
+  void print() { 
+    TG.print(*CreateInfoOutputFile()); 
   }
 
   /// getPassTimer - Return the timer for the specified pass if it exists.
@@ -554,7 +580,7 @@
 void PMTopLevelManager::collectLastUses(SmallVectorImpl<Pass *> &LastUses,
                                         Pass *P) {
   DenseMap<Pass *, SmallPtrSet<Pass *, 8> >::iterator DMI =
-    InversedLastUser.find(P);
+      InversedLastUser.find(P);
   if (DMI == InversedLastUser.end())
     return;
 
@@ -579,7 +605,7 @@
     // of dependencies.
     AnalysisUsage AU;
     P->getAnalysisUsage(AU);
-    
+
     AUFoldingSetNode* Node = nullptr;
     FoldingSetNodeID ID;
     AUFoldingSetNode::Profile(ID, AU);
@@ -873,7 +899,7 @@
 
   const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
   for (DenseMap<AnalysisID, Pass*>::iterator I = AvailableAnalysis.begin(),
-         E = AvailableAnalysis.end(); I != E; ) {
+        E = AvailableAnalysis.end(); I != E; ) {
     DenseMap<AnalysisID, Pass*>::iterator Info = I++;
     if (Info->second->getAsImmutablePass() == nullptr &&
         !is_contained(PreservedSet, Info->first)) {
@@ -895,8 +921,8 @@
       continue;
 
     for (DenseMap<AnalysisID, Pass*>::iterator
-           I = InheritedAnalysis[Index]->begin(),
-           E = InheritedAnalysis[Index]->end(); I != E; ) {
+             I = InheritedAnalysis[Index]->begin(),
+             E = InheritedAnalysis[Index]->end(); I != E; ) {
       DenseMap<AnalysisID, Pass *>::iterator Info = I++;
       if (Info->second->getAsImmutablePass() == nullptr &&
           !is_contained(PreservedSet, Info->first)) {
@@ -956,7 +982,7 @@
     const std::vector<const PassInfo*> &II = PInf->getInterfacesImplemented();
     for (unsigned i = 0, e = II.size(); i != e; ++i) {
       DenseMap<AnalysisID, Pass*>::iterator Pos =
-        AvailableAnalysis.find(II[i]->getTypeInfo());
+          AvailableAnalysis.find(II[i]->getTypeInfo());
       if (Pos != AvailableAnalysis.end() && Pos->second == P)
         AvailableAnalysis.erase(Pos);
     }
@@ -1120,16 +1146,16 @@
   for (Pass *P : PassVector) {
     if (PMDataManager *PMD = P->getAsPMDataManager())
       PMD->dumpPassArguments();
-    else
-      if (const PassInfo *PI =
+    else 
+      if (const PassInfo *PI = 
             TPM->findAnalysisPassInfo(P->getPassID()))
-        if (!PI->isAnalysisGroup())
-          dbgs() << " -" << PI->getPassArgument();
+      if (!PI->isAnalysisGroup())
+        dbgs() << " -" << PI->getPassArgument();
   }
 }
 
 void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1,
-                                 enum PassDebuggingString S2,
+                                 enum PassDebuggingString S2, 
                                  StringRef Msg) {
   if (PassDebugging < Executions)
     return;
@@ -1278,6 +1304,8 @@
     return false;
 
   bool Changed = doInitialization(F);
+  Module &M = *F.getParent();
+  int ModuleCount = M.getModuleInstrCount();
 
   for (BasicBlock &BB : F)
     for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
@@ -1294,7 +1322,17 @@
         PassManagerPrettyStackEntry X(BP, BB);
         TimeRegion PassTimer(getPassTimer(BP));
 
-        LocalChanged |= BP->runOnBasicBlock(BB);
+        int OrigBBCount = BB.size();
+
+        // Run BP on BB and check if anything changed.
+        if (BP->runOnBasicBlock(BB)) {
+          // It changed something. Keep track of the local change, and emit a
+          // remark if it changed the size of the module.
+          LocalChanged = true;
+          int InstrDiff = BB.size() - OrigBBCount;
+          emitIRSizeChangedRemark(BP, M, ModuleCount, ModuleCount + InstrDiff);
+          ModuleCount += InstrDiff;
+        }
       }
 
       Changed |= LocalChanged;
@@ -1368,12 +1406,12 @@
   FPM->setResolver(AR);
 }
 
-FunctionPassManager::~FunctionPassManager() {
-  delete FPM;
+FunctionPassManager::~FunctionPassManager() { 
+  delete FPM; 
 }
 
-void FunctionPassManager::add(Pass *P) {
-  FPM->add(P);
+void FunctionPassManager::add(Pass *P) { 
+  FPM->add(P); 
 }
 
 /// run - Execute all of the passes scheduled for execution.  Keep
@@ -1396,8 +1434,8 @@
 
 /// doFinalization - Run all of the finalizers for the function passes.
 ///
-bool FunctionPassManager::doFinalization() {
-  return FPM->doFinalization(*M);
+bool FunctionPassManager::doFinalization() { 
+  return FPM->doFinalization(*M); 
 }
 
 //===----------------------------------------------------------------------===//
@@ -1432,12 +1470,12 @@
 
 /// cleanup - After running all passes, clean up pass manager cache.
 void FPPassManager::cleanup() {
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
+  for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
     FunctionPass *FP = getContainedPass(Index);
     AnalysisResolver *AR = FP->getResolver();
     assert(AR && "Analysis Resolver is not set");
     AR->clearAnalysisImpls();
- }
+  }
 }
 
 void FunctionPassManagerImpl::releaseMemoryOnTheFly() {
@@ -1494,6 +1532,8 @@
     return false;
 
   bool Changed = false;
+  Module &M = *(F.getParent());
+  int ModuleCount = M.getModuleInstrCount();
 
   // Collect inherited analysis from Module level pass manager.
   populateInheritedAnalysis(TPM->activeStack);
@@ -1511,7 +1551,17 @@
       PassManagerPrettyStackEntry X(FP, F);
       TimeRegion PassTimer(getPassTimer(FP));
 
-      LocalChanged |= FP->runOnFunction(F);
+      int OrigFnCount = F.getFunctionInstrCount();
+
+      // Did FP modify F?
+      if (FP->runOnFunction(F)) {
+        // It changed something. Keep track of the local change, and emit a
+        // remark if it changed the size of the module.
+        LocalChanged = true;
+        int InstrDiff = F.getFunctionInstrCount() - OrigFnCount;
+        emitIRSizeChangedRemark(FP, M, ModuleCount, ModuleCount + InstrDiff);
+        ModuleCount += InstrDiff;
+      }      
     }
 
     Changed |= LocalChanged;
@@ -1588,11 +1638,15 @@
       PassManagerPrettyStackEntry X(MP, M);
       TimeRegion PassTimer(getPassTimer(MP));
 
+      int OriginalCount = M.getModuleInstrCount();
       LocalChanged |= MP->runOnModule(M);
+
+      // If MP changed the size of the module, then emit a remark.
+      emitIRSizeChangedRemark(MP, M, OriginalCount, M.getModuleInstrCount());
     }
 
     Changed |= LocalChanged;
-    if (LocalChanged)
+    if (LocalChanged) 
       dumpPassInfo(MP, MODIFICATION_MSG, ON_MODULE_MSG,
                    M.getModuleIdentifier());
     dumpPreservedSet(MP);
@@ -1646,7 +1700,7 @@
   Pass *FoundPass = nullptr;
   if (RequiredPassPI && RequiredPassPI->isAnalysis()) {
     FoundPass =
-      ((PMTopLevelManager*)FPP)->findAnalysisPass(RequiredPass->getPassID());
+        ((PMTopLevelManager*)FPP)->findAnalysisPass(RequiredPass->getPassID());
   }
   if (!FoundPass) {
     FoundPass = RequiredPass;
@@ -1902,4 +1956,4 @@
   BBP->add(this);
 }
 
-PassManagerBase::~PassManagerBase() {}
+PassManagerBase::~PassManagerBase() {}
\ No newline at end of file
Index: lib/IR/Module.cpp
===================================================================
--- lib/IR/Module.cpp
+++ lib/IR/Module.cpp
@@ -323,6 +323,13 @@
   return getOrInsertNamedMetadata("llvm.module.flags");
 }
 
+int Module::getModuleInstrCount() {
+  int IRCount = 0;
+  for (Function &F : FunctionList)
+      IRCount += F.getFunctionInstrCount();
+  return IRCount;
+}
+
 /// addModuleFlag - Add a module-level flag to the module-level flags
 /// metadata. It will create the module-level flags named metadata if it doesn't
 /// already exist.
Index: test/Other/size-remarks.ll
===================================================================
--- /dev/null
+++ test/Other/size-remarks.ll
@@ -0,0 +1,159 @@
+; Ensure that IR count remarks in the pass manager work for every type of
+; pass that we handle.
+
+; First, make sure remarks work for CGSCC passes.
+; RUN: opt < %s -inline -pass-remarks-analysis='size-info' -S 2>&1 \
+; RUN:     | FileCheck %s -check-prefix=CGSCC
+; CGSCC: remark: <unknown>:0:0: Function Integration/Inlining:
+; CGSCC-SAME: IR instruction count changed from 17 to 31; Delta: 14
+; RUN: opt < %s -inline -pass-remarks-analysis='size-info' -S \
+; RUN: -pass-remarks-output=%t.cgscc.yaml -o /dev/null 
+; RUN: cat %t.cgscc.yaml | FileCheck %s -check-prefix=CGSCC-YAML
+; CGSCC-YAML: --- !Analysis
+; CGSCC-YAML-NEXT: Pass:            size-info
+; CGSCC-YAML-NEXT: Name:            IRSizeChange
+; CGSCC-YAML-NEXT: Function:        baz
+; CGSCC-YAML-NEXT: Args:            
+; CGSCC-YAML-NEXT:  - Pass:            Function Integration/Inlining
+; CGSCC-YAML-NEXT:  - String:          ': IR instruction count changed from '
+; CGSCC-YAML-NEXT:  - IRInstrsBefore:  '17'
+; CGSCC-YAML-NEXT:  - String:          ' to '
+; CGSCC-YAML-NEXT:  - IRInstrsAfter:   '31'
+; CGSCC-YAML-NEXT:  - String:          '; Delta: '
+; CGSCC-YAML-NEXT:  - DeltaInstrCount: '14'
+
+; Next, make sure it works for function passes.
+; RUN: opt < %s -instcombine -pass-remarks-analysis='size-info' -S 2>&1 \
+; RUN:     | FileCheck %s -check-prefix=FUNC
+; FUNC: remark: <unknown>:0:0: Combine redundant instructions:
+; FUNC-SAME: IR instruction count changed from 17 to 16; Delta: -1
+; FUNC: remark: <unknown>:0:0: Combine redundant instructions:
+; FUNC-SAME: IR instruction count changed from 16 to 10; Delta: -6
+; FUNC: remark: <unknown>:0:0: Combine redundant instructions:
+; FUNC-SAME: IR instruction count changed from 10 to 6; Delta: -4
+; RUN: opt < %s -instcombine -pass-remarks-analysis='size-info' -S \
+; RUN: -pass-remarks-output=%t.func.yaml -o /dev/null 
+; RUN: cat %t.func.yaml | FileCheck %s -check-prefix=FUNC-YAML
+
+; FUNC-YAML: --- !Analysis
+; FUNC-YAML-NEXT: Pass:            size-info
+; FUNC-YAML-NEXT: Name:            IRSizeChange
+; FUNC-YAML-NEXT: Function:        baz
+; FUNC-YAML-NEXT: Args:            
+; FUNC-YAML-NEXT:  - Pass:            Combine redundant instructions
+; FUNC-YAML-NEXT:  - String:          ': IR instruction count changed from '
+; FUNC-YAML-NEXT:  - IRInstrsBefore:  '17'
+; FUNC-YAML-NEXT:  - String:          ' to '
+; FUNC-YAML-NEXT:  - IRInstrsAfter:   '16'
+; FUNC-YAML-NEXT:  - String:          '; Delta: '
+; FUNC-YAML-NEXT:  - DeltaInstrCount: '-1'
+
+; FUNC-YAML: --- !Analysis
+; FUNC-YAML-NEXT: Pass:            size-info
+; FUNC-YAML-NEXT: Name:            IRSizeChange
+; FUNC-YAML-NEXT: Function:        baz
+; FUNC-YAML-NEXT: Args:            
+; FUNC-YAML-NEXT:   - Pass:            Combine redundant instructions
+; FUNC-YAML-NEXT:   - String:          ': IR instruction count changed from '
+; FUNC-YAML-NEXT:   - IRInstrsBefore:  '16'
+; FUNC-YAML-NEXT:   - String:          ' to '
+; FUNC-YAML-NEXT:   - IRInstrsAfter:   '10'
+; FUNC-YAML-NEXT:   - String:          '; Delta: '
+; FUNC-YAML-NEXT:   - DeltaInstrCount: '-6'
+
+; FUNC-YAML: --- !Analysis
+; FUNC-YAML-NEXT: Pass:            size-info
+; FUNC-YAML-NEXT: Name:            IRSizeChange
+; FUNC-YAML-NEXT: Function:        baz
+; FUNC-YAML-NEXT: Args:            
+; FUNC-YAML-NEXT:  - Pass:            Combine redundant instructions
+; FUNC-YAML-NEXT:  - String:          ': IR instruction count changed from '
+; FUNC-YAML-NEXT:  - IRInstrsBefore:  '10'
+; FUNC-YAML-NEXT:  - String:          ' to '
+; FUNC-YAML-NEXT:  - IRInstrsAfter:   '6'
+; FUNC-YAML-NEXT:  - String:          '; Delta: '
+; FUNC-YAML-NEXT:  - DeltaInstrCount: '-4'
+
+; Make sure it works for module passes.
+; RUN: opt < %s -gvn -pass-remarks-analysis='size-info' -S 2>&1 \
+; RUN:     | FileCheck %s -check-prefix=MODULE
+; MODULE: remark: <unknown>:0:0: Global Value Numbering:
+; MODULE-SAME: IR instruction count changed from 17 to 15; Delta: -2
+; MODULE: remark: <unknown>:0:0: Global Value Numbering:
+; MODULE-SAME: IR instruction count changed from 15 to 13; Delta: -2
+; RUN: opt < %s -gvn -pass-remarks-analysis='size-info' -S \
+; RUN: -pass-remarks-output=%t.module.yaml -o /dev/null 
+; RUN: cat %t.module.yaml | FileCheck %s -check-prefix=MODULE-YAML
+; MODULE-YAML: --- !Analysis
+; MODULE-YAML-NEXT: Pass:            size-info
+; MODULE-YAML-NEXT: Name:            IRSizeChange
+; MODULE-YAML-NEXT: Function:        baz
+; MODULE-YAML-NEXT: Args:            
+; MODULE-YAML-NEXT:   - Pass:            Global Value Numbering
+; MODULE-YAML-NEXT:   - String:          ': IR instruction count changed from '
+; MODULE-YAML-NEXT:   - IRInstrsBefore:  '17'
+; MODULE-YAML-NEXT:   - String:          ' to '
+; MODULE-YAML-NEXT:   - IRInstrsAfter:   '15'
+; MODULE-YAML-NEXT:   - String:          '; Delta: '
+; MODULE-YAML-NEXT:   - DeltaInstrCount: '-2'
+; MODULE-YAML: --- !Analysis
+; MODULE-YAML-NEXT: Pass:            size-info
+; MODULE-YAML-NEXT: Name:            IRSizeChange
+; MODULE-YAML-NEXT: Function:        baz
+; MODULE-YAML-NEXT: Args:            
+; MODULE-YAML-NEXT:  - Pass:            Global Value Numbering
+; MODULE-YAML-NEXT:  - String:          ': IR instruction count changed from '
+; MODULE-YAML-NEXT:  - IRInstrsBefore:  '15'
+; MODULE-YAML-NEXT:  - String:          ' to '
+; MODULE-YAML-NEXT:  - IRInstrsAfter:   '13'
+; MODULE-YAML-NEXT:  - String:          '; Delta: '
+; MODULE-YAML-NEXT:  - DeltaInstrCount: '-2'
+
+; Make sure it works for basic block passes.
+; RUN: opt < %s -dce -pass-remarks-analysis='size-info' -S 2>&1 \
+; RUN:     | FileCheck %s -check-prefix=BB
+; BB: remark: <unknown>:0:0: Dead Code Elimination:
+; BB-SAME: IR instruction count changed from 17 to 16; Delta: -1
+; RUN: opt < %s -dce -pass-remarks-analysis='size-info' -S \
+; RUN: -pass-remarks-output=%t.bb.yaml -o /dev/null 
+; RUN: cat %t.bb.yaml | FileCheck %s -check-prefix=BB-YAML
+; BB-YAML: --- !Analysis
+; BB-YAML-NEXT: Pass:            size-info
+; BB-YAML-NEXT: Name:            IRSizeChange
+; BB-YAML-NEXT: Function:        baz
+; BB-YAML-NEXT: Args:            
+; BB-YAML-NEXT:   - Pass:            Dead Code Elimination
+; BB-YAML-NEXT:   - String:          ': IR instruction count changed from '
+; BB-YAML-NEXT:   - IRInstrsBefore:  '17'
+; BB-YAML-NEXT:   - String:          ' to '
+; BB-YAML-NEXT:   - IRInstrsAfter:   '16'
+; BB-YAML-NEXT:   - String:          '; Delta: '
+; BB-YAML-NEXT:   - DeltaInstrCount: '-1'
+
+define void @baz() #0 {
+  %x.addr = alloca i32, align 4
+  ret void
+}
+
+define i32 @foo(i32 %x, i32 %y) #0 {
+entry:
+  %x.addr = alloca i32, align 4
+  %y.addr = alloca i32, align 4
+  store i32 %x, i32* %x.addr, align 4
+  store i32 %y, i32* %y.addr, align 4
+  %0 = load i32, i32* %x.addr, align 4
+  %1 = load i32, i32* %y.addr, align 4
+  %add = add nsw i32 %0, %1
+  ret i32 %add
+}
+
+define i32 @bar(i32 %j) #0 {
+entry:
+  %j.addr = alloca i32, align 4
+  store i32 %j, i32* %j.addr, align 4
+  %0 = load i32, i32* %j.addr, align 4
+  %1 = load i32, i32* %j.addr, align 4
+  %sub = sub nsw i32 %1, 2
+  %call = call i32 @foo(i32 %0, i32 %sub)
+  ret i32 %call
+}
\ No newline at end of file