[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