[llvm] [SimplifyCFG] Do not redirect potential poison values from predecessors (PR #189966)

Gábor Spaits via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 1 07:13:33 PDT 2026


https://github.com/spaits created https://github.com/llvm/llvm-project/pull/189966

to PHI

My attempt to fix #189526 .

I have did some debugging in SimplifyCFG and found that the things may go wrong when redirecting values from predecessors to the PHI node: https://alive2.llvm.org/ce/z/MRGLNx .

The issue is caused by replacing a `undef` with a potential poison value.

Here is the code generated after the patch for the code snippet in the issue: https://alive2.llvm.org/ce/z/p5Hv_y .

This PR may cause some regressions while fixing the issue!

>From fb3e11c4b71565086040ce04819c049bebac238b Mon Sep 17 00:00:00 2001
From: Gabor Spaits <gabor.spaits at hightec-rt.com>
Date: Wed, 1 Apr 2026 16:06:41 +0200
Subject: [PATCH] [SimplifyCFG] Do not redirect potential poison values from
 predecessors to PHI

My attempt to fix #189526 .

I have did some debugging in SimplifyCFG and found that the things may
go wrong when redirecting values from predecessors to the PHI node: https://alive2.llvm.org/ce/z/MRGLNx .

The issue is caused by replacing a `undef` with a potential poison
value.

Here is the code generated after the patch for the code snippet in the
issue: https://alive2.llvm.org/ce/z/p5Hv_y .

This PR may cause some regressions while fixing the issue!
---
 llvm/lib/Transforms/Utils/Local.cpp           | 26 ++++++++++-
 .../ForwardSwitchConditionToPHI.ll            | 43 +++++++++++++++++--
 2 files changed, 63 insertions(+), 6 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 84c0989a7fe07..854e5d179f309 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -1084,7 +1084,7 @@ static bool introduceTooManyPhiEntries(BasicBlock *BB, BasicBlock *Succ) {
 /// \param BBPreds The predecessors of BB.
 /// \param PN The phi that we are updating.
 /// \param CommonPred The common predecessor of BB and PN's BasicBlock
-static void redirectValuesFromPredecessorsToPhi(BasicBlock *BB,
+static bool redirectValuesFromPredecessorsToPhi(BasicBlock *BB,
                                                 const PredBlockVector &BBPreds,
                                                 PHINode *PN,
                                                 BasicBlock *CommonPred) {
@@ -1124,6 +1124,16 @@ static void redirectValuesFromPredecessorsToPhi(BasicBlock *BB,
       Value *Selected =
           selectIncomingValueForBlock(PredVal, PredBB, IncomingValues);
 
+      // It can cause an issue if there was a 'undef' assigned for the block
+      // before and we replace that block with a value that might be poison.
+      int BlockIdx = PN->getBasicBlockIndex(PredBB);
+      if (BlockIdx > 0 && isa<UndefValue>(PN->getIncomingValue(BlockIdx)) &&
+          (!isa<Constant>(Selected) ||
+           !isGuaranteedNotToBeUndefOrPoison(Selected))) {
+        PN->addIncoming(OldVal, BB);
+        return false;
+      }
+
       // And add a new incoming value for this predecessor for the
       // newly retargeted branch.
       PN->addIncoming(Selected, PredBB);
@@ -1141,6 +1151,16 @@ static void redirectValuesFromPredecessorsToPhi(BasicBlock *BB,
       Value *Selected =
           selectIncomingValueForBlock(OldVal, PredBB, IncomingValues);
 
+      // It can cause an issue if there was a 'undef' assigned for the block
+      // before and we replace that block with a value that might be poison.
+      int BlockIdx = PN->getBasicBlockIndex(PredBB);
+      if (BlockIdx > 0 && isa<UndefValue>(PN->getIncomingValue(BlockIdx)) &&
+          (!isa<Constant>(Selected) ||
+           !isGuaranteedNotToBeUndefOrPoison(Selected))) {
+        PN->addIncoming(OldVal, BB);
+        return false;
+      }
+
       // And add a new incoming value for this predecessor for the
       // newly retargeted branch.
       PN->addIncoming(Selected, PredBB);
@@ -1150,6 +1170,7 @@ static void redirectValuesFromPredecessorsToPhi(BasicBlock *BB,
   }
 
   replaceUndefValuesInPhi(PN, IncomingValues);
+  return true;
 }
 
 bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
@@ -1327,7 +1348,8 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
     // Loop over all of the PHI nodes in the successor of BB.
     for (BasicBlock::iterator I = Succ->begin(); isa<PHINode>(I); ++I) {
       PHINode *PN = cast<PHINode>(I);
-      redirectValuesFromPredecessorsToPhi(BB, BBPreds, PN, CommonPred);
+      if (!redirectValuesFromPredecessorsToPhi(BB, BBPreds, PN, CommonPred))
+        return false;
     }
   }
 
diff --git a/llvm/test/Transforms/SimplifyCFG/ForwardSwitchConditionToPHI.ll b/llvm/test/Transforms/SimplifyCFG/ForwardSwitchConditionToPHI.ll
index ea81e0e4fa48c..df4b44aa941a6 100644
--- a/llvm/test/Transforms/SimplifyCFG/ForwardSwitchConditionToPHI.ll
+++ b/llvm/test/Transforms/SimplifyCFG/ForwardSwitchConditionToPHI.ll
@@ -206,15 +206,19 @@ define { i64, i64 } @PR95919(i64 noundef %arg, i64 noundef %arg1) {
 ;
 ; FWD-LABEL: @PR95919(
 ; FWD-NEXT:  bb:
-; FWD-NEXT:    [[SWITCH:%.*]] = icmp ult i64 [[ARG1:%.*]], 2
-; FWD-NEXT:    br i1 [[SWITCH]], label [[BB5:%.*]], label [[BB3:%.*]]
+; FWD-NEXT:    switch i64 [[ARG1:%.*]], label [[BB3:%.*]] [
+; FWD-NEXT:      i64 0, label [[BB5:%.*]]
+; FWD-NEXT:      i64 1, label [[BB2:%.*]]
+; FWD-NEXT:    ]
+; FWD:       bb2:
+; FWD-NEXT:    br label [[BB5]]
 ; FWD:       bb3:
 ; FWD-NEXT:    [[I:%.*]] = udiv i64 [[ARG:%.*]], [[ARG1]]
 ; FWD-NEXT:    [[I4:%.*]] = shl nuw i64 [[I]], 1
 ; FWD-NEXT:    br label [[BB5]]
 ; FWD:       bb5:
-; FWD-NEXT:    [[I6:%.*]] = phi i64 [ [[I4]], [[BB3]] ], [ [[ARG]], [[BB:%.*]] ]
-; FWD-NEXT:    [[I7:%.*]] = phi i64 [ 1, [[BB3]] ], [ [[ARG1]], [[BB]] ]
+; FWD-NEXT:    [[I6:%.*]] = phi i64 [ [[I4]], [[BB3]] ], [ undef, [[BB:%.*]] ], [ [[ARG]], [[BB2]] ]
+; FWD-NEXT:    [[I7:%.*]] = phi i64 [ 1, [[BB3]] ], [ [[ARG1]], [[BB2]] ], [ [[ARG1]], [[BB]] ]
 ; FWD-NEXT:    [[I8:%.*]] = insertvalue { i64, i64 } poison, i64 [[I7]], 0
 ; FWD-NEXT:    [[I9:%.*]] = insertvalue { i64, i64 } [[I8]], i64 [[I6]], 1
 ; FWD-NEXT:    ret { i64, i64 } [[I9]]
@@ -240,3 +244,34 @@ bb5: ; preds = %bb3, %bb2, %bb
   %i9 = insertvalue { i64, i64 } %i8, i64 %i6, 1
   ret { i64, i64 } %i9
 }
+
+define i32 @NotPropagatingPoisonToUndef(i8 %cond, i32 %x) {
+; NO_FWD-LABEL: @NotPropagatingPoisonToUndef(
+; NO_FWD-NEXT:  D:
+; NO_FWD-NEXT:    [[COND1:%.*]] = icmp eq i8 [[COND:%.*]], 0
+; NO_FWD-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[COND1]], i32 [[X:%.*]], i32 0
+; NO_FWD-NEXT:    ret i32 [[SPEC_SELECT]]
+;
+; FWD-LABEL: @NotPropagatingPoisonToUndef(
+; FWD-NEXT:  D:
+; FWD-NEXT:    [[COND1:%.*]] = icmp eq i8 [[COND:%.*]], 0
+; FWD-NEXT:    [[SPEC_SELECT:%.*]] = select i1 [[COND1]], i32 [[X:%.*]], i32 0
+; FWD-NEXT:    ret i32 [[SPEC_SELECT]]
+;
+  switch i8 %cond, label %A [
+  i8 0, label %B
+  i8 1, label %C
+  ]
+A:
+  br label %D
+B:
+  br label %D
+C:
+  br label %D
+D:
+  %y = phi i32 [ undef, %A ], [ %x, %B ], [ 0, %C ]
+  ret i32 %y
+}
+
+
+



More information about the llvm-commits mailing list