diff --git a/llvm/include/llvm/Analysis/CtxProfAnalysis.h b/llvm/include/llvm/Analysis/CtxProfAnalysis.h index d77c81d03582e..f0e2aeb0f92f7 100644 --- a/llvm/include/llvm/Analysis/CtxProfAnalysis.h +++ b/llvm/include/llvm/Analysis/CtxProfAnalysis.h @@ -9,10 +9,10 @@ #ifndef LLVM_ANALYSIS_CTXPROFANALYSIS_H #define LLVM_ANALYSIS_CTXPROFANALYSIS_H +#include "llvm/ADT/DenseMap.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/PassManager.h" #include "llvm/ProfileData/PGOCtxProfReader.h" -#include namespace llvm { @@ -20,12 +20,28 @@ class CtxProfAnalysis; /// The instrumented contextual profile, produced by the CtxProfAnalysis. class PGOContextualProfile { + friend class CtxProfAnalysis; + friend class CtxProfAnalysisPrinterPass; + struct FunctionInfo { + uint32_t NextCounterIndex = 0; + uint32_t NextCallsiteIndex = 0; + const std::string Name; + + FunctionInfo(StringRef Name) : Name(Name) {} + }; std::optional Profiles; + // For the GUIDs in this module, associate metadata about each function which + // we'll need when we maintain the profiles during IPO transformations. + DenseMap FuncInfo; -public: - explicit PGOContextualProfile(PGOCtxProfContext::CallTargetMapTy &&Profiles) - : Profiles(std::move(Profiles)) {} + /// Get the GUID of this Function if it's defined in this module. + GlobalValue::GUID getDefinedFunctionGUID(const Function &F) const; + + // This is meant to be constructed from CtxProfAnalysis, which will also set + // its state piecemeal. PGOContextualProfile() = default; + +public: PGOContextualProfile(const PGOContextualProfile &) = delete; PGOContextualProfile(PGOContextualProfile &&) = default; @@ -35,6 +51,20 @@ class PGOContextualProfile { return *Profiles; } + bool isFunctionKnown(const Function &F) const { + return getDefinedFunctionGUID(F) != 0; + } + + uint32_t allocateNextCounterIndex(const Function &F) { + assert(isFunctionKnown(F)); + return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCounterIndex++; + } + + uint32_t allocateNextCallsiteIndex(const Function &F) { + assert(isFunctionKnown(F)); + return FuncInfo.find(getDefinedFunctionGUID(F))->second.NextCallsiteIndex++; + } + bool invalidate(Module &, const PreservedAnalyses &PA, ModuleAnalysisManager::Invalidator &) { // Check whether the analysis has been explicitly invalidated. Otherwise, @@ -66,5 +96,27 @@ class CtxProfAnalysisPrinterPass PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); static bool isRequired() { return true; } }; + +/// Assign a GUID to functions as metadata. GUID calculation takes linkage into +/// account, which may change especially through and after thinlto. By +/// pre-computing and assigning as metadata, this mechanism is resilient to such +/// changes (as well as name changes e.g. suffix ".llvm." additions). + +// FIXME(mtrofin): we can generalize this mechanism to calculate a GUID early in +// the pass pipeline, associate it with any Global Value, and then use it for +// PGO and ThinLTO. +// At that point, this should be moved elsewhere. +class AssignGUIDPass : public PassInfoMixin { +public: + explicit AssignGUIDPass() = default; + + /// Assign a GUID *if* one is not already assign, as a function metadata named + /// `GUIDMetadataName`. + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); + static const char *GUIDMetadataName; + // This should become GlobalValue::getGUID + static uint64_t getGUID(const Function &F); +}; + } // namespace llvm #endif // LLVM_ANALYSIS_CTXPROFANALYSIS_H diff --git a/llvm/lib/Analysis/CtxProfAnalysis.cpp b/llvm/lib/Analysis/CtxProfAnalysis.cpp index fbae705127538..5bf336dd31115 100644 --- a/llvm/lib/Analysis/CtxProfAnalysis.cpp +++ b/llvm/lib/Analysis/CtxProfAnalysis.cpp @@ -14,12 +14,14 @@ #include "llvm/Analysis/CtxProfAnalysis.h" #include "llvm/ADT/STLExtras.h" #include "llvm/IR/Analysis.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" #include "llvm/ProfileData/PGOCtxProfReader.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/JSON.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Transforms/Instrumentation/PGOCtxProfLowering.h" #define DEBUG_TYPE "ctx_prof" @@ -64,10 +66,39 @@ Value toJSON(const PGOCtxProfContext::CallTargetMapTy &P) { } // namespace json } // namespace llvm +const char *AssignGUIDPass::GUIDMetadataName = "guid"; + +PreservedAnalyses AssignGUIDPass::run(Module &M, ModuleAnalysisManager &MAM) { + for (auto &F : M.functions()) { + if (F.isDeclaration()) + continue; + if (F.getMetadata(GUIDMetadataName)) + continue; + const GlobalValue::GUID GUID = F.getGUID(); + F.setMetadata(GUIDMetadataName, + MDNode::get(M.getContext(), + {ConstantAsMetadata::get(ConstantInt::get( + Type::getInt64Ty(M.getContext()), GUID))})); + } + return PreservedAnalyses::none(); +} + +GlobalValue::GUID AssignGUIDPass::getGUID(const Function &F) { + if (F.isDeclaration()) { + assert(GlobalValue::isExternalLinkage(F.getLinkage())); + return GlobalValue::getGUID(F.getGlobalIdentifier()); + } + auto *MD = F.getMetadata(GUIDMetadataName); + assert(MD && "guid not found for defined function"); + return cast(cast(MD->getOperand(0)) + ->getValue() + ->stripPointerCasts()) + ->getZExtValue(); +} AnalysisKey CtxProfAnalysis::Key; -CtxProfAnalysis::Result CtxProfAnalysis::run(Module &M, - ModuleAnalysisManager &MAM) { +PGOContextualProfile CtxProfAnalysis::run(Module &M, + ModuleAnalysisManager &MAM) { ErrorOr> MB = MemoryBuffer::getFile(Profile); if (auto EC = MB.getError()) { M.getContext().emitError("could not open contextual profile file: " + @@ -81,7 +112,55 @@ CtxProfAnalysis::Result CtxProfAnalysis::run(Module &M, toString(MaybeCtx.takeError())); return {}; } - return Result(std::move(*MaybeCtx)); + + PGOContextualProfile Result; + + for (const auto &F : M) { + if (F.isDeclaration()) + continue; + auto GUID = AssignGUIDPass::getGUID(F); + assert(GUID && "guid not found for defined function"); + const auto &Entry = F.begin(); + uint32_t MaxCounters = 0; // we expect at least a counter. + for (const auto &I : *Entry) + if (auto *C = dyn_cast(&I)) { + MaxCounters = + static_cast(C->getNumCounters()->getZExtValue()); + break; + } + if (!MaxCounters) + continue; + uint32_t MaxCallsites = 0; + for (const auto &BB : F) + for (const auto &I : BB) + if (auto *C = dyn_cast(&I)) { + MaxCallsites = + static_cast(C->getNumCounters()->getZExtValue()); + break; + } + auto [It, Ins] = Result.FuncInfo.insert( + {GUID, PGOContextualProfile::FunctionInfo(F.getName())}); + (void)Ins; + assert(Ins); + It->second.NextCallsiteIndex = MaxCallsites; + It->second.NextCounterIndex = MaxCounters; + } + // If we made it this far, the Result is valid - which we mark by setting + // .Profiles. + // Trim first the roots that aren't in this module. + DenseSet ProfiledGUIDs; + for (auto &[RootGuid, _] : llvm::make_early_inc_range(*MaybeCtx)) + if (!Result.FuncInfo.contains(RootGuid)) + MaybeCtx->erase(RootGuid); + Result.Profiles = std::move(*MaybeCtx); + return Result; +} + +GlobalValue::GUID +PGOContextualProfile::getDefinedFunctionGUID(const Function &F) const { + if (auto It = FuncInfo.find(AssignGUIDPass::getGUID(F)); It != FuncInfo.end()) + return It->first; + return 0; } PreservedAnalyses CtxProfAnalysisPrinterPass::run(Module &M, @@ -91,8 +170,16 @@ PreservedAnalyses CtxProfAnalysisPrinterPass::run(Module &M, M.getContext().emitError("Invalid CtxProfAnalysis"); return PreservedAnalyses::all(); } + + OS << "Function Info:\n"; + for (const auto &[Guid, FuncInfo] : C.FuncInfo) + OS << Guid << " : " << FuncInfo.Name + << ". MaxCounterID: " << FuncInfo.NextCounterIndex + << ". MaxCallsiteID: " << FuncInfo.NextCallsiteIndex << "\n"; + const auto JSONed = ::llvm::json::toJSON(C.profiles()); + OS << "\nCurrent Profile:\n"; OS << formatv("{0:2}", JSONed); OS << "\n"; return PreservedAnalyses::all(); diff --git a/llvm/lib/Passes/PassBuilderPipelines.cpp b/llvm/lib/Passes/PassBuilderPipelines.cpp index 6927a2886b962..0201e69f3e216 100644 --- a/llvm/lib/Passes/PassBuilderPipelines.cpp +++ b/llvm/lib/Passes/PassBuilderPipelines.cpp @@ -18,6 +18,7 @@ #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/BasicAliasAnalysis.h" #include "llvm/Analysis/CGSCCPassManager.h" +#include "llvm/Analysis/CtxProfAnalysis.h" #include "llvm/Analysis/GlobalsModRef.h" #include "llvm/Analysis/InlineAdvisor.h" #include "llvm/Analysis/ProfileSummaryInfo.h" @@ -1196,6 +1197,9 @@ PassBuilder::buildModuleSimplificationPipeline(OptimizationLevel Level, // In pre-link, we just want the instrumented IR. We use the contextual // profile in the post-thinlink phase. // The instrumentation will be removed in post-thinlink after IPO. + // FIXME(mtrofin): move AssignGUIDPass if there is agreement to use this + // mechanism for GUIDs. + MPM.addPass(AssignGUIDPass()); if (IsCtxProfUse) return MPM; addPostPGOLoopRotation(MPM, Level); diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index 4fdded7b82f36..18f4aa19224da 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -46,6 +46,7 @@ MODULE_ALIAS_ANALYSIS("globals-aa", GlobalsAA()) #endif MODULE_PASS("always-inline", AlwaysInlinerPass()) MODULE_PASS("annotation2metadata", Annotation2MetadataPass()) +MODULE_PASS("assign-guid", AssignGUIDPass()) MODULE_PASS("attributor", AttributorPass()) MODULE_PASS("attributor-light", AttributorLightPass()) MODULE_PASS("called-value-propagation", CalledValuePropagationPass()) diff --git a/llvm/lib/Transforms/Instrumentation/PGOCtxProfLowering.cpp b/llvm/lib/Transforms/Instrumentation/PGOCtxProfLowering.cpp index d6ba12465bb32..9b10cbba84075 100644 --- a/llvm/lib/Transforms/Instrumentation/PGOCtxProfLowering.cpp +++ b/llvm/lib/Transforms/Instrumentation/PGOCtxProfLowering.cpp @@ -8,6 +8,7 @@ // #include "llvm/Transforms/Instrumentation/PGOCtxProfLowering.h" +#include "llvm/Analysis/CtxProfAnalysis.h" #include "llvm/Analysis/OptimizationRemarkEmitter.h" #include "llvm/IR/Analysis.h" #include "llvm/IR/DiagnosticInfo.h" @@ -16,6 +17,7 @@ #include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Module.h" #include "llvm/IR/PassManager.h" +#include "llvm/ProfileData/InstrProf.h" #include "llvm/Support/CommandLine.h" #include @@ -223,8 +225,8 @@ bool CtxInstrumentationLowerer::lowerFunction(Function &F) { assert(Mark->getIndex()->isZero()); IRBuilder<> Builder(Mark); - // FIXME(mtrofin): use InstrProfSymtab::getCanonicalName - Guid = Builder.getInt64(F.getGUID()); + + Guid = Builder.getInt64(AssignGUIDPass::getGUID(F)); // The type of the context of this function is now knowable since we have // NrCallsites and NrCounters. We delcare it here because it's more // convenient - we have the Builder. diff --git a/llvm/test/Analysis/CtxProfAnalysis/full-cycle.ll b/llvm/test/Analysis/CtxProfAnalysis/full-cycle.ll new file mode 100644 index 0000000000000..0cdf82bd96efc --- /dev/null +++ b/llvm/test/Analysis/CtxProfAnalysis/full-cycle.ll @@ -0,0 +1,119 @@ +; REQUIRES: x86_64-linux +; +; RUN: rm -rf %t +; RUN: split-file %s %t +; +; Test that the GUID metadata survives through thinlink. +; +; RUN: llvm-ctxprof-util fromJSON --input=%t/profile.json --output=%t/profile.ctxprofdata +; +; RUN: opt -module-summary -passes='thinlto-pre-link' -use-ctx-profile=%t/profile.ctxprofdata -o %t/m1.bc %t/m1.ll +; RUN: opt -module-summary -passes='thinlto-pre-link' -use-ctx-profile=%t/profile.ctxprofdata -o %t/m2.bc %t/m2.ll +; +; RUN: rm -rf %t/postlink +; RUN: mkdir %t/postlink +; +; +; RUN: llvm-lto2 run %t/m1.bc %t/m2.bc -o %t/ -thinlto-distributed-indexes \ +; RUN: -use-ctx-profile=%t/profile.ctxprofdata \ +; RUN: -r %t/m1.bc,f1,plx \ +; RUN: -r %t/m2.bc,f1 \ +; RUN: -r %t/m2.bc,entrypoint,plx +; RUN: opt --passes='function-import,require,print' \ +; RUN: -summary-file=%t/m2.bc.thinlto.bc -use-ctx-profile=%t/profile.ctxprofdata %t/m2.bc \ +; RUN: -S -o %t/m2.post.ll 2> %t/profile.txt +; RUN: diff %t/expected.txt %t/profile.txt +;--- m1.ll +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +source_filename = "random_path/m1.cc" + +define private void @f2() #0 !guid !0 { + ret void +} + +define void @f1() #0 { + call void @f2() + ret void +} + +attributes #0 = { noinline } +!0 = !{ i64 3087265239403591524 } + +;--- m2.ll +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-pc-linux-gnu" + +source_filename = "random_path/m2.cc" + +declare void @f1() + +define void @entrypoint() { + call void @f1() + ret void +} +;--- profile.json +[ + { + "Callsites": [ + [ + { + "Callsites": [ + [ + { + "Counters": [ + 10 + ], + "Guid": 3087265239403591524 + } + ] + ], + "Counters": [ + 7 + ], + "Guid": 2072045998141807037 + } + ] + ], + "Counters": [ + 1 + ], + "Guid": 10507721908651011566 + } +] +;--- expected.txt +Function Info: +10507721908651011566 : entrypoint. MaxCounterID: 1. MaxCallsiteID: 1 +3087265239403591524 : f2.llvm.0. MaxCounterID: 1. MaxCallsiteID: 0 +2072045998141807037 : f1. MaxCounterID: 1. MaxCallsiteID: 1 + +Current Profile: +[ + { + "Callsites": [ + [ + { + "Callsites": [ + [ + { + "Counters": [ + 10 + ], + "Guid": 3087265239403591524 + } + ] + ], + "Counters": [ + 7 + ], + "Guid": 2072045998141807037 + } + ] + ], + "Counters": [ + 1 + ], + "Guid": 10507721908651011566 + } +] diff --git a/llvm/test/Analysis/CtxProfAnalysis/load.ll b/llvm/test/Analysis/CtxProfAnalysis/load.ll index 9cd78cfef187b..69806e334aaec 100644 --- a/llvm/test/Analysis/CtxProfAnalysis/load.ll +++ b/llvm/test/Analysis/CtxProfAnalysis/load.ll @@ -1,16 +1,22 @@ ; REQUIRES: x86_64-linux - +; +; RUN: rm -rf %t ; RUN: split-file %s %t ; RUN: llvm-ctxprof-util fromJSON --input=%t/profile.json --output=%t/profile.ctxprofdata ; RUN: not opt -passes='require,print' \ -; RUN: %t/empty.ll -S 2>&1 | FileCheck %s --check-prefix=NO-FILE +; RUN: %t/example.ll -S 2>&1 | FileCheck %s --check-prefix=NO-FILE ; RUN: not opt -passes='require,print' \ -; RUN: -use-ctx-profile=does_not_exist.ctxprofdata %t/empty.ll -S 2>&1 | FileCheck %s --check-prefix=NO-FILE +; RUN: -use-ctx-profile=does_not_exist.ctxprofdata %t/example.ll -S 2>&1 | FileCheck %s --check-prefix=NO-FILE +; RUN: opt -module-summary -passes='thinlto-pre-link' \ +; RUN: -use-ctx-profile=%t/profile.ctxprofdata %t/example.ll -S -o %t/prelink.ll + +; RUN: opt -module-summary -passes='thinlto-pre-link' -use-ctx-profile=%t/profile.ctxprofdata \ +; RUN: %t/example.ll -S -o %t/prelink.ll ; RUN: opt -passes='require,print' \ -; RUN: -use-ctx-profile=%t/profile.ctxprofdata %t/empty.ll -S 2> %t/output.json -; RUN: diff %t/profile.json %t/output.json +; RUN: -use-ctx-profile=%t/profile.ctxprofdata %t/prelink.ll -S 2> %t/output.txt +; RUN: diff %t/expected-profile-output.txt %t/output.txt ; NO-FILE: error: could not open contextual profile file ; @@ -18,41 +24,104 @@ ; output it from opt. ;--- profile.json [ + { + "Counters": [ + 9 + ], + "Guid": 12341 + }, + { + "Counters": [ + 5 + ], + "Guid": 12074870348631550642 + }, { "Callsites": [ - [], [ { "Counters": [ - 4, - 5 + 6, + 7 ], - "Guid": 2000 - }, + "Guid": 728453322856651412 + } + ] + ], + "Counters": [ + 1 + ], + "Guid": 11872291593386833696 + } +] +;--- expected-profile-output.txt +Function Info: +4909520559318251808 : an_entrypoint. MaxCounterID: 2. MaxCallsiteID: 1 +12074870348631550642 : another_entrypoint_no_callees. MaxCounterID: 1. MaxCallsiteID: 0 +11872291593386833696 : foo. MaxCounterID: 1. MaxCallsiteID: 1 + +Current Profile: +[ + { + "Callsites": [ + [ { "Counters": [ 6, - 7, - 8 + 7 ], - "Guid": 18446744073709551613 + "Guid": 728453322856651412 } ] ], "Counters": [ - 1, - 2, - 3 + 1 ], - "Guid": 1000 + "Guid": 11872291593386833696 }, { "Counters": [ - 5, - 9, - 10 + 5 ], - "Guid": 18446744073709551612 + "Guid": 12074870348631550642 } ] -;--- empty.ll +;--- example.ll +declare void @bar() + +define private void @foo(i32 %a, ptr %fct) #0 !guid !0 { + %t = icmp eq i32 %a, 0 + br i1 %t, label %yes, label %no +yes: + call void %fct(i32 %a) + br label %exit +no: + call void @bar() + br label %exit +exit: + ret void +} + +define void @an_entrypoint(i32 %a) { + %t = icmp eq i32 %a, 0 + br i1 %t, label %yes, label %no + +yes: + call void @foo(i32 1, ptr null) + ret void +no: + ret void +} + +define void @another_entrypoint_no_callees(i32 %a) { + %t = icmp eq i32 %a, 0 + br i1 %t, label %yes, label %no + +yes: + ret void +no: + ret void +} + +attributes #0 = { noinline } +!0 = !{ i64 11872291593386833696 } \ No newline at end of file diff --git a/llvm/test/Transforms/PGOProfile/ctx-instrumentation.ll b/llvm/test/Transforms/PGOProfile/ctx-instrumentation.ll index 56c7c7519f694..a70f94e1521f0 100644 --- a/llvm/test/Transforms/PGOProfile/ctx-instrumentation.ll +++ b/llvm/test/Transforms/PGOProfile/ctx-instrumentation.ll @@ -1,7 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-globals all --version 4 ; RUN: opt -passes=pgo-instr-gen -profile-context-root=an_entrypoint \ ; RUN: -S < %s | FileCheck --check-prefix=INSTRUMENT %s -; RUN: opt -passes=pgo-instr-gen,ctx-instr-lower -profile-context-root=an_entrypoint \ +; RUN: opt -passes=pgo-instr-gen,assign-guid,ctx-instr-lower -profile-context-root=an_entrypoint \ ; RUN: -profile-context-root=another_entrypoint_no_callees \ ; RUN: -S < %s | FileCheck --check-prefix=LOWERING %s @@ -46,7 +46,7 @@ define void @foo(i32 %a, ptr %fct) { ; INSTRUMENT-NEXT: ret void ; ; LOWERING-LABEL: define void @foo( -; LOWERING-SAME: i32 [[A:%.*]], ptr [[FCT:%.*]]) { +; LOWERING-SAME: i32 [[A:%.*]], ptr [[FCT:%.*]]) !guid [[META0:![0-9]+]] { ; LOWERING-NEXT: [[TMP1:%.*]] = call ptr @__llvm_ctx_profile_get_context(ptr @foo, i64 6699318081062747564, i32 2, i32 2) ; LOWERING-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 ; LOWERING-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], 1 @@ -104,7 +104,7 @@ define void @an_entrypoint(i32 %a) { ; INSTRUMENT-NEXT: ret void ; ; LOWERING-LABEL: define void @an_entrypoint( -; LOWERING-SAME: i32 [[A:%.*]]) { +; LOWERING-SAME: i32 [[A:%.*]]) !guid [[META1:![0-9]+]] { ; LOWERING-NEXT: [[TMP1:%.*]] = call ptr @__llvm_ctx_profile_start_context(ptr @an_entrypoint_ctx_root, i64 4909520559318251808, i32 2, i32 1) ; LOWERING-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 ; LOWERING-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], 1 @@ -154,7 +154,7 @@ define void @another_entrypoint_no_callees(i32 %a) { ; INSTRUMENT-NEXT: ret void ; ; LOWERING-LABEL: define void @another_entrypoint_no_callees( -; LOWERING-SAME: i32 [[A:%.*]]) { +; LOWERING-SAME: i32 [[A:%.*]]) !guid [[META2:![0-9]+]] { ; LOWERING-NEXT: [[TMP1:%.*]] = call ptr @__llvm_ctx_profile_start_context(ptr @another_entrypoint_no_callees_ctx_root, i64 -6371873725078000974, i32 2, i32 0) ; LOWERING-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 ; LOWERING-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], -2 @@ -188,7 +188,7 @@ define void @simple(i32 %a) { ; INSTRUMENT-NEXT: ret void ; ; LOWERING-LABEL: define void @simple( -; LOWERING-SAME: i32 [[A:%.*]]) { +; LOWERING-SAME: i32 [[A:%.*]]) !guid [[META3:![0-9]+]] { ; LOWERING-NEXT: [[TMP1:%.*]] = call ptr @__llvm_ctx_profile_get_context(ptr @simple, i64 -3006003237940970099, i32 1, i32 0) ; LOWERING-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 ; LOWERING-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], -2 @@ -212,7 +212,7 @@ define i32 @no_callsites(i32 %a) { ; INSTRUMENT-NEXT: ret i32 0 ; ; LOWERING-LABEL: define i32 @no_callsites( -; LOWERING-SAME: i32 [[A:%.*]]) { +; LOWERING-SAME: i32 [[A:%.*]]) !guid [[META4:![0-9]+]] { ; LOWERING-NEXT: [[TMP1:%.*]] = call ptr @__llvm_ctx_profile_get_context(ptr @no_callsites, i64 5679753335911435902, i32 2, i32 0) ; LOWERING-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 ; LOWERING-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], -2 @@ -243,7 +243,8 @@ define void @no_counters() { ; INSTRUMENT-NEXT: call void @bar() ; INSTRUMENT-NEXT: ret void ; -; LOWERING-LABEL: define void @no_counters() { +; LOWERING-LABEL: define void @no_counters( +; LOWERING-SAME: ) !guid [[META5:![0-9]+]] { ; LOWERING-NEXT: [[TMP1:%.*]] = call ptr @__llvm_ctx_profile_get_context(ptr @no_counters, i64 5458232184388660970, i32 1, i32 1) ; LOWERING-NEXT: [[TMP2:%.*]] = ptrtoint ptr [[TMP1]] to i64 ; LOWERING-NEXT: [[TMP3:%.*]] = and i64 [[TMP2]], 1 @@ -263,8 +264,15 @@ define void @no_counters() { ret void } ;. -; INSTRUMENT: attributes #[[ATTR0:[0-9]+]] = { nounwind } -;. ; LOWERING: attributes #[[ATTR0:[0-9]+]] = { nounwind } ; LOWERING: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) } ;. +; INSTRUMENT: attributes #[[ATTR0:[0-9]+]] = { nounwind } +;. +; LOWERING: [[META0]] = !{i64 6699318081062747564} +; LOWERING: [[META1]] = !{i64 4909520559318251808} +; LOWERING: [[META2]] = !{i64 -6371873725078000974} +; LOWERING: [[META3]] = !{i64 -3006003237940970099} +; LOWERING: [[META4]] = !{i64 5679753335911435902} +; LOWERING: [[META5]] = !{i64 5458232184388660970} +;. diff --git a/llvm/test/Transforms/PGOProfile/ctx-prof-use-prelink.ll b/llvm/test/Transforms/PGOProfile/ctx-prof-use-prelink.ll index 18ac2f92aa39d..cb8ab78dc0f41 100644 --- a/llvm/test/Transforms/PGOProfile/ctx-prof-use-prelink.ll +++ b/llvm/test/Transforms/PGOProfile/ctx-prof-use-prelink.ll @@ -12,7 +12,7 @@ declare void @bar() ;. define void @foo(i32 %a, ptr %fct) { ; CHECK-LABEL: define void @foo( -; CHECK-SAME: i32 [[A:%.*]], ptr [[FCT:%.*]]) local_unnamed_addr { +; CHECK-SAME: i32 [[A:%.*]], ptr [[FCT:%.*]]) local_unnamed_addr !guid [[META0:![0-9]+]] { ; CHECK-NEXT: call void @llvm.instrprof.increment(ptr @__profn_foo, i64 728453322856651412, i32 2, i32 0) ; CHECK-NEXT: [[T:%.*]] = icmp eq i32 [[A]], 0 ; CHECK-NEXT: br i1 [[T]], label %[[YES:.*]], label %[[NO:.*]] @@ -42,3 +42,5 @@ exit: ;. ; CHECK: attributes #[[ATTR0:[0-9]+]] = { nounwind } ;. +; CHECK: [[META0]] = !{i64 6699318081062747564} +;.