Skip to content

Commit 650b53d

Browse files
committed
[Bitcode] Fix incomplete deduplication of PHI entries
1 parent 394e7de commit 650b53d

File tree

6 files changed

+112
-6
lines changed

6 files changed

+112
-6
lines changed

llvm/include/llvm/IR/BasicBlock.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,10 @@ class BasicBlock final : public Value, // Basic blocks are data objects also
703703
/// block \p New instead of to it.
704704
LLVM_ABI void replaceSuccessorsPhiUsesWith(BasicBlock *New);
705705

706+
/// Update all phi nodes in this basic block by deduplicating the references
707+
/// to \p BB.
708+
LLVM_ABI void deduplicatePhiUsesOf(BasicBlock *BB);
709+
706710
/// Return true if this basic block is an exception handling block.
707711
bool isEHPad() const { return getFirstNonPHIIt()->isEHPad(); }
708712

llvm/lib/Bitcode/Reader/BitcodeReader.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6105,18 +6105,14 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
61056105
// seen value here, to avoid expanding a constant expression multiple
61066106
// times.
61076107
auto It = Args.find(BB);
6108-
BasicBlock *EdgeBB = ConstExprEdgeBBs.lookup({BB, CurBB});
61096108
if (It != Args.end()) {
6110-
// If this predecessor was also replaced with a constexpr basic
6111-
// block, it must be de-duplicated.
6112-
if (!EdgeBB) {
6113-
PN->addIncoming(It->second, BB);
6114-
}
6109+
PN->addIncoming(It->second, BB);
61156110
continue;
61166111
}
61176112

61186113
// If there already is a block for this edge (from a different phi),
61196114
// use it.
6115+
BasicBlock *EdgeBB = ConstExprEdgeBBs.lookup({BB, CurBB});
61206116
if (!EdgeBB) {
61216117
// Otherwise, use a temporary block (that we will discard if it
61226118
// turns out to be unnecessary).
@@ -6944,6 +6940,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) {
69446940
BranchInst::Create(To, EdgeBB);
69456941
From->getTerminator()->replaceSuccessorWith(To, EdgeBB);
69466942
To->replacePhiUsesWith(From, EdgeBB);
6943+
To->deduplicatePhiUsesOf(EdgeBB);
69476944
EdgeBB->moveBefore(To);
69486945
}
69496946

llvm/lib/IR/BasicBlock.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,26 @@ void BasicBlock::replaceSuccessorsPhiUsesWith(BasicBlock *New) {
658658
this->replaceSuccessorsPhiUsesWith(this, New);
659659
}
660660

661+
void BasicBlock::deduplicatePhiUsesOf(BasicBlock *BB) {
662+
// N.B. This might not be a complete BasicBlock, so don't assume
663+
// that it ends with a non-phi instruction.
664+
for (Instruction &I : *this) {
665+
PHINode *PN = dyn_cast<PHINode>(&I);
666+
if (!PN)
667+
break;
668+
// Since the order of basic blocks in a PHINode are sorted we can
669+
// use the index of \p BB + 1 as the first index to check for duplicates.
670+
unsigned Idx = PN->getBasicBlockIndex(BB) + 1;
671+
while (Idx < PN->getNumIncomingValues()) {
672+
BasicBlock *DuplicateBB = PN->getIncomingBlock(Idx);
673+
if (DuplicateBB != BB) {
674+
break;
675+
}
676+
PN->removeIncomingValue(Idx);
677+
}
678+
}
679+
}
680+
661681
bool BasicBlock::isLandingPad() const {
662682
return isa<LandingPadInst>(getFirstNonPHIIt());
663683
}

llvm/test/Bitcode/constexpr-to-instr-dups.ll

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,30 @@ cont:
2828
[1, %nonconst]
2929
ret i32 %res
3030
}
31+
32+
define i32 @test_multiple_phis(i32 %arg) {
33+
entry:
34+
switch i32 %arg, label %cont [
35+
i32 1, label %cont
36+
i32 2, label %nonconst
37+
]
38+
39+
nonconst: ; preds = %entry
40+
%cmp = icmp ne i32 %arg, 2
41+
br i1 %cmp, label %cont, label %cont
42+
43+
; CHECK-LABEL: phi.constexpr:
44+
; CHECK-NEXT: %constexpr = ptrtoint ptr @foo to i32
45+
; CHECK-NEXT: %constexpr1 = or i32 %constexpr, 5
46+
; CHECK-NEXT: br label %cont
47+
48+
49+
; CHECK-LABEL: cont:
50+
; CHECK-NEXT: %phi1 = phi i32 [ 0, %phi.constexpr ], [ 1, %nonconst ], [ 1, %nonconst ]
51+
; CHECK-NEXT: %phi2 = phi i32 [ %constexpr1, %phi.constexpr ], [ 1, %nonconst ], [ 1, %nonconst ]
52+
; CHECK-NEXT: ret i32 %phi2
53+
cont: ; preds = %nonconst, %nonconst, %entry, %entry
54+
%phi1 = phi i32 [ 0, %entry ], [ 0, %entry ], [ 1, %nonconst ], [ 1, %nonconst ]
55+
%phi2 = phi i32 [ or (i32 ptrtoint (ptr @foo to i32), i32 5), %entry ], [ or (i32 ptrtoint (ptr @foo to i32), i32 5), %entry ], [ 1, %nonconst ], [ 1, %nonconst ]
56+
ret i32 %phi2
57+
}
136 Bytes
Binary file not shown.

llvm/unittests/IR/BasicBlockTest.cpp

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,64 @@ TEST(BasicBlockTest, PhiRange) {
9494
}
9595
}
9696

97+
TEST(BasicBlockTest, DeduplicatePhiEntries) {
98+
LLVMContext Context;
99+
100+
// Create the main block.
101+
std::unique_ptr<BasicBlock> BB(BasicBlock::Create(Context));
102+
103+
// Create some predecessors of it.
104+
std::unique_ptr<BasicBlock> BB1(BasicBlock::Create(Context));
105+
BranchInst::Create(BB.get(), BB1.get());
106+
107+
// Make sure this doesn't crash if there are no phis.
108+
int PhiCount = 0;
109+
for (auto &PN : BB->phis()) {
110+
(void)PN;
111+
PhiCount++;
112+
}
113+
ASSERT_EQ(PhiCount, 0) << "empty block should have no phis";
114+
115+
// Make it a cycle.
116+
auto *BI = BranchInst::Create(BB.get(), BB.get());
117+
118+
// Now insert some PHI nodes.
119+
auto *Int32Ty = Type::getInt32Ty(Context);
120+
auto *P1 = PHINode::Create(Int32Ty, /*NumReservedValues*/ 3, "phi.1", BI);
121+
auto *P2 = PHINode::Create(Int32Ty, /*NumReservedValues*/ 3, "phi.2", BI);
122+
123+
// Some non-PHI nodes.
124+
auto *Sum = BinaryOperator::CreateAdd(P1, P2, "sum", BI);
125+
126+
// Now wire up the incoming values that are interesting.
127+
P1->addIncoming(P2, BB.get());
128+
P2->addIncoming(Sum, BB.get());
129+
130+
// Wire up the rest of the incoming values, we want duplicate entries.
131+
for (auto &PN : BB->phis()) {
132+
auto *SomeValue = UndefValue::get(Int32Ty);
133+
PN.addIncoming(SomeValue, BB1.get());
134+
PN.addIncoming(SomeValue, BB1.get());
135+
}
136+
137+
// Check that the phi nodes have 3 incoming values.
138+
EXPECT_EQ(P1->getNumIncomingValues(), 3u);
139+
EXPECT_EQ(P2->getNumIncomingValues(), 3u);
140+
141+
// Deduplicate the incoming values for BB1.
142+
BB->deduplicatePhiUsesOf(BB1.get());
143+
144+
// Check that the phi nodes have 2 incoming values.
145+
EXPECT_EQ(P1->getNumIncomingValues(), 2u);
146+
EXPECT_EQ(P2->getNumIncomingValues(), 2u);
147+
148+
// Check that the incoming values are unique.
149+
for (auto &PN : BB->phis()) {
150+
EXPECT_EQ(BB.get(), PN.getIncomingBlock(0));
151+
EXPECT_EQ(BB1.get(), PN.getIncomingBlock(1));
152+
}
153+
}
154+
97155
#define CHECK_ITERATORS(Range1, Range2) \
98156
EXPECT_EQ(std::distance(Range1.begin(), Range1.end()), \
99157
std::distance(Range2.begin(), Range2.end())); \

0 commit comments

Comments
 (0)