[llvm] b0efde6 - [SPIR-V]: Improve pattern matching to recognize a composite constant to be a constant (#96286)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 24 08:19:13 PDT 2024


Author: Vyacheslav Levytskyy
Date: 2024-06-24T17:19:08+02:00
New Revision: b0efde6db0282c0a98aec04806d7b8ba29e19a1b

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

LOG: [SPIR-V]: Improve pattern matching to recognize a composite constant to be a constant (#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

Added: 
    llvm/test/CodeGen/SPIRV/const-array-in-struct.ll
    llvm/test/CodeGen/SPIRV/const-nested-vecs.ll
    llvm/test/CodeGen/SPIRV/pointers/global-zeroinitializer.ll

Modified: 
    llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
    llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
    llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
    llvm/test/CodeGen/SPIRV/opencl/image.ll

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
index 5c10e04325d51..11e662c7f9ad9 100644
--- a/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVEmitIntrinsics.cpp
@@ -670,10 +670,8 @@ void SPIRVEmitIntrinsics::preprocessCompositeConstants(IRBuilder<> &B) {
         AggrConst = cast<Constant>(COp);
         ResTy = B.getInt32Ty();
       } else if (auto *COp = dyn_cast<ConstantAggregateZero>(Op)) {
-        if (!Op->getType()->isVectorTy()) {
-          AggrConst = cast<Constant>(COp);
-          ResTy = B.getInt32Ty();
-        }
+        AggrConst = cast<Constant>(COp);
+        ResTy = Op->getType()->isVectorTy() ? COp->getType() : B.getInt32Ty();
       }
       if (AggrConst) {
         SmallVector<Value *> Args;
@@ -1260,8 +1258,7 @@ void SPIRVEmitIntrinsics::processInstrAfterVisit(Instruction *I,
   }
   bool IsPhi = isa<PHINode>(I), BPrepared = false;
   for (const auto &Op : I->operands()) {
-    if ((isa<ConstantAggregateZero>(Op) && Op->getType()->isVectorTy()) ||
-        isa<PHINode>(I) || isa<SwitchInst>(I))
+    if (isa<PHINode>(I) || isa<SwitchInst>(I))
       TrackConstants = false;
     if ((isa<ConstantData>(Op) || isa<ConstantExpr>(Op)) && TrackConstants) {
       unsigned OpNo = Op.getOperandNo();

diff  --git a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
index cc4e20b8247cc..990d3328f6a30 100644
--- a/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
+++ b/llvm/lib/Target/SPIRV/SPIRVGlobalRegistry.h
@@ -329,6 +329,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 a7c6c713a110c..41a0d2c5e2f35 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -1445,20 +1445,50 @@ static unsigned getArrayComponentCount(MachineRegisterInfo *MRI,
 }
 
 // Return true if the type represents a constant register
-static bool isConstReg(MachineRegisterInfo *MRI, SPIRVType *OpDef) {
+static bool isConstReg(MachineRegisterInfo *MRI, SPIRVType *OpDef,
+                       SmallPtrSet<SPIRVType *, 4> &Visited) {
   if (OpDef->getOpcode() == SPIRV::ASSIGN_TYPE &&
       OpDef->getOperand(1).isReg()) {
     if (SPIRVType *RefDef = MRI->getVRegDef(OpDef->getOperand(1).getReg()))
       OpDef = RefDef;
   }
-  return OpDef->getOpcode() == TargetOpcode::G_CONSTANT ||
-         OpDef->getOpcode() == TargetOpcode::G_FCONSTANT;
+
+  if (Visited.contains(OpDef))
+    return true;
+  Visited.insert(OpDef);
+
+  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;
+  case TargetOpcode::G_BUILD_VECTOR:
+  case TargetOpcode::G_SPLAT_VECTOR: {
+    for (unsigned i = OpDef->getNumExplicitDefs(); i < OpDef->getNumOperands();
+         i++) {
+      SPIRVType *OpNestedDef =
+          OpDef->getOperand(i).isReg()
+              ? MRI->getVRegDef(OpDef->getOperand(i).getReg())
+              : nullptr;
+      if (OpNestedDef && !isConstReg(MRI, OpNestedDef, Visited))
+        return false;
+    }
+    return true;
+  }
+  }
+  return false;
 }
 
 // Return true if the virtual register represents a constant
 static bool isConstReg(MachineRegisterInfo *MRI, Register OpReg) {
+  SmallPtrSet<SPIRVType *, 4> Visited;
   if (SPIRVType *OpDef = MRI->getVRegDef(OpReg))
-    return isConstReg(MRI, OpDef);
+    return isConstReg(MRI, OpDef, Visited);
   return false;
 }
 
@@ -1882,8 +1912,10 @@ bool SPIRVInstructionSelector::wrapIntoSpecConstantOp(
     Register OpReg = I.getOperand(i).getReg();
     SPIRVType *OpDefine = MRI->getVRegDef(OpReg);
     SPIRVType *OpType = GR.getSPIRVTypeForVReg(OpReg);
-    if (!OpDefine || !OpType || isConstReg(MRI, OpDefine) ||
-        OpDefine->getOpcode() == TargetOpcode::G_ADDRSPACE_CAST) {
+    SmallPtrSet<SPIRVType *, 4> Visited;
+    if (!OpDefine || !OpType || isConstReg(MRI, OpDefine, Visited) ||
+        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);

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
+}

diff  --git a/llvm/test/CodeGen/SPIRV/const-nested-vecs.ll b/llvm/test/CodeGen/SPIRV/const-nested-vecs.ll
new file mode 100644
index 0000000000000..7b2b205c39674
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/const-nested-vecs.ll
@@ -0,0 +1,127 @@
+; 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 %}
+
+; TODO: llc -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s --check-prefix=CHECK-SPIRV
+; TODO: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-SPIRV: OpName %[[#Var:]] "var"
+; CHECK-SPIRV: OpName %[[#GVar:]] "g_var"
+; CHECK-SPIRV: OpName %[[#AVar:]] "a_var"
+; CHECK-SPIRV: OpName %[[#PVar:]] "p_var"
+
+; CHECK-SPIRV-DAG: %[[#CharTy:]] = OpTypeInt 8 0
+; CHECK-SPIRV-DAG: %[[#IntTy:]] = OpTypeInt 32 0
+; CHECK-SPIRV-DAG: %[[#V2CharTy:]] = OpTypeVector %[[#CharTy]] 2
+; CHECK-SPIRV-DAG: %[[#V2ConstNull:]] = OpConstantNull %[[#V2CharTy]]
+; CHECK-SPIRV-DAG: %[[#Const1:]] = OpConstant %[[#CharTy]] 1
+; CHECK-SPIRV-DAG: %[[#Const2:]] = OpConstant %[[#IntTy]] 2
+; CHECK-SPIRV-DAG: %[[#Arr2V2CharTy:]] = OpTypeArray %[[#V2CharTy]] %[[#Const2]]
+; CHECK-SPIRV-DAG: %[[#LongTy:]] = OpTypeInt 64 0
+; CHECK-SPIRV-DAG: %[[#PtrV2CharTy:]] = OpTypePointer CrossWorkgroup %[[#V2CharTy]]
+; CHECK-SPIRV-DAG: %[[#V2Char1:]] = OpConstantComposite %[[#V2CharTy]] %[[#Const1]] %[[#Const1]]
+; CHECK-SPIRV-DAG: %[[#Arr2V2Char:]] = OpConstantComposite %[[#Arr2V2CharTy]] %[[#V2Char1]] %[[#V2Char1]]
+; CHECK-SPIRV-DAG: %[[#PtrCharTy:]] = OpTypePointer CrossWorkgroup %[[#CharTy]]
+; CHECK-SPIRV-DAG: %[[#PtrArr2V2CharTy:]] = OpTypePointer CrossWorkgroup %[[#Arr2V2CharTy]]
+; CHECK-SPIRV-DAG: %[[#IntZero:]] = OpConstantNull %[[#IntTy]]
+; CHECK-SPIRV-DAG: %[[#LongZero:]] = OpConstantNull %[[#LongTy]]
+; CHECK-SPIRV-DAG: %[[#ConstLong2:]] = OpConstant %[[#LongTy]] 2
+; CHECK-SPIRV-DAG: %[[#PvarInit:]] = OpSpecConstantOp %[[#PtrCharTy]] 70 %[[#VarV2Char:]] %[[#IntZero]] %[[#ConstLong2]]
+; CHECK-SPIRV-DAG: %[[#PtrPtrCharTy:]] = OpTypePointer CrossWorkgroup %[[#PtrCharTy]]
+; CHECK-SPIRV-DAG: %[[#AVar]] = OpVariable %[[#PtrArr2V2CharTy]] CrossWorkgroup %[[#Arr2V2Char]]
+; CHECK-SPIRV-DAG: %[[#PVar]] = OpVariable %[[#PtrPtrCharTy]] CrossWorkgroup %[[#PvarInit]]
+; CHECK-SPIRV-DAG: %[[#GVar]] = OpVariable %[[#PtrV2CharTy]] CrossWorkgroup %[[#V2Char1]]
+; CHECK-SPIRV-DAG: %[[#]] = OpVariable %[[#PtrV2CharTy]] CrossWorkgroup %[[#V2ConstNull]]
+
+; As an option: %[[#Const0:]] = OpConstant %[[#CharTy]] 0
+;               %[[#V2CharZero:]] = OpConstantComposite %[[#V2CharTy]] %[[#Const0]] %[[#Const0]]
+;               %[[#]] = OpVariable %[[#PtrV2CharTy]] CrossWorkgroup %[[#V2CharZero]]
+
+ at var = addrspace(1) global <2 x i8> zeroinitializer, align 2
+ at g_var = addrspace(1) global <2 x i8> <i8 1, i8 1>, align 2
+ at a_var = addrspace(1) global [2 x <2 x i8>] [<2 x i8> <i8 1, i8 1>, <2 x i8> <i8 1, i8 1>], align 2
+ at p_var = addrspace(1) global ptr addrspace(1) getelementptr (i8, ptr addrspace(1) @a_var, i64 2), align 8
+
+define spir_func <2 x i8> @from_buf(<2 x i8> %a) #0 {
+entry:
+  ret <2 x i8> %a
+}
+
+define spir_func <2 x i8> @to_buf(<2 x i8> %a) #0 {
+entry:
+  ret <2 x i8> %a
+}
+
+define spir_kernel void @writer(ptr addrspace(1) %src, i32 %idx) #0 !kernel_arg_addr_space !5 !kernel_arg_access_qual !6 !kernel_arg_type !7 !kernel_arg_type_qual !8 !kernel_arg_base_type !7 !spirv.ParameterDecorations !9 {
+entry:
+  %arrayidx = getelementptr inbounds <2 x i8>, ptr addrspace(1) %src, i64 0
+  %0 = load <2 x i8>, ptr addrspace(1) %arrayidx, align 2
+  %call = call spir_func <2 x i8> @from_buf(<2 x i8> %0) #0
+  store <2 x i8> %call, ptr addrspace(1) @var, align 2
+  %arrayidx1 = getelementptr inbounds <2 x i8>, ptr addrspace(1) %src, i64 1
+  %1 = load <2 x i8>, ptr addrspace(1) %arrayidx1, align 2
+  %call2 = call spir_func <2 x i8> @from_buf(<2 x i8> %1) #0
+  store <2 x i8> %call2, ptr addrspace(1) @g_var, align 2
+  %arrayidx3 = getelementptr inbounds <2 x i8>, ptr addrspace(1) %src, i64 2
+  %2 = load <2 x i8>, ptr addrspace(1) %arrayidx3, align 2
+  %call4 = call spir_func <2 x i8> @from_buf(<2 x i8> %2) #0
+  %3 = getelementptr inbounds [2 x <2 x i8>], ptr addrspace(1) @a_var, i64 0, i64 0
+  store <2 x i8> %call4, ptr addrspace(1) %3, align 2
+  %arrayidx5 = getelementptr inbounds <2 x i8>, ptr addrspace(1) %src, i64 3
+  %4 = load <2 x i8>, ptr addrspace(1) %arrayidx5, align 2
+  %call6 = call spir_func <2 x i8> @from_buf(<2 x i8> %4) #0
+  %5 = getelementptr inbounds [2 x <2 x i8>], ptr addrspace(1) @a_var, i64 0, i64 1
+  store <2 x i8> %call6, ptr addrspace(1) %5, align 2
+  %idx.ext = zext i32 %idx to i64
+  %add.ptr = getelementptr inbounds <2 x i8>, ptr addrspace(1) %3, i64 %idx.ext
+  store ptr addrspace(1) %add.ptr, ptr addrspace(1) @p_var, align 8
+  ret void
+}
+
+define spir_kernel void @reader(ptr addrspace(1) %dest, <2 x i8> %ptr_write_val) #0 !kernel_arg_addr_space !5 !kernel_arg_access_qual !6 !kernel_arg_type !10 !kernel_arg_type_qual !8 !kernel_arg_base_type !10 !spirv.ParameterDecorations !9 {
+entry:
+  %call = call spir_func <2 x i8> @from_buf(<2 x i8> %ptr_write_val) #0
+  %0 = load ptr addrspace(1), ptr addrspace(1) @p_var, align 8
+  store volatile <2 x i8> %call, ptr addrspace(1) %0, align 2
+  %1 = load <2 x i8>, ptr addrspace(1) @var, align 2
+  %call1 = call spir_func <2 x i8> @to_buf(<2 x i8> %1) #0
+  %arrayidx = getelementptr inbounds <2 x i8>, ptr addrspace(1) %dest, i64 0
+  store <2 x i8> %call1, ptr addrspace(1) %arrayidx, align 2
+  %2 = load <2 x i8>, ptr addrspace(1) @g_var, align 2
+  %call2 = call spir_func <2 x i8> @to_buf(<2 x i8> %2) #0
+  %arrayidx3 = getelementptr inbounds <2 x i8>, ptr addrspace(1) %dest, i64 1
+  store <2 x i8> %call2, ptr addrspace(1) %arrayidx3, align 2
+  %3 = getelementptr inbounds [2 x <2 x i8>], ptr addrspace(1) @a_var, i64 0, i64 0
+  %4 = load <2 x i8>, ptr addrspace(1) %3, align 2
+  %call4 = call spir_func <2 x i8> @to_buf(<2 x i8> %4) #0
+  %arrayidx5 = getelementptr inbounds <2 x i8>, ptr addrspace(1) %dest, i64 2
+  store <2 x i8> %call4, ptr addrspace(1) %arrayidx5, align 2
+  %5 = getelementptr inbounds [2 x <2 x i8>], ptr addrspace(1) @a_var, i64 0, i64 1
+  %6 = load <2 x i8>, ptr addrspace(1) %5, align 2
+  %call6 = call spir_func <2 x i8> @to_buf(<2 x i8> %6) #0
+  %arrayidx7 = getelementptr inbounds <2 x i8>, ptr addrspace(1) %dest, i64 3
+  store <2 x i8> %call6, ptr addrspace(1) %arrayidx7, align 2
+  ret void
+}
+
+attributes #0 = { nounwind }
+
+!spirv.MemoryModel = !{!0}
+!opencl.enable.FP_CONTRACT = !{}
+!spirv.Source = !{!1}
+!opencl.spir.version = !{!2}
+!opencl.ocl.version = !{!2}
+!opencl.used.extensions = !{!3}
+!opencl.used.optional.core.features = !{!3}
+!spirv.Generator = !{!4}
+
+!0 = !{i32 2, i32 2}
+!1 = !{i32 3, i32 200000}
+!2 = !{i32 2, i32 0}
+!3 = !{}
+!4 = !{i16 6, i16 14}
+!5 = !{i32 1, i32 0}
+!6 = !{!"none", !"none"}
+!7 = !{!"char2*", !"int"}
+!8 = !{!"", !""}
+!9 = !{!3, !3}
+!10 = !{!"char2*", !"char2"}

diff  --git a/llvm/test/CodeGen/SPIRV/opencl/image.ll b/llvm/test/CodeGen/SPIRV/opencl/image.ll
index ea8208c221bbd..d87bb89fd2a6c 100644
--- a/llvm/test/CodeGen/SPIRV/opencl/image.ll
+++ b/llvm/test/CodeGen/SPIRV/opencl/image.ll
@@ -1,4 +1,8 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; 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
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
 
 ;; FIXME: Write tests to ensure invalid usage of image are rejected, such as:
 ;;  - invalid AS (only global is allowed);

diff  --git a/llvm/test/CodeGen/SPIRV/pointers/global-zeroinitializer.ll b/llvm/test/CodeGen/SPIRV/pointers/global-zeroinitializer.ll
new file mode 100644
index 0000000000000..fdfcbba723641
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/pointers/global-zeroinitializer.ll
@@ -0,0 +1,25 @@
+; RUN: llc -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; 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
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK: OpName %[[#Var:]] "var"
+; CHECK-DAG: %[[#Char:]] = OpTypeInt 8 0
+; CHECK-DAG: %[[#Vec2Char:]] = OpTypeVector %[[#Char]] 2
+; CHECK-DAG: %[[#PtrVec2Char:]] = OpTypePointer CrossWorkgroup %[[#Vec2Char]]
+; CHECK-DAG: %[[#ConstNull:]] = OpConstantNull %[[#Vec2Char]]
+; CHECK: %[[#]] = OpVariable %[[#PtrVec2Char]] CrossWorkgroup %[[#ConstNull]]
+; As an option: %[[#C0:]] = OpConstant %[[#Char]] 0
+;               %[[#VecZero:]] = OpConstantComposite %[[#Vec2Char]] %[[#C0]] %[[#C0]]
+;               %[[#]] = OpVariable %[[#PtrVec2Char]] CrossWorkgroup %[[#VecZero]]
+; CHECK: OpFunction
+
+ at var = addrspace(1) global <2 x i8> zeroinitializer
+;@var = addrspace(1) global <2 x i8> <i8 1, i8 1>
+
+define spir_kernel void @foo() {
+entry:
+  %addr = load <2 x i8>, ptr addrspace(1) @var, align 2
+  ret void
+}


        


More information about the llvm-commits mailing list