[llvm] [X86] Don't form pmaddwd for shift by 15 (PR #206473)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 29 05:45:30 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-x86
Author: Nikita Popov (nikic)
<details>
<summary>Changes</summary>
I believe the transform is not correct for shifts by 15, because the multiplier gets sign extended, turning a multiply by 2^15 into one by -2^15.
---
Full diff: https://github.com/llvm/llvm-project/pull/206473.diff
2 Files Affected:
- (modified) llvm/lib/Target/X86/X86ISelLowering.cpp (+2-2)
- (modified) llvm/test/CodeGen/X86/madd.ll (+54)
``````````diff
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index b95ac78f50049..5575b68ed7c72 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -59681,9 +59681,9 @@ static SDValue matchPMADDWD(SelectionDAG &DAG, SDNode *N,
if (N0.getValueType().getScalarType() != MVT::i16)
return SDValue();
- // A shift by more than 15 would overflow an i16.
+ // A shift by more 15 or more would overflow a signed i16.
if (!ISD::matchUnaryPredicate(Mul.getOperand(1), [](ConstantSDNode *C) {
- return C->getAPIntValue().ule(15);
+ return C->getAPIntValue().ult(15);
}))
return SDValue();
diff --git a/llvm/test/CodeGen/X86/madd.ll b/llvm/test/CodeGen/X86/madd.ll
index 4ca0b05dbe92b..4ee77c0bdf70c 100644
--- a/llvm/test/CodeGen/X86/madd.ll
+++ b/llvm/test/CodeGen/X86/madd.ll
@@ -3882,3 +3882,57 @@ define <3 x i32> @oddvector_shl(<12 x i16> %A) {
%ret = add <3 x i32> %odd, %even
ret <3 x i32> %ret
}
+
+; Don't form pmaddwd for shift by 15, because this would get interpreted as
+; a multiply by -2^15 rather than +2^15.
+define <4 x i32> @shl15(<8 x i16> %x) {
+; SSE2-LABEL: shl15:
+; SSE2: # %bb.0:
+; SSE2-NEXT: punpcklwd {{.*#+}} xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1],xmm1[2],xmm0[2],xmm1[3],xmm0[3]
+; SSE2-NEXT: psrad $16, %xmm1
+; SSE2-NEXT: punpckhwd {{.*#+}} xmm0 = xmm0[4,4,5,5,6,6,7,7]
+; SSE2-NEXT: psrad $16, %xmm0
+; SSE2-NEXT: pslld $15, %xmm0
+; SSE2-NEXT: pslld $15, %xmm1
+; SSE2-NEXT: movdqa %xmm1, %xmm2
+; SSE2-NEXT: shufps {{.*#+}} xmm2 = xmm2[0,2],xmm0[0,2]
+; SSE2-NEXT: shufps {{.*#+}} xmm1 = xmm1[1,3],xmm0[1,3]
+; SSE2-NEXT: paddd %xmm2, %xmm1
+; SSE2-NEXT: movdqa %xmm1, %xmm0
+; SSE2-NEXT: retq
+;
+; SSE42-LABEL: shl15:
+; SSE42: # %bb.0:
+; SSE42-NEXT: pshufd {{.*#+}} xmm1 = xmm0[2,3,2,3]
+; SSE42-NEXT: pmovsxwd %xmm1, %xmm1
+; SSE42-NEXT: pmovsxwd %xmm0, %xmm0
+; SSE42-NEXT: pslld $15, %xmm0
+; SSE42-NEXT: pslld $15, %xmm1
+; SSE42-NEXT: phaddd %xmm1, %xmm0
+; SSE42-NEXT: retq
+;
+; AVX1-LABEL: shl15:
+; AVX1: # %bb.0:
+; AVX1-NEXT: vpshufd {{.*#+}} xmm1 = xmm0[2,3,2,3]
+; AVX1-NEXT: vpmovsxwd %xmm1, %xmm1
+; AVX1-NEXT: vpmovsxwd %xmm0, %xmm0
+; AVX1-NEXT: vpslld $15, %xmm0, %xmm0
+; AVX1-NEXT: vpslld $15, %xmm1, %xmm1
+; AVX1-NEXT: vphaddd %xmm1, %xmm0, %xmm0
+; AVX1-NEXT: retq
+;
+; AVX256-LABEL: shl15:
+; AVX256: # %bb.0:
+; AVX256-NEXT: vpmovsxwd %xmm0, %ymm0
+; AVX256-NEXT: vpslld $15, %ymm0, %ymm0
+; AVX256-NEXT: vextracti128 $1, %ymm0, %xmm1
+; AVX256-NEXT: vphaddd %xmm1, %xmm0, %xmm0
+; AVX256-NEXT: vzeroupper
+; AVX256-NEXT: retq
+ %s = sext <8 x i16> %x to <8 x i32>
+ %m = shl <8 x i32> %s, splat (i32 15)
+ %even = shufflevector <8 x i32> %m, <8 x i32> poison, <4 x i32> <i32 0, i32 2, i32 4, i32 6>
+ %odd = shufflevector <8 x i32> %m, <8 x i32> poison, <4 x i32> <i32 1, i32 3, i32 5, i32 7>
+ %r = add <4 x i32> %even, %odd
+ ret <4 x i32> %r
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/206473
More information about the llvm-commits
mailing list