diff --git a/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h b/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h index 1619671d8f7d..aa3e20c914ab 100644 --- a/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h +++ b/llvm/include/llvm/Analysis/FunctionPropertiesAnalysis.h @@ -185,8 +185,14 @@ public: }; /// Statistics pass for the FunctionPropertiesAnalysis results. -struct FunctionPropertiesStatisticsPass - : PassInfoMixin { +class FunctionPropertiesStatisticsPass + : public PassInfoMixin { + bool IsPreOptimization; + +public: + explicit FunctionPropertiesStatisticsPass(bool IsPreOptimization = false) + : IsPreOptimization(IsPreOptimization) {} + PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM); }; diff --git a/llvm/include/llvm/Analysis/InstCount.h b/llvm/include/llvm/Analysis/InstCount.h index e5ce822caf6e..4a19dbad5751 100644 --- a/llvm/include/llvm/Analysis/InstCount.h +++ b/llvm/include/llvm/Analysis/InstCount.h @@ -19,8 +19,14 @@ namespace llvm { class Function; -struct InstCountPass : PassInfoMixin { - PreservedAnalyses run(Function &F, FunctionAnalysisManager &); +class InstCountPass : public PassInfoMixin { + bool IsPreOptimization; + +public: + explicit InstCountPass(bool IsPreOptimization = false) + : IsPreOptimization(IsPreOptimization) {} + + PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM); }; } // end namespace llvm diff --git a/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp b/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp index 4a66d8835281..21eeb05a9041 100644 --- a/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp +++ b/llvm/lib/Analysis/FunctionPropertiesAnalysis.cpp @@ -29,8 +29,13 @@ using namespace llvm; #define DEBUG_TYPE "func-properties-stats" -#define FUNCTION_PROPERTY(Name, Description) STATISTIC(Num##Name, Description); +#define FUNCTION_PROPERTY(Name, Description) \ + STATISTIC(Num##Name##PreOptimization, \ + Description " (before optimizations)"); \ + STATISTIC(Num##Name, Description); #define DETAILED_FUNCTION_PROPERTY(Name, Description) \ + STATISTIC(Num##Name##PreOptimization, \ + Description " (before optimizations)"); \ STATISTIC(Num##Name, Description); #include "llvm/IR/FunctionProperties.def" @@ -378,11 +383,22 @@ FunctionPropertiesStatisticsPass::run(Function &F, LLVM_DEBUG(dbgs() << "STATSCOUNT: running on function " << F.getName() << "\n"); auto &AnalysisResults = FAM.getResult(F); - + if (IsPreOptimization) { +#define FUNCTION_PROPERTY(Name, Description) \ + Num##Name##PreOptimization += AnalysisResults.Name; +#define DETAILED_FUNCTION_PROPERTY(Name, Description) \ + Num##Name##PreOptimization += AnalysisResults.Name; +#include "llvm/IR/FunctionProperties.def" +#undef FUNCTION_PROPERTY +#undef DETAILED_FUNCTION_PROPERTY + } else { #define FUNCTION_PROPERTY(Name, Description) Num##Name += AnalysisResults.Name; #define DETAILED_FUNCTION_PROPERTY(Name, Description) \ Num##Name += AnalysisResults.Name; #include "llvm/IR/FunctionProperties.def" +#undef FUNCTION_PROPERTY +#undef DETAILED_FUNCTION_PROPERTY + } return PreservedAnalyses::all(); } diff --git a/llvm/lib/Analysis/InstCount.cpp b/llvm/lib/Analysis/InstCount.cpp index 7a797767f97c..34a200dd879d 100644 --- a/llvm/lib/Analysis/InstCount.cpp +++ b/llvm/lib/Analysis/InstCount.cpp @@ -21,15 +21,29 @@ using namespace llvm; #define DEBUG_TYPE "instcount" -STATISTIC(TotalInsts, "Number of instructions (of all types)"); +STATISTIC(TotalInstsPreOptimization, + "Number of instructions of all types (before optimizations)"); +STATISTIC(TotalInsts, "Number of instructions of all types"); +STATISTIC(TotalBlocksPreOptimization, + "Number of basic blocks (before optimizations)"); STATISTIC(TotalBlocks, "Number of basic blocks"); +STATISTIC(TotalFuncsPreOptimization, + "Number of non-external functions (before optimizations)"); STATISTIC(TotalFuncs, "Number of non-external functions"); +STATISTIC(LargestFunctionSizePreOptimization, + "Largest number of instructions in a single function (before " + "optimizations)"); STATISTIC(LargestFunctionSize, "Largest number of instructions in a single function"); +STATISTIC(LargestFunctionBBCountPreOptimization, + "Largest number of basic blocks in a single function (before " + "optimizations)"); STATISTIC(LargestFunctionBBCount, "Largest number of basic blocks in a single function"); #define HANDLE_INST(N, OPCODE, CLASS) \ + STATISTIC(Num##OPCODE##InstPreOptimization, \ + "Number of " #OPCODE " insts (before optimizations)"); \ STATISTIC(Num##OPCODE##Inst, "Number of " #OPCODE " insts"); #include "llvm/IR/Instruction.def" @@ -37,18 +51,39 @@ STATISTIC(LargestFunctionBBCount, namespace { class InstCount : public InstVisitor { friend class InstVisitor; + bool IsPreOptimization; + +public: + InstCount(bool IsPreOptimization) : IsPreOptimization(IsPreOptimization) {} void visitFunction(Function &F) { - ++TotalFuncs; - LargestFunctionSize.updateMax(F.getInstructionCount()); - LargestFunctionBBCount.updateMax(F.size()); + if (IsPreOptimization) { + ++TotalFuncsPreOptimization; + LargestFunctionSizePreOptimization.updateMax(F.getInstructionCount()); + LargestFunctionBBCountPreOptimization.updateMax(F.size()); + } else { + ++TotalFuncs; + LargestFunctionSize.updateMax(F.getInstructionCount()); + LargestFunctionBBCount.updateMax(F.size()); + } + } + + void visitBasicBlock(BasicBlock &BB) { + if (IsPreOptimization) + ++TotalBlocksPreOptimization; + else + ++TotalBlocks; } - void visitBasicBlock(BasicBlock &BB) { ++TotalBlocks; } #define HANDLE_INST(N, OPCODE, CLASS) \ void visit##OPCODE(CLASS &) { \ - ++Num##OPCODE##Inst; \ - ++TotalInsts; \ + if (IsPreOptimization) { \ + ++Num##OPCODE##InstPreOptimization; \ + ++TotalInstsPreOptimization; \ + } else { \ + ++Num##OPCODE##Inst; \ + ++TotalInsts; \ + } \ } #include "llvm/IR/Instruction.def" @@ -64,7 +99,7 @@ PreservedAnalyses InstCountPass::run(Function &F, FunctionAnalysisManager &FAM) { LLVM_DEBUG(dbgs() << "INSTCOUNT: running on function " << F.getName() << "\n"); - InstCount().visit(F); + InstCount(this->IsPreOptimization).visit(F); return PreservedAnalyses::all(); } diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index e1a04186967f..715f4d2c0abc 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -806,6 +806,17 @@ Expected parseLintOptions(StringRef Params) { "LintPass"); } +/// Parser of parameters for FunctionPropertiesStatistics pass. +Expected parseFunctionPropertiesStatisticsOptions(StringRef Params) { + return PassBuilder::parseSinglePassOption(Params, "pre-opt", + "FunctionPropertiesStatisticsPass"); +} + +/// Parser of parameters for InstCount pass. +Expected parseInstCountOptions(StringRef Params) { + return PassBuilder::parseSinglePassOption(Params, "pre-opt", "InstCountPass"); +} + /// Parser of parameters for LoopUnroll pass. Expected parseLoopUnrollOptions(StringRef Params) { LoopUnrollOptions UnrollOpts; diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index 6f7ace93b78e..f017419791a8 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -413,15 +413,19 @@ void PassBuilder::invokePipelineEarlySimplificationEPCallbacks( C(MPM, Level, Phase); } +// Get IR stats with InstCount and FunctionPropertiesAnalysis. +static void instructionCountersPass(ModulePassManager &MPM, + bool IsPreOptimization) { + if (AreStatisticsEnabled()) { + MPM.addPass( + createModuleToFunctionPassAdaptor(InstCountPass(IsPreOptimization))); + MPM.addPass(createModuleToFunctionPassAdaptor( + FunctionPropertiesStatisticsPass(IsPreOptimization))); + } +} // Helper to add AnnotationRemarksPass. static void addAnnotationRemarksPass(ModulePassManager &MPM) { MPM.addPass(createModuleToFunctionPassAdaptor(AnnotationRemarksPass())); - // Count the stats for InstCount and FunctionPropertiesAnalysis - if (AreStatisticsEnabled()) { - MPM.addPass(createModuleToFunctionPassAdaptor(InstCountPass())); - MPM.addPass( - createModuleToFunctionPassAdaptor(FunctionPropertiesStatisticsPass())); - } } // Helper to check if the current compilation phase is preparing for LTO @@ -1712,6 +1716,7 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level, return buildO0DefaultPipeline(Level, Phase); ModulePassManager MPM; + instructionCountersPass(MPM, /*IsPreOptimization=*/true); // Currently this pipeline is only invoked in an LTO pre link pass or when we // are not running LTO. If that changes the below checks may need updating. @@ -1750,6 +1755,9 @@ PassBuilder::buildPerModuleDefaultPipeline(OptimizationLevel Level, if (isLTOPreLink(Phase)) addRequiredLTOPreLinkPasses(MPM); + + instructionCountersPass(MPM, /*IsPreOptimization=*/false); + return MPM; } @@ -1757,6 +1765,9 @@ ModulePassManager PassBuilder::buildFatLTODefaultPipeline(OptimizationLevel Level, bool ThinLTO, bool EmitSummary) { ModulePassManager MPM; + + instructionCountersPass(MPM, /*IsPreOptimization=*/true); + if (ThinLTO) MPM.addPass(buildThinLTOPreLinkDefaultPipeline(Level)); else @@ -1799,6 +1810,9 @@ PassBuilder::buildFatLTODefaultPipeline(OptimizationLevel Level, bool ThinLTO, // Emit annotation remarks. addAnnotationRemarksPass(MPM); } + + instructionCountersPass(MPM, /*IsPreOptimization=*/false); + return MPM; } @@ -1809,6 +1823,8 @@ PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) { ModulePassManager MPM; + instructionCountersPass(MPM, /*IsPreOptimization=*/true); + // Convert @llvm.global.annotations to !annotation metadata. MPM.addPass(Annotation2MetadataPass()); @@ -1861,6 +1877,8 @@ PassBuilder::buildThinLTOPreLinkDefaultPipeline(OptimizationLevel Level) { addRequiredLTOPreLinkPasses(MPM); + instructionCountersPass(MPM, /*IsPreOptimization=*/false); + return MPM; } @@ -1868,6 +1886,8 @@ ModulePassManager PassBuilder::buildThinLTODefaultPipeline( OptimizationLevel Level, const ModuleSummaryIndex *ImportSummary) { ModulePassManager MPM; + instructionCountersPass(MPM, /*IsPreOptimization=*/true); + // If we are invoking this without a summary index noting that we are linking // with a library containing the necessary APIs, remove any MemProf related // attributes and metadata. @@ -1916,6 +1936,8 @@ ModulePassManager PassBuilder::buildThinLTODefaultPipeline( // globals in the object file. MPM.addPass(EliminateAvailableExternallyPass()); MPM.addPass(GlobalDCEPass()); + + instructionCountersPass(MPM, /*IsPreOptimization=*/false); return MPM; } if (!UseCtxProfile.empty()) { @@ -1933,6 +1955,8 @@ ModulePassManager PassBuilder::buildThinLTODefaultPipeline( // Emit annotation remarks. addAnnotationRemarksPass(MPM); + instructionCountersPass(MPM, /*IsPreOptimization=*/false); + return MPM; } @@ -1948,6 +1972,8 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, ModuleSummaryIndex *ExportSummary) { ModulePassManager MPM; + instructionCountersPass(MPM, /*IsPreOptimization=*/true); + invokeFullLinkTimeOptimizationEarlyEPCallbacks(MPM, Level); // If we are invoking this without a summary index noting that we are linking @@ -2308,6 +2334,8 @@ PassBuilder::buildLTODefaultPipeline(OptimizationLevel Level, // Emit annotation remarks. addAnnotationRemarksPass(MPM); + instructionCountersPass(MPM, /*IsPreOptimization=*/false); + return MPM; } @@ -2319,6 +2347,8 @@ PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level, ModulePassManager MPM; + instructionCountersPass(MPM, /*IsPreOptimization=*/true); + // Perform pseudo probe instrumentation in O0 mode. This is for the // consistency between different build modes. For example, a LTO build can be // mixed with an O0 prelink and an O2 postlink. Loading a sample profile in @@ -2432,6 +2462,8 @@ PassBuilder::buildO0DefaultPipeline(OptimizationLevel Level, // Emit annotation remarks. addAnnotationRemarksPass(MPM); + instructionCountersPass(MPM, /*IsPreOptimization=*/false); + return MPM; } diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index c92d93d7ae39..9fe40d441e0a 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -440,7 +440,6 @@ FUNCTION_PASS("fix-irreducible", FixIrreduciblePass()) FUNCTION_PASS("flatten-cfg", FlattenCFGPass()) FUNCTION_PASS("float2int", Float2IntPass()) FUNCTION_PASS("free-machine-function", FreeMachineFunctionPass()) -FUNCTION_PASS("func-properties-stats", FunctionPropertiesStatisticsPass()) FUNCTION_PASS("gc-lowering", GCLoweringPass()) FUNCTION_PASS("guard-widening", GuardWideningPass()) FUNCTION_PASS("gvn-hoist", GVNHoistPass()) @@ -451,7 +450,6 @@ FUNCTION_PASS("infer-address-spaces", InferAddressSpacesPass()) FUNCTION_PASS("infer-alignment", InferAlignmentPass()) FUNCTION_PASS("inject-tli-mappings", InjectTLIMappings()) FUNCTION_PASS("inline-asm-prepare", InlineAsmPreparePass()) -FUNCTION_PASS("instcount", InstCountPass()) FUNCTION_PASS("instnamer", InstructionNamerPass()) FUNCTION_PASS("instsimplify", InstSimplifyPass()) FUNCTION_PASS("interleaved-access", InterleavedAccessPass(*TM)) @@ -589,6 +587,13 @@ FUNCTION_PASS_WITH_PARAMS( "ee-instrument", "EntryExitInstrumenterPass", [](bool PostInlining) { return EntryExitInstrumenterPass(PostInlining); }, parseEntryExitInstrumenterPassOptions, "post-inline") +FUNCTION_PASS_WITH_PARAMS( + "func-properties-stats", + "FunctionPropertiesStatisticsPass", + [](bool IsPreOptimizations) { + return FunctionPropertiesStatisticsPass(IsPreOptimizations); + }, + parseFunctionPropertiesStatisticsOptions, "pre-opt") FUNCTION_PASS_WITH_PARAMS( "function-simplification", "", [this](OptimizationLevel OL) { @@ -612,6 +617,12 @@ FUNCTION_PASS_WITH_PARAMS( [](InstCombineOptions Opts) { return InstCombinePass(Opts); }, parseInstCombineOptions, "no-verify-fixpoint;verify-fixpoint;max-iterations=N") +FUNCTION_PASS_WITH_PARAMS( + "instcount", "InstCountPass", + [](bool IsPreOptimizations) { + return InstCountPass(IsPreOptimizations); + }, + parseInstCountOptions, "pre-opt") FUNCTION_PASS_WITH_PARAMS( "lint", "LintPass", [](bool AbortOnError) { return LintPass(AbortOnError); }, parseLintOptions, diff --git a/llvm/test/Analysis/FunctionPropertiesAnalysis/properties-stats.ll b/llvm/test/Analysis/FunctionPropertiesAnalysis/function-properties-analysis.ll similarity index 70% rename from llvm/test/Analysis/FunctionPropertiesAnalysis/properties-stats.ll rename to llvm/test/Analysis/FunctionPropertiesAnalysis/function-properties-analysis.ll index f7907c73728a..555d73c82b50 100644 --- a/llvm/test/Analysis/FunctionPropertiesAnalysis/properties-stats.ll +++ b/llvm/test/Analysis/FunctionPropertiesAnalysis/function-properties-analysis.ll @@ -1,11 +1,5 @@ -; Testing with all of the below run lines that the pass gets added to the appropriate pipelines ; REQUIRES: asserts ; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes=func-properties-stats < %s 2>&1 | FileCheck %s -; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes='thinlto' < %s 2>&1 | FileCheck %s -; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes='thinlto-pre-link' < %s 2>&1 | FileCheck %s -; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes='lto' < %s 2>&1 | FileCheck %s -; RUN: opt -stats -enable-detailed-function-properties -disable-output -O3 < %s 2>&1 | FileCheck %s -; RUN: opt -stats -enable-detailed-function-properties -disable-output -O0 < %s 2>&1 | FileCheck %s ; CHECK-DAG: 10 func-properties-stats - Number of basic blocks ; CHECK-DAG: 8 func-properties-stats - Number of branch instructions @@ -17,7 +11,6 @@ ; CHECK-DAG: 1 func-properties-stats - Number of switch instructions ; CHECK-DAG: 4 func-properties-stats - Number of switch successors - define void @foo(i32 %i, i32 %j, i32 %n) { entry: %cmp = icmp slt i32 %i, %j diff --git a/llvm/test/Analysis/FunctionPropertiesAnalysis/pipeline.ll b/llvm/test/Analysis/FunctionPropertiesAnalysis/pipeline.ll new file mode 100644 index 000000000000..5ed52f5bf982 --- /dev/null +++ b/llvm/test/Analysis/FunctionPropertiesAnalysis/pipeline.ll @@ -0,0 +1,41 @@ +; REQUIRES: asserts +; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes='func-properties-stats' < %s 2>&1 | FileCheck %s --check-prefix=PRE +; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes='func-properties-stats' < %s 2>&1 | FileCheck %s --check-prefixes=POSTNOOPT +; RUN: opt -stats -enable-detailed-function-properties -disable-output -O0 < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POSTNOOPT +; RUN: opt -stats -enable-detailed-function-properties -disable-output -O3 < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POST +; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes='lto' < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POST +; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes='lto-pre-link' < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POST +; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes='lto-pre-link' < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POST +; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes='thinlto' < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POST +; RUN: opt -stats -enable-detailed-function-properties -disable-output -passes='thinlto-pre-link' < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POST + +; --- --- +; PRE-DAG: 4 func-properties-stats - Number of basic blocks (before optimizations) +; PRE-DAG: 5 func-properties-stats - Number of instructions (of all types) (before optimizations) +; PRE-DAG: 4 func-properties-stats - Number of basic block successors (before optimizations) + +; --- No in pass but no optimization passes run --- +; POSTNOOPT-DAG: 4 func-properties-stats - Number of basic blocks +; POSTNOOPT-DAG: 5 func-properties-stats - Number of instructions (of all types) +; POSTNOOPT-DAG: 4 func-properties-stats - Number of basic block successors + +; --- Post optimization values --- +; POST-DAG: 1 func-properties-stats - Number of basic blocks +; POST-DAG: 1 func-properties-stats - Number of instructions (of all types) +; POST-NOT: func-properties-stats - Number of basic block successors + +define i32 @test_count() { +entry: + ; This branch is trivially resolvable + br i1 true, label %then, label %else + +then: + br label %end + +else: + br label %end + +end: + %phi = phi i32 [ 1, %then ], [ 2, %else ] + ret i32 %phi +} diff --git a/llvm/test/Analysis/InstCount/instcount.ll b/llvm/test/Analysis/InstCount/instcount.ll index 9c4d3f3d0645..6c7ba690fdf0 100644 --- a/llvm/test/Analysis/InstCount/instcount.ll +++ b/llvm/test/Analysis/InstCount/instcount.ll @@ -1,11 +1,5 @@ ; REQUIRES: asserts ; RUN: opt -stats -passes=instcount -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt -stats -passes='thinlto' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt -stats -passes='thinlto-pre-link' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt -stats -passes='lto' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt -stats -passes='lto-pre-link' -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt -stats -O3 -disable-output < %s 2>&1 | FileCheck %s -; RUN: opt -stats -O0 -disable-output < %s 2>&1 | FileCheck %s ; CHECK-DAG: 10 instcount - Largest number of basic blocks in a single function ; CHECK-DAG: 18 instcount - Largest number of instructions in a single function @@ -17,7 +11,7 @@ ; CHECK-DAG: 1 instcount - Number of Switch insts ; CHECK-DAG: 11 instcount - Number of basic blocks ; CHECK-DAG: 2 instcount - Number of non-external functions -; CHECK-DAG: 19 instcount - Number of instructions (of all types) +; CHECK-DAG: 19 instcount - Number of instructions of all types define void @foo(i32 %i, i32 %j, i32 %n) { entry: diff --git a/llvm/test/Analysis/InstCount/pipeline.ll b/llvm/test/Analysis/InstCount/pipeline.ll new file mode 100644 index 000000000000..bb203cca0a97 --- /dev/null +++ b/llvm/test/Analysis/InstCount/pipeline.ll @@ -0,0 +1,41 @@ +; REQUIRES: asserts +; RUN: opt -stats -disable-output -passes='instcount' < %s 2>&1 | FileCheck %s --check-prefix=PRE +; RUN: opt -stats -disable-output -passes='instcount' < %s 2>&1 | FileCheck %s --check-prefixes=POSTNOOPT +; RUN: opt -stats -disable-output -O0 < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POSTNOOPT +; RUN: opt -stats -disable-output -O3 < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POST +; RUN: opt -stats -disable-output -passes='lto' < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POST +; RUN: opt -stats -disable-output -passes='lto-pre-link' < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POST +; RUN: opt -stats -disable-output -passes='lto-pre-link' < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POST +; RUN: opt -stats -disable-output -passes='thinlto' < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POST +; RUN: opt -stats -disable-output -passes='thinlto-pre-link' < %s 2>&1 | FileCheck %s --check-prefixes=PRE,POST + +; --- --- +; PRE-DAG: 4 instcount - Number of basic blocks (before optimizations) +; PRE-DAG: 5 instcount - Number of instructions of all types (before optimizations) +; PRE-DAG: 1 instcount - Number of CondBr insts (before optimizations) + +; --- No in pass but no optimization passes run --- +; POSTNOOPT-DAG: 4 instcount - Number of basic blocks +; POSTNOOPT-DAG: 5 instcount - Number of instructions of all types +; POSTNOOPT-DAG: 1 instcount - Number of CondBr insts + +; --- Post optimization values --- +; POST-DAG: 1 instcount - Number of basic blocks +; POST-DAG: 1 instcount - Number of instructions of all types +; POST-NOT: instcount - Number of CondBr insts + +define i32 @test_count() { +entry: + ; This branch is trivially resolvable + br i1 true, label %then, label %else + +then: + br label %end + +else: + br label %end + +end: + %phi = phi i32 [ 1, %then ], [ 2, %else ] + ret i32 %phi +}