[llvm] Fix SCC enter block collection in BPI (PR #210580)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Jul 19 01:32:45 PDT 2026
https://github.com/SomeFlyingThing updated https://github.com/llvm/llvm-project/pull/210580
>From cac5a3984be931effb38e1aaf8a69cce34b72c6f Mon Sep 17 00:00:00 2001
From: SomeFlyingThing <306498559+SomeFlyingThing at users.noreply.github.com>
Date: Sun, 19 Jul 2026 09:16:13 +0100
Subject: [PATCH 1/2] Fix SCC enter block collection in BPI
---
llvm/lib/Analysis/BranchProbabilityInfo.cpp | 2 +-
.../Analysis/BranchProbabilityInfo/loop.ll | 30 +++++++++++++++++++
2 files changed, 31 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/Analysis/BranchProbabilityInfo.cpp b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
index 1b0a8b8e74f4a..feb0b34cd4c48 100644
--- a/llvm/lib/Analysis/BranchProbabilityInfo.cpp
+++ b/llvm/lib/Analysis/BranchProbabilityInfo.cpp
@@ -391,7 +391,7 @@ void BPIConstruction::SccInfo::getSccEnterBlocks(
if (isSCCHeader(BB, SccNum))
for (const auto *Pred : predecessors(BB))
if (getSCCNum(Pred) != SccNum)
- Enters.push_back(const_cast<BasicBlock *>(BB));
+ Enters.push_back(const_cast<BasicBlock *>(Pred));
}
}
diff --git a/llvm/test/Analysis/BranchProbabilityInfo/loop.ll b/llvm/test/Analysis/BranchProbabilityInfo/loop.ll
index ffac1cd466641..e6b8429eddaa7 100644
--- a/llvm/test/Analysis/BranchProbabilityInfo/loop.ll
+++ b/llvm/test/Analysis/BranchProbabilityInfo/loop.ll
@@ -722,4 +722,34 @@ exit:
}
+; Check that a cold irreducible loop propagates its estimated weight through
+; the blocks entering the SCC.
+define void @test19(i1 %arg, i1 %arg2, i1 %arg3, i1 %arg4) {
+; CHECK: edge %entry -> %dispatch probability is 0x078780e3 / 0x80000000 = 5.88%
+; CHECK: edge %entry -> %exit probability is 0x78787f1d / 0x80000000 = 94.12% [HOT edge]
+
+entry:
+ br i1 %arg, label %dispatch, label %exit
+
+dispatch:
+ br i1 %arg2, label %entry1, label %entry2
+
+entry1:
+ br label %loop1
+
+entry2:
+ br label %loop2
+
+loop1:
+ br i1 %arg3, label %loop2, label %cold
+
+loop2:
+ br i1 %arg4, label %loop1, label %cold
+cold:
+ call void @cold()
+ br label %exit
+
+exit:
+ ret void
+}
>From 15512df9332340f8511cb40dd9105fc198a65370 Mon Sep 17 00:00:00 2001
From: SomeFlyingThing <306498559+SomeFlyingThing at users.noreply.github.com>
Date: Sun, 19 Jul 2026 09:32:33 +0100
Subject: [PATCH 2/2] [StackLifetime] Handle lifetime.end-only allocas
---
llvm/include/llvm/Analysis/StackLifetime.h | 8 ++-
llvm/lib/Analysis/StackLifetime.cpp | 21 +++++---
.../Analysis/StackSafetyAnalysis/lifetime.ll | 54 +++++++++++++++++--
3 files changed, 71 insertions(+), 12 deletions(-)
diff --git a/llvm/include/llvm/Analysis/StackLifetime.h b/llvm/include/llvm/Analysis/StackLifetime.h
index ccc5fae1bc0cc..6ff3fad3f368e 100644
--- a/llvm/include/llvm/Analysis/StackLifetime.h
+++ b/llvm/include/llvm/Analysis/StackLifetime.h
@@ -108,9 +108,13 @@ class StackLifetime {
/// LiveRange for allocas.
SmallVector<LiveRange, 8> LiveRanges;
- /// The set of allocas that have at least one lifetime.start. All other
+ /// The set of allocas that have at least one lifetime marker. All other
/// allocas get LiveRange that corresponds to the entire function.
- BitVector InterestingAllocas;
+ BitVector MarkerAllocas;
+
+ /// The set of allocas that have at least one lifetime.start and are
+ /// therefore initially dead.
+ BitVector StartAllocas;
struct Marker {
unsigned AllocaNo;
diff --git a/llvm/lib/Analysis/StackLifetime.cpp b/llvm/lib/Analysis/StackLifetime.cpp
index 30e0316b882cc..726b743f60ae3 100644
--- a/llvm/lib/Analysis/StackLifetime.cpp
+++ b/llvm/lib/Analysis/StackLifetime.cpp
@@ -60,7 +60,8 @@ bool StackLifetime::isAliveAfter(const AllocaInst *AI,
}
void StackLifetime::collectMarkers() {
- InterestingAllocas.resize(NumAllocas);
+ MarkerAllocas.resize(NumAllocas);
+ StartAllocas.resize(NumAllocas);
DenseMap<const BasicBlock *, SmallDenseMap<const IntrinsicInst *, Marker>>
BBMarkerSet;
@@ -78,8 +79,9 @@ void StackLifetime::collectMarkers() {
continue;
auto AllocaNo = It->second;
bool IsStart = II->getIntrinsicID() == Intrinsic::lifetime_start;
+ MarkerAllocas.set(AllocaNo);
if (IsStart)
- InterestingAllocas.set(AllocaNo);
+ StartAllocas.set(AllocaNo);
BBMarkerSet[BB][II] = {AllocaNo, IsStart};
}
}
@@ -168,9 +170,16 @@ void StackLifetime::calculateLocalLiveness() {
BitsIn |= I->second.LiveOut;
}
- // Everything is "may be dead" for entry without predecessors.
- if (Type == LivenessType::Must && BitsIn.empty())
- BitsIn.resize(NumAllocas, true);
+ // Allocas with a lifetime.start are initially dead. Allocas with only
+ // lifetime.end markers are initially alive.
+ if (BB == &F.getEntryBlock()) {
+ if (Type == LivenessType::May) {
+ BitsIn = MarkerAllocas;
+ BitsIn.reset(StartAllocas);
+ } else {
+ BitsIn = StartAllocas;
+ }
+ }
// Update block LiveIn set, noting whether it has changed.
if (!BitsIn.subsetOf(BlockInfo.LiveIn)) {
@@ -303,7 +312,7 @@ StackLifetime::StackLifetime(const Function &F,
void StackLifetime::run() {
LiveRanges.resize(NumAllocas, LiveRange(Instructions.size()));
for (unsigned I = 0; I < NumAllocas; ++I)
- if (!InterestingAllocas.test(I))
+ if (!MarkerAllocas.test(I))
LiveRanges[I] = getFullLiveRange();
calculateLocalLiveness();
diff --git a/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll b/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll
index 51bfa154e957a..e67c96a3becbd 100644
--- a/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll
+++ b/llvm/test/Analysis/StackSafetyAnalysis/lifetime.ll
@@ -438,23 +438,23 @@ entry:
call void @capture32(ptr %x)
call void @llvm.lifetime.end.p0(ptr %x)
; CHECK: call void @llvm.lifetime.end.p0(ptr %x)
-; CHECK-NEXT: Alive: <x>
+; CHECK-NEXT: Alive: <>
br i1 %d, label %bb2, label %bb3
bb2: ; preds = %entry
; CHECK: bb2:
-; CHECK-NEXT: Alive: <x>
+; CHECK-NEXT: Alive: <>
call void @llvm.lifetime.start.p0(ptr %y)
; CHECK: call void @llvm.lifetime.start.p0(ptr %y)
-; CHECK-NEXT: Alive: <x y>
+; CHECK-NEXT: Alive: <y>
call void @capture32(ptr %y)
ret void
bb3: ; preds = %entry
; CHECK: bb3:
-; CHECK-NEXT: Alive: <x>
+; CHECK-NEXT: Alive: <>
ret void
}
@@ -949,6 +949,52 @@ if.end:
ret void
}
+define void @end_only() {
+; CHECK-LABEL: define void @end_only()
+entry:
+ %x = alloca i8
+; CHECK: %x = alloca i8
+; CHECK-NEXT: Alive: <x>
+
+ call void @llvm.lifetime.end.p0(ptr %x)
+; CHECK: call void @llvm.lifetime.end.p0(ptr %x)
+; CHECK-NEXT: Alive: <>
+
+ ret void
+}
+
+define void @end_only_propagates() {
+; CHECK-LABEL: define void @end_only_propagates()
+entry:
+ %x = alloca i8
+ call void @llvm.lifetime.end.p0(ptr %x)
+
+ br label %next
+; CHECK: br label %next
+; CHECK-NEXT: Alive: <>
+
+next:
+; CHECK: next:
+; CHECK-NEXT: Alive: <>
+ ret void
+}
+
+define void @start_propagates() {
+; CHECK-LABEL: define void @start_propagates()
+entry:
+ %x = alloca i8
+ call void @llvm.lifetime.start.p0(ptr %x)
+
+ br label %next
+; CHECK: br label %next
+; CHECK-NEXT: Alive: <x>
+
+next:
+; CHECK: next:
+; CHECK-NEXT: Alive: <x>
+ ret void
+}
+
declare void @llvm.lifetime.start.p0(ptr captures(none))
declare void @llvm.lifetime.end.p0(ptr captures(none))
declare void @capture8(ptr)
More information about the llvm-commits
mailing list