Skip to content

Commit be258a2

Browse files
authored
[SSAUpdaterBulk] Fix incorrect live-in values for a block. (llvm#131762)
The previous implementation incorrectly calculated incoming values from loop backedges, as demonstrated by the tests. The issue was that it did not distinguish between live-in and live-out values for blocks. This patch addresses the problem and fixes llvm#131761. To avoid bloating storage in `R.Defines`, processing data has been moved to a temporary map `BBInfos`. This change helps manage heap allocation more efficiently and likely improves caching.
1 parent 058a4e8 commit be258a2

File tree

3 files changed

+73
-37
lines changed

3 files changed

+73
-37
lines changed

llvm/include/llvm/Transforms/Utils/SSAUpdaterBulk.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class DominatorTree;
3838
/// is used).
3939
class SSAUpdaterBulk {
4040
struct RewriteInfo {
41-
DenseMap<BasicBlock *, Value *> Defines;
41+
SmallVector<std::pair<BasicBlock *, Value *>, 4> Defines;
4242
SmallVector<Use *, 4> Uses;
4343
StringRef Name;
4444
Type *Ty;
@@ -49,8 +49,6 @@ class SSAUpdaterBulk {
4949

5050
PredIteratorCache PredCache;
5151

52-
Value *computeValueAt(BasicBlock *BB, RewriteInfo &R, DominatorTree *DT);
53-
5452
public:
5553
explicit SSAUpdaterBulk() = default;
5654
SSAUpdaterBulk(const SSAUpdaterBulk &) = delete;

llvm/lib/Transforms/Utils/SSAUpdaterBulk.cpp

Lines changed: 68 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ void SSAUpdaterBulk::AddAvailableValue(unsigned Var, BasicBlock *BB, Value *V) {
5353
LLVM_DEBUG(dbgs() << "SSAUpdater: Var=" << Var
5454
<< ": added new available value " << *V << " in "
5555
<< BB->getName() << "\n");
56-
Rewrites[Var].Defines[BB] = V;
56+
Rewrites[Var].Defines.emplace_back(BB, V);
5757
}
5858

5959
/// Record a use of the symbolic value. This use will be updated with a
@@ -65,21 +65,6 @@ void SSAUpdaterBulk::AddUse(unsigned Var, Use *U) {
6565
Rewrites[Var].Uses.push_back(U);
6666
}
6767

68-
// Compute value at the given block BB. We either should already know it, or we
69-
// should be able to recursively reach it going up dominator tree.
70-
Value *SSAUpdaterBulk::computeValueAt(BasicBlock *BB, RewriteInfo &R,
71-
DominatorTree *DT) {
72-
if (!R.Defines.count(BB)) {
73-
if (DT->isReachableFromEntry(BB) && PredCache.get(BB).size()) {
74-
BasicBlock *IDom = DT->getNode(BB)->getIDom()->getBlock();
75-
Value *V = computeValueAt(IDom, R, DT);
76-
R.Defines[BB] = V;
77-
} else
78-
R.Defines[BB] = UndefValue::get(R.Ty);
79-
}
80-
return R.Defines[BB];
81-
}
82-
8368
/// Given sets of UsingBlocks and DefBlocks, compute the set of LiveInBlocks.
8469
/// This is basically a subgraph limited by DefBlocks and UsingBlocks.
8570
static void
@@ -117,11 +102,19 @@ ComputeLiveInBlocks(const SmallPtrSetImpl<BasicBlock *> &UsingBlocks,
117102
}
118103
}
119104

105+
struct BBValueInfo {
106+
Value *LiveInValue = nullptr;
107+
Value *LiveOutValue = nullptr;
108+
};
109+
120110
/// Perform all the necessary updates, including new PHI-nodes insertion and the
121111
/// requested uses update.
122112
void SSAUpdaterBulk::RewriteAllUses(DominatorTree *DT,
123113
SmallVectorImpl<PHINode *> *InsertedPHIs) {
114+
DenseMap<BasicBlock *, BBValueInfo> BBInfos;
124115
for (auto &R : Rewrites) {
116+
BBInfos.clear();
117+
125118
// Compute locations for new phi-nodes.
126119
// For that we need to initialize DefBlocks from definitions in R.Defines,
127120
// UsingBlocks from uses in R.Uses, then compute LiveInBlocks, and then use
@@ -132,8 +125,8 @@ void SSAUpdaterBulk::RewriteAllUses(DominatorTree *DT,
132125
<< " use(s)\n");
133126

134127
SmallPtrSet<BasicBlock *, 2> DefBlocks;
135-
for (auto &Def : R.Defines)
136-
DefBlocks.insert(Def.first);
128+
for (auto [BB, V] : R.Defines)
129+
DefBlocks.insert(BB);
137130
IDF.setDefiningBlocks(DefBlocks);
138131

139132
SmallPtrSet<BasicBlock *, 2> UsingBlocks;
@@ -143,34 +136,82 @@ void SSAUpdaterBulk::RewriteAllUses(DominatorTree *DT,
143136
SmallVector<BasicBlock *, 32> IDFBlocks;
144137
SmallPtrSet<BasicBlock *, 32> LiveInBlocks;
145138
ComputeLiveInBlocks(UsingBlocks, DefBlocks, LiveInBlocks, PredCache);
146-
IDF.resetLiveInBlocks();
147139
IDF.setLiveInBlocks(LiveInBlocks);
148140
IDF.calculate(IDFBlocks);
149141

142+
// Reserve sufficient buckets to prevent map growth. [1]
143+
BBInfos.reserve(LiveInBlocks.size() + DefBlocks.size());
144+
145+
for (auto [BB, V] : R.Defines)
146+
BBInfos[BB].LiveOutValue = V;
147+
150148
// We've computed IDF, now insert new phi-nodes there.
151-
SmallVector<PHINode *, 4> InsertedPHIsForVar;
152149
for (auto *FrontierBB : IDFBlocks) {
153150
IRBuilder<> B(FrontierBB, FrontierBB->begin());
154151
PHINode *PN = B.CreatePHI(R.Ty, 0, R.Name);
155-
R.Defines[FrontierBB] = PN;
156-
InsertedPHIsForVar.push_back(PN);
152+
BBInfos[FrontierBB].LiveInValue = PN;
157153
if (InsertedPHIs)
158154
InsertedPHIs->push_back(PN);
159155
}
160156

157+
// IsLiveOut indicates whether we are computing live-out values (true) or
158+
// live-in values (false).
159+
auto ComputeValue = [&](BasicBlock *BB, bool IsLiveOut) -> Value * {
160+
auto *BBInfo = &BBInfos[BB];
161+
162+
if (IsLiveOut && BBInfo->LiveOutValue)
163+
return BBInfo->LiveOutValue;
164+
165+
if (BBInfo->LiveInValue)
166+
return BBInfo->LiveInValue;
167+
168+
SmallVector<BBValueInfo *, 4> Stack = {BBInfo};
169+
Value *V = nullptr;
170+
171+
while (DT->isReachableFromEntry(BB) && !PredCache.get(BB).empty() &&
172+
(BB = DT->getNode(BB)->getIDom()->getBlock())) {
173+
BBInfo = &BBInfos[BB];
174+
175+
if (BBInfo->LiveOutValue) {
176+
V = BBInfo->LiveOutValue;
177+
break;
178+
}
179+
180+
if (BBInfo->LiveInValue) {
181+
V = BBInfo->LiveInValue;
182+
break;
183+
}
184+
185+
Stack.emplace_back(BBInfo);
186+
}
187+
188+
if (!V)
189+
V = UndefValue::get(R.Ty);
190+
191+
for (auto *BBInfo : Stack)
192+
// Loop above can insert new entries into the BBInfos map: assume the
193+
// map shouldn't grow due to [1] and BBInfo references are valid.
194+
BBInfo->LiveInValue = V;
195+
196+
return V;
197+
};
198+
161199
// Fill in arguments of the inserted PHIs.
162-
for (auto *PN : InsertedPHIsForVar) {
163-
BasicBlock *PBB = PN->getParent();
164-
for (BasicBlock *Pred : PredCache.get(PBB))
165-
PN->addIncoming(computeValueAt(Pred, R, DT), Pred);
200+
for (auto *BB : IDFBlocks) {
201+
auto *PHI = cast<PHINode>(&BB->front());
202+
for (BasicBlock *Pred : PredCache.get(BB))
203+
PHI->addIncoming(ComputeValue(Pred, /*IsLiveOut=*/true), Pred);
166204
}
167205

168206
// Rewrite actual uses with the inserted definitions.
169207
SmallPtrSet<Use *, 4> ProcessedUses;
170208
for (Use *U : R.Uses) {
171209
if (!ProcessedUses.insert(U).second)
172210
continue;
173-
Value *V = computeValueAt(getUserBB(U), R, DT);
211+
212+
auto *User = cast<Instruction>(U->getUser());
213+
BasicBlock *BB = getUserBB(U);
214+
Value *V = ComputeValue(BB, /*IsLiveOut=*/BB != User->getParent());
174215
Value *OldVal = U->get();
175216
assert(OldVal && "Invalid use!");
176217
// Notify that users of the existing value that it is being replaced.

llvm/unittests/Transforms/Utils/SSAUpdaterBulkTest.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include "llvm/IR/LLVMContext.h"
1616
#include "llvm/IR/Module.h"
1717
#include "llvm/Support/SourceMgr.h"
18-
#include "gtest/gtest-spi.h"
1918
#include "gtest/gtest.h"
2019

2120
using namespace llvm;
@@ -236,7 +235,7 @@ TEST(SSAUpdaterBulk, SingleBBLoop) {
236235
Loop->dump();
237236
// Output:
238237
// loop: ; preds = %loop, %entry
239-
// %i.prev = phi i32 [ %i.prev, %loop ], [ 0, %entry ]
238+
// %i.prev = phi i32 [ %i, %loop ], [ 0, %entry ]
240239
// %i = add i32 %i.prev, 1
241240
// %cmp = icmp slt i32 %i, 42
242241
// br i1 %cmp, label %loop, label %exit
@@ -246,8 +245,7 @@ TEST(SSAUpdaterBulk, SingleBBLoop) {
246245
PHINode *Phi = Inserted[0];
247246
EXPECT_EQ(Phi, dyn_cast<PHINode>(I->getOperand(0)));
248247
EXPECT_EQ(Phi->getIncomingValueForBlock(Entry), ConstantInt::get(I32Ty, 0));
249-
EXPECT_NONFATAL_FAILURE(EXPECT_EQ(Phi->getIncomingValueForBlock(Loop), I),
250-
"Expected equality of these values");
248+
EXPECT_EQ(Phi->getIncomingValueForBlock(Loop), I);
251249
}
252250

253251
TEST(SSAUpdaterBulk, TwoBBLoop) {
@@ -298,15 +296,14 @@ TEST(SSAUpdaterBulk, TwoBBLoop) {
298296
// %i.prev = phi i32 [ %i, %loop ], [ 0, %entry ]
299297
// br label %loop
300298
// loop: ; preds = %loop_header
301-
// %i = add i32 %i, 1
299+
// %i = add i32 %i.prev, 1
302300
// %cmp = icmp slt i32 %i, 42
303301
// br i1 %cmp, label %loop_header, label %exit
304302
#endif
305303

306304
ASSERT_EQ(Inserted.size(), 1u);
307305
PHINode *Phi = Inserted[0];
308-
EXPECT_NONFATAL_FAILURE(EXPECT_EQ(Phi, dyn_cast<PHINode>(I->getOperand(0))),
309-
"Expected equality of these values");
306+
EXPECT_EQ(Phi, dyn_cast<PHINode>(I->getOperand(0)));
310307
EXPECT_EQ(Phi->getParent(), LoopHdr);
311308
EXPECT_EQ(Phi->getIncomingValueForBlock(Entry), ConstantInt::get(I32Ty, 0));
312309
EXPECT_EQ(Phi->getIncomingValueForBlock(Loop), I);

0 commit comments

Comments
 (0)