[llvm] [SelectionDAG] Fold subvector inserts into concat operands (PR #200937)
Krzysztof Drewniak via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 9 12:46:34 PDT 2026
https://github.com/krzysz00 updated https://github.com/llvm/llvm-project/pull/200937
>From 52e4e592722e5223c3668bd3f8b396672f945ba4 Mon Sep 17 00:00:00 2001
From: Krzysztof Drewniak <Krzysztof.Drewniak at amd.com>
Date: Sat, 30 May 2026 02:18:03 +0000
Subject: [PATCH 1/2] [SelectionDAG] Fold subvector inserts into concat
operands
Push insert_subvector into the containing CONCAT_VECTORS operand when the insertion is wholly contained there.
AI note: an LLM generated the code and the test, I've read them
Co-Authored-By: OpenAI Codex <codex at openai.com>
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 44 ++++++++++++++-----
.../vector-shuffle-combining-avx512bwvl.ll | 44 ++++---------------
2 files changed, 42 insertions(+), 46 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 549d9052a71be..eb5fa5407205b 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -29503,16 +29503,40 @@ SDValue DAGCombiner::visitINSERT_SUBVECTOR(SDNode *N) {
}
}
- // If the input vector is a concatenation, and the insert replaces
- // one of the pieces, we can optimize into a single concat_vectors.
- if (N0.getOpcode() == ISD::CONCAT_VECTORS && N0.hasOneUse() &&
- N0.getOperand(0).getValueType() == N1.getValueType() &&
- N0.getOperand(0).getValueType().isScalableVector() ==
- N1.getValueType().isScalableVector()) {
- unsigned Factor = N1.getValueType().getVectorMinNumElements();
- SmallVector<SDValue, 8> Ops(N0->ops());
- Ops[InsIdx / Factor] = N1;
- return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VT, Ops);
+ // If the input vector is a concatenation and the insert is wholly contained
+ // in one of its operands, push the insertion into that operand.
+ if (N0.getOpcode() == ISD::CONCAT_VECTORS && N0.hasOneUse()) {
+ EVT ConcatOpVT = N0.getOperand(0).getValueType();
+ EVT InsVT = N1.getValueType();
+ unsigned Factor = ConcatOpVT.getVectorMinNumElements();
+ unsigned ConcatOpIdx = InsIdx / Factor;
+ unsigned RelativeIdx = InsIdx - ConcatOpIdx * Factor;
+ if (ConcatOpIdx < N0.getNumOperands()) {
+ // If the insert replaces a whole concat operand, optimize into a single
+ // concat_vectors.
+ if (ConcatOpVT == InsVT &&
+ ConcatOpVT.isScalableVector() == InsVT.isScalableVector() &&
+ RelativeIdx == 0) {
+ SmallVector<SDValue, 8> Ops(N0->ops());
+ Ops[ConcatOpIdx] = N1;
+ return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VT, Ops);
+ }
+
+ if (VT.isFixedLengthVector() && ConcatOpVT.isFixedLengthVector() &&
+ InsVT.isFixedLengthVector() &&
+ ConcatOpVT.getVectorElementType() == InsVT.getVectorElementType() &&
+ hasOperation(ISD::INSERT_SUBVECTOR, ConcatOpVT)) {
+ unsigned NumConcatOpElts = ConcatOpVT.getVectorNumElements();
+ unsigned NumInsElts = InsVT.getVectorNumElements();
+ if (RelativeIdx % NumInsElts == 0 &&
+ RelativeIdx + NumInsElts <= NumConcatOpElts) {
+ SmallVector<SDValue, 8> Ops(N0->ops());
+ Ops[ConcatOpIdx] = DAG.getInsertSubvector(SDLoc(N), Ops[ConcatOpIdx],
+ N1, RelativeIdx);
+ return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VT, Ops);
+ }
+ }
+ }
}
// Simplify source operands based on insertion.
diff --git a/llvm/test/CodeGen/X86/vector-shuffle-combining-avx512bwvl.ll b/llvm/test/CodeGen/X86/vector-shuffle-combining-avx512bwvl.ll
index cc84738ed3915..ee56b9633fb89 100644
--- a/llvm/test/CodeGen/X86/vector-shuffle-combining-avx512bwvl.ll
+++ b/llvm/test/CodeGen/X86/vector-shuffle-combining-avx512bwvl.ll
@@ -319,26 +319,12 @@ define <32 x i16> @insert_concat_select(i1 %cond, <16 x i16> %a, <16 x i16> %b,
; X86-NEXT: testb $1, 8(%ebp)
; X86-NEXT: jne .LBB16_1
; X86-NEXT: # %bb.2:
-; X86-NEXT: vmovdqa64 72(%ebp), %zmm0
+; X86-NEXT: vmovaps 72(%ebp), %zmm0
; X86-NEXT: jmp .LBB16_3
; X86-NEXT: .LBB16_1:
-; X86-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm0
-; X86-NEXT: vmovd %xmm2, %eax
-; X86-NEXT: movl $65536, %ecx # imm = 0x10000
-; X86-NEXT: kmovd %ecx, %k1
-; X86-NEXT: vpbroadcastw %eax, %zmm0 {%k1}
-; X86-NEXT: vpextrw $1, %xmm2, %eax
-; X86-NEXT: movl $131072, %ecx # imm = 0x20000
-; X86-NEXT: kmovd %ecx, %k1
-; X86-NEXT: vpbroadcastw %eax, %zmm0 {%k1}
-; X86-NEXT: vpextrw $2, %xmm2, %eax
-; X86-NEXT: movl $262144, %ecx # imm = 0x40000
-; X86-NEXT: kmovd %ecx, %k1
-; X86-NEXT: vpbroadcastw %eax, %zmm0 {%k1}
-; X86-NEXT: vpextrw $3, %xmm2, %eax
-; X86-NEXT: movl $524288, %ecx # imm = 0x80000
-; X86-NEXT: kmovd %ecx, %k1
-; X86-NEXT: vpbroadcastw %eax, %zmm0 {%k1}
+; X86-NEXT: vblendps {{.*#+}} xmm2 = xmm2[0,1],xmm1[2,3]
+; X86-NEXT: vblendps {{.*#+}} ymm1 = ymm2[0,1,2,3],ymm1[4,5,6,7]
+; X86-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm0
; X86-NEXT: .LBB16_3:
; X86-NEXT: movl %ebp, %esp
; X86-NEXT: popl %ebp
@@ -351,25 +337,11 @@ define <32 x i16> @insert_concat_select(i1 %cond, <16 x i16> %a, <16 x i16> %b,
; X64-NEXT: testb $1, %dil
; X64-NEXT: je .LBB16_2
; X64-NEXT: # %bb.1:
-; X64-NEXT: vinserti64x4 $1, %ymm1, %zmm0, %zmm3
-; X64-NEXT: vmovd %xmm2, %eax
-; X64-NEXT: movl $65536, %ecx # imm = 0x10000
-; X64-NEXT: kmovd %ecx, %k1
-; X64-NEXT: vpbroadcastw %eax, %zmm3 {%k1}
-; X64-NEXT: vpextrw $1, %xmm2, %eax
-; X64-NEXT: movl $131072, %ecx # imm = 0x20000
-; X64-NEXT: kmovd %ecx, %k1
-; X64-NEXT: vpbroadcastw %eax, %zmm3 {%k1}
-; X64-NEXT: vpextrw $2, %xmm2, %eax
-; X64-NEXT: movl $262144, %ecx # imm = 0x40000
-; X64-NEXT: kmovd %ecx, %k1
-; X64-NEXT: vpbroadcastw %eax, %zmm3 {%k1}
-; X64-NEXT: vpextrw $3, %xmm2, %eax
-; X64-NEXT: movl $524288, %ecx # imm = 0x80000
-; X64-NEXT: kmovd %ecx, %k1
-; X64-NEXT: vpbroadcastw %eax, %zmm3 {%k1}
+; X64-NEXT: vblendps {{.*#+}} xmm2 = xmm2[0,1],xmm1[2,3]
+; X64-NEXT: vblendps {{.*#+}} ymm1 = ymm2[0,1,2,3],ymm1[4,5,6,7]
+; X64-NEXT: vinsertf64x4 $1, %ymm1, %zmm0, %zmm3
; X64-NEXT: .LBB16_2:
-; X64-NEXT: vmovdqa64 %zmm3, %zmm0
+; X64-NEXT: vmovaps %zmm3, %zmm0
; X64-NEXT: retq
%wide = shufflevector <16 x i16> %a, <16 x i16> %b, <32 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23, i32 24, i32 25, i32 26, i32 27, i32 28, i32 29, i32 30, i32 31>
%ins = call <32 x i16> @llvm.vector.insert.v32i16.v4i16(<32 x i16> %wide, <4 x i16> %sub, i64 16)
>From cdae94b6fe57fcf6fbee56c5f9662684eaa7953e Mon Sep 17 00:00:00 2001
From: Krzysztof Drewniak <Krzysztof.Drewniak at amd.com>
Date: Tue, 9 Jun 2026 19:46:05 +0000
Subject: [PATCH 2/2] Remove pointless checks
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 42 +++++++++----------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index eb5fa5407205b..716e4f75454f1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -29511,31 +29511,29 @@ SDValue DAGCombiner::visitINSERT_SUBVECTOR(SDNode *N) {
unsigned Factor = ConcatOpVT.getVectorMinNumElements();
unsigned ConcatOpIdx = InsIdx / Factor;
unsigned RelativeIdx = InsIdx - ConcatOpIdx * Factor;
- if (ConcatOpIdx < N0.getNumOperands()) {
- // If the insert replaces a whole concat operand, optimize into a single
- // concat_vectors.
- if (ConcatOpVT == InsVT &&
- ConcatOpVT.isScalableVector() == InsVT.isScalableVector() &&
- RelativeIdx == 0) {
+ assert(ConcatOpIdx < N0.getNumOperands() && "have enoug concat operands");
+
+ // If the insert replaces a whole concat operand, optimize into a single
+ // concat_vectors.
+ if (RelativeIdx == 0 && ConcatOpVT == InsVT &&
+ ConcatOpVT.isScalableVector() == InsVT.isScalableVector()) {
+ SmallVector<SDValue, 8> Ops(N0->ops());
+ Ops[ConcatOpIdx] = N1;
+ return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VT, Ops);
+ }
+
+ if (VT.isFixedLengthVector() && ConcatOpVT.isFixedLengthVector() &&
+ InsVT.isFixedLengthVector() &&
+ hasOperation(ISD::INSERT_SUBVECTOR, ConcatOpVT)) {
+ unsigned NumConcatOpElts = ConcatOpVT.getVectorNumElements();
+ unsigned NumInsElts = InsVT.getVectorNumElements();
+ if (RelativeIdx % NumInsElts == 0 &&
+ RelativeIdx + NumInsElts <= NumConcatOpElts) {
SmallVector<SDValue, 8> Ops(N0->ops());
- Ops[ConcatOpIdx] = N1;
+ Ops[ConcatOpIdx] =
+ DAG.getInsertSubvector(SDLoc(N), Ops[ConcatOpIdx], N1, RelativeIdx);
return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VT, Ops);
}
-
- if (VT.isFixedLengthVector() && ConcatOpVT.isFixedLengthVector() &&
- InsVT.isFixedLengthVector() &&
- ConcatOpVT.getVectorElementType() == InsVT.getVectorElementType() &&
- hasOperation(ISD::INSERT_SUBVECTOR, ConcatOpVT)) {
- unsigned NumConcatOpElts = ConcatOpVT.getVectorNumElements();
- unsigned NumInsElts = InsVT.getVectorNumElements();
- if (RelativeIdx % NumInsElts == 0 &&
- RelativeIdx + NumInsElts <= NumConcatOpElts) {
- SmallVector<SDValue, 8> Ops(N0->ops());
- Ops[ConcatOpIdx] = DAG.getInsertSubvector(SDLoc(N), Ops[ConcatOpIdx],
- N1, RelativeIdx);
- return DAG.getNode(ISD::CONCAT_VECTORS, SDLoc(N), VT, Ops);
- }
- }
}
}
More information about the llvm-commits
mailing list