From a1d65a5f38898b3c60bc751ef71e1df7e2a1f4fc Mon Sep 17 00:00:00 2001 From: Florian Stamer Date: Fri, 10 Oct 2025 16:15:13 +0200 Subject: [PATCH] [Bitcode] Fix incomplete deduplication of PHI entries --- llvm/lib/Bitcode/Reader/BitcodeReader.cpp | 33 ++++++++++++++---- llvm/test/Bitcode/constexpr-to-instr-dups.ll | 27 ++++++++++++++ .../Bitcode/constexpr-to-instr-dups.ll.bc | Bin 1436 -> 1572 bytes 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index aaee1f0a7687c..dae7b3966d507 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -4093,6 +4093,30 @@ GlobalValue::SanitizerMetadata deserializeSanitizerMetadata(unsigned V) { return Meta; } +static void deduplicatePhiUsesOf(BasicBlock *BB, BasicBlock *ToDeduplicateBB) { + // N.B. This might not be a complete BasicBlock, so don't assume + // that it ends with a non-phi instruction. + for (Instruction &I : *BB) { + PHINode *PN = dyn_cast(&I); + if (!PN) + break; + // Since the order of basic blocks in a PHINode are not generally sorted we + // have to iterate over all indicies. + unsigned Idx = 0; + bool SkippedFirstOccurrence = false; + while (Idx < PN->getNumIncomingValues()) { + if (PN->getIncomingBlock(Idx) == ToDeduplicateBB) { + if (SkippedFirstOccurrence) { + PN->removeIncomingValue(Idx); + continue; + } + SkippedFirstOccurrence = true; + } + ++Idx; + } + } +} + Error BitcodeReader::parseGlobalVarRecord(ArrayRef Record) { // v1: [pointer type, isconst, initid, linkage, alignment, section, // visibility, threadlocal, unnamed_addr, externally_initialized, @@ -6105,18 +6129,14 @@ Error BitcodeReader::parseFunctionBody(Function *F) { // seen value here, to avoid expanding a constant expression multiple // times. auto It = Args.find(BB); - BasicBlock *EdgeBB = ConstExprEdgeBBs.lookup({BB, CurBB}); if (It != Args.end()) { - // If this predecessor was also replaced with a constexpr basic - // block, it must be de-duplicated. - if (!EdgeBB) { - PN->addIncoming(It->second, BB); - } + PN->addIncoming(It->second, BB); continue; } // If there already is a block for this edge (from a different phi), // use it. + BasicBlock *EdgeBB = ConstExprEdgeBBs.lookup({BB, CurBB}); if (!EdgeBB) { // Otherwise, use a temporary block (that we will discard if it // turns out to be unnecessary). @@ -6944,6 +6964,7 @@ Error BitcodeReader::parseFunctionBody(Function *F) { BranchInst::Create(To, EdgeBB); From->getTerminator()->replaceSuccessorWith(To, EdgeBB); To->replacePhiUsesWith(From, EdgeBB); + deduplicatePhiUsesOf(To, EdgeBB); EdgeBB->moveBefore(To); } diff --git a/llvm/test/Bitcode/constexpr-to-instr-dups.ll b/llvm/test/Bitcode/constexpr-to-instr-dups.ll index dee9490b616fa..d439a6dcf0c7b 100644 --- a/llvm/test/Bitcode/constexpr-to-instr-dups.ll +++ b/llvm/test/Bitcode/constexpr-to-instr-dups.ll @@ -28,3 +28,30 @@ cont: [1, %nonconst] ret i32 %res } + +define i32 @test_multiple_phis(i32 %arg) { +entry: + switch i32 %arg, label %cont [ + i32 1, label %cont + i32 2, label %nonconst + ] + +nonconst: ; preds = %entry + %cmp = icmp ne i32 %arg, 2 + br i1 %cmp, label %cont, label %cont + +; CHECK-LABEL: phi.constexpr: +; CHECK-NEXT: %constexpr = ptrtoint ptr @foo to i32 +; CHECK-NEXT: %constexpr1 = or i32 %constexpr, 5 +; CHECK-NEXT: br label %cont + + +; CHECK-LABEL: cont: +; CHECK-NEXT: %phi1 = phi i32 [ 0, %phi.constexpr ], [ 1, %nonconst ], [ 1, %nonconst ] +; CHECK-NEXT: %phi2 = phi i32 [ %constexpr1, %phi.constexpr ], [ 1, %nonconst ], [ 1, %nonconst ] +; CHECK-NEXT: ret i32 %phi2 +cont: ; preds = %nonconst, %nonconst, %entry, %entry + %phi1 = phi i32 [ 0, %entry ], [ 0, %entry ], [ 1, %nonconst ], [ 1, %nonconst ] + %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 ] + ret i32 %phi2 +} diff --git a/llvm/test/Bitcode/constexpr-to-instr-dups.ll.bc b/llvm/test/Bitcode/constexpr-to-instr-dups.ll.bc index 7897f51322fcc3e9ce738c66fc90d36dde5c1fb1..15a3eeb449d8780f44eedf7707916aa474a7fff3 100644 GIT binary patch delta 478 zcmbQky@Y3ih~V1aTl~2L8+;fU7#I|J7#OlAs%F>o0y#!XCpZ+6+!z$KRc7!gssaf~ zb)MEG6B3M4ViZ)8n;xvNWHK;tG7>OgHDEGu7XWHu@Z#qXoaE5fGlhZC#A(KytjF7{ z{q!F{{3Q1GuGjA8C6(PV?dM~2%oy4D7$kytTR>W1pn$=7m9r3p2c`HNlA0YJZf9U< zh~U}y^F0%z`sA0)vl!VY&tY-mNscCllv)_KFljL8f`l1jfgum_wGi`^N)SISKfffk zxCDgbb4zndG7EB2;|nq}iw({64D<|=^Ye;JQY#9IbW8GeGlA?PUA~mkf?~a#9FT4x F0071Sd4T`` delta 341 zcmZ3&GlzSEh~VDeTh?<2Hux|yFfb_cFfe#bRL#x=(hN#zECQRHnobG?0f`BPhXOpf zIMtkwu{s&4aq!JjW@uJYVP*_wP-ZA*0qJG%;^z>Y4-hyjk_ff0P=SGg8OS!`6Hsbl+yJx|0%C!l6b3Sdn5Wc&MAGu}OHzwV49)cn z^vo2D4b3bqO$|+q%~DLwl2QyTlFSVaO-#*93@nok4UJ7qL`}?0ER)PFL3;FZav)|h F004YlPpSX_