[llvm] [SPIR-V]: Improve pattern matching to recognize an aggregate constant to be a constant (PR #96286)

Vyacheslav Levytskyy via llvm-commits llvm-commits at lists.llvm.org
Fri Jun 21 01:27:23 PDT 2024


https://github.com/VyacheslavLevytskyy created https://github.com/llvm/llvm-project/pull/96286

This PR is to fix https://github.com/llvm/llvm-project/issues/96285 by:
* improve pattern matching to recognize an aggregate constant to be a constant
* do not emit Bitcast for an aggregate type

>From 795132c67fd769011b8ad8152a3a7a6bfd956e63 Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Fri, 21 Jun 2024 01:05:28 -0700
Subject: [PATCH 1/2] improve pattern matching to recognize an aggregate
 constant to be a constant

---
 .../Target/SPIRV/SPIRVInstructionSelector.cpp | 14 +++++++++++--
 .../CodeGen/SPIRV/const-array-in-struct.ll    | 21 +++++++++++++++++++
 2 files changed, 33 insertions(+), 2 deletions(-)
 create mode 100644 llvm/test/CodeGen/SPIRV/const-array-in-struct.ll

diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index d7b96b28445d6..9b069614a5ce7 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -1451,8 +1451,18 @@ static bool isConstReg(MachineRegisterInfo *MRI, SPIRVType *OpDef) {
     if (SPIRVType *RefDef = MRI->getVRegDef(OpDef->getOperand(1).getReg()))
       OpDef = RefDef;
   }
-  return OpDef->getOpcode() == TargetOpcode::G_CONSTANT ||
-         OpDef->getOpcode() == TargetOpcode::G_FCONSTANT;
+  unsigned Opcode = OpDef->getOpcode();
+  switch (Opcode) {
+  case TargetOpcode::G_CONSTANT:
+  case TargetOpcode::G_FCONSTANT:
+    return true;
+  case TargetOpcode::G_INTRINSIC:
+  case TargetOpcode::G_INTRINSIC_W_SIDE_EFFECTS:
+  case TargetOpcode::G_INTRINSIC_CONVERGENT_W_SIDE_EFFECTS:
+    return cast<GIntrinsic>(*OpDef).getIntrinsicID() ==
+           Intrinsic::spv_const_composite;
+  }
+  return false;
 }
 
 // Return true if the virtual register represents a constant
diff --git a/llvm/test/CodeGen/SPIRV/const-array-in-struct.ll b/llvm/test/CodeGen/SPIRV/const-array-in-struct.ll
new file mode 100644
index 0000000000000..ac39f3d28d073
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/const-array-in-struct.ll
@@ -0,0 +1,21 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; RUN: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-SPIRV: %[[#IntTy:]] = OpTypeInt 32 0
+; CHECK-SPIRV: %[[#Const16:]] = OpConstant %[[#IntTy]] 16
+; CHECK-SPIRV: %[[#ArrayTy:]] = OpTypeArray %[[#IntTy]] %[[#Const16]]
+; CHECK-SPIRV: %[[#StructTy:]] = OpTypeStruct %[[#ArrayTy]]
+; CHECK-SPIRV-COUNT-16: %[[#]] = OpConstant %[[#IntTy]] {{[0-9]+}}
+; CHECK-SPIRV: %[[#ConstArray:]] = OpConstantComposite %[[#ArrayTy]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]] %[[#]]
+; CHECK-SPIRV: %[[#]] = OpConstantComposite %[[#StructTy]] %[[#ConstArray]]
+
+%struct_array_16i32 = type { [16 x i32] }
+
+ at G = private unnamed_addr addrspace(1) constant %struct_array_16i32 { [16 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] }, align 4
+
+define spir_kernel void @test() {
+  ret void
+}

>From 6f60c2533a649f333ba466c072abb33b4e5ac4fc Mon Sep 17 00:00:00 2001
From: "Levytskyy, Vyacheslav" <vyacheslav.levytskyy at intel.com>
Date: Fri, 21 Jun 2024 01:26:26 -0700
Subject: [PATCH 2/2] do not emit Bitcast for an aggregate type

---
 llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h        | 6 ++++++
 llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp | 3 ++-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index db01f68f48de9..2182ad70cab46 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -327,6 +327,12 @@ class SPIRVGlobalRegistry {
     return Ret;
   }
 
+  // Return true if the type is an aggregate type.
+  bool isAggregateType(SPIRVType *Type) const {
+    return Type && (Type->getOpcode() == SPIRV::OpTypeStruct &&
+                    Type->getOpcode() == SPIRV::OpTypeArray);
+  }
+
   // Whether the given VReg has an OpTypeXXX instruction mapped to it with the
   // given opcode (e.g. OpTypeFloat).
   bool isScalarOfType(Register VReg, unsigned TypeOpcode) const;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 9b069614a5ce7..7a538736c77d6 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -1893,7 +1893,8 @@ bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
     SPIRVType *OpDefine = MRI->getVRegDef(OpReg);
     SPIRVType *OpType = GR.getSPIRVTypeForVReg(OpReg);
     if (!OpDefine || !OpType || isConstReg(MRI, OpDefine) ||
-        OpDefine->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST) {
+        OpDefine->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST ||
+        GR.isAggregateType(OpType)) {
       // The case of G_ADDRSPACE_CAST inside spv_const_composite() is processed
       // by selectAddrSpaceCast()
       CompositeArgs.push_back(OpReg);



More information about the llvm-commits mailing list