From 23a6ad39cc7cc7f7cf0d16cc961c46ebd2d281c3 Mon Sep 17 00:00:00 2001 From: Artur Gainullin Date: Mon, 16 Mar 2020 13:18:36 -0700 Subject: [PATCH] [SYCL] Mark calls to barrier and work-item functions as convergent Calls to work-item functions and barrier function must be convergent to preserve semantics of these functions during llvm optimizations. Signed-off-by: Artur Gainullin --- llvm/lib/SYCLLowerIR/LowerWGScope.cpp | 19 +++++++++--- llvm/test/SYCLLowerIR/convergent.ll | 43 +++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 llvm/test/SYCLLowerIR/convergent.ll diff --git a/llvm/lib/SYCLLowerIR/LowerWGScope.cpp b/llvm/lib/SYCLLowerIR/LowerWGScope.cpp index f8bb128a435e8..7514682df4435 100644 --- a/llvm/lib/SYCLLowerIR/LowerWGScope.cpp +++ b/llvm/lib/SYCLLowerIR/LowerWGScope.cpp @@ -874,10 +874,15 @@ Value *spirv::genLinearLocalID(Instruction &Before, const Triple &TT) { IRBuilder<> Bld(Ctx); Bld.SetInsertPoint(&Before); + AttributeList Attr; + Attr = Attr.addAttribute(Ctx, AttributeList::FunctionIndex, + Attribute::Convergent); + #define CREATE_CALLEE(NAME, FN_NAME) \ - FunctionCallee FnCallee##NAME = M.getOrInsertFunction(FN_NAME, RetTy); \ + FunctionCallee FnCallee##NAME = M.getOrInsertFunction(FN_NAME, Attr, RetTy); \ assert(FnCallee##NAME && "spirv intrinsic creation failed"); \ - auto NAME = Bld.CreateCall(FnCallee##NAME, {}); + auto NAME = Bld.CreateCall(FnCallee##NAME, {}); \ + NAME->addAttribute(AttributeList::FunctionIndex, Attribute::Convergent); CREATE_CALLEE(LocalInvocationId_X, "_Z27__spirv_LocalInvocationId_xv"); CREATE_CALLEE(LocalInvocationId_Y, "_Z27__spirv_LocalInvocationId_yv"); @@ -937,8 +942,11 @@ Instruction *spirv::genWGBarrier(Instruction &Before, const Triple &TT) { Type *SemanticsTy = Type::getInt32Ty(Ctx); Type *RetTy = Type::getVoidTy(Ctx); + AttributeList Attr; + Attr = Attr.addAttribute(Ctx, AttributeList::FunctionIndex, + Attribute::Convergent); FunctionCallee FC = - M.getOrInsertFunction(Name, RetTy, ScopeTy, ScopeTy, SemanticsTy); + M.getOrInsertFunction(Name, Attr, RetTy, ScopeTy, ScopeTy, SemanticsTy); assert(FC.getCallee() && "spirv intrinsic creation failed"); IRBuilder<> Bld(Ctx); @@ -948,5 +956,8 @@ Instruction *spirv::genWGBarrier(Instruction &Before, const Triple &TT) { auto ArgSema = ConstantInt::get( ScopeTy, asUInt(spirv::MemorySemantics::SequentiallyConsistent) | asUInt(spirv::MemorySemantics::WorkgroupMemory)); - return Bld.CreateCall(FC, {ArgExec, ArgMem, ArgSema}); + auto BarrierCall = Bld.CreateCall(FC, {ArgExec, ArgMem, ArgSema}); + BarrierCall->addAttribute(llvm::AttributeList::FunctionIndex, + llvm::Attribute::Convergent); + return BarrierCall; } diff --git a/llvm/test/SYCLLowerIR/convergent.ll b/llvm/test/SYCLLowerIR/convergent.ll new file mode 100644 index 0000000000000..80f255c93edb3 --- /dev/null +++ b/llvm/test/SYCLLowerIR/convergent.ll @@ -0,0 +1,43 @@ +; RUN: opt < %s -LowerWGScope -S | FileCheck %s +; RUN: opt < %s -LowerWGScope --mtriple=nvptx -S | FileCheck %s -check-prefix=CHECK-PTX + + +%struct.baz = type { i64 } + +define internal spir_func void @wibble(%struct.baz* byval(%struct.baz) %arg1) !work_group_scope !0 { +; CHECK-PTX: %1 = call i64 @_Z27__spirv_LocalInvocationId_xv() #0 +; CHECK-PTX: %2 = call i64 @_Z27__spirv_LocalInvocationId_yv() #0 +; CHECK-PTX: %3 = call i64 @_Z27__spirv_LocalInvocationId_zv() #0 +; CHECK-PTX: %4 = call i64 @_Z23__spirv_WorkgroupSize_yv() #0 +; CHECK-PTX: %5 = call i64 @_Z23__spirv_WorkgroupSize_zv() #0 +; CHECK-PTX: call void @_Z22__spirv_ControlBarrierN5__spv5ScopeES0_j(i32 2, i32 2, i32 272) #0 +; CHECK: call void @__spirv_ControlBarrier(i32 2, i32 2, i32 272) #1 + ret void +} + +; CHECK-PTX: ; Function Attrs: convergent +; CHECK-PTX: declare i64 @_Z27__spirv_LocalInvocationId_xv() #0 + +; CHECK-PTX: ; Function Attrs: convergent +; CHECK-PTX: declare i64 @_Z27__spirv_LocalInvocationId_yv() #0 + +; CHECK-PTX: ; Function Attrs: convergent +; CHECK-PTX: declare i64 @_Z27__spirv_LocalInvocationId_zv() #0 + +; CHECK-PTX: ; Function Attrs: convergent +; CHECK-PTX: declare i64 @_Z23__spirv_WorkgroupSize_yv() #0 + +; CHECK-PTX: ; Function Attrs: convergent +; CHECK-PTX: declare i64 @_Z23__spirv_WorkgroupSize_zv() #0 + +; CHECK-PTX: ; Function Attrs: convergent +; CHECK-PTX: declare void @_Z22__spirv_ControlBarrierN5__spv5ScopeES0_j(i32, i32, i32) #0 + +; CHECK-PTX: attributes #0 = { convergent } + +; CHECK: ; Function Attrs: convergent +; CHECK: declare void @__spirv_ControlBarrier(i32, i32, i32) #1 + +; CHECK: attributes #1 = { convergent } + +!0 = !{}