[llvm-branch-commits] [llvm] [SelectionDAG] Track ISD::BITCAST demanded elements in noundef tests (PR #200933)

Krzysztof Drewniak via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jun 2 23:49:18 PDT 2026


https://github.com/krzysz00 updated https://github.com/llvm/llvm-project/pull/200933

>From d7eb426c167aa9820787b4ef2ad97db16cd10e96 Mon Sep 17 00:00:00 2001
From: Krzysztof Drewniak <Krzysztof.Drewniak at amd.com>
Date: Fri, 29 May 2026 22:30:39 +0000
Subject: [PATCH] [SelectionDAG] Track bitcast demanded elements in noundef
 tests

Bitcasts preserve undef/poison status, but vector bitcasts can change
which source lanes cover a demanded result lane. Map the demanded
element mask through fixed-length vector bitcasts before checking the
source where possible.

AI note: an LLM generated the code and the test, I've read them

Co-Authored-By: OpenAI Codex <codex at openai.com>
---
 .../lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 41 +++++++++++++++++++
 ...dagcombine-freeze-bitcast-demanded-elts.ll | 15 ++-----
 2 files changed, 44 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 057b3df5a4627..eba9327c83cd4 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -5654,6 +5654,47 @@ bool SelectionDAG::isGuaranteedNotToBeUndefOrPoison(SDValue Op,
   case ISD::UNDEF:
     return !includesUndef(Kind);
 
+  case ISD::BITCAST: {
+    if (!DemandedElts)
+      return true;
+
+    SDValue Src = Op.getOperand(0);
+    EVT SrcVT = Src.getValueType();
+    EVT DstVT = Op.getValueType();
+
+    if (!SrcVT.isFixedLengthVector() || !DstVT.isFixedLengthVector())
+      return isGuaranteedNotToBeUndefOrPoison(Src, Kind, Depth + 1);
+
+    unsigned SrcEltBits = SrcVT.getScalarSizeInBits();
+    unsigned DstEltBits = DstVT.getScalarSizeInBits();
+    unsigned NumSrcElts = SrcVT.getVectorNumElements();
+    unsigned NumDstElts = DstVT.getVectorNumElements();
+
+    if (SrcEltBits == DstEltBits)
+      return isGuaranteedNotToBeUndefOrPoison(Src, DemandedElts, Kind,
+                                              Depth + 1);
+
+    if (SrcEltBits < DstEltBits) {
+      if (DstEltBits % SrcEltBits != 0)
+        return isGuaranteedNotToBeUndefOrPoison(Src, Kind, Depth + 1);
+
+      assert(NumSrcElts == NumDstElts * (DstEltBits / SrcEltBits) &&
+             "Unexpected fixed-width vector bitcast");
+      APInt DemandedSrcElts = APIntOps::ScaleBitMask(DemandedElts, NumSrcElts);
+      return isGuaranteedNotToBeUndefOrPoison(Src, DemandedSrcElts, Kind,
+                                              Depth + 1);
+    }
+
+    if (SrcEltBits % DstEltBits != 0)
+      return isGuaranteedNotToBeUndefOrPoison(Src, Kind, Depth + 1);
+
+    assert(NumDstElts == NumSrcElts * (SrcEltBits / DstEltBits) &&
+           "Unexpected fixed-width vector bitcast");
+    APInt DemandedSrcElts = APIntOps::ScaleBitMask(DemandedElts, NumSrcElts);
+    return isGuaranteedNotToBeUndefOrPoison(Src, DemandedSrcElts, Kind,
+                                            Depth + 1);
+  }
+
   case ISD::BUILD_VECTOR:
     // NOTE: BUILD_VECTOR has implicit truncation of wider scalar elements -
     // this shouldn't affect the result.
diff --git a/llvm/test/CodeGen/X86/dagcombine-freeze-bitcast-demanded-elts.ll b/llvm/test/CodeGen/X86/dagcombine-freeze-bitcast-demanded-elts.ll
index aa619567c56af..f61418ceed5d0 100644
--- a/llvm/test/CodeGen/X86/dagcombine-freeze-bitcast-demanded-elts.ll
+++ b/llvm/test/CodeGen/X86/dagcombine-freeze-bitcast-demanded-elts.ll
@@ -7,10 +7,7 @@ declare <2 x i64> @llvm.vector.extract.v2i64.v4i64(<4 x i64>, i64 immarg)
 define <4 x i32> @freeze_extract_bitcast_high_demanded(<2 x i64> %a, <2 x i64> %b) {
 ; CHECK-LABEL: freeze_extract_bitcast_high_demanded:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    vinserti128 $1, %xmm1, %ymm0, %ymm0
-; CHECK-NEXT:    vpsrld $1, %ymm0, %ymm0
-; CHECK-NEXT:    vextracti128 $1, %ymm0, %xmm0
-; CHECK-NEXT:    vzeroupper
+; CHECK-NEXT:    vpsrld $1, %xmm1, %xmm0
 ; CHECK-NEXT:    retq
   %poisonable = add nsw <2 x i64> %a, <i64 9223372036854775807, i64 9223372036854775807>
   %wide = shufflevector <2 x i64> %poisonable, <2 x i64> %b, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
@@ -24,10 +21,7 @@ define <4 x i32> @freeze_extract_bitcast_high_demanded(<2 x i64> %a, <2 x i64> %
 define <2 x i64> @freeze_extract_bitcast_low_width_high_demanded(<4 x i32> %a, <4 x i32> %b) {
 ; CHECK-LABEL: freeze_extract_bitcast_low_width_high_demanded:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    vinserti128 $1, %xmm1, %ymm0, %ymm0
-; CHECK-NEXT:    vpsrlq $1, %ymm0, %ymm0
-; CHECK-NEXT:    vextracti128 $1, %ymm0, %xmm0
-; CHECK-NEXT:    vzeroupper
+; CHECK-NEXT:    vpsrlq $1, %xmm1, %xmm0
 ; CHECK-NEXT:    retq
   %poisonable = add nsw <4 x i32> %a, <i32 2147483647, i32 2147483647, i32 2147483647, i32 2147483647>
   %wide = shufflevector <4 x i32> %poisonable, <4 x i32> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
@@ -41,10 +35,7 @@ define <2 x i64> @freeze_extract_bitcast_low_width_high_demanded(<4 x i32> %a, <
 define <4 x i32> @freeze_extract_bitcast_equal_width_high_demanded(<4 x float> %a, <4 x float> %b) {
 ; CHECK-LABEL: freeze_extract_bitcast_equal_width_high_demanded:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    vinserti128 $1, %xmm1, %ymm0, %ymm0
-; CHECK-NEXT:    vpsrld $1, %ymm0, %ymm0
-; CHECK-NEXT:    vextracti128 $1, %ymm0, %xmm0
-; CHECK-NEXT:    vzeroupper
+; CHECK-NEXT:    vpsrld $1, %xmm1, %xmm0
 ; CHECK-NEXT:    retq
   %poisonable = fadd nnan <4 x float> %a, zeroinitializer
   %wide = shufflevector <4 x float> %poisonable, <4 x float> %b, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>



More information about the llvm-branch-commits mailing list