[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