[llvm] [DAGCombiner] Fix divide-by-zero in visitSUBSAT when LHS is known-zero (PR #218284)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 23 13:06:15 PDT 2026
https://github.com/sipher-01 created https://github.com/llvm/llvm-project/pull/218284
Fixes a crash introduced by #206592.
When the LHS of `usub.sat` is a known-zero value, `ActiveBits` is 0 and `NarrowBits` starts at 0, causing a divide-by-zero via `ActiveBits % NarrowBits` in `visitSUBSAT`.
Guard the loop with `NarrowBits != 0` to skip the narrowing optimization in this case. Other folds handle the known-zero
case correctly.
A regression test has been added to `usubsat-narrow.ll` using a known-zero LHS (`xor v, v`) to prevent future regressions.
Reported by: @Benjins in #217964
>From 9c872810d3af31a4fc1c459e5f855c47a0452b7c Mon Sep 17 00:00:00 2001
From: Sipher <sourav2003singhkatoch at gmail.com>
Date: Mon, 24 Aug 2026 01:14:43 +0530
Subject: [PATCH] [DAGCombiner] Fix divide-by-zero in visitSUBSAT for
known-zero LHS
When the LHS of usub.sat is a known-zero value, ActiveBits is 0 and
NarrowBits starts at 0, causing a divide-by-zero via ActiveBits % NarrowBits.
Guard the loop with NarrowBits != 0 to skip the narrowing optimization in this case.
Fixes a crash introduced by #206592, reported via fuzzer testing.
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 2 +-
llvm/test/CodeGen/X86/usubsat-narrow.ll | 27 +++++++++++++++++++
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 09e26fe2aa58c..5f0b21205b98e 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -4726,7 +4726,7 @@ SDValue DAGCombiner::visitSUBSAT(SDNode *N) {
KnownBits Known0 = DAG.computeKnownBits(N0);
unsigned ActiveBits = Known0.countMaxActiveBits();
for (unsigned NarrowBits = PowerOf2Ceil(ActiveBits);
- NarrowBits < ScalarBits; NarrowBits *= 2) {
+ NarrowBits != 0 && NarrowBits < ScalarBits; NarrowBits *= 2) {
unsigned Scale = ScalarBits / NarrowBits;
unsigned NumElts = VT.getVectorNumElements() * Scale;
MVT NarrowSVT = MVT::getIntegerVT(NarrowBits);
diff --git a/llvm/test/CodeGen/X86/usubsat-narrow.ll b/llvm/test/CodeGen/X86/usubsat-narrow.ll
index 31fd26cd5effe..5ef367c2f298c 100644
--- a/llvm/test/CodeGen/X86/usubsat-narrow.ll
+++ b/llvm/test/CodeGen/X86/usubsat-narrow.ll
@@ -404,3 +404,30 @@ define <8 x i32> @usubsat_v8i32_both_narrow(<8 x i32> %x, <8 x i32> %y) {
%z = call <8 x i32> @llvm.usub.sat.v8i32(<8 x i32> %mx, <8 x i32> %my)
ret <8 x i32> %z
}
+
+; Regression test: known-zero LHS caused divide-by-zero crash in visitSUBSAT
+; when ActiveBits == 0 and NarrowBits == 0.
+define <4 x i32> @usubsat_known_zero_lhs(<4 x i32> %v3) {
+; SSE2-LABEL: usubsat_known_zero_lhs:
+; SSE2: # %bb.0:
+; SSE2-NEXT: xorps %xmm0, %xmm0
+; SSE2-NEXT: retq
+;
+; SSE42-LABEL: usubsat_known_zero_lhs:
+; SSE42: # %bb.0:
+; SSE42-NEXT: psubd %xmm0, %xmm0
+; SSE42-NEXT: retq
+;
+; AVX2-LABEL: usubsat_known_zero_lhs:
+; AVX2: # %bb.0:
+; AVX2-NEXT: vpsubd %xmm0, %xmm0, %xmm0
+; AVX2-NEXT: retq
+;
+; AVX512-LABEL: usubsat_known_zero_lhs:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vpsubd %xmm0, %xmm0, %xmm0
+; AVX512-NEXT: retq
+ %v5 = xor <4 x i32> %v3, %v3
+ %v7 = call <4 x i32> @llvm.usub.sat.v4i32(<4 x i32> %v5, <4 x i32> %v3)
+ ret <4 x i32> %v7
+}
More information about the llvm-commits
mailing list