diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -1312,11 +1312,12 @@ /*DropTypeTests=*/true)); }); - if (Level != PassBuilder::OptimizationLevel::O0) { + if (CodeGenOpts.InstrumentFunctions || + CodeGenOpts.InstrumentFunctionsAfterInlining || + CodeGenOpts.InstrumentFunctionEntryBare) { PB.registerPipelineStartEPCallback( [](ModulePassManager &MPM, PassBuilder::OptimizationLevel Level) { - MPM.addPass(createModuleToFunctionPassAdaptor( - EntryExitInstrumenterPass(/*PostInlining=*/false))); + MPM.addPass(EntryExitInstrumenterPass(/*PostInlining=*/false)); }); } diff --git a/llvm/include/llvm/Transforms/Utils/EntryExitInstrumenter.h b/llvm/include/llvm/Transforms/Utils/EntryExitInstrumenter.h --- a/llvm/include/llvm/Transforms/Utils/EntryExitInstrumenter.h +++ b/llvm/include/llvm/Transforms/Utils/EntryExitInstrumenter.h @@ -19,15 +19,15 @@ namespace llvm { -class Function; - -struct EntryExitInstrumenterPass +class EntryExitInstrumenterPass : public PassInfoMixin { - EntryExitInstrumenterPass(bool PostInlining) : PostInlining(PostInlining) {} + bool PostInlining; - PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); +public: + EntryExitInstrumenterPass(bool PostInlining) : PostInlining(PostInlining) {} - bool PostInlining; + PreservedAnalyses run(Module &M, ModuleAnalysisManager &); + static bool isRequired() { return true; } }; } // namespace llvm diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -120,6 +120,8 @@ MODULE_PASS("memprof-module", ModuleMemProfilerPass()) MODULE_PASS("poison-checking", PoisonCheckingPass()) MODULE_PASS("pseudo-probe-update", PseudoProbeUpdatePass()) +MODULE_PASS("ee-instrument", EntryExitInstrumenterPass(/*PostInlining=*/false)) +MODULE_PASS("post-inline-ee-instrument", EntryExitInstrumenterPass(/*PostInlining=*/true)) #undef MODULE_PASS #ifndef CGSCC_ANALYSIS @@ -217,10 +219,8 @@ FUNCTION_PASS("dot-cfg-only", CFGOnlyPrinterPass()) FUNCTION_PASS("early-cse", EarlyCSEPass(/*UseMemorySSA=*/false)) FUNCTION_PASS("early-cse-memssa", EarlyCSEPass(/*UseMemorySSA=*/true)) -FUNCTION_PASS("ee-instrument", EntryExitInstrumenterPass(/*PostInlining=*/false)) FUNCTION_PASS("fix-irreducible", FixIrreduciblePass()) FUNCTION_PASS("make-guards-explicit", MakeGuardsExplicitPass()) -FUNCTION_PASS("post-inline-ee-instrument", EntryExitInstrumenterPass(/*PostInlining=*/true)) FUNCTION_PASS("gvn-hoist", GVNHoistPass()) FUNCTION_PASS("gvn-sink", GVNSinkPass()) FUNCTION_PASS("helloworld", HelloWorldPass()) diff --git a/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp b/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp --- a/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp +++ b/llvm/lib/Transforms/Utils/EntryExitInstrumenter.cpp @@ -176,9 +176,12 @@ return new PostInlineEntryExitInstrumenter(); } -PreservedAnalyses -llvm::EntryExitInstrumenterPass::run(Function &F, FunctionAnalysisManager &AM) { - runOnFunction(F, PostInlining); +PreservedAnalyses llvm::EntryExitInstrumenterPass::run(Module &M, + ModuleAnalysisManager &MAM) { + for (Function &F : M) { + runOnFunction(F, PostInlining); + } + PreservedAnalyses PA; PA.preserveSet(); return PA; diff --git a/llvm/test/Transforms/EntryExitInstrumenter/debug-info.ll b/llvm/test/Transforms/EntryExitInstrumenter/debug-info.ll --- a/llvm/test/Transforms/EntryExitInstrumenter/debug-info.ll +++ b/llvm/test/Transforms/EntryExitInstrumenter/debug-info.ll @@ -1,4 +1,4 @@ -; RUN: opt -passes="function(ee-instrument),cgscc(inline),function(post-inline-ee-instrument)" -S < %s | FileCheck %s +; RUN: opt -passes="ee-instrument,cgscc(inline),post-inline-ee-instrument" -S < %s | FileCheck %s target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" diff --git a/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll b/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll --- a/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll +++ b/llvm/test/Transforms/EntryExitInstrumenter/mcount.ll @@ -1,7 +1,10 @@ -; RUN: opt -passes="function(ee-instrument),cgscc(inline),function(post-inline-ee-instrument)" -S < %s | FileCheck %s +; RUN: opt --O0 --ee-instrument --inline --post-inline-ee-instrument -S < %s | FileCheck %s + +; Check if the pass is enabbled on both -O0 and higher optimization levels +; RUN: opt --O2 --ee-instrument --post-inline-ee-instrument -S < %s | FileCheck --check-prefix=OPT %s ; Running the passes twice should not result in more instrumentation. -; RUN: opt -passes="function(ee-instrument),function(ee-instrument),cgscc(inline),function(post-inline-ee-instrument),function(post-inline-ee-instrument)" -S < %s | FileCheck %s +; RUN: opt -passes="ee-instrument,ee-instrument,cgscc(inline),post-inline-ee-instrument,post-inline-ee-instrument" -S < %s | FileCheck %s target datalayout = "E-m:e-i64:64-n32:64" target triple = "powerpc64le-unknown-linux" @@ -18,6 +21,15 @@ ; CHECK-NEXT: %1 = call i8* @llvm.returnaddress(i32 0) ; CHECK-NEXT: call void @__cyg_profile_func_exit(i8* bitcast (void ()* @leaf_function to i8*), i8* %1) ; CHECK-NEXT: ret void + +; OPT-LABEL: define void @leaf_function() +; OPT: entry: +; OPT-NEXT: call void @mcount() +; OPT-NEXT: %0 = call i8* @llvm.returnaddress(i32 0) +; OPT-NEXT: call void @__cyg_profile_func_enter(i8* bitcast (void ()* @leaf_function to i8*), i8* %0) +; OPT-NEXT: %1 = call i8* @llvm.returnaddress(i32 0) +; OPT-NEXT: call void @__cyg_profile_func_exit(i8* bitcast (void ()* @leaf_function to i8*), i8* %1) +; OPT-NEXT: ret void } @@ -42,6 +54,16 @@ ; CHECK-NEXT: call void @__cyg_profile_func_exit(i8* bitcast (void ()* @root_function to i8*), i8* %3) ; CHECK-NEXT: ret void + +; OPT-LABEL: define void @root_function() +; OPT: entry: +; OPT-NEXT: call void @mcount() + +; OPT-NEXT: %0 = call i8* @llvm.returnaddress(i32 0) +; OPT-NEXT: call void @__cyg_profile_func_enter(i8* bitcast (void ()* @root_function to i8*), i8* %0) +; OPT-NEXT: %1 = call i8* @llvm.returnaddress(i32 0) +; OPT-NEXT: call void @__cyg_profile_func_exit(i8* bitcast (void ()* @root_function to i8*), i8* %1) +; OPT-NEXT: ret void }