[llvm] [SPIRV] Scalarize single-element vectors in type creation (PR #180735)
Dmitry Sidorov via llvm-commits
llvm-commits at lists.llvm.org
Tue Feb 10 05:25:52 PST 2026
https://github.com/MrSidims updated https://github.com/llvm/llvm-project/pull/180735
>From cd82ea34ae200595d0ca64f0e23c0ad25f26ff1b Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Fri, 6 Feb 2026 00:21:41 +0100
Subject: [PATCH 1/3] [SPIRV] Scalarize single-element vectors in type creation
SPIR-V requires vectors to have at least 2 components. So treat <1 x T>
as T.
---
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 12 +++++
.../CodeGen/SPIRV/single-element-vector.ll | 52 +++++++++++++++++++
2 files changed, 64 insertions(+)
create mode 100644 llvm/test/CodeGen/SPIRV/single-element-vector.ll
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index 14f1c97741ccc..dae85278f199f 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -311,6 +311,7 @@ SPIRVType *SPIRVGlobalRegistry::getOpTypeVector(uint32_t NumElems,
MachineIRBuilder &MIRBuilder) {
auto EleOpc = ElemType->getOpcode();
(void)EleOpc;
+ assert(NumElems >= 2 && "SPIR-V OpTypeVector requires at least 2 components");
assert((EleOpc == SPIRV::OpTypeInt || EleOpc == SPIRV::OpTypeFloat ||
EleOpc == SPIRV::OpTypeBool) &&
"Invalid vector element type");
@@ -1278,6 +1279,11 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVType(
const Type *Ty, MachineIRBuilder &MIRBuilder,
SPIRV::AccessQualifier::AccessQualifier AccessQual,
bool ExplicitLayoutRequired, bool EmitIR) {
+ // SPIR-V doesn't support single-element vectors. Treat <1 x T> as T.
+ if (auto *FVT = dyn_cast<FixedVectorType>(Ty);
+ FVT && FVT->getNumElements() == 1)
+ return getOrCreateSPIRVType(FVT->getElementType(), MIRBuilder, AccessQual,
+ ExplicitLayoutRequired, EmitIR);
const MachineFunction *MF = &MIRBuilder.getMF();
Register Reg;
if (auto *ExtTy = dyn_cast<TargetExtType>(Ty);
@@ -1896,6 +1902,9 @@ SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineInstr &I,
SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder,
bool EmitIR) {
+ // SPIR-V doesn't support single-element vectors.
+ if (NumElements == 1)
+ return BaseType;
return getOrCreateSPIRVType(
FixedVectorType::get(const_cast<Type *>(getTypeForSPIRVType(BaseType)),
NumElements),
@@ -1905,6 +1914,9 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
const SPIRVInstrInfo &TII) {
+ // SPIR-V doesn't support single-element vectors.
+ if (NumElements == 1)
+ return BaseType;
Type *Ty = FixedVectorType::get(
const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
if (const MachineInstr *MI = findMI(Ty, false, CurMF))
diff --git a/llvm/test/CodeGen/SPIRV/single-element-vector.ll b/llvm/test/CodeGen/SPIRV/single-element-vector.ll
new file mode 100644
index 0000000000000..4cc14489b0df0
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/single-element-vector.ll
@@ -0,0 +1,52 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+
+; Verify that <1 x T> types are scalarized to T since SPIR-V doesn't support
+; single-element vectors.
+
+; CHECK-DAG: %[[#INT16:]] = OpTypeInt 16 0
+; CHECK-DAG: %[[#FLOAT64:]] = OpTypeFloat 64
+; CHECK-DAG: %[[#VEC4:]] = OpTypeVector %[[#FLOAT64]] 4
+; CHECK-DAG: %[[#FNTY:]] = OpTypeFunction %[[#VEC4]] %[[#INT16]]
+; CHECK-DAG: %[[#ZERO:]] = OpConstantNull %[[#INT16]]
+
+; CHECK: OpFunctionCall %[[#VEC4]] %[[#]] %[[#ZERO]]
+define spir_func <4 x double> @caller() {
+entry:
+ %C = call <4 x double> @callee(<1 x i16> zeroinitializer)
+ ret <4 x double> %C
+}
+declare <4 x double> @callee(<1 x i16>)
+
+; CHECK: %[[#EXTRACT_RES:]] = OpFunctionParameter %[[#INT16]]
+; CHECK: OpReturnValue %[[#EXTRACT_RES]]
+define spir_func i16 @test_extractelement(<1 x i16> %v) {
+entry:
+ %e = extractelement <1 x i16> %v, i32 0
+ ret i16 %e
+}
+
+; CHECK: %[[#INSERT_VAL:]] = OpFunctionParameter %[[#INT16]]
+; CHECK: OpReturnValue %[[#INSERT_VAL]]
+define spir_func <1 x i16> @test_insertelement(i16 %val) {
+entry:
+ %v = insertelement <1 x i16> undef, i16 %val, i32 0
+ ret <1 x i16> %v
+}
+
+; CHECK: %[[#SHUF_PARAM:]] = OpFunctionParameter %[[#INT16]]
+; CHECK: OpReturnValue %[[#SHUF_PARAM]]
+define spir_func <1 x i16> @test_shufflevector(<1 x i16> %v) {
+entry:
+ %s = shufflevector <1 x i16> %v, <1 x i16> undef, <1 x i32> zeroinitializer
+ ret <1 x i16> %s
+}
+
+; CHECK: %[[#LHS_PARAM:]] = OpFunctionParameter %[[#INT16]]
+; CHECK: %[[#RHS_PARAM:]] = OpFunctionParameter %[[#INT16]]
+; CHECK: %[[#RET:]] = OpIAdd %[[#INT16]] %[[#LHS_PARAM]] %[[#RHS_PARAM]]
+; CHECK: OpReturnValue %[[#RET]]
+define spir_func <1 x i16> @test_arithm(<1 x i16> %v1, <1 x i16> %v2) {
+entry:
+ %s = add <1 x i16> %v1, %v2
+ ret <1 x i16> %s
+}
>From 4d8fc05431c15df2abd11e0a426db80b6a3fea20 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Tue, 10 Feb 2026 07:24:26 -0600
Subject: [PATCH 2/3] remove some unneeded checksY
---
llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp | 6 ------
1 file changed, 6 deletions(-)
diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
index dae85278f199f..df4d01c22ea85 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.cpp
@@ -1902,9 +1902,6 @@ SPIRVGlobalRegistry::getOrCreateSPIRVBoolType(MachineInstr &I,
SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
SPIRVType *BaseType, unsigned NumElements, MachineIRBuilder &MIRBuilder,
bool EmitIR) {
- // SPIR-V doesn't support single-element vectors.
- if (NumElements == 1)
- return BaseType;
return getOrCreateSPIRVType(
FixedVectorType::get(const_cast<Type *>(getTypeForSPIRVType(BaseType)),
NumElements),
@@ -1914,9 +1911,6 @@ SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
SPIRVType *SPIRVGlobalRegistry::getOrCreateSPIRVVectorType(
SPIRVType *BaseType, unsigned NumElements, MachineInstr &I,
const SPIRVInstrInfo &TII) {
- // SPIR-V doesn't support single-element vectors.
- if (NumElements == 1)
- return BaseType;
Type *Ty = FixedVectorType::get(
const_cast<Type *>(getTypeForSPIRVType(BaseType)), NumElements);
if (const MachineInstr *MI = findMI(Ty, false, CurMF))
>From 8fdc4f5bb65c51bb55a896c16544367cb833ad44 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Tue, 10 Feb 2026 07:25:33 -0600
Subject: [PATCH 3/3] undef -> poison
---
llvm/test/CodeGen/SPIRV/single-element-vector.ll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/llvm/test/CodeGen/SPIRV/single-element-vector.ll b/llvm/test/CodeGen/SPIRV/single-element-vector.ll
index 4cc14489b0df0..c4f176027d70c 100644
--- a/llvm/test/CodeGen/SPIRV/single-element-vector.ll
+++ b/llvm/test/CodeGen/SPIRV/single-element-vector.ll
@@ -29,7 +29,7 @@ entry:
; CHECK: OpReturnValue %[[#INSERT_VAL]]
define spir_func <1 x i16> @test_insertelement(i16 %val) {
entry:
- %v = insertelement <1 x i16> undef, i16 %val, i32 0
+ %v = insertelement <1 x i16> poison, i16 %val, i32 0
ret <1 x i16> %v
}
@@ -37,7 +37,7 @@ entry:
; CHECK: OpReturnValue %[[#SHUF_PARAM]]
define spir_func <1 x i16> @test_shufflevector(<1 x i16> %v) {
entry:
- %s = shufflevector <1 x i16> %v, <1 x i16> undef, <1 x i32> zeroinitializer
+ %s = shufflevector <1 x i16> %v, <1 x i16> poison, <1 x i32> zeroinitializer
ret <1 x i16> %s
}
More information about the llvm-commits
mailing list