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 7897f51322fcc..15a3eeb449d87 100644 Binary files a/llvm/test/Bitcode/constexpr-to-instr-dups.ll.bc and b/llvm/test/Bitcode/constexpr-to-instr-dups.ll.bc differ