diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td index e30d37f69f781..b7e45f3f7a05e 100644 --- a/llvm/include/llvm/IR/IntrinsicsDirectX.td +++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td @@ -35,6 +35,9 @@ def int_dx_typedBufferLoad_checkbit def int_dx_typedBufferStore : DefaultAttrsIntrinsic<[], [llvm_any_ty, llvm_i32_ty, llvm_anyvector_ty]>; +def int_dx_updateCounter + : DefaultAttrsIntrinsic<[], [llvm_any_ty, llvm_i8_ty]>; + // Cast between target extension handle types and dxil-style opaque handles def int_dx_cast_handle : Intrinsic<[llvm_any_ty], [llvm_any_ty]>; diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index af12b74351058..cc29e0f40be9d 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -730,6 +730,13 @@ def BufferStore : DXILOp<69, bufferStore> { let stages = [Stages]; } +def UpdateCounter : DXILOp<70, bufferUpdateCounter> { + let Doc = "increments/decrements a buffer counter"; + let arguments = [HandleTy, Int8Ty]; + let result = VoidTy; + let stages = [Stages]; +} + def CheckAccessFullyMapped : DXILOp<71, checkAccessFullyMapped> { let Doc = "checks whether a Sample, Gather, or Load operation " "accessed mapped tiles in a tiled resource"; diff --git a/llvm/lib/Target/DirectX/DXILOpLowering.cpp b/llvm/lib/Target/DirectX/DXILOpLowering.cpp index 8acc9c1efa08c..0dd3a8dc1ad4c 100644 --- a/llvm/lib/Target/DirectX/DXILOpLowering.cpp +++ b/llvm/lib/Target/DirectX/DXILOpLowering.cpp @@ -463,6 +463,28 @@ class OpLowerer { }); } + [[nodiscard]] bool lowerUpdateCounter(Function &F) { + IRBuilder<> &IRB = OpBuilder.getIRB(); + + return replaceFunction(F, [&](CallInst *CI) -> Error { + IRB.SetInsertPoint(CI); + Value *Handle = + createTmpHandleCast(CI->getArgOperand(0), OpBuilder.getHandleType()); + Value *Op1 = CI->getArgOperand(1); + + std::array Args{Handle, Op1}; + + Expected OpCall = + OpBuilder.tryCreateOp(OpCode::UpdateCounter, Args, CI->getName()); + + if (Error E = OpCall.takeError()) + return E; + + CI->eraseFromParent(); + return Error::success(); + }); + } + [[nodiscard]] bool lowerTypedBufferStore(Function &F) { IRBuilder<> &IRB = OpBuilder.getIRB(); Type *Int8Ty = IRB.getInt8Ty(); @@ -600,6 +622,9 @@ class OpLowerer { case Intrinsic::dx_typedBufferStore: HasErrors |= lowerTypedBufferStore(F); break; + case Intrinsic::dx_updateCounter: + HasErrors |= lowerUpdateCounter(F); + break; // TODO: this can be removed when // https://github.com/llvm/llvm-project/issues/113192 is fixed case Intrinsic::dx_splitdouble: diff --git a/llvm/test/CodeGen/DirectX/updateCounter.ll b/llvm/test/CodeGen/DirectX/updateCounter.ll new file mode 100644 index 0000000000000..68ea1e9eac9d5 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/updateCounter.ll @@ -0,0 +1,41 @@ +; RUN: opt -S -dxil-op-lower %s | FileCheck %s + + +target triple = "dxil-pc-shadermodel6.6-compute" + + ; CHECK-LABEL: define void @update_counter_decrement_vector() { +define void @update_counter_decrement_vector() { + ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, + %buffer = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_0_0_0( + i32 0, i32 0, i32 1, i32 0, i1 false) + + ; CHECK-NEXT: [[BUFFANOT:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]] + ; CHECK-NEXT: call void @dx.op.bufferUpdateCounter(i32 70, %dx.types.Handle [[BUFFANOT]], i8 -1) + call void @llvm.dx.updateCounter(target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i8 -1) + ret void +} + + ; CHECK-LABEL: define void @update_counter_increment_vector() { +define void @update_counter_increment_vector() { + ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, + %buffer = call target("dx.TypedBuffer", <4 x float>, 0, 0, 0) + @llvm.dx.handle.fromBinding.tdx.TypedBuffer_v4f32_0_0_0( + i32 0, i32 0, i32 1, i32 0, i1 false) + ; CHECK-NEXT: [[BUFFANOT:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]] + ; CHECK-NEXT: call void @dx.op.bufferUpdateCounter(i32 70, %dx.types.Handle [[BUFFANOT]], i8 1) + call void @llvm.dx.updateCounter(target("dx.TypedBuffer", <4 x float>, 0, 0, 0) %buffer, i8 1) + ret void +} + +; CHECK-LABEL: define void @update_counter_decrement_scalar() { +define void @update_counter_decrement_scalar() { + ; CHECK: [[BIND:%.*]] = call %dx.types.Handle @dx.op.createHandleFromBinding(i32 217, + %buffer = call target("dx.RawBuffer", i8, 0, 0) + @llvm.dx.handle.fromBinding.tdx.RawBuffer_i8_0_0t( + i32 1, i32 8, i32 1, i32 0, i1 false) + ; CHECK-NEXT: [[BUFFANOT:%.*]] = call %dx.types.Handle @dx.op.annotateHandle(i32 216, %dx.types.Handle [[BIND]] + ; CHECK-NEXT: call void @dx.op.bufferUpdateCounter(i32 70, %dx.types.Handle [[BUFFANOT]], i8 -1) + call void @llvm.dx.updateCounter(target("dx.RawBuffer", i8, 0, 0) %buffer, i8 -1) + ret void +}