[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