[llvm] 3f28ade - [SPIRV] Support selection of G_CONCAT_VECTORS (#201686)

via llvm-commits llvm-commits at lists.llvm.org
Tue Jun 9 07:10:40 PDT 2026


Author: Nick Sarnie
Date: 2026-06-09T14:10:34Z
New Revision: 3f28ade7a938f410baa061c4fe0c69a98dd58281

URL: https://github.com/llvm/llvm-project/commit/3f28ade7a938f410baa061c4fe0c69a98dd58281
DIFF: https://github.com/llvm/llvm-project/commit/3f28ade7a938f410baa061c4fe0c69a98dd58281.diff

LOG: [SPIRV] Support selection of G_CONCAT_VECTORS (#201686)

Implement the G_CONCAT_VECTOR opcode using `OpCompositeConstruct`. The
semantics are similar so the implementation is straightforward.

This opcode being generated is somewhat rare, in this case it seems to
have remained due to the non-power of 2 vector length ABI.

Co-Authored-By: Claude Opus 4.8 <noreply at anthropic.com>

Co-authored-by: Claude Opus 4.8 <noreply at anthropic.com>

Added: 
    llvm/test/CodeGen/SPIRV/concat-vectors.ll

Modified: 
    llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index dc8a7c2148aa9..3b0242d970359 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -210,6 +210,8 @@ class SPIRVInstructionSelector : public InstructionSelector {
                          MachineInstr &I) const;
   bool selectSplatVector(Register ResVReg, SPIRVTypeInst ResType,
                          MachineInstr &I) const;
+  bool selectConcatVectors(Register ResVReg, SPIRVTypeInst ResType,
+                           MachineInstr &I) const;
 
   bool selectCmp(Register ResVReg, SPIRVTypeInst ResType,
                  unsigned comparisonOpcode, MachineInstr &I) const;
@@ -1015,6 +1017,8 @@ bool SPIRVInstructionSelector::spvSelect(Register ResVReg,
     return selectBuildVector(ResVReg, ResType, I);
   case TargetOpcode::G_SPLAT_VECTOR:
     return selectSplatVector(ResVReg, ResType, I);
+  case TargetOpcode::G_CONCAT_VECTORS:
+    return selectConcatVectors(ResVReg, ResType, I);
 
   case TargetOpcode::G_SHUFFLE_VECTOR: {
     MachineBasicBlock &BB = *I.getParent();
@@ -3975,6 +3979,27 @@ bool SPIRVInstructionSelector::selectSplatVector(Register ResVReg,
   return true;
 }
 
+bool SPIRVInstructionSelector::selectConcatVectors(Register ResVReg,
+                                                   SPIRVTypeInst ResType,
+                                                   MachineInstr &I) const {
+  // Implement G_CONCAT_VECTORS using OpCompositeConstruct, which allows vector
+  // constituents that share the result's component type to be
+  // concatenated in operand order.
+  if (ResType->getOpcode() != SPIRV::OpTypeVector)
+    report_fatal_error(
+        "Cannot select G_CONCAT_VECTORS with a non-vector result");
+
+  auto MIB = BuildMI(*I.getParent(), I, I.getDebugLoc(),
+                     TII.get(SPIRV::OpCompositeConstruct))
+                 .addDef(ResVReg)
+                 .addUse(GR.getSPIRVTypeID(ResType));
+  for (unsigned OpIdx = I.getNumExplicitDefs();
+       OpIdx < I.getNumExplicitOperands(); ++OpIdx)
+    MIB.addUse(I.getOperand(OpIdx).getReg());
+  MIB.constrainAllUses(TII, TRI, RBI);
+  return true;
+}
+
 bool SPIRVInstructionSelector::selectDiscard(Register ResVReg,
                                              SPIRVTypeInst ResType,
                                              MachineInstr &I) const {

diff  --git a/llvm/test/CodeGen/SPIRV/concat-vectors.ll b/llvm/test/CodeGen/SPIRV/concat-vectors.ll
new file mode 100644
index 0000000000000..cc7d593dbacb0
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/concat-vectors.ll
@@ -0,0 +1,25 @@
+; RUN: llc -O0 -global-isel -verify-machineinstrs -mtriple=spirv64 %s -o - | FileCheck %s
+; spirv-val errors about a 7 element vector.
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv64 < %s -o - -filetype=obj | spirv-val %}
+
+; G_CONCAT_VECTORS should select to OpCompositeConstruct, which
+; concatenates its vector constituents (each sharing the result component type).
+
+; Note we have to use a non-power of 2 vector length (7 here) that cannot be legalized to actually
+; generate the G_CONCAT_VECTOR Opcode. Usually it would be legalized but here it can't because it's
+; part of the ABI.
+
+; CHECK: %[[#I8:]] = OpTypeInt 8 0
+; CHECK: %[[#V4:]] = OpTypeVector %[[#I8]] 4
+; CHECK: %[[#V8:]] = OpTypeVector %[[#I8]] 8
+; CHECK: %[[#UNDEF:]] = OpUndef %[[#V4]]
+; CHECK: OpFunction
+; CHECK: %[[#A:]] = OpFunctionParameter %[[#V4]]
+; CHECK: %[[#CONCAT:]] = OpCompositeConstruct %[[#V8]] %[[#A]] %[[#UNDEF]]
+
+define spir_func <7 x i8> @extend_vec4_to_vec7(<4 x i8> %x) {
+
+entry:
+  %r = shufflevector <4 x i8> %x, <4 x i8> poison, <7 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison>
+  ret <7 x i8> %r
+}


        


More information about the llvm-commits mailing list