diff --git a/include/LLVMSPIRVExtensions.inc b/include/LLVMSPIRVExtensions.inc index 30ba8b9b47..0e47bf70ce 100644 --- a/include/LLVMSPIRVExtensions.inc +++ b/include/LLVMSPIRVExtensions.inc @@ -46,3 +46,4 @@ EXT(SPV_INTEL_debug_module) EXT(SPV_INTEL_runtime_aligned) EXT(SPV_INTEL_arithmetic_fence) EXT(SPV_INTEL_bfloat16_conversion) +EXT(SPV_INTEL_split_barrier) diff --git a/lib/SPIRV/OCLToSPIRV.cpp b/lib/SPIRV/OCLToSPIRV.cpp index 116c236c8e..76857a2053 100644 --- a/lib/SPIRV/OCLToSPIRV.cpp +++ b/lib/SPIRV/OCLToSPIRV.cpp @@ -262,8 +262,11 @@ class OCLToSPIRVBase : public InstVisitor { void visitSubgroupAVCBuiltinCall(CallInst *CI, StringRef DemangledName); void visitSubgroupAVCWrapperBuiltinCall(CallInst *CI, Op WrappedOC, StringRef DemangledName); + 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); @@ -584,6 +587,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 @@ -2048,6 +2055,37 @@ void OCLToSPIRVBase::visitSubgroupAVCBuiltinCallWithSampler( &Attrs); } +void OCLToSPIRVBase::visitCallSplitBarrierINTEL(CallInst *CI, + StringRef DemangledName) { + auto Lit = getBarrierLiterals(CI); + AttributeList Attrs = CI->getCalledFunction()->getAttributes(); + Op OpCode = + StringSwitch(DemangledName) + .Case("intel_work_group_barrier_arrive", OpControlBarrierArriveINTEL) + .Case("intel_work_group_barrier_wait", OpControlBarrierWaitINTEL) + .Default(OpNop); + + mutateCallInstSPIRV( + M, CI, + [=](CallInst *, std::vector &Args) { + Args.resize(3); + // Execution scope + Args[0] = addInt32(map(std::get<2>(Lit))); + // Memory scope + Args[1] = addInt32(map(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); diff --git a/lib/SPIRV/OCLUtil.cpp b/lib/SPIRV/OCLUtil.cpp index 57f9759d51..b5dbaa4749 100644 --- a/lib/SPIRV/OCLUtil.cpp +++ b/lib/SPIRV/OCLUtil.cpp @@ -421,6 +421,9 @@ template <> void SPIRVMap::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 } @@ -1026,7 +1029,9 @@ class OCLBuiltinFuncMangleInfo : public SPIRV::BuiltinFuncMangleInfo { } 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); diff --git a/lib/SPIRV/OCLUtil.h b/lib/SPIRV/OCLUtil.h index 1c7fb955f3..b8d316f36d 100644 --- a/lib/SPIRV/OCLUtil.h +++ b/lib/SPIRV/OCLUtil.h @@ -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[] = \ diff --git a/lib/SPIRV/SPIRVReader.cpp b/lib/SPIRV/SPIRVReader.cpp index 999beafcb6..cdb430ff15 100644 --- a/lib/SPIRV/SPIRVReader.cpp +++ b/lib/SPIRV/SPIRVReader.cpp @@ -2950,7 +2950,9 @@ Instruction *SPIRVToLLVM::transBuiltinFromInst(const std::string &FuncName, if (isFuncNoUnwind()) Func->addFnAttr(Attribute::NoUnwind); auto OC = BI->getOpCode(); - if (isGroupOpCode(OC) || isIntelSubgroupOpCode(OC)) + if (isGroupOpCode(OC) || isIntelSubgroupOpCode(OC) || + isSplitBarrierINTELOpCode(OC)) + Func->addFnAttr(Attribute::Convergent); } auto Call = diff --git a/lib/SPIRV/SPIRVToOCL.cpp b/lib/SPIRV/SPIRVToOCL.cpp index 26ac5e3fb8..55d8a67fa5 100644 --- a/lib/SPIRV/SPIRVToOCL.cpp +++ b/lib/SPIRV/SPIRVToOCL.cpp @@ -107,6 +107,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; diff --git a/lib/SPIRV/SPIRVToOCL.h b/lib/SPIRV/SPIRVToOCL.h index 62b49e91ee..128e82d376 100644 --- a/lib/SPIRV/SPIRVToOCL.h +++ b/lib/SPIRV/SPIRVToOCL.h @@ -222,6 +222,11 @@ class SPIRVToOCLBase : public InstVisitor { /// - OCL1.2: barrier virtual void visitCallSPIRVControlBarrier(CallInst *CI) = 0; + /// Transform split __spirv_ControlBarrier 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; @@ -290,6 +295,10 @@ class SPIRVToOCL12Base : public SPIRVToOCLBase { /// barrier(flag(sema)) void visitCallSPIRVControlBarrier(CallInst *CI) override; + /// Transform split __spirv_ControlBarrier 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; @@ -379,6 +388,10 @@ class SPIRVToOCL20Base : public SPIRVToOCLBase { /// sub_group_barrier(flag(sema), map(memScope)) void visitCallSPIRVControlBarrier(CallInst *CI) override; + /// Transform split __spirv_ControlBarrier 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)) diff --git a/lib/SPIRV/SPIRVToOCL12.cpp b/lib/SPIRV/SPIRVToOCL12.cpp index f34564b02a..8f510d56fe 100644 --- a/lib/SPIRV/SPIRVToOCL12.cpp +++ b/lib/SPIRV/SPIRVToOCL12.cpp @@ -102,6 +102,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 &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( diff --git a/lib/SPIRV/SPIRVToOCL20.cpp b/lib/SPIRV/SPIRVToOCL20.cpp index c9bb28297d..3186c0eaa7 100644 --- a/lib/SPIRV/SPIRVToOCL20.cpp +++ b/lib/SPIRV/SPIRVToOCL20.cpp @@ -121,6 +121,28 @@ void SPIRVToOCL20Base::visitCallSPIRVControlBarrier(CallInst *CI) { &Attrs); } +void SPIRVToOCL20Base::visitCallSPIRVSplitBarrierINTEL(CallInst *CI, Op OC) { + AttributeList Attrs = CI->getCalledFunction()->getAttributes(); + mutateCallInstOCL( + M, CI, + [=](CallInst *, std::vector &Args) { + auto GetArg = [=](unsigned I) { + return cast(Args[I])->getZExtValue(); + }; + Value *MemScope = + getInt32(M, rmap(static_cast(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!"); diff --git a/lib/SPIRV/libSPIRV/SPIRVInstruction.h b/lib/SPIRV/libSPIRV/SPIRVInstruction.h index 87d8b03b42..2e30e951a5 100644 --- a/lib/SPIRV/libSPIRV/SPIRVInstruction.h +++ b/lib/SPIRV/libSPIRV/SPIRVInstruction.h @@ -3269,6 +3269,25 @@ class SPIRVBfloat16ConversionINTELInstBase : public SPIRVUnaryInst { _SPIRV_OP(ConvertFToBF16INTEL) _SPIRV_OP(ConvertBF16ToFINTEL) #undef _SPIRV_OP + +class SPIRVSplitBarrierINTELBase : public SPIRVInstTemplateBase { +protected: + SPIRVCapVec getRequiredCapability() const override { + return getVec(CapabilitySplitBarrierINTEL); + } + + llvm::Optional getRequiredExtension() const override { + return ExtensionID::SPV_INTEL_split_barrier; + } +}; + +#define _SPIRV_OP(x, ...) \ + typedef SPIRVInstTemplate \ + SPIRV##x; +_SPIRV_OP(ControlBarrierArriveINTEL, false, 4) +_SPIRV_OP(ControlBarrierWaitINTEL, false, 4) +#undef _SPIRV_OP + } // namespace SPIRV #endif // SPIRV_LIBSPIRV_SPIRVINSTRUCTION_H diff --git a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h index 8cac6d9d74..1233ac7d4d 100644 --- a/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h +++ b/lib/SPIRV/libSPIRV/SPIRVNameMapEnum.h @@ -572,6 +572,7 @@ template <> inline void SPIRVMap::init() { add(internal::CapabilityOptNoneINTEL, "OptNoneINTEL"); add(internal::CapabilityMemoryAccessAliasingINTEL, "MemoryAccessAliasingINTEL"); + add(CapabilitySplitBarrierINTEL, "SplitBarrierINTEL"); add(internal::CapabilityFPGAInvocationPipeliningAttributesINTEL, "FPGAInvocationPipeliningAttributesINTEL"); add(internal::CapabilityTokenTypeINTEL, "TokenTypeINTEL"); diff --git a/lib/SPIRV/libSPIRV/SPIRVOpCode.h b/lib/SPIRV/libSPIRV/SPIRVOpCode.h index fb9467428a..97d1892fa6 100644 --- a/lib/SPIRV/libSPIRV/SPIRVOpCode.h +++ b/lib/SPIRV/libSPIRV/SPIRVOpCode.h @@ -243,6 +243,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 diff --git a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h index 748257b9e1..62de06ed7b 100644 --- a/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h +++ b/lib/SPIRV/libSPIRV/SPIRVOpCodeEnum.h @@ -543,3 +543,5 @@ _SPIRV_OP(TypeBufferSurfaceINTEL, 6086) _SPIRV_OP(TypeStructContinuedINTEL, 6090) _SPIRV_OP(ConstantCompositeContinuedINTEL, 6091) _SPIRV_OP(SpecConstantCompositeContinuedINTEL, 6092) +_SPIRV_OP(ControlBarrierArriveINTEL, 6142) +_SPIRV_OP(ControlBarrierWaitINTEL, 6143) 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 index 0000000000..8ab1e85ca3 --- /dev/null +++ b/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_12.ll @@ -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 index 0000000000..4cdbcf232f --- /dev/null +++ b/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_20.ll @@ -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 index 0000000000..ae5b57f155 --- /dev/null +++ b/test/transcoding/SPV_INTEL_split_barrier/split_work_group_barrier_spirv.ll @@ -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 = !{!""}