[llvm] [X86] combineConcatVectorOps - IsConcatFree - detect splats that comes from a common load/broadcastload (PR #174986)
Simon Pilgrim via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 8 07:02:00 PST 2026
https://github.com/RKSimon created https://github.com/llvm/llvm-project/pull/174986
Allows us to handle freely concatable cases after a broadcast load has become shared by different vector width uses by peeking through bitcasts/extract_subvector nodes
>From 2da2967c3517cf3a072631ec88530e3da5767229 Mon Sep 17 00:00:00 2001
From: Simon Pilgrim <llvm-dev at redking.me.uk>
Date: Thu, 8 Jan 2026 15:00:55 +0000
Subject: [PATCH] [X86] combineConcatVectorOps - IsConcatFree - detect splats
that comes from a common load/broadcastload
Allows us to handle freely concatable cases after a broadcast load has become shared by different vector width uses by peeking through bitcasts/extract_subvector nodes
---
llvm/lib/Target/X86/X86ISelLowering.cpp | 8 +++-
llvm/test/CodeGen/X86/combine-fma-concat.ll | 41 +++++++++++++--------
2 files changed, 32 insertions(+), 17 deletions(-)
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 1835d58f7cd41..40ea3cb76bae4 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -59234,7 +59234,13 @@ static SDValue combineConcatVectorOps(const SDLoc &DL, MVT VT,
if (all_of(SubOps, [&](SDValue SubOp) {
return SubOp0 == SubOp.getOperand(Op);
})) {
- if (isa<LoadSDNode>(peekThroughBitcasts(SubOp0)))
+ SDValue Src = SubOp0;
+ while (Src.getOpcode() == ISD::BITCAST ||
+ Src.getOpcode() == ISD::EXTRACT_SUBVECTOR)
+ Src = Src.getOperand(0);
+ if (ISD::isNormalLoad(Src.getNode()) ||
+ Src.getOpcode() == X86ISD::VBROADCAST_LOAD ||
+ Src.getOpcode() == X86ISD::SUBV_BROADCAST_LOAD)
return true;
}
SmallVector<SDValue> Subs;
diff --git a/llvm/test/CodeGen/X86/combine-fma-concat.ll b/llvm/test/CodeGen/X86/combine-fma-concat.ll
index fe66918b66568..3404fede6f23b 100644
--- a/llvm/test/CodeGen/X86/combine-fma-concat.ll
+++ b/llvm/test/CodeGen/X86/combine-fma-concat.ll
@@ -279,32 +279,41 @@ define <8 x double> @concat_fma_fmsub_v8f64_v4f64_constant_repeatedop_commute(<4
ret <8 x double> %r
}
-; FIXME: FMA can't be concatenated until after max intrinsics have lowered, but then the v4f32 broadcasted constant is hidden behind an EXTRACT_SUBVECTOR
+; FMA can't be concatenated until after max intrinsics have lowered, but then the v4f32 broadcasted constant is hidden behind an EXTRACT_SUBVECTOR
define <8 x float> @concat_fma_v8f32_v4f32_late_concat(<4 x float> %x, <4 x float> %y, <8 x float> %z) {
; FMA4-LABEL: concat_fma_v8f32_v4f32_late_concat:
; FMA4: # %bb.0:
-; FMA4-NEXT: vmovaps {{.*#+}} ymm3 = [2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0]
-; FMA4-NEXT: vfmaddps {{.*#+}} xmm0 = (xmm0 * xmm0) + xmm3
-; FMA4-NEXT: vfmaddps {{.*#+}} xmm1 = (xmm1 * xmm1) + xmm3
-; FMA4-NEXT: vmaxps %ymm3, %ymm2, %ymm2
; FMA4-NEXT: vbroadcastf128 {{.*#+}} ymm3 = [2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0]
; FMA4-NEXT: # ymm3 = mem[0,1,0,1]
+; FMA4-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0
; FMA4-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0
+; FMA4-NEXT: vmaxps {{\.?LCPI[0-9]+_[0-9]+}}(%rip), %ymm2, %ymm2
+; FMA4-NEXT: vfmaddps {{.*#+}} ymm0 = (ymm0 * ymm0) + ymm3
; FMA4-NEXT: vmaxps %ymm3, %ymm0, %ymm0
; FMA4-NEXT: vaddps %ymm2, %ymm0, %ymm0
; FMA4-NEXT: retq
;
-; FMA3-LABEL: concat_fma_v8f32_v4f32_late_concat:
-; FMA3: # %bb.0:
-; FMA3-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0
-; FMA3-NEXT: vbroadcastss {{.*#+}} ymm3 = [2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0]
-; FMA3-NEXT: vfmadd213ps {{.*#+}} xmm0 = (xmm0 * xmm0) + xmm3
-; FMA3-NEXT: vfmadd213ps {{.*#+}} xmm1 = (xmm1 * xmm1) + xmm3
-; FMA3-NEXT: vmaxps %ymm3, %ymm2, %ymm2
-; FMA3-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0
-; FMA3-NEXT: vmaxps %ymm3, %ymm0, %ymm0
-; FMA3-NEXT: vaddps %ymm2, %ymm0, %ymm0
-; FMA3-NEXT: retq
+; AVX2-LABEL: concat_fma_v8f32_v4f32_late_concat:
+; AVX2: # %bb.0:
+; AVX2-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0
+; AVX2-NEXT: vbroadcastss {{.*#+}} ymm3 = [2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0]
+; AVX2-NEXT: vmaxps %ymm3, %ymm2, %ymm2
+; AVX2-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0
+; AVX2-NEXT: vfmadd213ps {{.*#+}} ymm0 = (ymm0 * ymm0) + ymm3
+; AVX2-NEXT: vmaxps %ymm3, %ymm0, %ymm0
+; AVX2-NEXT: vaddps %ymm2, %ymm0, %ymm0
+; AVX2-NEXT: retq
+;
+; AVX512-LABEL: concat_fma_v8f32_v4f32_late_concat:
+; AVX512: # %bb.0:
+; AVX512-NEXT: vbroadcastss {{.*#+}} ymm3 = [2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0,2.0E+0]
+; AVX512-NEXT: # kill: def $xmm0 killed $xmm0 def $ymm0
+; AVX512-NEXT: vmaxps %ymm3, %ymm2, %ymm2
+; AVX512-NEXT: vinsertf128 $1, %xmm1, %ymm0, %ymm0
+; AVX512-NEXT: vfmadd213ps {{.*#+}} ymm0 = (ymm0 * ymm0) + ymm3
+; AVX512-NEXT: vmaxps %ymm3, %ymm0, %ymm0
+; AVX512-NEXT: vaddps %ymm2, %ymm0, %ymm0
+; AVX512-NEXT: retq
%xx = call <4 x float> @llvm.fma.v4f32(<4 x float> %x, <4 x float> %x, <4 x float> splat (float 2.000000e+00))
%yy = call <4 x float> @llvm.fma.v4f32(<4 x float> %y, <4 x float> %y, <4 x float> splat (float 2.000000e+00))
%lo = call <4 x float> @llvm.x86.sse.max.ps(<4 x float> %xx, <4 x float> splat (float 2.000000e+00))
More information about the llvm-commits
mailing list