[llvm] [SelectionDAG] Look through freeze in undef demanded checks (PR #200931)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 1 13:48:14 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-x86

Author: Krzysztof Drewniak (krzysz00)

<details>
<summary>Changes</summary>

There were cycles where the freeze combiner and thet
demanded-elements simplification code would get into fights about
whethere the operands to a shuffle or a concat should be
`freeze undef` or `undef` once the simplifier had concluded zero
elements were demanded from some operation. This PR prevents such
cases.

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

Co-Authored-By: OpenAI Codex <codex@<!-- -->openai.com>

---

<sub>Stack created with <a href="https://github.com/github/gh-stack">GitHub Stacks CLI</a> • <a href="https://gh.io/stacks-feedback">Give Feedback 💬</a></sub>

---
Full diff: https://github.com/llvm/llvm-project/pull/200931.diff


3 Files Affected:

- (modified) llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp (+11-7) 
- (added) llvm/test/CodeGen/X86/dagcombine-freeze-undef-demanded-elts.ll (+88) 
- (modified) llvm/test/CodeGen/X86/pr91005.ll (+2-1) 


``````````diff
diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 8b3143553a666..7123daf9856ee 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -714,8 +714,10 @@ SDValue TargetLowering::SimplifyMultipleUseDemandedBits(
   if (Depth >= SelectionDAG::MaxRecursionDepth)
     return SDValue();
 
-  // Ignore UNDEFs.
-  if (Op.isUndef())
+  // Ignore undef/poison, including frozen undef/poison. Replacing a freeze of
+  // undef/poison with another undef node is unnecessary and can fight with
+  // freeze sinking.
+  if (peekThroughFreeze(Op).isUndef())
     return SDValue();
 
   // Not demanding any bits/elts from Op.
@@ -1181,7 +1183,7 @@ bool TargetLowering::SimplifyDemandedBits(
   SDLoc dl(Op);
 
   // Undef operand.
-  if (Op.isUndef())
+  if (peekThroughFreeze(Op).isUndef())
     return false;
 
   // We can't simplify target constants.
@@ -3233,6 +3235,8 @@ bool TargetLowering::SimplifyDemandedVectorElts(
     KnownUndef.setAllBits();
     return false;
   }
+  if (peekThroughFreeze(Op).isUndef())
+    return false;
 
   // If Op has other users, assume that all elements are needed.
   if (!AssumeSingleUse && !Op.getNode()->hasOneUse())
@@ -3407,7 +3411,7 @@ bool TargetLowering::SimplifyDemandedVectorElts(
         SmallVector<SDValue, 32> Ops(Op->ops());
         bool Updated = false;
         for (unsigned i = 0; i != NumElts; ++i) {
-          if (!DemandedElts[i] && !Ops[i].isUndef()) {
+          if (!DemandedElts[i] && !peekThroughFreeze(Ops[i]).isUndef()) {
             Ops[i] = TLO.DAG.getUNDEF(Ops[0].getValueType());
             KnownUndef.setBit(i);
             Updated = true;
@@ -3484,7 +3488,7 @@ bool TargetLowering::SimplifyDemandedVectorElts(
       return true;
 
     // If none of the src operand elements are demanded, replace it with undef.
-    if (!DemandedSrcElts && !Src.isUndef())
+    if (!DemandedSrcElts && !peekThroughFreeze(Src).isUndef())
       return TLO.CombineTo(Op, TLO.DAG.getNode(ISD::INSERT_SUBVECTOR, DL, VT,
                                                TLO.DAG.getUNDEF(VT), Sub,
                                                Op.getOperand(2)));
@@ -3629,8 +3633,8 @@ bool TargetLowering::SimplifyDemandedVectorElts(
     // If either side isn't demanded, replace it by UNDEF. We handle this
     // explicitly here to also simplify in case of multiple uses (on the
     // contrary to the SimplifyDemandedVectorElts calls below).
-    bool FoldLHS = !DemandedLHS && !LHS.isUndef();
-    bool FoldRHS = !DemandedRHS && !RHS.isUndef();
+    bool FoldLHS = !DemandedLHS && !peekThroughFreeze(LHS).isUndef();
+    bool FoldRHS = !DemandedRHS && !peekThroughFreeze(RHS).isUndef();
     if (FoldLHS || FoldRHS) {
       LHS = FoldLHS ? TLO.DAG.getUNDEF(LHS.getValueType()) : LHS;
       RHS = FoldRHS ? TLO.DAG.getUNDEF(RHS.getValueType()) : RHS;
diff --git a/llvm/test/CodeGen/X86/dagcombine-freeze-undef-demanded-elts.ll b/llvm/test/CodeGen/X86/dagcombine-freeze-undef-demanded-elts.ll
new file mode 100644
index 0000000000000..d356dd818c545
--- /dev/null
+++ b/llvm/test/CodeGen/X86/dagcombine-freeze-undef-demanded-elts.ll
@@ -0,0 +1,88 @@
+; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=+f16c \
+; RUN:   -stop-after=x86-isel < %s | FileCheck %s --check-prefix=COMBINE
+; RUN: llc -mtriple=x86_64-unknown-unknown -mattr=+f16c \
+; RUN:   -combiner-disabled -stop-after=x86-isel < %s | FileCheck %s \
+; RUN:   --check-prefix=NOCOMBINE
+
+define void @freeze_undef_demanded_elts(ptr %p) minsize {
+  ; COMBINE-LABEL: name: freeze_undef_demanded_elts
+  ; COMBINE: bb.0 (%ir-block.0):
+  ; COMBINE-NEXT:   successors: %bb.2(0x40000000), %bb.1(0x40000000)
+  ; COMBINE-NEXT:   liveins: $rdi
+  ; COMBINE-NEXT: {{  $}}
+  ; COMBINE-NEXT:   [[COPY:%[0-9]+]]:gr64 = COPY $rdi
+  ; COMBINE-NEXT:   [[DEF:%[0-9]+]]:vr128 = IMPLICIT_DEF
+  ; COMBINE-NEXT:   [[DEF1:%[0-9]+]]:gr8 = IMPLICIT_DEF
+  ; COMBINE-NEXT:   [[DEF2:%[0-9]+]]:gr8 = IMPLICIT_DEF
+  ; COMBINE-NEXT:   TEST8rr [[DEF1]], [[DEF2]], implicit-def $eflags
+  ; COMBINE-NEXT:   JCC_1 %bb.2, 5, implicit $eflags
+  ; COMBINE-NEXT:   JMP_1 %bb.1
+  ; COMBINE-NEXT: {{  $}}
+  ; COMBINE-NEXT: bb.1.ret:
+  ; COMBINE-NEXT:   RET 0
+  ; COMBINE-NEXT: {{  $}}
+  ; COMBINE-NEXT: bb.2.bb:
+  ; COMBINE-NEXT:   successors: %bb.1(0x80000000)
+  ; COMBINE-NEXT: {{  $}}
+  ; COMBINE-NEXT:   [[MOV32ri:%[0-9]+]]:gr32 = MOV32ri 31744
+  ; COMBINE-NEXT:   [[VMOVDI2PDIrr:%[0-9]+]]:vr128 = VMOVDI2PDIrr killed [[MOV32ri]]
+  ; COMBINE-NEXT:   [[VPCMPEQWrr:%[0-9]+]]:vr128 = VPCMPEQWrr [[DEF]], killed [[VMOVDI2PDIrr]]
+  ; COMBINE-NEXT:   [[MOVZX32rm16_:%[0-9]+]]:gr32 = MOVZX32rm16 $rip, 1, $noreg, %const.0, $noreg :: (load (s16) from constant-pool)
+  ; COMBINE-NEXT:   [[VMOVDI2PDIrr1:%[0-9]+]]:vr128 = VMOVDI2PDIrr killed [[MOVZX32rm16_]]
+  ; COMBINE-NEXT:   [[VPANDrr:%[0-9]+]]:vr128 = VPANDrr killed [[VPCMPEQWrr]], killed [[VMOVDI2PDIrr1]]
+  ; COMBINE-NEXT:   [[VCVTPH2PSrr:%[0-9]+]]:vr128 = nofpexcept VCVTPH2PSrr killed [[VPANDrr]], implicit $mxcsr
+  ; COMBINE-NEXT:   [[COPY1:%[0-9]+]]:fr32 = COPY killed [[VCVTPH2PSrr]]
+  ; COMBINE-NEXT:   [[FsFLD0SS:%[0-9]+]]:fr32 = FsFLD0SS
+  ; COMBINE-NEXT:   [[VMULSSrr:%[0-9]+]]:fr32 = nofpexcept VMULSSrr killed [[COPY1]], killed [[FsFLD0SS]], implicit $mxcsr
+  ; COMBINE-NEXT:   [[COPY2:%[0-9]+]]:vr128 = COPY killed [[VMULSSrr]]
+  ; COMBINE-NEXT:   [[VCVTPS2PHrr:%[0-9]+]]:vr128 = nofpexcept VCVTPS2PHrr killed [[COPY2]], 4, implicit $mxcsr
+  ; COMBINE-NEXT:   VPEXTRWmri [[COPY]], 1, $noreg, 0, $noreg, killed [[VCVTPS2PHrr]], 0 :: (store (s16) into %ir.p)
+  ; COMBINE-NEXT:   JMP_1 %bb.1
+  ;
+  ; NOCOMBINE-LABEL: name: freeze_undef_demanded_elts
+  ; NOCOMBINE: bb.0 (%ir-block.0):
+  ; NOCOMBINE-NEXT:   successors: %bb.2(0x40000000), %bb.1(0x40000000)
+  ; NOCOMBINE-NEXT:   liveins: $rdi
+  ; NOCOMBINE-NEXT: {{  $}}
+  ; NOCOMBINE-NEXT:   [[COPY:%[0-9]+]]:gr64 = COPY $rdi
+  ; NOCOMBINE-NEXT:   [[DEF:%[0-9]+]]:vr128 = IMPLICIT_DEF
+  ; NOCOMBINE-NEXT:   [[DEF1:%[0-9]+]]:gr8 = IMPLICIT_DEF
+  ; NOCOMBINE-NEXT:   [[DEF2:%[0-9]+]]:gr8 = IMPLICIT_DEF
+  ; NOCOMBINE-NEXT:   TEST8rr [[DEF1]], [[DEF2]], implicit-def $eflags
+  ; NOCOMBINE-NEXT:   JCC_1 %bb.2, 5, implicit $eflags
+  ; NOCOMBINE-NEXT:   JMP_1 %bb.1
+  ; NOCOMBINE-NEXT: {{  $}}
+  ; NOCOMBINE-NEXT: bb.1.ret:
+  ; NOCOMBINE-NEXT:   RET 0
+  ; NOCOMBINE-NEXT: {{  $}}
+  ; NOCOMBINE-NEXT: bb.2.bb:
+  ; NOCOMBINE-NEXT:   successors: %bb.1(0x80000000)
+  ; NOCOMBINE-NEXT: {{  $}}
+  ; NOCOMBINE-NEXT:   [[VPCMPEQWrm:%[0-9]+]]:vr128 = VPCMPEQWrm [[DEF]], $rip, 1, $noreg, %const.0, $noreg :: (load (s128) from constant-pool)
+  ; NOCOMBINE-NEXT:   [[VMOVAPSrm:%[0-9]+]]:vr128 = VMOVAPSrm $rip, 1, $noreg, %const.1, $noreg :: (load (s128) from constant-pool)
+  ; NOCOMBINE-NEXT:   [[V_SET0_:%[0-9]+]]:vr128 = V_SET0
+  ; NOCOMBINE-NEXT:   [[VPBLENDVBrrr:%[0-9]+]]:vr128 = VPBLENDVBrrr killed [[V_SET0_]], killed [[VMOVAPSrm]], killed [[VPCMPEQWrm]]
+  ; NOCOMBINE-NEXT:   [[VCVTPH2PSYrr:%[0-9]+]]:vr256 = nofpexcept VCVTPH2PSYrr killed [[VPBLENDVBrrr]], implicit $mxcsr
+  ; NOCOMBINE-NEXT:   [[AVX_SET0_:%[0-9]+]]:vr256 = AVX_SET0
+  ; NOCOMBINE-NEXT:   [[VMULPSYrr:%[0-9]+]]:vr256 = nofpexcept VMULPSYrr killed [[VCVTPH2PSYrr]], killed [[AVX_SET0_]], implicit $mxcsr
+  ; NOCOMBINE-NEXT:   [[VCVTPS2PHYrr:%[0-9]+]]:vr128 = nofpexcept VCVTPS2PHYrr killed [[VMULPSYrr]], 4, implicit $mxcsr
+  ; NOCOMBINE-NEXT:   [[COPY1:%[0-9]+]]:fr16 = COPY killed [[VCVTPS2PHYrr]]
+  ; NOCOMBINE-NEXT:   [[COPY2:%[0-9]+]]:vr128 = COPY killed [[COPY1]]
+  ; NOCOMBINE-NEXT:   VPEXTRWmri [[COPY]], 1, $noreg, 0, $noreg, killed [[COPY2]], 0 :: (store (s16) into %ir.p)
+  ; NOCOMBINE-NEXT:   JMP_1 %bb.1
+  %poison.as.i16 = bitcast <2 x half> poison to <2 x i16>
+  %cmp = icmp eq <2 x i16> %poison.as.i16, <i16 31744, i16 31744>
+  br i1 poison, label %bb, label %ret
+
+ret:
+  ret void
+
+bb:
+  %sel = select <2 x i1> %cmp, <2 x half> <half 0xH3C00, half 0xH3C00>, <2 x half> zeroinitializer
+  %mul = fmul <2 x half> %sel, zeroinitializer
+  %sub = fsub <2 x half> %mul, zeroinitializer
+  %elt = extractelement <2 x half> %sub, i64 0
+  store half %elt, ptr %p, align 2
+  br label %ret
+}
diff --git a/llvm/test/CodeGen/X86/pr91005.ll b/llvm/test/CodeGen/X86/pr91005.ll
index de3642b2bd05b..f9727e6b03ab3 100644
--- a/llvm/test/CodeGen/X86/pr91005.ll
+++ b/llvm/test/CodeGen/X86/pr91005.ll
@@ -10,7 +10,8 @@ define void @PR91005(ptr %0) minsize {
 ; CHECK-NEXT:    movl $31744, %eax # imm = 0x7C00
 ; CHECK-NEXT:    vmovd %eax, %xmm0
 ; CHECK-NEXT:    vpcmpeqw %xmm0, %xmm0, %xmm0
-; CHECK-NEXT:    vpinsrw $0, {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %xmm0, %xmm1
+; CHECK-NEXT:    movzwl {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %eax
+; CHECK-NEXT:    vmovd %eax, %xmm1
 ; CHECK-NEXT:    vpand %xmm1, %xmm0, %xmm0
 ; CHECK-NEXT:    vcvtph2ps %xmm0, %xmm0
 ; CHECK-NEXT:    vpxor %xmm1, %xmm1, %xmm1

``````````

</details>


https://github.com/llvm/llvm-project/pull/200931


More information about the llvm-commits mailing list