[llvm] d8bc546 - [InstCombine] Fix phi or icmp fold with disjoint flag

Nikita Popov via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 30 07:23:15 PST 2023


Author: Nikita Popov
Date: 2023-11-30T16:23:00+01:00
New Revision: d8bc5465330474b80c02ca37e76a9a51245f1d79

URL: https://github.com/llvm/llvm-project/commit/d8bc5465330474b80c02ca37e76a9a51245f1d79
DIFF: https://github.com/llvm/llvm-project/commit/d8bc5465330474b80c02ca37e76a9a51245f1d79.diff

LOG: [InstCombine] Fix phi or icmp fold with disjoint flag

We're changing the operand of the or here, such that the disjoint
flag may no longer hold. Clear it.

Added: 
    

Modified: 
    llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
    llvm/test/Transforms/InstCombine/phi.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
index f8507e4929788c2..20b34c1379d575d 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombinePHI.cpp
@@ -1460,13 +1460,16 @@ Instruction *InstCombinerImpl::visitPHINode(PHINode &PN) {
   // icmp(or(phi)) can equally be replaced with any non-zero constant as the
   // "or" will only add bits.
   if (!PN.hasNUsesOrMore(3)) {
-    bool AllUsesOfPhiEndsInCmp = all_of(PN.users(), [&PN](User *U) {
+    SmallVector<Instruction *> DropPoisonFlags;
+    bool AllUsesOfPhiEndsInCmp = all_of(PN.users(), [&](User *U) {
       auto *CmpInst = dyn_cast<ICmpInst>(U);
       if (!CmpInst) {
         // This is always correct as OR only add bits and we are checking
         // against 0.
-        if (U->hasOneUse() && match(U, m_c_Or(m_Specific(&PN), m_Value())))
+        if (U->hasOneUse() && match(U, m_c_Or(m_Specific(&PN), m_Value()))) {
+          DropPoisonFlags.push_back(cast<Instruction>(U));
           CmpInst = dyn_cast<ICmpInst>(U->user_back());
+        }
       }
       if (!CmpInst || !isa<IntegerType>(PN.getType()) ||
           !CmpInst->isEquality() || !match(CmpInst->getOperand(1), m_Zero())) {
@@ -1486,6 +1489,9 @@ Instruction *InstCombinerImpl::visitPHINode(PHINode &PN) {
             NonZeroConst = getAnyNonZeroConstInt(PN);
           if (NonZeroConst != VA) {
             replaceOperand(PN, I, NonZeroConst);
+            // The "disjoint" flag may no longer hold after the transform.
+            for (Instruction *I : DropPoisonFlags)
+              I->dropPoisonGeneratingFlags();
             MadeChange = true;
           }
         }

diff  --git a/llvm/test/Transforms/InstCombine/phi.ll b/llvm/test/Transforms/InstCombine/phi.ll
index 787cad287406c6b..90818771675b2ed 100644
--- a/llvm/test/Transforms/InstCombine/phi.ll
+++ b/llvm/test/Transforms/InstCombine/phi.ll
@@ -1421,7 +1421,6 @@ if.end:
   ret i1  %cmp1
 }
 
-; FIXME: This is a miscompile.
 define i1 @phi_knownnonzero_eq_or_disjoint_icmp(i32 %n, i32 %s, ptr %P, i32 %val) {
 ; CHECK-LABEL: @phi_knownnonzero_eq_or_disjoint_icmp(
 ; CHECK-NEXT:  entry:
@@ -1431,7 +1430,7 @@ define i1 @phi_knownnonzero_eq_or_disjoint_icmp(i32 %n, i32 %s, ptr %P, i32 %val
 ; CHECK-NEXT:    br label [[IF_END]]
 ; CHECK:       if.end:
 ; CHECK-NEXT:    [[PHI:%.*]] = phi i32 [ 1, [[IF_THEN]] ], [ [[N]], [[ENTRY:%.*]] ]
-; CHECK-NEXT:    [[ORPHI:%.*]] = or disjoint i32 [[PHI]], [[VAL:%.*]]
+; CHECK-NEXT:    [[ORPHI:%.*]] = or i32 [[PHI]], [[VAL:%.*]]
 ; CHECK-NEXT:    [[CMP1:%.*]] = icmp eq i32 [[ORPHI]], 0
 ; CHECK-NEXT:    ret i1 [[CMP1]]
 ;


        


More information about the llvm-commits mailing list