[PATCH 02/79] Add support for split barriers extension SPV_INTEL_split_barrier (...
authorHaonan Yang <haonan.yang@intel.com>
Thu, 20 Oct 2022 11:46:13 +0000 (19:46 +0800)
committerAndreas Beckmann <anbe@debian.org>
Thu, 8 Feb 2024 21:48:18 +0000 (22:48 +0100)
This PR adds support for split barriers and the SPV_INTEL_split_barrier extension.

The related SPIR-V extension spec can be found here:

* https://github.com/KhronosGroup/SPIRV-Registry/pull/136

The related OpenCL C extension spec can be found here:

* https://github.com/KhronosGroup/OpenCL-Docs/pull/765

Co-authored-by: Ben Ashbaugh <ben.ashbaugh@intel.com>
Gbp-Pq: Name 0002-Add-support-for-split-barriers-extension-SPV_INTEL_s.patch

16 files changed:
include/LLVMSPIRVExtensions.inc
lib/SPIRV/OCLToSPIRV.cpp
lib/SPIRV/OCLToSPIRV.h
lib/SPIRV/OCLUtil.cpp
lib/SPIRV/OCLUtil.h
lib/SPIRV/SPIRVReader.cpp
lib/SPIRV/SPIRVToOCL.cpp
lib/SPIRV/SPIRVToOCL.h
lib/SPIRV/SPIRVToOCL12.cpp
lib/SPIRV/SPIRVToOCL20.cpp
lib/SPIRV/libSPIRV/SPIRVInstruction.h
lib/SPIRV/libSPIRV/SPIRVOpCode.h
lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h
test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_12.ll [new file with mode: 0644]
test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_20.ll [new file with mode: 0644]
test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_spirv.ll [new file with mode: 0644]

index 8eaf24de174c6a5f105b393f4d783fdd74b2a96d..3d0eae8ce0e3fdb9284b4076d69ea01cf47db129 100644 (file)
@@ -53,3 +53,4 @@ EXT(SPV_INTEL_hw_thread_queries)
 EXT(SPV_INTEL_global_variable_decorations)
 EXT(SPV_INTEL_non_constant_addrspace_printf)
 EXT(SPV_INTEL_complex_float_mul_div)
+EXT(SPV_INTEL_split_barrier)
index 7db6d37f9a886c79c68cfc6e2fcd97378d8e6a61..8870a299bf1fb698817b00a1e31fe1d686cb71f5 100644 (file)
@@ -381,6 +381,10 @@ void OCLToSPIRVBase::visitCallInst(CallInst &CI) {
     visitSubgroupImageMediaBlockINTEL(&CI, DemangledName);
     return;
   }
+  if (DemangledName.find(kOCLBuiltinName::SplitBarrierINTELPrefix) == 0) {
+    visitCallSplitBarrierINTEL(&CI, DemangledName);
+    return;
+  }
   // Handle 'cl_intel_device_side_avc_motion_estimation' extension built-ins
   if (DemangledName.find(kOCLSubgroupsAVCIntel::Prefix) == 0 ||
       // Workaround for a bug in the extension specification
@@ -1879,6 +1883,37 @@ void OCLToSPIRVBase::visitSubgroupAVCBuiltinCallWithSampler(
       &Attrs);
 }
 
+void OCLToSPIRVBase::visitCallSplitBarrierINTEL(CallInst *CI,
+                                                StringRef DemangledName) {
+  auto Lit = getBarrierLiterals(CI);
+  AttributeList Attrs = CI->getCalledFunction()->getAttributes();
+  Op OpCode =
+      StringSwitch<Op>(DemangledName)
+          .Case("intel_work_group_barrier_arrive", OpControlBarrierArriveINTEL)
+          .Case("intel_work_group_barrier_wait", OpControlBarrierWaitINTEL)
+          .Default(OpNop);
+
+  mutateCallInstSPIRV(
+      M, CI,
+      [=](CallInst *, std::vector<Value *> &Args) {
+        Args.resize(3);
+        // Execution scope
+        Args[0] = addInt32(map<Scope>(std::get<2>(Lit)));
+        // Memory scope
+        Args[1] = addInt32(map<Scope>(std::get<1>(Lit)));
+        // Memory semantics
+        // OpControlBarrierArriveINTEL -> Release,
+        // OpControlBarrierWaitINTEL -> Acquire
+        unsigned MemFenceFlag = std::get<0>(Lit);
+        OCLMemOrderKind MemOrder = OpCode == OpControlBarrierArriveINTEL
+                                       ? OCLMO_release
+                                       : OCLMO_acquire;
+        Args[2] = addInt32(mapOCLMemSemanticToSPIRV(MemFenceFlag, MemOrder));
+        return getSPIRVFuncName(OpCode);
+      },
+      &Attrs);
+}
+
 void OCLToSPIRVBase::visitCallLdexp(CallInst *CI, StringRef MangledName,
                                     StringRef DemangledName) {
   auto Args = getArguments(CI);
index 7b1c3086e2b6f94b8a4acb51db3bd7f10a107f4c..8707ad88d41edb026bd69ecff43482e86f346f80 100644 (file)
@@ -247,6 +247,9 @@ public:
   void visitSubgroupAVCBuiltinCallWithSampler(CallInst *CI,
                                               StringRef DemangledName);
 
+  /// For cl_intel_split_work_group_barrier built-ins:
+  void visitCallSplitBarrierINTEL(CallInst *CI, StringRef DemangledName);
+
   void visitCallLdexp(CallInst *CI, StringRef MangledName,
                       StringRef DemangledName);
 
index c696e25b3f9149216f78f3cc5ffa68be9d2cdcc6..53ebc362c6f12591c33a93c27f2f880a37337ff0 100644 (file)
@@ -432,6 +432,9 @@ template <> void SPIRVMap<std::string, Op, SPIRVInstruction>::init() {
   _SPIRV_OP(bitfield_extract_signed, BitFieldSExtract)
   _SPIRV_OP(bitfield_extract_unsigned, BitFieldUExtract)
   _SPIRV_OP(bit_reverse, BitReverse)
+  // cl_khr_split_work_group_barrier
+  _SPIRV_OP(intel_work_group_barrier_arrive, ControlBarrierArriveINTEL)
+  _SPIRV_OP(intel_work_group_barrier_wait, ControlBarrierWaitINTEL)
 #undef _SPIRV_OP
 }
 
@@ -1038,7 +1041,9 @@ public:
     } else if (NameRef.contains("barrier")) {
       addUnsignedArg(0);
       if (NameRef.equals("work_group_barrier") ||
-          NameRef.equals("sub_group_barrier"))
+          NameRef.equals("sub_group_barrier") ||
+          NameRef.equals("intel_work_group_barrier_arrive") ||
+          NameRef.equals("intel_work_group_barrier_wait"))
         setEnumArg(1, SPIR::PRIMITIVE_MEMORY_SCOPE);
     } else if (NameRef.startswith("atomic_work_item_fence")) {
       addUnsignedArg(0);
index 1c0d8605432d61a9bb3895c03895d3f6ada0db91..2bfe78f66cf956c9123350df93bb34141a671e67 100644 (file)
@@ -307,6 +307,7 @@ const static char SubgroupBlockWriteINTELPrefix[] =
     "intel_sub_group_block_write";
 const static char SubgroupImageMediaBlockINTELPrefix[] =
     "intel_sub_group_media_block";
+const static char SplitBarrierINTELPrefix[] = "intel_work_group_barrier_";
 const static char LDEXP[] = "ldexp";
 #define _SPIRV_OP(x)                                                           \
   const static char ConvertBFloat16##x##AsUShort##x[] =                        \
index cbf2dd333097c265e9f81f822bc40a8087486591..cbfc74998dd04ba710389e90e236874bea202d71 100644 (file)
@@ -3146,7 +3146,7 @@ Instruction *SPIRVToLLVM::transBuiltinFromInst(const std::string &FuncName,
       Func->addFnAttr(Attribute::NoUnwind);
     auto OC = BI->getOpCode();
     if (isGroupOpCode(OC) || isIntelSubgroupOpCode(OC) ||
-        OC == OpControlBarrier)
+        isSplitBarrierINTELOpCode(OC) || OC == OpControlBarrier)
       Func->addFnAttr(Attribute::Convergent);
   }
   auto Call =
index f66ac077ba0c41934f404ea44bde1b5a1625a27a..c255b60af7dd7f747f3feb72da4783ba7ae06415 100644 (file)
@@ -118,6 +118,10 @@ void SPIRVToOCLBase::visitCallInst(CallInst &CI) {
   if (OC == OpControlBarrier) {
     visitCallSPIRVControlBarrier(&CI);
   }
+  if (isSplitBarrierINTELOpCode(OC)) {
+    visitCallSPIRVSplitBarrierINTEL(&CI, OC);
+    return;
+  }
   if (isAtomicOpCode(OC)) {
     visitCallSPIRVAtomicBuiltin(&CI, OC);
     return;
index 92afee9daa0c4d44faf4dd7483b09ea2021548ea..944b978f0ad3cac323dc283e05e9765e8e527345 100644 (file)
@@ -222,6 +222,12 @@ public:
   /// - OCL1.2: barrier
   virtual void visitCallSPIRVControlBarrier(CallInst *CI) = 0;
 
+  /// Transform split __spirv_ControlBarrierArriveINTEL and
+  /// __spirv_ControlBarrierWaitINTEL barrier to:
+  /// - OCL2.0: overload with a memory_scope argument
+  /// - OCL1.2: overload with no memory_scope argument
+  virtual void visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) = 0;
+
   /// Transform __spirv_EnqueueKernel to __enqueue_kernel
   virtual void visitCallSPIRVEnqueueKernel(CallInst *CI, Op OC) = 0;
 
@@ -305,6 +311,11 @@ public:
   ///       barrier(flag(sema))
   void visitCallSPIRVControlBarrier(CallInst *CI) override;
 
+  /// Transform split __spirv_ControlBarrierArriveINTEL and
+  /// __spirv_ControlBarrierWaitINTEL barrier to overloads without a
+  /// memory_scope argument.
+  void visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) override;
+
   /// Transform __spirv_OpAtomic functions. It firstly conduct generic
   /// mutations for all builtins and then mutate some of them seperately
   Instruction *visitCallSPIRVAtomicBuiltin(CallInst *CI, Op OC) override;
@@ -394,6 +405,11 @@ public:
   ///         sub_group_barrier(flag(sema), map(memScope))
   void visitCallSPIRVControlBarrier(CallInst *CI) override;
 
+  /// Transform split __spirv_ControlBarrierArriveINTEL and
+  /// __spirv_ControlBarrierWaitINTEL barrier to overloads with a
+  /// memory_scope argument.
+  void visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) override;
+
   /// Transform __spirv_Atomic* to atomic_*.
   ///   __spirv_Atomic*(atomic_op, scope, sema, ops, ...) =>
   ///      atomic_*(generic atomic_op, ops, ..., order(sema), map(scope))
index 0af545e1cdbc6a0f82a31c7d3d2249969b36e067..091a5f353c18c6a278e5a248c6491dbb10b5bf2e 100644 (file)
@@ -100,6 +100,19 @@ void SPIRVToOCL12Base::visitCallSPIRVControlBarrier(CallInst *CI) {
       &Attrs);
 }
 
+void SPIRVToOCL12Base::visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) {
+  AttributeList Attrs = CI->getCalledFunction()->getAttributes();
+  mutateCallInstOCL(
+      M, CI,
+      [=](CallInst *, std::vector<Value *> &Args) {
+        Value *MemFenceFlags =
+            SPIRV::transSPIRVMemorySemanticsIntoOCLMemFenceFlags(Args[2], CI);
+        Args.assign(1, MemFenceFlags);
+        return OCLSPIRVBuiltinMap::rmap(OC);
+      },
+      &Attrs);
+}
+
 Instruction *SPIRVToOCL12Base::visitCallSPIRVAtomicIncDec(CallInst *CI, Op OC) {
   AttributeList Attrs = CI->getCalledFunction()->getAttributes();
   return mutateCallInstOCL(
index 8a679d640b810c2bd4c1acbe129a41f3ea11814f..58d66564b6651574318eacb6e4b2cb8209a142bf 100644 (file)
@@ -123,6 +123,28 @@ void SPIRVToOCL20Base::visitCallSPIRVControlBarrier(CallInst *CI) {
       &NewAttrs);
 }
 
+void SPIRVToOCL20Base::visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) {
+  AttributeList Attrs = CI->getCalledFunction()->getAttributes();
+  mutateCallInstOCL(
+      M, CI,
+      [=](CallInst *, std::vector<Value *> &Args) {
+        auto GetArg = [=](unsigned I) {
+          return cast<ConstantInt>(Args[I])->getZExtValue();
+        };
+        Value *MemScope =
+            getInt32(M, rmap<OCLScopeKind>(static_cast<Scope>(GetArg(1))));
+        Value *MemFenceFlags =
+            SPIRV::transSPIRVMemorySemanticsIntoOCLMemFenceFlags(Args[2], CI);
+
+        Args.resize(2);
+        Args[0] = MemFenceFlags;
+        Args[1] = MemScope;
+
+        return OCLSPIRVBuiltinMap::rmap(OC);
+      },
+      &Attrs);
+}
+
 std::string SPIRVToOCL20Base::mapFPAtomicName(Op OC) {
   assert(isFPAtomicOpCode(OC) && "Not intended to handle other opcodes than "
                                  "AtomicF{Add/Min/Max}EXT!");
index 5cb3363b04cbe06b5f1717de0b62e42de45b149a..5c83b1ecba577e20aa0bc569ca4b4265169e2d9f 100644 (file)
@@ -3327,6 +3327,24 @@ _SPIRV_OP(JointMatrixMad, true, 7)
 _SPIRV_OP(JointMatrixWorkItemLength, true, 4)
 #undef _SPIRV_OP
 
+class SPIRVSplitBarrierINTELBase : public SPIRVInstTemplateBase {
+protected:
+  SPIRVCapVec getRequiredCapability() const override {
+    return getVec(CapabilitySplitBarrierINTEL);
+  }
+
+  llvm::Optional<ExtensionID> getRequiredExtension() const override {
+    return ExtensionID::SPV_INTEL_split_barrier;
+  }
+};
+
+#define _SPIRV_OP(x, ...)                                                      \
+  typedef SPIRVInstTemplate<SPIRVSplitBarrierINTELBase, Op##x, __VA_ARGS__>    \
+      SPIRV##x;
+_SPIRV_OP(ControlBarrierArriveINTEL, false, 4)
+_SPIRV_OP(ControlBarrierWaitINTEL, false, 4)
+#undef _SPIRV_OP
+
 class SPIRVGroupUniformArithmeticKHRInstBase : public SPIRVInstTemplateBase {
 public:
   SPIRVCapVec getRequiredCapability() const override {
index 350624633b4f5508752f2b784ecca05a4a3985cf..da1f4b1a1e514f2382c8a7c198a582a5f6e33f2f 100644 (file)
@@ -252,6 +252,11 @@ inline bool isEventOpCode(Op OpCode) {
   return OpRetainEvent <= OpCode && OpCode <= OpCaptureEventProfilingInfo;
 }
 
+inline bool isSplitBarrierINTELOpCode(Op OpCode) {
+  return OpCode == OpControlBarrierArriveINTEL ||
+         OpCode == OpControlBarrierWaitINTEL;
+}
+
 } // namespace SPIRV
 
 #endif // SPIRV_LIBSPIRV_SPIRVOPCODE_H
index 9d7da279798800031ea8efea3a5fd730c2caa769..94197e7bb0400ac9af6c0aa0923de39b854530b2 100644 (file)
@@ -547,6 +547,8 @@ _SPIRV_OP(TypeBufferSurfaceINTEL, 6086)
 _SPIRV_OP(TypeStructContinuedINTEL, 6090)
 _SPIRV_OP(ConstantCompositeContinuedINTEL, 6091)
 _SPIRV_OP(SpecConstantCompositeContinuedINTEL, 6092)
+_SPIRV_OP(ControlBarrierArriveINTEL, 6142)
+_SPIRV_OP(ControlBarrierWaitINTEL, 6143)
 _SPIRV_OP(GroupIMulKHR, 6401)
 _SPIRV_OP(GroupFMulKHR, 6402)
 _SPIRV_OP(GroupBitwiseAndKHR, 6403)
diff --git a/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_12.ll b/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_12.ll
new file mode 100644 (file)
index 0000000..8ab1e85
--- /dev/null
@@ -0,0 +1,99 @@
+;; kernel void test(global uint* dst)
+;; {
+;;     intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE);
+;;     intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE);
+;;     intel_work_group_barrier_arrive(CLK_GLOBAL_MEM_FENCE);
+;;     intel_work_group_barrier_wait(CLK_GLOBAL_MEM_FENCE);
+;;
+;;     intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);
+;;     intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);
+;;}
+
+; Test for SPV_INTEL_split_barrier (OpenCL C LLVM IR)
+; RUN: llvm-as %s -o %t.bc
+; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_split_barrier
+; RUN: llvm-spirv %t.spv -o %t.spt --to-text
+; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
+; RUN: llvm-spirv %t.spv -o %t.rev.bc -r --spirv-target-env=CL1.2
+; RUN: llvm-dis %t.rev.bc -o %t.rev.ll
+; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
+
+; RUN: not llvm-spirv %t.bc 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+; CHECK-ERROR: RequiresExtension: Feature requires the following SPIR-V extension:
+; CHECK-ERROR-NEXT: SPV_INTEL_split_barrier
+
+; ModuleID = 'split_barrier.cl'
+source_filename = "split_barrier.cl"
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
+target triple = "spir64"
+
+; CHECK-SPIRV: Capability SplitBarrierINTEL
+; CHECK-SPIRV: Extension "SPV_INTEL_split_barrier"
+; CHECK-SPIRV: TypeInt [[UINT:[0-9]+]] 32 0
+;
+; Scopes:
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_WORK_GROUP:[0-9]+]] 2
+;
+; Memory Semantics:
+; 0x2 Acquire + 0x100 WorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL:[0-9]+]] 258
+; 0x4 Release + 0x100 WorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL:[0-9]+]] 260
+; 0x2 Acquire + 0x200 CrossWorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_GLOBAL:[0-9]+]] 514
+; 0x4 Release + 0x200 CrossWorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_GLOBAL:[0-9]+]] 516
+; 0x2 Acquire + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL_GLOBAL:[0-9]+]] 770
+; 0x4 Release + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL_GLOBAL:[0-9]+]] 772
+;
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_GLOBAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_GLOBAL]]
+;
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL_GLOBAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL_GLOBAL]]
+
+; CHECK-LLVM-LABEL: define spir_kernel void @test
+; Function Attrs: convergent norecurse nounwind
+define dso_local spir_kernel void @test(i32 addrspace(1)* nocapture noundef readnone align 4 %0) local_unnamed_addr #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !5 !kernel_arg_type !6 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 {
+  tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 1) #2
+    ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 1)
+  tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 1) #2
+    ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj(i32 1)
+  tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 2) #2
+    ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 2)
+  tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 2) #2
+    ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj(i32 2)
+  tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 3) #2
+    ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 3)
+  tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 3) #2
+    ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj(i32 3)
+  ret void
+}
+
+; Function Attrs: convergent
+declare dso_local spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef) local_unnamed_addr #1
+
+; Function Attrs: convergent
+declare dso_local spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef) local_unnamed_addr #1
+
+attributes #0 = { convergent norecurse nounwind "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "uniform-work-group-size"="true" }
+attributes #1 = { convergent "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #2 = { convergent nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!opencl.ocl.version = !{!2}
+!opencl.spir.version = !{!2}
+!llvm.ident = !{!3}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 7, !"frame-pointer", i32 2}
+!2 = !{i32 1, i32 2}
+!3 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project 861386dbd6ff0d91636b7c674c2abb2eccd9d3f2)"}
+!4 = !{i32 1}
+!5 = !{!"none"}
+!6 = !{!"uint*"}
+!7 = !{!""}
diff --git a/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_20.ll b/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_20.ll
new file mode 100644 (file)
index 0000000..4cdbcf2
--- /dev/null
@@ -0,0 +1,175 @@
+;; kernel void test(global uint* dst)
+;; {
+;;     intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE);
+;;     intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE);
+;;     intel_work_group_barrier_arrive(CLK_GLOBAL_MEM_FENCE);
+;;     intel_work_group_barrier_wait(CLK_GLOBAL_MEM_FENCE);
+;;     intel_work_group_barrier_arrive(CLK_IMAGE_MEM_FENCE);
+;;     intel_work_group_barrier_wait(CLK_IMAGE_MEM_FENCE);
+;;
+;;     intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);
+;;     intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE);
+;;     intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE | CLK_IMAGE_MEM_FENCE);
+;;     intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE | CLK_GLOBAL_MEM_FENCE | CLK_IMAGE_MEM_FENCE);
+;;
+;;     intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE, memory_scope_work_item);
+;;     intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE, memory_scope_work_item);
+;;     intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE, memory_scope_work_group);
+;;     intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE, memory_scope_work_group);
+;;     intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE, memory_scope_device);
+;;     intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE, memory_scope_device);
+;;     intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE, memory_scope_all_svm_devices);
+;;     intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE, memory_scope_all_svm_devices);
+;;     intel_work_group_barrier_arrive(CLK_LOCAL_MEM_FENCE, memory_scope_sub_group);
+;;     intel_work_group_barrier_wait(CLK_LOCAL_MEM_FENCE, memory_scope_sub_group);
+;;}
+
+; Test for SPV_INTEL_split_barrier (OpenCL C LLVM IR)
+; RUN: llvm-as %s -o %t.bc
+; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_split_barrier
+; RUN: llvm-spirv %t.spv -o %t.spt --to-text
+; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
+; RUN: llvm-spirv %t.spv -o %t.rev.bc -r --spirv-target-env=CL2.0
+; RUN: llvm-dis %t.rev.bc -o %t.rev.ll
+; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
+
+; RUN: not llvm-spirv %t.bc 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+; CHECK-ERROR: RequiresExtension: Feature requires the following SPIR-V extension:
+; CHECK-ERROR-NEXT: SPV_INTEL_split_barrier
+
+; ModuleID = 'split_barrier.cl'
+source_filename = "split_barrier.cl"
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
+target triple = "spir64"
+
+; CHECK-SPIRV: Capability SplitBarrierINTEL
+; CHECK-SPIRV: Extension "SPV_INTEL_split_barrier"
+; CHECK-SPIRV: TypeInt [[UINT:[0-9]+]] 32 0
+;
+; Scopes:
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_WORK_GROUP:[0-9]+]] 2
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_INVOCATION:[0-9]+]] 4
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_DEVICE:[0-9]+]] 1
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_CROSS_DEVICE:[0-9]+]] 0
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_SUBGROUP:[0-9]+]] 3
+;
+; Memory Semantics:
+; 0x2 Acquire + 0x100 WorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL:[0-9]+]] 258
+; 0x4 Release + 0x100 WorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL:[0-9]+]] 260
+; 0x2 Acquire + 0x200 CrossWorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_GLOBAL:[0-9]+]] 514
+; 0x4 Release + 0x200 CrossWorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_GLOBAL:[0-9]+]] 516
+; 0x2 Acquire + 0x800 ImageMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_IMAGE:[0-9]+]] 2050
+; 0x4 Acquire + 0x800 ImageMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_IMAGE:[0-9]+]] 2052
+; 0x2 Acquire + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL_GLOBAL:[0-9]+]] 770
+; 0x4 Release + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL_GLOBAL:[0-9]+]] 772
+; 0x2 Acquire + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory + 0x800 ImageMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL_GLOBAL_IMAGE:[0-9]+]] 2818
+; 0x4 Release + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory + 0x800 ImageMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL_GLOBAL_IMAGE:[0-9]+]] 2820
+;
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_GLOBAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_GLOBAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_IMAGE]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_IMAGE]]
+;
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL_GLOBAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL_GLOBAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL_GLOBAL_IMAGE]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL_GLOBAL_IMAGE]]
+;
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_INVOCATION]] [[RELEASE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_INVOCATION]] [[ACQUIRE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_DEVICE]] [[RELEASE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_DEVICE]] [[ACQUIRE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_CROSS_DEVICE]] [[RELEASE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_CROSS_DEVICE]] [[ACQUIRE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_SUBGROUP]] [[RELEASE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_SUBGROUP]] [[ACQUIRE_LOCAL]]
+
+; CHECK-LLVM-LABEL: define spir_kernel void @test
+; Function Attrs: convergent norecurse nounwind
+define dso_local spir_kernel void @test(i32 addrspace(1)* nocapture noundef readnone align 4 %0) local_unnamed_addr #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !5 !kernel_arg_type !6 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 {
+  tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 1) #2
+    ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 1, i32 1)
+  tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 1) #2
+    ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 1, i32 1)
+  tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 2) #2
+    ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 2, i32 1)
+  tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 2) #2
+    ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 2, i32 1)
+  tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 4) #2
+    ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 4, i32 1)
+  tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 4) #2
+    ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 4, i32 1)
+  tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 3) #2
+    ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 3, i32 1)
+  tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 3) #2
+    ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 3, i32 1)
+  tail call spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef 7) #2
+    ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 7, i32 1)
+  tail call spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef 7) #2
+    ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 7, i32 1)
+  tail call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 noundef 1, i32 noundef 0) #2
+    ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 1, i32 0)
+  tail call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 noundef 1, i32 noundef 0) #2
+    ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 1, i32 0)
+  tail call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 noundef 1, i32 noundef 1) #2
+    ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 1, i32 1)
+  tail call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 noundef 1, i32 noundef 1) #2
+    ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 1, i32 1)
+  tail call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 noundef 1, i32 noundef 2) #2
+    ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 1, i32 2)
+  tail call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 noundef 1, i32 noundef 2) #2
+    ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 1, i32 2)
+  tail call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 noundef 1, i32 noundef 3) #2
+    ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 1, i32 3)
+  tail call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 noundef 1, i32 noundef 3) #2
+    ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 1, i32 3)
+  tail call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 noundef 1, i32 noundef 4) #2
+    ; CHECK-LLVM: call spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 1, i32 4)
+  tail call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 noundef 1, i32 noundef 4) #2
+    ; CHECK-LLVM: call spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 1, i32 4)
+  ret void
+}
+
+; Function Attrs: convergent
+declare dso_local spir_func void @_Z31intel_work_group_barrier_arrivej(i32 noundef) local_unnamed_addr #1
+
+; Function Attrs: convergent
+declare dso_local spir_func void @_Z29intel_work_group_barrier_waitj(i32 noundef) local_unnamed_addr #1
+
+; Function Attrs: convergent
+declare dso_local spir_func void @_Z31intel_work_group_barrier_arrivej12memory_scope(i32 noundef, i32 noundef) local_unnamed_addr #1
+
+; Function Attrs: convergent
+declare dso_local spir_func void @_Z29intel_work_group_barrier_waitj12memory_scope(i32 noundef, i32 noundef) local_unnamed_addr #1
+
+attributes #0 = { convergent norecurse nounwind "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "uniform-work-group-size"="false" }
+attributes #1 = { convergent "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #2 = { convergent nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!opencl.ocl.version = !{!2}
+!opencl.spir.version = !{!2}
+!llvm.ident = !{!3}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 7, !"frame-pointer", i32 2}
+!2 = !{i32 2, i32 0}
+!3 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project 861386dbd6ff0d91636b7c674c2abb2eccd9d3f2)"}
+!4 = !{i32 1}
+!5 = !{!"none"}
+!6 = !{!"uint*"}
+!7 = !{!""}
diff --git a/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_spirv.ll b/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_spirv.ll
new file mode 100644 (file)
index 0000000..ae5b57f
--- /dev/null
@@ -0,0 +1,170 @@
+;; kernel void test(global uint* dst)
+;; {
+;;    __spirv_ControlBarrierArriveINTEL(2, 2, 260);  // local
+;;    __spirv_ControlBarrierWaitINTEL(2, 2, 258);    // local
+;;    __spirv_ControlBarrierArriveINTEL(2, 2, 516);  // global
+;;    __spirv_ControlBarrierWaitINTEL(2, 2, 514);    // global
+;;    __spirv_ControlBarrierArriveINTEL(2, 2, 2052); // image
+;;    __spirv_ControlBarrierWaitINTEL(2, 2, 2050);   // image
+;;
+;;    __spirv_ControlBarrierArriveINTEL(2, 2, 772);  // local + global
+;;    __spirv_ControlBarrierWaitINTEL(2, 2, 770);    // local + global
+;;    __spirv_ControlBarrierArriveINTEL(2, 2, 2820); // local + global + image
+;;    __spirv_ControlBarrierWaitINTEL(2, 2, 2818);   // local + global + image
+;;
+;;    __spirv_ControlBarrierArriveINTEL(2, 4, 260);  // local, work_item
+;;    __spirv_ControlBarrierWaitINTEL(2, 4, 258);    // local, work_item
+;;    __spirv_ControlBarrierArriveINTEL(2, 2, 260);  // local, work_group
+;;    __spirv_ControlBarrierWaitINTEL(2, 2, 258);    // local, work_group
+;;    __spirv_ControlBarrierArriveINTEL(2, 1, 260);  // local, device
+;;    __spirv_ControlBarrierWaitINTEL(2, 1, 258);    // local, device
+;;    __spirv_ControlBarrierArriveINTEL(2, 0, 260);  // local, all_svm_devices
+;;    __spirv_ControlBarrierWaitINTEL(2, 0, 258);    // local, all_svm_devices
+;;    __spirv_ControlBarrierArriveINTEL(2, 3, 260);  // local, subgroup
+;;    __spirv_ControlBarrierWaitINTEL(2, 3, 258);    // local, subgroup
+;;}
+
+; Test for SPV_INTEL_split_barrier (SPIR-V friendly LLVM IR)
+; RUN: llvm-as %s -o %t.bc
+; RUN: llvm-spirv %t.bc -o %t.spv --spirv-ext=+SPV_INTEL_split_barrier
+; RUN: llvm-spirv %t.spv -o %t.spt --to-text
+; RUN: FileCheck < %t.spt %s --check-prefix=CHECK-SPIRV
+
+; RUN: llvm-spirv %t.spv -o %t.rev.bc -r --spirv-target-env=SPV-IR
+; RUN: llvm-dis %t.rev.bc -o %t.rev.ll
+; RUN: FileCheck < %t.rev.ll %s --check-prefix=CHECK-LLVM
+
+; RUN: not llvm-spirv %t.bc 2>&1 | FileCheck %s --check-prefix=CHECK-ERROR
+; CHECK-ERROR: RequiresExtension: Feature requires the following SPIR-V extension:
+; CHECK-ERROR-NEXT: SPV_INTEL_split_barrier
+
+; ModuleID = 'split_barrier_spirv.cl'
+source_filename = "split_barrier_spirv.cl"
+target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024"
+target triple = "spir64"
+
+; CHECK-SPIRV: Capability SplitBarrierINTEL
+; CHECK-SPIRV: Extension "SPV_INTEL_split_barrier"
+; CHECK-SPIRV: TypeInt [[UINT:[0-9]+]] 32 0
+;
+; Scopes:
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_WORK_GROUP:[0-9]+]] 2
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_INVOCATION:[0-9]+]] 4
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_DEVICE:[0-9]+]] 1
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_CROSS_DEVICE:[0-9]+]] 0
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[SCOPE_SUBGROUP:[0-9]+]] 3
+;
+; Memory Semantics:
+; 0x2 Acquire + 0x100 WorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL:[0-9]+]] 258
+; 0x4 Release + 0x100 WorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL:[0-9]+]] 260
+; 0x2 Acquire + 0x200 CrossWorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_GLOBAL:[0-9]+]] 514
+; 0x4 Release + 0x200 CrossWorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_GLOBAL:[0-9]+]] 516
+; 0x2 Acquire + 0x800 ImageMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_IMAGE:[0-9]+]] 2050
+; 0x4 Acquire + 0x800 ImageMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_IMAGE:[0-9]+]] 2052
+; 0x2 Acquire + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL_GLOBAL:[0-9]+]] 770
+; 0x4 Release + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL_GLOBAL:[0-9]+]] 772
+; 0x2 Acquire + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory + 0x800 ImageMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[ACQUIRE_LOCAL_GLOBAL_IMAGE:[0-9]+]] 2818
+; 0x4 Release + 0x100 WorkgroupMemory + 0x200 CrossWorkgroupMemory + 0x800 ImageMemory
+; CHECK-SPIRV-DAG: Constant [[UINT]] [[RELEASE_LOCAL_GLOBAL_IMAGE:[0-9]+]] 2820
+;
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_GLOBAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_GLOBAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_IMAGE]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_IMAGE]]
+;
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL_GLOBAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL_GLOBAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL_GLOBAL_IMAGE]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL_GLOBAL_IMAGE]]
+;
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_INVOCATION]] [[RELEASE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_INVOCATION]] [[ACQUIRE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[RELEASE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_WORK_GROUP]] [[ACQUIRE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_DEVICE]] [[RELEASE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_DEVICE]] [[ACQUIRE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_CROSS_DEVICE]] [[RELEASE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_CROSS_DEVICE]] [[ACQUIRE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierArriveINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_SUBGROUP]] [[RELEASE_LOCAL]]
+; CHECK-SPIRV: ControlBarrierWaitINTEL [[SCOPE_WORK_GROUP]] [[SCOPE_SUBGROUP]] [[ACQUIRE_LOCAL]]
+
+; CHECK-LLVM-LABEL: define spir_kernel void @test
+; Function Attrs: convergent norecurse nounwind
+define dso_local spir_kernel void @test(i32 addrspace(1)* nocapture noundef readnone align 4 %0) local_unnamed_addr #0 !kernel_arg_addr_space !4 !kernel_arg_access_qual !5 !kernel_arg_type !6 !kernel_arg_base_type !6 !kernel_arg_type_qual !7 {
+  tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 260) #2
+    ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 2, i32 260) #1
+  tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 258) #2
+    ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 2, i32 258) #1
+  tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 516) #2
+    ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 2, i32 516) #1
+  tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 514) #2
+    ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 2, i32 514) #1
+  tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 2052) #2
+    ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 2, i32 2052) #1
+  tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 2050) #2
+    ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 2, i32 2050) #1
+  tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 772) #2
+    ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 2, i32 772) #1
+  tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 770) #2
+    ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 2, i32 770) #1
+  tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 2820) #2
+    ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 2, i32 2820) #1
+  tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 2818) #2
+    ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 2, i32 2818) #1
+  tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 4, i32 noundef 260) #2
+    ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 4, i32 260) #1
+  tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 4, i32 noundef 258) #2
+    ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 4, i32 258) #1
+  tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 260) #2
+    ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 2, i32 260) #1
+  tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 2, i32 noundef 258) #2
+    ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 2, i32 258) #1
+  tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 1, i32 noundef 260) #2
+    ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 1, i32 260) #1
+  tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 1, i32 noundef 258) #2
+    ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 1, i32 258) #1
+  tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 0, i32 noundef 260) #2
+    ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 0, i32 260) #1
+  tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 0, i32 noundef 258) #2
+    ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 0, i32 258) #1
+  tail call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef 2, i32 noundef 3, i32 noundef 260) #2
+    ; CHECK-LLVM: call spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 2, i32 3, i32 260) #1
+  tail call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef 2, i32 noundef 3, i32 noundef 258) #2
+    ; CHECK-LLVM: call spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 2, i32 3, i32 258) #1
+  ret void
+}
+
+; Function Attrs: convergent
+declare dso_local spir_func void @_Z33__spirv_ControlBarrierArriveINTELiii(i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr #1
+
+; Function Attrs: convergent
+declare dso_local spir_func void @_Z31__spirv_ControlBarrierWaitINTELiii(i32 noundef, i32 noundef, i32 noundef) local_unnamed_addr #1
+
+attributes #0 = { convergent norecurse nounwind "frame-pointer"="all" "min-legal-vector-width"="0" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "uniform-work-group-size"="false" }
+attributes #1 = { convergent "frame-pointer"="all" "no-trapping-math"="true" "stack-protector-buffer-size"="8" }
+attributes #2 = { convergent nounwind }
+
+!llvm.module.flags = !{!0, !1}
+!opencl.ocl.version = !{!2}
+!opencl.spir.version = !{!2}
+!llvm.ident = !{!3}
+
+!0 = !{i32 1, !"wchar_size", i32 4}
+!1 = !{i32 7, !"frame-pointer", i32 2}
+!2 = !{i32 2, i32 0}
+!3 = !{!"clang version 15.0.0 (https://github.com/llvm/llvm-project 861386dbd6ff0d91636b7c674c2abb2eccd9d3f2)"}
+!4 = !{i32 1}
+!5 = !{!"none"}
+!6 = !{!"uint*"}
+!7 = !{!""}