[llvm] [Bitcode] Fix constexpr expansion creating invalid PHIs (PR #141560)

Timothy Werquin via llvm-commits llvm-commits at lists.llvm.org
Tue May 27 01:06:35 PDT 2025


https://github.com/timower created https://github.com/llvm/llvm-project/pull/141560

Fixes errors about duplicate PHI edges when the input had duplicates with constexprs in them. The constexpr translation makes new basic blocks, causing the verifier to complain about duplicate entries in PHI nodes.

>From 1d651a49abc09cf913bf959731f242a5d7d8aae2 Mon Sep 17 00:00:00 2001
From: Timothy Werquin <timothy.werquin at guardsquare.com>
Date: Fri, 23 May 2025 19:27:33 +0200
Subject: [PATCH] [Bitcode] Fix constexpr expansion creating invalid PHIs

Fixes errors about duplicate PHI edges when the input had duplicates with
constexprs in them. The constexpr translation makes new basic blocks,
causing the verifier to complain about duplicate entries in PHI nodes.
---
 llvm/lib/Bitcode/Reader/BitcodeReader.cpp     |   8 +++--
 llvm/test/Bitcode/constexpr-to-instr-dups.ll  |  32 ++++++++++++++++++
 .../Bitcode/constexpr-to-instr-dups.ll.bc     | Bin 0 -> 1436 bytes
 llvm/test/Bitcode/constexpr-to-instr.ll       |   3 +-
 4 files changed, 40 insertions(+), 3 deletions(-)
 create mode 100644 llvm/test/Bitcode/constexpr-to-instr-dups.ll
 create mode 100644 llvm/test/Bitcode/constexpr-to-instr-dups.ll.bc

diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
index 58625ee49c8ad..119caad26830e 100644
--- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
+++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp
@@ -6095,14 +6095,18 @@ 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()) {
-          PN->addIncoming(It->second, BB);
+          /// If this predecessor was also replaced with a constexpr basic
+          /// block, it must be de-duplicated.
+          if (!EdgeBB) {
+            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).
diff --git a/llvm/test/Bitcode/constexpr-to-instr-dups.ll b/llvm/test/Bitcode/constexpr-to-instr-dups.ll
new file mode 100644
index 0000000000000..5478327d07355
--- /dev/null
+++ b/llvm/test/Bitcode/constexpr-to-instr-dups.ll
@@ -0,0 +1,32 @@
+; RUN: opt -expand-constant-exprs -p verify %s.bc
+; RUN: llvm-dis -expand-constant-exprs < %s.bc | FileCheck %s
+
+ at foo = external constant i32
+
+define i32 @test(i32 %arg) {
+entry:
+  switch i32 %arg, label %cont [
+    i32 1, label %cont
+    i32 2, label %nonconst
+  ]
+
+nonconst:
+  %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:    %res = phi i32 [ %constexpr1, %phi.constexpr ], [ 1, %nonconst ], [ 1, %nonconst ]
+; CHECK-NEXT:    ret i32 %res
+cont:
+  %res = phi i32 [or (i32 5, i32 ptrtoint (ptr @foo to i32)), %entry],
+                 [or (i32 5, i32 ptrtoint (ptr @foo to i32)), %entry],
+                 [1, %nonconst],
+                 [1, %nonconst]
+  ret i32 %res
+}
diff --git a/llvm/test/Bitcode/constexpr-to-instr-dups.ll.bc b/llvm/test/Bitcode/constexpr-to-instr-dups.ll.bc
new file mode 100644
index 0000000000000000000000000000000000000000..7897f51322fcc3e9ce738c66fc90d36dde5c1fb1
GIT binary patch
literal 1436
zcmXw3e{2&~9Dmo_c4aH?%BaxEUA?0d8-jTKv8~6o$<{+t0Z9S>m<fip%m$P|x7Gau
zO-qM2Vol1@#A-0v68 at 0CEM|XTG7arbEVIHyW0trqt?OWzf(uMSB7gY3p)YygckkuB
z at B4f|pU*p=d~Kn{gitL)C}a?t_q_F8_}hObziK!T+eg3}Z$QWo9}PMl>0rJIIu*BG
z=qS{@UT1WOW5kHz#aexnrRL*M%<!ttH`d_mHabjhy?JlF!!hcQO!L;=jY`tkF{bM-
z=&zVK`L$8*2H|jwn77-ur|f64hc9qy0rH;b5Q6K_)^LsSYv0)$#)A-2J^6sYe%&_t
zdaci~O^-jfqQur_k~oB{sINwYi1yI>4P)&eCDVv-`OJ?q`r{8jJ%>mN87|lPv<?3^
zH#)ywckVN&BV>oQZ=gH%F=o2VgiVBZRCbT3NneZ_8l?I%J%&4ozHh{<G3+$>EcqOJ
zbAkyAwQJiFTZ*K&AbXRfw>X%LMyS(zYRIodBGhn%>>pGjoYGX>fU7B77U+`#y|{u`
z0@!JsW*2y7j%V{hOISEBO(mpRS)3$2Qwh%qDHT^t{aw`QV^rHQr59pMiKLWB7u9d0
z`k&N7+JTsIM6dLimEMdpl!@<nu!0|y at ZZ;PRUku!38pf^6xZT>keT6`={P$Rtotn`
ziv?NCti`LUJ1x6MNhz(q0+&8LEB#7JS=I2vaV65J^hOfVW7J at m5;ZH)ai!_zA^HKL
z9|mwGg%{iDGKZ^B1!rUDbC!IE<u=dE$1U?Erc!4ABrIX`0e4p3bul3o1I_;x(xnUx
zQiGWT`&Lu5#(?Er%S at 12=GlcD`ypY`0Q2lhu<p%s33pMIva%Nld7AfBWN8$pYV!Mf
zs8ksMJbG%_M)hXmhZl{wdJQiH at FT&RyWL at _lsC_n*#!XLZ<4YJ?_^@ji0V$tVo~*6
z&4~pSYV;KSlRbJ0Q1t+Tol4X1*KxIrzF(?a;pioSUgGG-0esSk7X=K{N2R)ZC0q&M
zCxZ2lYLLmt*}3xOD$m~G*=e2y1(*33!rT|ql<d7qis^({?3 at Diq1a)-=~o6KO4E;b
z at m~U6F5!Fa^u2MoMJ33-FDa<yNCvE;F&v!*DdQs at Vo3$+yr5LEeR`aonP5vDmW3P>
zZaymDvZgN$NtOhePrPrY`uxg~apg=5&R$6qo}}tYtL|BO7ucx?j2Zm=bH1Pjpx(@}
z2jeDm*^JQ3;Pr<3UK at Cb8t#l_0JnCfIIEt$!(5+Ozuci&9L_w`W|M2N3*QZZ<a9+7
zp1vEvtJzqb8nUf9a!>&_H9a~b7ghHpAzey%)2i-0FgG(_X68Aj64c^y+>#G6vlC3=
z8HvFhL9cRjIY7g^Y8ZW1OzkZ<K%WDHsz9X#%E7xTkdpRne>Ngi2P0MVTuMk6!MLP%
zJmCQor&R6n2RVeEhjC+#yaTqP8tCapn{F>k=WXgis2m}ciSq{C21A>9x4G!h`-DKF
z5fK8h at q`g;``1C=CZG$!b at FciOYQpo&Zayk+^Xe1`9;6q`UVv+{$vVjiJ<jx2$3*4
zuyN}Mk=1^QYwd0LaczXJMl$_ at wh%sbD*8 at e)ZVsJ*xAZC?X9BNVs|-PyIWdA-GV#R
gX1BXqT3v#8)NXgWT&`A^7-|!>BRfx=Sj&jeznPuq-v9sr

literal 0
HcmV?d00001

diff --git a/llvm/test/Bitcode/constexpr-to-instr.ll b/llvm/test/Bitcode/constexpr-to-instr.ll
index c099273de810f..e00de3925d370 100644
--- a/llvm/test/Bitcode/constexpr-to-instr.ll
+++ b/llvm/test/Bitcode/constexpr-to-instr.ll
@@ -1,4 +1,5 @@
 ; RUN: llvm-dis -expand-constant-exprs < %s.bc | FileCheck %s
+; RUN: opt -expand-constant-exprs -p verify %s.bc
 
 @g = extern_weak global i32
 @g2 = extern_weak global i32
@@ -225,7 +226,7 @@ define i64 @test_phi_multiple_identical_predecessors(i32 %x) {
 ; CHECK-NEXT: %constexpr = ptrtoint ptr @g to i64
 ; CHECK-NEXT: br label %join
 ; CHECK: join:
-; CHECK-NEXT: %phi = phi i64 [ %constexpr, %phi.constexpr ], [ %constexpr, %phi.constexpr ], [ 0, %default ]
+; CHECK-NEXT: %phi = phi i64 [ %constexpr, %phi.constexpr ], [ 0, %default ]
 ; CHECK-NEXT: ret i64 %phi
 entry:
   switch i32 %x, label %default [



More information about the llvm-commits mailing list