[llvm] [Coroutines] Conditional elide coroutines based on hot/cold information (PR #162276)
Adrian Vogelsgesang via llvm-commits
llvm-commits at lists.llvm.org
Tue Oct 7 05:38:46 PDT 2025
https://github.com/vogelsgesang updated https://github.com/llvm/llvm-project/pull/162276
>From 8a0904b8d5b9a7904e8285ddb3932248bbffa75c Mon Sep 17 00:00:00 2001
From: Adrian Vogelsgesang <avogelsgesang at salesforce.com>
Date: Tue, 7 Oct 2025 11:12:27 +0000
Subject: [PATCH 1/4] [Coroutines] Conditional elide coroutines based on
hot/cold information
Unconditionally eliding all `[[clang::coro_await_elidable]]` coroutines
is not good.
For example,
```
Task bar();
Task foo(bool b) {
if (b) [[unlikely]] {
co_await bar();
}
}
```
Assume Task is marked with [[clang::coro_await_elidable]], now we will
always elide the call to bar() into the frame of foo(). But this may be
a regression instead of an optimization if b is always false.
This patch tries to mitigate the problem by leveraging hot/cold
information. This can be optimized further in the future but at least
this patch makes things better.
This patch was originally written by ChuanqiXu9, but stalled during PR
review because the diagnostics were not integrated with the existing
optimization remarks. I rebased the original patch, integrated it with
the optimization remarks, and did a couple of smaller cosmetic changes
(e.g., made the test case expectations more targetted, etc.)
Co-Authored-by: Chuanqi Xu <yedeng.yd at linux.alibaba.com>
---
.../Coroutines/CoroAnnotationElide.cpp | 77 ++++++++++++++++++
llvm/lib/Transforms/IPO/PartialInlining.cpp | 2 +-
.../Coroutines/coro-conditional-elide.ll | 79 +++++++++++++++++++
3 files changed, 157 insertions(+), 1 deletion(-)
create mode 100644 llvm/test/Transforms/Coroutines/coro-conditional-elide.ll
diff --git a/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp b/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp
index 9115946d205a4..d4d0c0f0895bb 100644
--- a/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp
@@ -24,6 +24,9 @@
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
+#include "llvm/Support/BranchProbability.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Transforms/Utils/CallGraphUpdater.h"
#include "llvm/Transforms/Utils/Cloning.h"
@@ -33,6 +36,49 @@ using namespace llvm;
#define DEBUG_TYPE "coro-annotation-elide"
+static cl::opt<float> CoroElideBranchRatio(
+ "coro-elide-branch-ratio", cl::init(0.55), cl::Hidden,
+ cl::desc("Minimum BranchProbability to consider a elide a coroutine."));
+extern cl::opt<unsigned> MinBlockCounterExecution;
+
+static cl::opt<bool>
+ PrintElidedCoroutine("print-elided-coroutine-stats", cl::init(false),
+ cl::Hidden,
+ cl::desc("Print stats for elided coroutine"));
+
+static cl::opt<std::string>
+ ElideStatOutput("coro-elide-stat-output", cl::init(""), cl::Hidden,
+ cl::desc("Output file for -print-elided-coroutine-stats. "
+ "Defaults to standard error output."));
+
+// The return value is used to indicate the owner of the resources. The users
+// should use the output parameter.
+static std::unique_ptr<llvm::raw_ostream>
+getCoroElidedStatsOStream(llvm::raw_ostream *&OS) {
+ if (!PrintElidedCoroutine) {
+ OS = &llvm::nulls();
+ return nullptr;
+ }
+
+ if (ElideStatOutput.empty()) {
+ OS = &llvm::errs();
+ return nullptr;
+ }
+
+ std::error_code EC;
+ auto ret = std::make_unique<llvm::raw_fd_ostream>(ElideStatOutput, EC,
+ sys::fs::OF_Append);
+
+ if (EC) {
+ llvm::errs() << "llvm cannot open file: " << EC.message() << "\n";
+ OS = &llvm::nulls();
+ return nullptr;
+ }
+
+ OS = ret.get();
+ return ret;
+}
+
static Instruction *getFirstNonAllocaInTheEntryBlock(Function *F) {
for (Instruction &I : F->getEntryBlock())
if (!isa<AllocaInst>(&I))
@@ -145,6 +191,37 @@ PreservedAnalyses CoroAnnotationElidePass::run(LazyCallGraph::SCC &C,
bool IsCallerPresplitCoroutine = Caller->isPresplitCoroutine();
bool HasAttr = CB->hasFnAttr(llvm::Attribute::CoroElideSafe);
if (IsCallerPresplitCoroutine && HasAttr) {
+
+ llvm::raw_ostream *OS = nullptr;
+ auto _ = getCoroElidedStatsOStream(OS);
+ assert(OS && "At least we should able to get access to standard error");
+
+ auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(*Caller);
+ if (BFI.getBlockFreq(CB->getParent()) <
+ BFI.getEntryFreq()) {
+ static BranchProbability MinBranchProbability(
+ static_cast<int>(CoroElideBranchRatio * MinBlockCounterExecution),
+ MinBlockCounterExecution);
+
+ auto Prob = BranchProbability::getBranchProbability(
+ BFI.getBlockFreq(CB->getParent()).getFrequency(),
+ BFI.getEntryFreq().getFrequency());
+
+ if (Prob < MinBranchProbability) {
+ *OS << "Not eliding " << *CB
+ << " with estimated probability: " << Prob << "\n";
+ continue;
+ }
+
+ *OS << "BB Prob: \t" << Prob << "\n";
+ } else {
+ *OS << "BB Freq: \t"
+ << BFI.getBlockFreq(CB->getParent()).getFrequency() << "\n";
+ *OS << "Entry Freq: \t" << BFI.getEntryFreq().getFrequency() << "\n";
+ }
+
+ *OS << "eliding " << *CB << "\n";
+
auto *CallerN = CG.lookup(*Caller);
auto *CallerC = CallerN ? CG.lookupSCC(*CallerN) : nullptr;
// If CallerC is nullptr, it means LazyCallGraph hasn't visited Caller
diff --git a/llvm/lib/Transforms/IPO/PartialInlining.cpp b/llvm/lib/Transforms/IPO/PartialInlining.cpp
index 2583249e65484..1a00d173d3ae0 100644
--- a/llvm/lib/Transforms/IPO/PartialInlining.cpp
+++ b/llvm/lib/Transforms/IPO/PartialInlining.cpp
@@ -109,7 +109,7 @@ static cl::opt<float> MinRegionSizeRatio(
"outline candidate and original function"));
// Used to tune the minimum number of execution counts needed in the predecessor
// block to the cold edge. ie. confidence interval.
-static cl::opt<unsigned>
+cl::opt<unsigned>
MinBlockCounterExecution("min-block-execution", cl::init(100), cl::Hidden,
cl::desc("Minimum block executions to consider "
"its BranchProbabilityInfo valid"));
diff --git a/llvm/test/Transforms/Coroutines/coro-conditional-elide.ll b/llvm/test/Transforms/Coroutines/coro-conditional-elide.ll
new file mode 100644
index 0000000000000..04c5bf0494278
--- /dev/null
+++ b/llvm/test/Transforms/Coroutines/coro-conditional-elide.ll
@@ -0,0 +1,79 @@
+; Testing elide performed its job for calls to coroutines marked safe.
+; RUN: opt < %s -S -passes='cgscc(coro-annotation-elide)' -coro-elide-branch-ratio=0.55 | FileCheck %s
+
+%struct.Task = type { ptr }
+
+declare void @print(i32) nounwind
+
+; resume part of the coroutine
+define fastcc void @callee.resume(ptr dereferenceable(1)) {
+ tail call void @print(i32 0)
+ ret void
+}
+
+; destroy part of the coroutine
+define fastcc void @callee.destroy(ptr) {
+ tail call void @print(i32 1)
+ ret void
+}
+
+; cleanup part of the coroutine
+define fastcc void @callee.cleanup(ptr) {
+ tail call void @print(i32 2)
+ ret void
+}
+
+ at callee.resumers = internal constant [3 x ptr] [
+ ptr @callee.resume, ptr @callee.destroy, ptr @callee.cleanup]
+
+declare void @alloc(i1) nounwind
+
+; CHECK-LABEL: define ptr @callee
+define ptr @callee(i8 %arg) {
+entry:
+ %task = alloca %struct.Task, align 8
+ %id = call token @llvm.coro.id(i32 0, ptr null,
+ ptr @callee,
+ ptr @callee.resumers)
+ %alloc = call i1 @llvm.coro.alloc(token %id)
+ %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
+ store ptr %hdl, ptr %task
+ ret ptr %task
+}
+
+; CHECK-LABEL: define ptr @callee.noalloc
+define ptr @callee.noalloc(i8 %arg, ptr dereferenceable(32) align(8) %frame) {
+ entry:
+ %task = alloca %struct.Task, align 8
+ %id = call token @llvm.coro.id(i32 0, ptr null,
+ ptr @callee,
+ ptr @callee.resumers)
+ %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
+ store ptr %hdl, ptr %task
+ ret ptr %task
+}
+
+; CHECK-LABEL: define ptr @caller(i1 %cond)
+; Function Attrs: presplitcoroutine
+define ptr @caller(i1 %cond) #0 {
+entry:
+ br i1 %cond, label %call, label %ret
+
+call:
+ %task = call ptr @callee(i8 0) #1
+ br label %ret
+
+ret:
+ %retval = phi ptr [ %task, %call ], [ null, %entry ]
+ ret ptr %retval
+ ; CHECK-NOT: alloca
+}
+
+declare token @llvm.coro.id(i32, ptr, ptr, ptr)
+declare ptr @llvm.coro.begin(token, ptr)
+declare ptr @llvm.coro.frame()
+declare ptr @llvm.coro.subfn.addr(ptr, i8)
+declare i1 @llvm.coro.alloc(token)
+
+attributes #0 = { presplitcoroutine }
+attributes #1 = { coro_elide_safe }
>From c1cb5d9f68f97b256f40745185e5ca5e416bd7cd Mon Sep 17 00:00:00 2001
From: Adrian Vogelsgesang <avogelsgesang at salesforce.com>
Date: Tue, 7 Oct 2025 11:50:08 +0000
Subject: [PATCH 2/4] Integrate with Optimization Remarks
---
llvm/include/llvm/IR/DiagnosticInfo.h | 2 +
llvm/lib/IR/DiagnosticInfo.cpp | 7 ++
.../Coroutines/CoroAnnotationElide.cpp | 82 ++++---------------
3 files changed, 26 insertions(+), 65 deletions(-)
diff --git a/llvm/include/llvm/IR/DiagnosticInfo.h b/llvm/include/llvm/IR/DiagnosticInfo.h
index 5f7225e878eb1..a426fb079ec04 100644
--- a/llvm/include/llvm/IR/DiagnosticInfo.h
+++ b/llvm/include/llvm/IR/DiagnosticInfo.h
@@ -20,6 +20,7 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/DebugLoc.h"
+#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/CBindingWrapping.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
@@ -555,6 +556,7 @@ class LLVM_ABI DiagnosticInfoOptimizationBase
Argument(StringRef Key, bool B) : Key(Key), Val(B ? "true" : "false") {}
LLVM_ABI Argument(StringRef Key, DebugLoc dl);
LLVM_ABI Argument(StringRef Key, InstructionCost C);
+ LLVM_ABI Argument(StringRef Key, BranchProbability P);
};
/// \p PassName is the name of the pass emitting this diagnostic. \p
diff --git a/llvm/lib/IR/DiagnosticInfo.cpp b/llvm/lib/IR/DiagnosticInfo.cpp
index 4f3762427e012..44574362e3405 100644
--- a/llvm/lib/IR/DiagnosticInfo.cpp
+++ b/llvm/lib/IR/DiagnosticInfo.cpp
@@ -273,6 +273,13 @@ DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
C.print(OS);
}
+DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
+ BranchProbability P)
+: Key(std::string(Key)) {
+ raw_string_ostream OS(Val);
+ P.print(OS);
+}
+
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key, DebugLoc Loc)
: Key(std::string(Key)), Loc(Loc) {
if (Loc) {
diff --git a/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp b/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp
index d4d0c0f0895bb..6cbda6b38768d 100644
--- a/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp
@@ -41,44 +41,6 @@ static cl::opt<float> CoroElideBranchRatio(
cl::desc("Minimum BranchProbability to consider a elide a coroutine."));
extern cl::opt<unsigned> MinBlockCounterExecution;
-static cl::opt<bool>
- PrintElidedCoroutine("print-elided-coroutine-stats", cl::init(false),
- cl::Hidden,
- cl::desc("Print stats for elided coroutine"));
-
-static cl::opt<std::string>
- ElideStatOutput("coro-elide-stat-output", cl::init(""), cl::Hidden,
- cl::desc("Output file for -print-elided-coroutine-stats. "
- "Defaults to standard error output."));
-
-// The return value is used to indicate the owner of the resources. The users
-// should use the output parameter.
-static std::unique_ptr<llvm::raw_ostream>
-getCoroElidedStatsOStream(llvm::raw_ostream *&OS) {
- if (!PrintElidedCoroutine) {
- OS = &llvm::nulls();
- return nullptr;
- }
-
- if (ElideStatOutput.empty()) {
- OS = &llvm::errs();
- return nullptr;
- }
-
- std::error_code EC;
- auto ret = std::make_unique<llvm::raw_fd_ostream>(ElideStatOutput, EC,
- sys::fs::OF_Append);
-
- if (EC) {
- llvm::errs() << "llvm cannot open file: " << EC.message() << "\n";
- OS = &llvm::nulls();
- return nullptr;
- }
-
- OS = ret.get();
- return ret;
-}
-
static Instruction *getFirstNonAllocaInTheEntryBlock(Function *F) {
for (Instruction &I : F->getEntryBlock())
if (!isa<AllocaInst>(&I))
@@ -191,37 +153,27 @@ PreservedAnalyses CoroAnnotationElidePass::run(LazyCallGraph::SCC &C,
bool IsCallerPresplitCoroutine = Caller->isPresplitCoroutine();
bool HasAttr = CB->hasFnAttr(llvm::Attribute::CoroElideSafe);
if (IsCallerPresplitCoroutine && HasAttr) {
-
- llvm::raw_ostream *OS = nullptr;
- auto _ = getCoroElidedStatsOStream(OS);
- assert(OS && "At least we should able to get access to standard error");
+ static BranchProbability MinBranchProbability(
+ static_cast<int>(CoroElideBranchRatio * MinBlockCounterExecution),
+ MinBlockCounterExecution);
auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(*Caller);
- if (BFI.getBlockFreq(CB->getParent()) <
- BFI.getEntryFreq()) {
- static BranchProbability MinBranchProbability(
- static_cast<int>(CoroElideBranchRatio * MinBlockCounterExecution),
- MinBlockCounterExecution);
- auto Prob = BranchProbability::getBranchProbability(
- BFI.getBlockFreq(CB->getParent()).getFrequency(),
- BFI.getEntryFreq().getFrequency());
-
- if (Prob < MinBranchProbability) {
- *OS << "Not eliding " << *CB
- << " with estimated probability: " << Prob << "\n";
- continue;
- }
-
- *OS << "BB Prob: \t" << Prob << "\n";
- } else {
- *OS << "BB Freq: \t"
- << BFI.getBlockFreq(CB->getParent()).getFrequency() << "\n";
- *OS << "Entry Freq: \t" << BFI.getEntryFreq().getFrequency() << "\n";
+ auto Prob = BranchProbability::getBranchProbability(
+ BFI.getBlockFreq(CB->getParent()).getFrequency(),
+ BFI.getEntryFreq().getFrequency());
+
+ if (Prob < MinBranchProbability) {
+ ORE.emit([&]() {
+ return OptimizationRemarkMissed(DEBUG_TYPE, "CoroAnnotationElideUnlikely", Caller)
+ << "'" << ore::NV("callee", Callee->getName())
+ << "' not elided in '" << ore::NV("caller", Caller->getName())
+ << "' because of low probability: " << ore::NV("probability", Prob)
+ << " (threshold: " << ore::NV("threshold", MinBranchProbability) << ")";
+ });
+ continue;
}
- *OS << "eliding " << *CB << "\n";
-
auto *CallerN = CG.lookup(*Caller);
auto *CallerC = CallerN ? CG.lookupSCC(*CallerN) : nullptr;
// If CallerC is nullptr, it means LazyCallGraph hasn't visited Caller
@@ -233,7 +185,7 @@ PreservedAnalyses CoroAnnotationElidePass::run(LazyCallGraph::SCC &C,
return OptimizationRemark(DEBUG_TYPE, "CoroAnnotationElide", Caller)
<< "'" << ore::NV("callee", Callee->getName())
<< "' elided in '" << ore::NV("caller", Caller->getName())
- << "'";
+ << "' (probability: " << ore::NV("probability", Prob) << ")";
});
FAM.invalidate(*Caller, PreservedAnalyses::none());
>From 1304785a1197dffbbeeea66b6faf41233b171e8a Mon Sep 17 00:00:00 2001
From: Adrian Vogelsgesang <avogelsgesang at salesforce.com>
Date: Tue, 7 Oct 2025 11:59:40 +0000
Subject: [PATCH 3/4] Change test case
---
.../Coroutines/coro-conditional-elide.ll | 79 -------------------
...sform-must-elide.ll => coro-elide-safe.ll} | 28 ++++++-
2 files changed, 25 insertions(+), 82 deletions(-)
delete mode 100644 llvm/test/Transforms/Coroutines/coro-conditional-elide.ll
rename llvm/test/Transforms/Coroutines/{coro-transform-must-elide.ll => coro-elide-safe.ll} (74%)
diff --git a/llvm/test/Transforms/Coroutines/coro-conditional-elide.ll b/llvm/test/Transforms/Coroutines/coro-conditional-elide.ll
deleted file mode 100644
index 04c5bf0494278..0000000000000
--- a/llvm/test/Transforms/Coroutines/coro-conditional-elide.ll
+++ /dev/null
@@ -1,79 +0,0 @@
-; Testing elide performed its job for calls to coroutines marked safe.
-; RUN: opt < %s -S -passes='cgscc(coro-annotation-elide)' -coro-elide-branch-ratio=0.55 | FileCheck %s
-
-%struct.Task = type { ptr }
-
-declare void @print(i32) nounwind
-
-; resume part of the coroutine
-define fastcc void @callee.resume(ptr dereferenceable(1)) {
- tail call void @print(i32 0)
- ret void
-}
-
-; destroy part of the coroutine
-define fastcc void @callee.destroy(ptr) {
- tail call void @print(i32 1)
- ret void
-}
-
-; cleanup part of the coroutine
-define fastcc void @callee.cleanup(ptr) {
- tail call void @print(i32 2)
- ret void
-}
-
- at callee.resumers = internal constant [3 x ptr] [
- ptr @callee.resume, ptr @callee.destroy, ptr @callee.cleanup]
-
-declare void @alloc(i1) nounwind
-
-; CHECK-LABEL: define ptr @callee
-define ptr @callee(i8 %arg) {
-entry:
- %task = alloca %struct.Task, align 8
- %id = call token @llvm.coro.id(i32 0, ptr null,
- ptr @callee,
- ptr @callee.resumers)
- %alloc = call i1 @llvm.coro.alloc(token %id)
- %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
- store ptr %hdl, ptr %task
- ret ptr %task
-}
-
-; CHECK-LABEL: define ptr @callee.noalloc
-define ptr @callee.noalloc(i8 %arg, ptr dereferenceable(32) align(8) %frame) {
- entry:
- %task = alloca %struct.Task, align 8
- %id = call token @llvm.coro.id(i32 0, ptr null,
- ptr @callee,
- ptr @callee.resumers)
- %hdl = call ptr @llvm.coro.begin(token %id, ptr null)
- store ptr %hdl, ptr %task
- ret ptr %task
-}
-
-; CHECK-LABEL: define ptr @caller(i1 %cond)
-; Function Attrs: presplitcoroutine
-define ptr @caller(i1 %cond) #0 {
-entry:
- br i1 %cond, label %call, label %ret
-
-call:
- %task = call ptr @callee(i8 0) #1
- br label %ret
-
-ret:
- %retval = phi ptr [ %task, %call ], [ null, %entry ]
- ret ptr %retval
- ; CHECK-NOT: alloca
-}
-
-declare token @llvm.coro.id(i32, ptr, ptr, ptr)
-declare ptr @llvm.coro.begin(token, ptr)
-declare ptr @llvm.coro.frame()
-declare ptr @llvm.coro.subfn.addr(ptr, i8)
-declare i1 @llvm.coro.alloc(token)
-
-attributes #0 = { presplitcoroutine }
-attributes #1 = { coro_elide_safe }
diff --git a/llvm/test/Transforms/Coroutines/coro-transform-must-elide.ll b/llvm/test/Transforms/Coroutines/coro-elide-safe.ll
similarity index 74%
rename from llvm/test/Transforms/Coroutines/coro-transform-must-elide.ll
rename to llvm/test/Transforms/Coroutines/coro-elide-safe.ll
index 4eec7edad8b0f..722693d4caafd 100644
--- a/llvm/test/Transforms/Coroutines/coro-transform-must-elide.ll
+++ b/llvm/test/Transforms/Coroutines/coro-elide-safe.ll
@@ -1,4 +1,8 @@
-; Testing elide performed its job for calls to coroutines marked safe.
+; Coroutine calls marked with `coro_elide_safe` should be elided.
+; Inside `caller`, we expect the `callee` coroutine to be elided.
+; Inside `caller_conditional`, `callee` is only called on an unlikely
+; path, hence we expect the `callee` coroutine NOT to be elided.
+;
; RUN: opt < %s -S -passes='cgscc(coro-annotation-elide)' | FileCheck %s
%struct.Task = type { ptr }
@@ -57,7 +61,7 @@ define ptr @callee.noalloc(i8 %arg, ptr dereferenceable(32) align(8) %frame) {
; Function Attrs: presplitcoroutine
define ptr @caller() #0 {
entry:
- %task = call ptr @callee(i8 0) #1
+ %task = call ptr @callee(i8 0) coro_elide_safe
ret ptr %task
; CHECK: %[[TASK:.+]] = alloca %struct.Task, align 8
; CHECK-NEXT: %[[FRAME:.+]] = alloca [32 x i8], align 8
@@ -69,6 +73,25 @@ entry:
; CHECK-NEXT: ret ptr %[[TASK]]
}
+; CHECK-LABEL: define ptr @caller_conditional(i1 %cond)
+; Function Attrs: presplitcoroutine
+define ptr @caller_conditional(i1 %cond) #0 {
+entry:
+ br i1 %cond, label %call, label %ret
+
+call:
+ ; CHECK-NOT: alloca
+ ; CHECK-NOT: @llvm.coro.id({{.*}}, ptr @callee, {{.*}})
+ ; CHECK: %task = call ptr @callee(i8 0)
+ ; CHECK-NEXT: br label %ret
+ %task = call ptr @callee(i8 0) coro_elide_safe
+ br label %ret
+
+ret:
+ %retval = phi ptr [ %task, %call ], [ null, %entry ]
+ ret ptr %retval
+}
+
declare token @llvm.coro.id(i32, ptr, ptr, ptr)
declare ptr @llvm.coro.begin(token, ptr)
declare ptr @llvm.coro.frame()
@@ -76,4 +99,3 @@ declare ptr @llvm.coro.subfn.addr(ptr, i8)
declare i1 @llvm.coro.alloc(token)
attributes #0 = { presplitcoroutine }
-attributes #1 = { coro_elide_safe }
>From b2ac353139444af7d5482f70d87e53e918a34fc2 Mon Sep 17 00:00:00 2001
From: Adrian Vogelsgesang <avogelsgesang at salesforce.com>
Date: Tue, 7 Oct 2025 12:38:27 +0000
Subject: [PATCH 4/4] Fix formatting
---
llvm/lib/IR/DiagnosticInfo.cpp | 2 +-
.../Coroutines/CoroAnnotationElide.cpp | 17 ++++++++++-------
2 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/llvm/lib/IR/DiagnosticInfo.cpp b/llvm/lib/IR/DiagnosticInfo.cpp
index 44574362e3405..8e6d654f6afb3 100644
--- a/llvm/lib/IR/DiagnosticInfo.cpp
+++ b/llvm/lib/IR/DiagnosticInfo.cpp
@@ -275,7 +275,7 @@ DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
DiagnosticInfoOptimizationBase::Argument::Argument(StringRef Key,
BranchProbability P)
-: Key(std::string(Key)) {
+ : Key(std::string(Key)) {
raw_string_ostream OS(Val);
P.print(OS);
}
diff --git a/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp b/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp
index 6cbda6b38768d..120ffc489fa68 100644
--- a/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp
+++ b/llvm/lib/Transforms/Coroutines/CoroAnnotationElide.cpp
@@ -154,8 +154,8 @@ PreservedAnalyses CoroAnnotationElidePass::run(LazyCallGraph::SCC &C,
bool HasAttr = CB->hasFnAttr(llvm::Attribute::CoroElideSafe);
if (IsCallerPresplitCoroutine && HasAttr) {
static BranchProbability MinBranchProbability(
- static_cast<int>(CoroElideBranchRatio * MinBlockCounterExecution),
- MinBlockCounterExecution);
+ static_cast<int>(CoroElideBranchRatio * MinBlockCounterExecution),
+ MinBlockCounterExecution);
auto &BFI = FAM.getResult<BlockFrequencyAnalysis>(*Caller);
@@ -165,11 +165,14 @@ PreservedAnalyses CoroAnnotationElidePass::run(LazyCallGraph::SCC &C,
if (Prob < MinBranchProbability) {
ORE.emit([&]() {
- return OptimizationRemarkMissed(DEBUG_TYPE, "CoroAnnotationElideUnlikely", Caller)
- << "'" << ore::NV("callee", Callee->getName())
- << "' not elided in '" << ore::NV("caller", Caller->getName())
- << "' because of low probability: " << ore::NV("probability", Prob)
- << " (threshold: " << ore::NV("threshold", MinBranchProbability) << ")";
+ return OptimizationRemarkMissed(
+ DEBUG_TYPE, "CoroAnnotationElideUnlikely", Caller)
+ << "'" << ore::NV("callee", Callee->getName())
+ << "' not elided in '"
+ << ore::NV("caller", Caller->getName())
+ << "' because of low probability: "
+ << ore::NV("probability", Prob) << " (threshold: "
+ << ore::NV("threshold", MinBranchProbability) << ")";
});
continue;
}
More information about the llvm-commits
mailing list