[llvm] [DAG] isKnownToBeAPowerOfTwo - add missing DemandedElts handling to ISD::TRUNCATE and hidden m_Neg pattern (PR #190190)

Simon Pilgrim via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 2 08:04:57 PDT 2026


https://github.com/RKSimon created https://github.com/llvm/llvm-project/pull/190190

Use MaskedVectorIsZero to match X & -X pattern when only DemandedElts match the negation pattern

Fixes #181654 (properly)

>From ec07558faebb3bcfb12900bf19b7029e51904660 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Thu, 2 Apr 2026 16:02:54 +0100
Subject: [PATCH] [DAG] isKnownToBeAPowerOfTwo - add missing DemandedElts
 handling to ISD::TRUNCATE and hidden m_Neg pattern

Use MaskedVectorIsZero to match X & -X pattern when only DemandedElts match the negation pattern

Fixes #181654
---
 llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 14 ++++++++------
 llvm/test/CodeGen/X86/known-pow2.ll            |  7 +++----
 2 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 60b1fc6a5166b..5e728e7be8f61 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -4775,8 +4775,10 @@ bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val,
     // If x != 0:
     //    x & -x -> non-zero pow2
     // so if we find the pattern return whether we know `x` is non-zero.
-    SDValue X;
-    if (sd_match(Val, m_And(m_Value(X), m_Neg(m_Deferred(X)))))
+    SDValue X, Z;
+    if (sd_match(Val, m_And(m_Value(X), m_Neg(m_Deferred(X)))) ||
+        (sd_match(Val, m_And(m_Value(X), m_Sub(m_Value(Z), m_Deferred(X)))) &&
+         MaskedVectorIsZero(Z, DemandedElts, Depth + 1)))
       return OrZero || isKnownNeverZero(X, DemandedElts, Depth);
     break;
   }
@@ -4803,10 +4805,10 @@ bool SelectionDAG::isKnownToBeAPowerOfTwo(SDValue Val,
                                   Depth + 1);
   }
 
-  case ISD::TRUNCATE: {
-    return (OrZero || isKnownNeverZero(Val, Depth)) &&
-           isKnownToBeAPowerOfTwo(Val.getOperand(0), OrZero, Depth + 1);
-  }
+  case ISD::TRUNCATE:
+    return (OrZero || isKnownNeverZero(Val, DemandedElts, Depth)) &&
+           isKnownToBeAPowerOfTwo(Val.getOperand(0), DemandedElts, OrZero,
+                                  Depth + 1);
 
   case ISD::ROTL:
   case ISD::ROTR:
diff --git a/llvm/test/CodeGen/X86/known-pow2.ll b/llvm/test/CodeGen/X86/known-pow2.ll
index 9e71dd890f81f..47bf4e348e26a 100644
--- a/llvm/test/CodeGen/X86/known-pow2.ll
+++ b/llvm/test/CodeGen/X86/known-pow2.ll
@@ -1373,14 +1373,13 @@ define i8 @pow2_trunc_vec(i8 %x8, <4 x i32> %a, ptr %p) {
 ; CHECK-NEXT:    movdqa {{.*#+}} xmm1 = [0,4294967295,4294967295,4294967295]
 ; CHECK-NEXT:    psubd %xmm0, %xmm1
 ; CHECK-NEXT:    pand %xmm0, %xmm1
-; CHECK-NEXT:    movd %xmm1, %ecx
+; CHECK-NEXT:    movd %xmm1, %eax
 ; CHECK-NEXT:    pand {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm1
 ; CHECK-NEXT:    packuswb %xmm1, %xmm1
 ; CHECK-NEXT:    packuswb %xmm1, %xmm1
 ; CHECK-NEXT:    movd %xmm1, (%rsi)
-; CHECK-NEXT:    movzbl %dil, %eax
-; CHECK-NEXT:    divb %cl
-; CHECK-NEXT:    movzbl %ah, %eax
+; CHECK-NEXT:    decb %al
+; CHECK-NEXT:    andb %dil, %al
 ; CHECK-NEXT:    # kill: def $al killed $al killed $eax
 ; CHECK-NEXT:    retq
   %a.neg = sub <4 x i32> <i32 0, i32 -1, i32 -1, i32 -1>, %a



More information about the llvm-commits mailing list