Index: include/llvm/IR/LegacyPassManagers.h =================================================================== --- include/llvm/IR/LegacyPassManagers.h +++ include/llvm/IR/LegacyPassManagers.h @@ -406,11 +406,23 @@ /// Set the initial size of the module if the user has specified that they /// want remarks for size. /// Returns 0 if the remark was not requested. - unsigned initSizeRemarkInfo(Module &M); - - /// Emit a remark signifying that the number of IR instructions in the module - /// changed. - void emitInstrCountChangedRemark(Pass *P, Module &M, unsigned CountBefore); + unsigned + initSizeRemarkInfo(Module &M, + StringMap> + &FunctionToInstrCount); + + /// Emits remarks reflecting changes in the IR count of \p M after the pass + /// \p P runs. Emits a remark for each change in function IR counts, recorded + /// in \p FunctionToInstrCount. + /// + /// \p FunctionToInstrCount maps the name of a \p Function to a pair. The + /// first member of the pair is the IR count of the \p Function before running + /// \p P, and the second member is the IR count of the \p Function after + /// running \p P. + void emitInstrCountChangedRemark( + Pass *P, Module &M, unsigned CountBefore, + StringMap> + &FunctionToInstrCount); protected: // Top level manager. Index: lib/Analysis/CallGraphSCCPass.cpp =================================================================== --- lib/Analysis/CallGraphSCCPass.cpp +++ lib/Analysis/CallGraphSCCPass.cpp @@ -132,16 +132,17 @@ { unsigned InstrCount = 0; + StringMap> FunctionToInstrCount; bool EmitICRemark = M.shouldEmitInstrCountChangedRemark(); TimeRegion PassTimer(getPassTimer(CGSP)); if (EmitICRemark) - InstrCount = initSizeRemarkInfo(M); + InstrCount = initSizeRemarkInfo(M, FunctionToInstrCount); Changed = CGSP->runOnSCC(CurSCC); // If the pass modified the module, it may have modified the instruction // count of the module. Try emitting a remark. if (EmitICRemark) - emitInstrCountChangedRemark(P, M, InstrCount); + emitInstrCountChangedRemark(P, M, InstrCount, FunctionToInstrCount); } // After the CGSCCPass is done, when assertions are enabled, use Index: lib/Analysis/LoopPass.cpp =================================================================== --- lib/Analysis/LoopPass.cpp +++ lib/Analysis/LoopPass.cpp @@ -195,6 +195,7 @@ // Walk Loops unsigned InstrCount = 0; + StringMap> FunctionToInstrCount; bool EmitICRemark = M.shouldEmitInstrCountChangedRemark(); while (!LQ.empty()) { CurrentLoopDeleted = false; @@ -214,10 +215,10 @@ PassManagerPrettyStackEntry X(P, *CurrentLoop->getHeader()); TimeRegion PassTimer(getPassTimer(P)); if (EmitICRemark) - InstrCount = initSizeRemarkInfo(M); + InstrCount = initSizeRemarkInfo(M, FunctionToInstrCount); Changed |= P->runOnLoop(CurrentLoop, *this); if (EmitICRemark) - emitInstrCountChangedRemark(P, M, InstrCount); + emitInstrCountChangedRemark(P, M, InstrCount, FunctionToInstrCount); } if (Changed) Index: lib/IR/LegacyPassManager.cpp =================================================================== --- lib/IR/LegacyPassManager.cpp +++ lib/IR/LegacyPassManager.cpp @@ -136,13 +136,31 @@ return PassDebugging >= Executions; } -unsigned PMDataManager::initSizeRemarkInfo(Module &M) { +unsigned PMDataManager::initSizeRemarkInfo( + Module &M, StringMap> &FunctionToInstrCount) { // Only calculate getInstructionCount if the size-info remark is requested. - return M.getInstructionCount(); + unsigned InstrCount = 0; + + // Collect instruction counts for every function. We'll use this to emit + // per-function size remarks later. + for (Function &F : M) { + unsigned FCount = F.getInstructionCount(); + + // Insert a record into FunctionToInstrCount keeping track of the current + // size of the function as the first member of a pair. Set the second + // member to 0; if the function is deleted by the pass, then when we get + // here, we'll be able to let the user know that F no longer contributes to + // the module. + FunctionToInstrCount[F.getName().str()] = + std::pair(FCount, 0); + InstrCount += FCount; + } + return InstrCount; } -void PMDataManager::emitInstrCountChangedRemark(Pass *P, Module &M, - unsigned CountBefore) { +void PMDataManager::emitInstrCountChangedRemark( + Pass *P, Module &M, unsigned CountBefore, + StringMap> &FunctionToInstrCount) { // We need a function containing at least one basic block in order to output // remarks. Since it's possible that the first function in the module doesn't // actually contain a basic block, we have to go and find one that's suitable @@ -155,10 +173,29 @@ return; // We found a function containing at least one basic block. - Function *F = &*It; - - // How many instructions are in the module now? - unsigned CountAfter = M.getInstructionCount(); + Function *SomeFunction = &*It; + + // Calculate the module instruction count and function instruction counts + // for after the pass ran. + unsigned CountAfter = 0; + for (Function &F : M) { + // Update the total module count. + unsigned FnSize = F.getInstructionCount(); + CountAfter += FnSize; + auto It = FunctionToInstrCount.find(F.getName()); + + // If we created a new function, then we need to add it to the map and say + // that it changed from 0 instructions to FnSize. + if (It == FunctionToInstrCount.end()) { + std::pair ChangePair(0, FnSize); + FunctionToInstrCount.insert( + std::make_pair(F.getName().str(), ChangePair)); + continue; + } + // Insert the new function size into the second member of the pair. This + // tells us whether or not this function changed in size. + It->second.second = FnSize; + } // If there was no change, don't emit a remark. if (CountBefore == CountAfter) @@ -176,7 +213,7 @@ int64_t Delta = static_cast(CountAfter) - static_cast(CountBefore); - BasicBlock &BB = *F->begin(); + BasicBlock &BB = *SomeFunction->begin(); OptimizationRemarkAnalysis R("size-info", "IRSizeChange", DiagnosticLocation(), &BB); // FIXME: Move ore namespace to DiagnosticInfo so that we can use it. This @@ -188,7 +225,40 @@ << DiagnosticInfoOptimizationBase::Argument("IRInstrsAfter", CountAfter) << "; Delta: " << DiagnosticInfoOptimizationBase::Argument("DeltaInstrCount", Delta); - F->getContext().diagnose(R); // Not using ORE for layering reasons. + SomeFunction->getContext().diagnose(R); // Not using ORE for layering reasons. + // Emit per-function size change remarks separately. + // FIXME: We shouldn't use BB for the location here. Unfortunately, because + // the function that we're looking at could have been deleted, we can't use + // it for the source location. We *want* remarks when a function is deleted + // though, so we're kind of stuck here as is. (This remark, along with the + // whole-module size change remarks really ought not to have source locations + // at all.) + for (auto &Fname : FunctionToInstrCount.keys()) { + OptimizationRemarkAnalysis FR("size-info", "FunctionIRSizeChange", + DiagnosticLocation(), &BB); + unsigned FnCountBefore, FnCountAfter; + std::tie(FnCountBefore, FnCountAfter) = FunctionToInstrCount[Fname]; + int64_t FnDelta = static_cast(FnCountAfter) - + static_cast(FnCountBefore); + + // If there was a change in the function, emit a remark. Otherwise, do + // nothing. + if (FnDelta != 0) { + FR << DiagnosticInfoOptimizationBase::Argument("Pass", P->getPassName()) + << ": Function: " + << DiagnosticInfoOptimizationBase::Argument("Function", Fname) + << ": IR instruction count changed from " + << DiagnosticInfoOptimizationBase::Argument("IRInstrsBefore", + FnCountBefore) + << " to " + << DiagnosticInfoOptimizationBase::Argument("IRInstrsAfter", + FnCountAfter) + << "; Delta: " + << DiagnosticInfoOptimizationBase::Argument("DeltaInstrCount", + FnDelta); + SomeFunction->getContext().diagnose(FR); + } + } } void PassManagerPrettyStackEntry::print(raw_ostream &OS) const { @@ -1288,6 +1358,8 @@ Module &M = *F.getParent(); unsigned InstrCount = 0; + StringMap> FunctionToInstrCount; + bool EmitICRemark = M.shouldEmitInstrCountChangedRemark(); for (BasicBlock &BB : F) for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { @@ -1304,10 +1376,10 @@ PassManagerPrettyStackEntry X(BP, BB); TimeRegion PassTimer(getPassTimer(BP)); if (EmitICRemark) - InstrCount = initSizeRemarkInfo(M); + InstrCount = initSizeRemarkInfo(M, FunctionToInstrCount); LocalChanged |= BP->runOnBasicBlock(BB); if (EmitICRemark) - emitInstrCountChangedRemark(BP, M, InstrCount); + emitInstrCountChangedRemark(BP, M, InstrCount, FunctionToInstrCount); } Changed |= LocalChanged; @@ -1511,6 +1583,7 @@ populateInheritedAnalysis(TPM->activeStack); unsigned InstrCount = 0; + StringMap> FunctionToInstrCount; bool EmitICRemark = M.shouldEmitInstrCountChangedRemark(); for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { FunctionPass *FP = getContainedPass(Index); @@ -1525,10 +1598,10 @@ PassManagerPrettyStackEntry X(FP, F); TimeRegion PassTimer(getPassTimer(FP)); if (EmitICRemark) - InstrCount = initSizeRemarkInfo(M); + InstrCount = initSizeRemarkInfo(M, FunctionToInstrCount); LocalChanged |= FP->runOnFunction(F); if (EmitICRemark) - emitInstrCountChangedRemark(FP, M, InstrCount); + emitInstrCountChangedRemark(FP, M, InstrCount, FunctionToInstrCount); } Changed |= LocalChanged; @@ -1593,6 +1666,7 @@ Changed |= getContainedPass(Index)->doInitialization(M); unsigned InstrCount = 0; + StringMap> FunctionToInstrCount; bool EmitICRemark = M.shouldEmitInstrCountChangedRemark(); for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { ModulePass *MP = getContainedPass(Index); @@ -1608,10 +1682,10 @@ TimeRegion PassTimer(getPassTimer(MP)); if (EmitICRemark) - InstrCount = initSizeRemarkInfo(M); + InstrCount = initSizeRemarkInfo(M, FunctionToInstrCount); LocalChanged |= MP->runOnModule(M); if (EmitICRemark) - emitInstrCountChangedRemark(MP, M, InstrCount); + emitInstrCountChangedRemark(MP, M, InstrCount, FunctionToInstrCount); } Changed |= LocalChanged; Index: test/Other/size-remarks.ll =================================================================== --- test/Other/size-remarks.ll +++ test/Other/size-remarks.ll @@ -1,6 +1,8 @@ ; Ensure that IR count remarks in the legacy pass manager work. ; What this test should check for: -; * Positive, nonzero sizes before/after +; * Positive, nonzero sizes before/after for whole-module remarks +; (It's okay to have nonzero sizes in per-function remarks, since a function +; can be created/destroyed by a pass.) ; * Nonzero deltas ; * Sizes are being tracked properly across multiple remarks. E.g, if we have ; original_count_1, final_count_1, and @@ -20,11 +22,16 @@ ; CGSCC-SAME: IR instruction count changed from ; CGSCC-SAME: [[ORIG:[1-9][0-9]*]] to [[FINAL:[1-9][0-9]*]]; ; CGSCC-SAME: Delta: [[DELTA:-?[1-9][0-9]*]] +; CGSCC-NEXT: remark: :0:0: Function Integration/Inlining: +; CGSCC-SAME: Function: bar: IR instruction count changed from +; CGSCC-SAME: [[ORIGFN:[1-9][0-9]*]] to [[FINALFN:[0-9][0-9]*]]; +; CGSCC-SAME: Delta: [[DELTAFN:-?[1-9][0-9]*]] + ; CGSCC: --- !Analysis ; CGSCC-NEXT: Pass: size-info ; CGSCC-NEXT: Name: IRSizeChange ; CGSCC-NEXT: Function: -; CGSCC-NEXT: Args: +; CGSCC-NEXT: Args: ; CGSCC-NEXT: - Pass: Function Integration/Inlining ; CGSCC-NEXT: - String: ': IR instruction count changed from ' ; CGSCC-NEXT: - IRInstrsBefore: '[[ORIG]]' @@ -32,23 +39,46 @@ ; CGSCC-NEXT: - IRInstrsAfter: '[[FINAL]]' ; CGSCC-NEXT: - String: '; Delta: ' ; CGSCC-NEXT: - DeltaInstrCount: '[[DELTA]]' +; CGSCC-DAG: --- !Analysis +; CGSCC-NEXT: Pass: size-info +; CGSCC-NEXT: Name: FunctionIRSizeChange +; CGSCC-NEXT: Function: +; CGSCC-NEXT: Args: +; CGSCC-NEXT: - Pass: Function Integration/Inlining +; CGSCC-NEXT: - String: ': Function: ' +; CGSCC-NEXT: - Function: bar +; CGSCC-NEXT: - String: ': IR instruction count changed from ' +; CGSCC-NEXT: - IRInstrsBefore: '[[ORIGFN]]' +; CGSCC-NEXT: - String: ' to ' +; CGSCC-NEXT: - IRInstrsAfter: '[[FINALFN]]' +; CGSCC-NEXT: - String: '; Delta: ' +; CGSCC-NEXT: - DeltaInstrCount: '[[DELTAFN]]' +; CGSCC-NEXT: ... ; RUN: opt < %s -instcombine -pass-remarks-analysis='size-info' \ ; RUN:-pass-remarks-output=%t.yaml -S -o /dev/null 2> %t; \ ; RUN: cat %t %t.yaml | FileCheck %s -check-prefix=FUNC ; FUNC: remark: :0:0: Combine redundant instructions: ; FUNC-SAME: IR instruction count changed from -; FUNC-SAME: [[SIZE1:[1-9][0-9]*]] to [[SIZE2:[1-9][0-9]*]]; +; FUNC-SAME: [[SIZE1:[1-9][0-9]*]] to [[SIZE2:[0-9][0-9]*]]; ; FUNC-SAME: Delta: [[DELTA1:-?[1-9][0-9]*]] +; FUNC-NEXT: remark: :0:0: Combine redundant instructions: Function: +; FUNC-SAME: foo: IR instruction count changed from +; FUNC-SAME: [[FOOSIZE1:[1-9][0-9]*]] to [[FOOSIZE2:[0-9][0-9]*]]; +; FUNC-SAME: Delta: [[DELTAFOO:-?[1-9][0-9]*]] ; FUNC-NEXT: remark: :0:0: Combine redundant instructions: ; FUNC-SAME: IR instruction count changed from ; FUNC-SAME: [[SIZE2]] to [[SIZE3:[1-9][0-9]*]]; ; FUNC-SAME: Delta: [[DELTA2:-?[1-9][0-9]*]] +; FUNC-NEXT: remark: :0:0: Combine redundant instructions: Function: +; FUNC-SAME: bar: IR instruction count changed from +; FUNC-SAME: [[BARSIZE1:[1-9][0-9]*]] to [[BARSIZE2:[0-9][0-9]*]]; +; FUNC-SAME: Delta: [[DELTABAR:-?[1-9][0-9]*]] ; FUNC: --- !Analysis ; FUNC-NEXT: Pass: size-info ; FUNC-NEXT: Name: IRSizeChange ; FUNC-NEXT: Function: -; FUNC-NEXT: Args: +; FUNC-NEXT: Args: ; FUNC-NEXT: - Pass: Combine redundant instructions ; FUNC-NEXT: - String: ': IR instruction count changed from ' ; FUNC-NEXT: - IRInstrsBefore: '[[SIZE1]]' @@ -56,11 +86,25 @@ ; FUNC-NEXT: - IRInstrsAfter: '[[SIZE2]]' ; FUNC-NEXT: - String: '; Delta: ' ; FUNC-NEXT: - DeltaInstrCount: '[[DELTA1]]' +; FUNC-DAG: --- !Analysis +; FUNC-NEXT: Pass: size-info +; FUNC-NEXT: Name: FunctionIRSizeChange +; FUNC-NEXT: Function: +; FUNC-NEXT: Args: +; FUNC-NEXT: - Pass: Combine redundant instructions +; FUNC-NEXT: - String: ': Function: ' +; FUNC-NEXT: - Function: foo +; FUNC-NEXT: - String: ': IR instruction count changed from ' +; FUNC-NEXT: - IRInstrsBefore: '[[FOOSIZE1]]' +; FUNC-NEXT: - String: ' to ' +; FUNC-NEXT: - IRInstrsAfter: '[[FOOSIZE2]]' +; FUNC-NEXT: - String: '; Delta: ' +; FUNC-NEXT: - DeltaInstrCount: '[[DELTAFOO]]' ; FUNC: --- !Analysis ; FUNC-NEXT: Pass: size-info ; FUNC-NEXT: Name: IRSizeChange ; FUNC-NEXT: Function: -; FUNC-NEXT: Args: +; FUNC-NEXT: Args: ; FUNC-NEXT: - Pass: Combine redundant instructions ; FUNC-NEXT: - String: ': IR instruction count changed from ' ; FUNC-NEXT: - IRInstrsBefore: '[[SIZE2]]' @@ -68,6 +112,20 @@ ; FUNC-NEXT: - IRInstrsAfter: '[[SIZE3]]' ; FUNC-NEXT: - String: '; Delta: ' ; FUNC-NEXT: - DeltaInstrCount: '[[DELTA2]]' +; FUNC-DAG: --- !Analysis +; FUNC-NEXT: Pass: size-info +; FUNC-NEXT: Name: FunctionIRSizeChange +; FUNC-NEXT: Function: +; FUNC-NEXT: Args: +; FUNC-NEXT: - Pass: Combine redundant instructions +; FUNC-NEXT: - String: ': Function: ' +; FUNC-NEXT: - Function: bar +; FUNC-NEXT: - String: ': IR instruction count changed from ' +; FUNC-NEXT: - IRInstrsBefore: '[[BARSIZE1]]' +; FUNC-NEXT: - String: ' to ' +; FUNC-NEXT: - IRInstrsAfter: '[[BARSIZE2]]' +; FUNC-NEXT: - String: '; Delta: ' +; FUNC-NEXT: - DeltaInstrCount: '[[DELTABAR]]' ; RUN: opt < %s -globaldce -pass-remarks-analysis='size-info' \ ; RUN: -pass-remarks-output=%t.yaml -S -o /dev/null 2> %t; \ @@ -77,11 +135,15 @@ ; MODULE-SAME: IR instruction count changed from ; MODULE-SAME: [[ORIG:[1-9][0-9]*]] to [[FINAL:[1-9][0-9]*]]; ; MODULE-SAME: Delta: [[DELTA:-?[1-9][0-9]*]] +; MODULE-NEXT: remark: +; MODULE-SAME: Dead Global Elimination: Function: pluto: +; MODULE-SAME: IR instruction count changed from [[ORIGFN:[1-9][0-9]*]] to +; MODULE-SAME: [[FINALFN:[0-9][0-9]*]]; Delta: [[DELTAFN:-?[1-9][0-9]*]] ; MODULE: --- !Analysis ; MODULE-NEXT: Pass: size-info ; MODULE-NEXT: Name: IRSizeChange ; MODULE-NEXT: Function: -; MODULE-NEXT: Args: +; MODULE-NEXT: Args: ; MODULE-NEXT: - Pass: Dead Global Elimination ; MODULE-NEXT: - String: ': IR instruction count changed from ' ; MODULE-NEXT: - IRInstrsBefore: '[[ORIG]]' @@ -89,6 +151,20 @@ ; MODULE-NEXT: - IRInstrsAfter: '[[FINAL]]' ; MODULE-NEXT: - String: '; Delta: ' ; MODULE-NEXT: - DeltaInstrCount: '[[DELTA]]' +; MODULE-DAG: --- !Analysis +; MODULE-NEXT: Pass: size-info +; MODULE-NEXT: Name: FunctionIRSizeChange +; MODULE-NEXT: Function: +; MODULE-NEXT: Args: +; MODULE-NEXT: - Pass: Dead Global Elimination +; MODULE-NEXT: - String: ': Function: ' +; MODULE-NEXT: - Function: pluto +; MODULE-NEXT: - String: ': IR instruction count changed from ' +; MODULE-NEXT: - IRInstrsBefore: '[[ORIGFN]]' +; MODULE-NEXT: - String: ' to ' +; MODULE-NEXT: - IRInstrsAfter: '[[FINALFN]]' +; MODULE-NEXT: - String: '; Delta: ' +; MODULE-NEXT: - DeltaInstrCount: '[[DELTAFN]]' ; RUN: opt < %s -dce -pass-remarks-analysis='size-info' \ ; RUN: -pass-remarks-output=%t.yaml -S -o /dev/null 2> %t; \ @@ -97,6 +173,9 @@ ; BB-SAME: IR instruction count changed from ; BB-SAME: [[ORIG:[1-9][0-9]*]] to [[FINAL:[1-9][0-9]*]]; ; BB-SAME: Delta: [[DELTA:-?[1-9][0-9]*]] +; BB-NEXT: remark: :0:0: Dead Code Elimination: Function: bar: +; BB-SAME: IR instruction count changed from [[ORIGFN:[1-9][0-9]*]] to +; BB-SAME: [[FINALFN:[0-9][0-9]*]]; Delta: [[DELTAFN:-?[1-9][0-9]*]] ; BB: --- !Analysis ; BB-NEXT: Pass: size-info ; BB-NEXT: Name: IRSizeChange @@ -109,6 +188,20 @@ ; BB-NEXT: - IRInstrsAfter: '[[FINAL]]' ; BB-NEXT: - String: '; Delta: ' ; BB-NEXT: - DeltaInstrCount: '[[DELTA]]' +; BB-DAG: --- !Analysis +; BB-NEXT: Pass: size-info +; BB-NEXT: Name: FunctionIRSizeChange +; BB-NEXT: Function: +; BB-NEXT: Args: +; BB-NEXT: - Pass: Dead Code Elimination +; BB-NEXT: - String: ': Function: ' +; BB-NEXT: - Function: bar +; BB-NEXT: - String: ': IR instruction count changed from ' +; BB-NEXT: - IRInstrsBefore: '[[ORIGFN]]' +; BB-NEXT: - String: ' to ' +; BB-NEXT: - IRInstrsAfter: '[[FINALFN]]' +; BB-NEXT: - String: '; Delta: ' +; BB-NEXT: - DeltaInstrCount: '[[DELTAFN]]' ; RUN: opt < %s -loop-unroll -pass-remarks-analysis='size-info' \ ; RUN: -pass-remarks-output=%t.yaml -S -o /dev/null 2> %t; \ @@ -117,11 +210,17 @@ ; LOOP-SAME: IR instruction count changed from ; LOOP-SAME: [[ORIG:[1-9][0-9]*]] to [[FINAL:[1-9][0-9]*]]; ; LOOP-SAME: Delta: [[DELTA:-?[1-9][0-9]*]] +; LOOP-NEXT: remark: :0:0: Unroll loops: Function: bar: +; LOOP-SAME: IR instruction count changed from [[ORIGFN:[1-9][0-9]*]] +; LOOP-SAME: to [[FINALFN:[0-9][0-9]*]]; +; Since bar is the only function containing a loop, its delta must be identical +; to the whole module remark's delta. +; LOOP-SAME: Delta: [[DELTA]] ; LOOP: --- !Analysis ; LOOP-NEXT: Pass: size-info ; LOOP-NEXT: Name: IRSizeChange ; LOOP-NEXT: Function: -; LOOP-NEXT: Args: +; LOOP-NEXT: Args: ; LOOP-DAG: - Pass: Unroll loops ; LOOP-NEXT: - String: ': IR instruction count changed from ' ; LOOP-NEXT: - IRInstrsBefore: '[[ORIG]]' @@ -129,6 +228,20 @@ ; LOOP-NEXT: - IRInstrsAfter: '[[FINAL]]' ; LOOP-NEXT: - String: '; Delta: ' ; LOOP-NEXT: - DeltaInstrCount: '[[DELTA]]' +; LOOP-DAG: --- !Analysis +; LOOP-NEXT: Pass: size-info +; LOOP-NEXT: Name: FunctionIRSizeChange +; LOOP-NEXT: Function: +; LOOP-NEXT: Args: +; LOOP-NEXT: - Pass: Unroll loops +; LOOP-NEXT: - String: ': Function: ' +; LOOP-NEXT: - Function: bar +; LOOP-NEXT: - String: ': IR instruction count changed from ' +; LOOP-NEXT: - IRInstrsBefore: '[[ORIGFN]]' +; LOOP-NEXT: - String: ' to ' +; LOOP-NEXT: - IRInstrsAfter: '[[FINALFN]]' +; LOOP-NEXT: - String: '; Delta: ' +; LOOP-NEXT: - DeltaInstrCount: '[[DELTA]]' declare i1 ()* @boop() define internal i1 @pluto() {