Skip to content

Commit 9243841

Browse files
committed
Revert "[coro][CoroSplit] Use llvm.lifetime.end to compute putting objects on the frame vs the stack (#90265)"
This reverts commit fcf341d. Causes major compile-time regressions when not using coroutines.
1 parent 6e5ed35 commit 9243841

File tree

4 files changed

+24
-222
lines changed

4 files changed

+24
-222
lines changed

llvm/include/llvm/Analysis/CFG.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,18 +96,6 @@ bool isPotentiallyReachableFromMany(
9696
const SmallPtrSetImpl<BasicBlock *> *ExclusionSet,
9797
const DominatorTree *DT = nullptr, const LoopInfo *LI = nullptr);
9898

99-
/// Determine whether there is a potentially a path from at least one block in
100-
/// 'Worklist' to at least one block in 'StopSet' within a single function
101-
/// without passing through any of the blocks in 'ExclusionSet'. Returns false
102-
/// only if we can prove that once any block in 'Worklist' has been reached then
103-
/// no blocks in 'StopSet' can be executed without passing through any blocks in
104-
/// 'ExclusionSet'. Conservatively returns true.
105-
bool isManyPotentiallyReachableFromMany(
106-
SmallVectorImpl<BasicBlock *> &Worklist,
107-
const SmallPtrSetImpl<const BasicBlock *> &StopSet,
108-
const SmallPtrSetImpl<BasicBlock *> *ExclusionSet,
109-
const DominatorTree *DT = nullptr, const LoopInfo *LI = nullptr);
110-
11199
/// Return true if the control flow in \p RPOTraversal is irreducible.
112100
///
113101
/// This is a generic implementation to detect CFG irreducibility based on loop

llvm/lib/Analysis/CFG.cpp

Lines changed: 7 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -134,21 +134,10 @@ bool llvm::isPotentiallyReachableFromMany(
134134
SmallVectorImpl<BasicBlock *> &Worklist, const BasicBlock *StopBB,
135135
const SmallPtrSetImpl<BasicBlock *> *ExclusionSet, const DominatorTree *DT,
136136
const LoopInfo *LI) {
137-
return isManyPotentiallyReachableFromMany(
138-
Worklist, llvm::SmallPtrSet<const BasicBlock *, 1>{StopBB}, ExclusionSet,
139-
DT, LI);
140-
}
141-
142-
bool llvm::isManyPotentiallyReachableFromMany(
143-
SmallVectorImpl<BasicBlock *> &Worklist,
144-
const SmallPtrSetImpl<const BasicBlock *> &StopSet,
145-
const SmallPtrSetImpl<BasicBlock *> *ExclusionSet, const DominatorTree *DT,
146-
const LoopInfo *LI) {
147-
// When a stop block is unreachable, it's dominated from everywhere,
137+
// When the stop block is unreachable, it's dominated from everywhere,
148138
// regardless of whether there's a path between the two blocks.
149-
llvm::DenseMap<const BasicBlock *, bool> StopBBReachable;
150-
for (auto *BB : StopSet)
151-
StopBBReachable[BB] = DT && DT->isReachableFromEntry(BB);
139+
if (DT && !DT->isReachableFromEntry(StopBB))
140+
DT = nullptr;
152141

153142
// We can't skip directly from a block that dominates the stop block if the
154143
// exclusion block is potentially in between.
@@ -166,23 +155,19 @@ bool llvm::isManyPotentiallyReachableFromMany(
166155
}
167156
}
168157

169-
llvm::DenseMap<const BasicBlock *, const Loop *> StopLoops;
170-
for (auto *StopBB : StopSet)
171-
StopLoops[StopBB] = LI ? getOutermostLoop(LI, StopBB) : nullptr;
158+
const Loop *StopLoop = LI ? getOutermostLoop(LI, StopBB) : nullptr;
172159

173160
unsigned Limit = DefaultMaxBBsToExplore;
174161
SmallPtrSet<const BasicBlock*, 32> Visited;
175162
do {
176163
BasicBlock *BB = Worklist.pop_back_val();
177164
if (!Visited.insert(BB).second)
178165
continue;
179-
if (StopSet.contains(BB))
166+
if (BB == StopBB)
180167
return true;
181168
if (ExclusionSet && ExclusionSet->count(BB))
182169
continue;
183-
if (DT && llvm::any_of(StopSet, [&](const BasicBlock *StopBB) {
184-
return StopBBReachable[BB] && DT->dominates(BB, StopBB);
185-
}))
170+
if (DT && DT->dominates(BB, StopBB))
186171
return true;
187172

188173
const Loop *Outer = nullptr;
@@ -194,10 +179,7 @@ bool llvm::isManyPotentiallyReachableFromMany(
194179
// excluded block. Clear Outer so we process BB's successors.
195180
if (LoopsWithHoles.count(Outer))
196181
Outer = nullptr;
197-
if (llvm::any_of(StopSet, [&](const BasicBlock *StopBB) {
198-
const Loop *StopLoop = StopLoops[StopBB];
199-
return StopLoop && StopLoop == Outer;
200-
}))
182+
if (StopLoop && Outer == StopLoop)
201183
return true;
202184
}
203185

llvm/lib/Transforms/Coroutines/CoroFrame.cpp

Lines changed: 17 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
#include "llvm/ADT/PostOrderIterator.h"
2020
#include "llvm/ADT/ScopeExit.h"
2121
#include "llvm/ADT/SmallString.h"
22-
#include "llvm/Analysis/CFG.h"
2322
#include "llvm/Analysis/PtrUseVisitor.h"
2423
#include "llvm/Analysis/StackLifetime.h"
2524
#include "llvm/Config/llvm-config.h"
@@ -1441,22 +1440,17 @@ namespace {
14411440
struct AllocaUseVisitor : PtrUseVisitor<AllocaUseVisitor> {
14421441
using Base = PtrUseVisitor<AllocaUseVisitor>;
14431442
AllocaUseVisitor(const DataLayout &DL, const DominatorTree &DT,
1444-
const coro::Shape &CoroShape,
1445-
const SuspendCrossingInfo &Checker,
1443+
const CoroBeginInst &CB, const SuspendCrossingInfo &Checker,
14461444
bool ShouldUseLifetimeStartInfo)
1447-
: PtrUseVisitor(DL), DT(DT), CoroShape(CoroShape), Checker(Checker),
1448-
ShouldUseLifetimeStartInfo(ShouldUseLifetimeStartInfo) {
1449-
for (AnyCoroSuspendInst *SuspendInst : CoroShape.CoroSuspends)
1450-
CoroSuspendBBs.insert(SuspendInst->getParent());
1451-
}
1445+
: PtrUseVisitor(DL), DT(DT), CoroBegin(CB), Checker(Checker),
1446+
ShouldUseLifetimeStartInfo(ShouldUseLifetimeStartInfo) {}
14521447

14531448
void visit(Instruction &I) {
14541449
Users.insert(&I);
14551450
Base::visit(I);
14561451
// If the pointer is escaped prior to CoroBegin, we have to assume it would
14571452
// be written into before CoroBegin as well.
1458-
if (PI.isEscaped() &&
1459-
!DT.dominates(CoroShape.CoroBegin, PI.getEscapingInst())) {
1453+
if (PI.isEscaped() && !DT.dominates(&CoroBegin, PI.getEscapingInst())) {
14601454
MayWriteBeforeCoroBegin = true;
14611455
}
14621456
}
@@ -1559,19 +1553,10 @@ struct AllocaUseVisitor : PtrUseVisitor<AllocaUseVisitor> {
15591553
// When we found the lifetime markers refers to a
15601554
// subrange of the original alloca, ignore the lifetime
15611555
// markers to avoid misleading the analysis.
1562-
if (!IsOffsetKnown || !Offset.isZero())
1563-
return Base::visitIntrinsicInst(II);
1564-
switch (II.getIntrinsicID()) {
1565-
default:
1556+
if (II.getIntrinsicID() != Intrinsic::lifetime_start || !IsOffsetKnown ||
1557+
!Offset.isZero())
15661558
return Base::visitIntrinsicInst(II);
1567-
case Intrinsic::lifetime_start:
1568-
LifetimeStarts.insert(&II);
1569-
LifetimeStartBBs.push_back(II.getParent());
1570-
break;
1571-
case Intrinsic::lifetime_end:
1572-
LifetimeEndBBs.insert(II.getParent());
1573-
break;
1574-
}
1559+
LifetimeStarts.insert(&II);
15751560
}
15761561

15771562
void visitCallBase(CallBase &CB) {
@@ -1601,17 +1586,14 @@ struct AllocaUseVisitor : PtrUseVisitor<AllocaUseVisitor> {
16011586

16021587
private:
16031588
const DominatorTree &DT;
1604-
const coro::Shape &CoroShape;
1589+
const CoroBeginInst &CoroBegin;
16051590
const SuspendCrossingInfo &Checker;
16061591
// All alias to the original AllocaInst, created before CoroBegin and used
16071592
// after CoroBegin. Each entry contains the instruction and the offset in the
16081593
// original Alloca. They need to be recreated after CoroBegin off the frame.
16091594
DenseMap<Instruction *, std::optional<APInt>> AliasOffetMap{};
16101595
SmallPtrSet<Instruction *, 4> Users{};
16111596
SmallPtrSet<IntrinsicInst *, 2> LifetimeStarts{};
1612-
SmallVector<BasicBlock *> LifetimeStartBBs{};
1613-
SmallPtrSet<BasicBlock *, 2> LifetimeEndBBs{};
1614-
SmallPtrSet<const BasicBlock *, 2> CoroSuspendBBs{};
16151597
bool MayWriteBeforeCoroBegin{false};
16161598
bool ShouldUseLifetimeStartInfo{true};
16171599

@@ -1623,19 +1605,10 @@ struct AllocaUseVisitor : PtrUseVisitor<AllocaUseVisitor> {
16231605
// every basic block that uses the pointer to see if they cross suspension
16241606
// points. The uses cover both direct uses as well as indirect uses.
16251607
if (ShouldUseLifetimeStartInfo && !LifetimeStarts.empty()) {
1626-
// If there is no explicit lifetime.end, then assume the address can
1627-
// cross suspension points.
1628-
if (LifetimeEndBBs.empty())
1629-
return true;
1630-
1631-
// If there is a path from a lifetime.start to a suspend without a
1632-
// corresponding lifetime.end, then the alloca's lifetime persists
1633-
// beyond that suspension point and the alloca must go on the frame.
1634-
llvm::SmallVector<BasicBlock *> Worklist(LifetimeStartBBs);
1635-
if (isManyPotentiallyReachableFromMany(Worklist, CoroSuspendBBs,
1636-
&LifetimeEndBBs, &DT))
1637-
return true;
1638-
1608+
for (auto *I : Users)
1609+
for (auto *S : LifetimeStarts)
1610+
if (Checker.isDefinitionAcrossSuspend(*S, I))
1611+
return true;
16391612
// Addresses are guaranteed to be identical after every lifetime.start so
16401613
// we cannot use the local stack if the address escaped and there is a
16411614
// suspend point between lifetime markers. This should also cover the
@@ -1673,13 +1646,13 @@ struct AllocaUseVisitor : PtrUseVisitor<AllocaUseVisitor> {
16731646
}
16741647

16751648
void handleMayWrite(const Instruction &I) {
1676-
if (!DT.dominates(CoroShape.CoroBegin, &I))
1649+
if (!DT.dominates(&CoroBegin, &I))
16771650
MayWriteBeforeCoroBegin = true;
16781651
}
16791652

16801653
bool usedAfterCoroBegin(Instruction &I) {
16811654
for (auto &U : I.uses())
1682-
if (DT.dominates(CoroShape.CoroBegin, U))
1655+
if (DT.dominates(&CoroBegin, U))
16831656
return true;
16841657
return false;
16851658
}
@@ -1688,7 +1661,7 @@ struct AllocaUseVisitor : PtrUseVisitor<AllocaUseVisitor> {
16881661
// We track all aliases created prior to CoroBegin but used after.
16891662
// These aliases may need to be recreated after CoroBegin if the alloca
16901663
// need to live on the frame.
1691-
if (DT.dominates(CoroShape.CoroBegin, &I) || !usedAfterCoroBegin(I))
1664+
if (DT.dominates(&CoroBegin, &I) || !usedAfterCoroBegin(I))
16921665
return;
16931666

16941667
if (!IsOffsetKnown) {
@@ -2857,7 +2830,8 @@ static void collectFrameAlloca(AllocaInst *AI, coro::Shape &Shape,
28572830
bool ShouldUseLifetimeStartInfo =
28582831
(Shape.ABI != coro::ABI::Async && Shape.ABI != coro::ABI::Retcon &&
28592832
Shape.ABI != coro::ABI::RetconOnce);
2860-
AllocaUseVisitor Visitor{AI->getModule()->getDataLayout(), DT, Shape, Checker,
2833+
AllocaUseVisitor Visitor{AI->getModule()->getDataLayout(), DT,
2834+
*Shape.CoroBegin, Checker,
28612835
ShouldUseLifetimeStartInfo};
28622836
Visitor.visitPtr(*AI);
28632837
if (!Visitor.getShouldLiveOnFrame())

llvm/test/Transforms/Coroutines/coro-lifetime-end.ll

Lines changed: 0 additions & 142 deletions
This file was deleted.

0 commit comments

Comments
 (0)