[llvm] [IR][NFC] Avoid unneccessary move of analysis results (PR #210540)
Alexis Engelke via llvm-commits
llvm-commits at lists.llvm.org
Sat Jul 18 13:03:50 PDT 2026
https://github.com/aengelke created https://github.com/llvm/llvm-project/pull/210540
While benchmarking CycleAnalysis, I noticed that each analysis result is
constructed on the stack first and then moved to its final place on the
heap. This is unnecessary -- directly construct the analysis result in
its final place. Consequently, analysis results can be immovable.
>From b0be6ec9e83dbe639d402cd58b2c8136ceeef64e Mon Sep 17 00:00:00 2001
From: Alexis Engelke <engelke at in.tum.de>
Date: Sat, 18 Jul 2026 20:03:11 +0000
Subject: [PATCH] [spr] initial version
Created using spr 1.3.8-wip
---
llvm/include/llvm/IR/PassManagerInternal.h | 45 ++++++----------------
llvm/unittests/IR/PassManagerTest.cpp | 5 +++
2 files changed, 17 insertions(+), 33 deletions(-)
diff --git a/llvm/include/llvm/IR/PassManagerInternal.h b/llvm/include/llvm/IR/PassManagerInternal.h
index 376dcd7d3af62..ba1f717fd76b1 100644
--- a/llvm/include/llvm/IR/PassManagerInternal.h
+++ b/llvm/include/llvm/IR/PassManagerInternal.h
@@ -226,22 +226,11 @@ template <typename IRUnitT, typename PassT, typename ResultT,
typename InvalidatorT>
struct AnalysisResultModel<IRUnitT, PassT, ResultT, InvalidatorT, false>
: AnalysisResultConcept<IRUnitT, InvalidatorT> {
- explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
- AnalysisResultModel(AnalysisResultModel &&Arg)
- : Result(std::move(Arg.Result)) {}
-
- friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
- using std::swap;
- swap(LHS.Result, RHS.Result);
- }
-
- AnalysisResultModel &operator=(AnalysisResultModel RHS) {
- swap(*this, RHS);
- return *this;
- }
+ template <typename... ExtraArgTs>
+ AnalysisResultModel(PassT &Pass, IRUnitT &IR,
+ AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
+ ExtraArgTs &&...ExtraArgs)
+ : Result(Pass.run(IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...)) {}
/// The model bases invalidation solely on being in the preserved set.
//
@@ -264,22 +253,11 @@ template <typename IRUnitT, typename PassT, typename ResultT,
typename InvalidatorT>
struct AnalysisResultModel<IRUnitT, PassT, ResultT, InvalidatorT, true>
: AnalysisResultConcept<IRUnitT, InvalidatorT> {
- explicit AnalysisResultModel(ResultT Result) : Result(std::move(Result)) {}
- // We have to explicitly define all the special member functions because MSVC
- // refuses to generate them.
- AnalysisResultModel(const AnalysisResultModel &Arg) : Result(Arg.Result) {}
- AnalysisResultModel(AnalysisResultModel &&Arg)
- : Result(std::move(Arg.Result)) {}
-
- friend void swap(AnalysisResultModel &LHS, AnalysisResultModel &RHS) {
- using std::swap;
- swap(LHS.Result, RHS.Result);
- }
-
- AnalysisResultModel &operator=(AnalysisResultModel RHS) {
- swap(*this, RHS);
- return *this;
- }
+ template <typename... ExtraArgTs>
+ AnalysisResultModel(PassT &Pass, IRUnitT &IR,
+ AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
+ ExtraArgTs &&...ExtraArgs)
+ : Result(Pass.run(IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...)) {}
/// The model delegates to the \c ResultT method.
bool invalidate(IRUnitT &IR, const PreservedAnalyses &PA,
@@ -344,8 +322,9 @@ struct AnalysisPassModel
std::unique_ptr<AnalysisResultConcept<IRUnitT, InvalidatorT>>
run(IRUnitT &IR, AnalysisManager<IRUnitT, ExtraArgTs...> &AM,
ExtraArgTs... ExtraArgs) override {
+ // Call Pass.run in constructor to avoid move of analysis result.
return std::make_unique<ResultModelT>(
- Pass.run(IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...));
+ Pass, IR, AM, std::forward<ExtraArgTs>(ExtraArgs)...);
}
/// The model delegates to a static \c PassT::name method.
diff --git a/llvm/unittests/IR/PassManagerTest.cpp b/llvm/unittests/IR/PassManagerTest.cpp
index fd4e3c97cb48a..8fd6ecfdfd09b 100644
--- a/llvm/unittests/IR/PassManagerTest.cpp
+++ b/llvm/unittests/IR/PassManagerTest.cpp
@@ -28,6 +28,11 @@ class TestFunctionAnalysis : public AnalysisInfoMixin<TestFunctionAnalysis> {
public:
struct Result {
Result(int Count) : InstructionCount(Count) {}
+
+ // Test that analysis results can be immovable.
+ Result(const Result &) = delete;
+ Result &operator=(const Result &) = delete;
+
int InstructionCount;
bool invalidate(Function &, const PreservedAnalyses &PA,
FunctionAnalysisManager::Invalidator &) {
More information about the llvm-commits
mailing list