llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-hlsl Author: Joshua Batista (bob80905) <details> <summary>Changes</summary> This PR adds the `InterlockedCompareExchangeFloatBitwise` standalone function and resource methods. It completes the interlocked stack. The operation matches `InterlockedCompareStoreFloatBitwise`, except that it reports the previous value. Clang bitcasts both float arguments to `i32` before the `cmpxchg`, then bitcasts the extracted result back to `float` before it stores it through the `original_value` reference parameter. As with the compare-store form, DXC declares this function for 32-bit float alone, so the overload set is float only, and the operation reuses the 32-bit integer DXIL operation, so it works from shader model 6.0 without capability bits. Fixes: https://github.com/llvm/llvm-project/issues/99203 Assisted by: Github Copilot --- Patch is 22.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/222167.diff 11 Files Affected: - (modified) clang/include/clang/Basic/Builtins.td (+7) - (modified) clang/lib/CodeGen/CGHLSLBuiltins.cpp (+6-1) - (modified) clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp (+4-2) - (modified) clang/lib/Sema/HLSLExternalSemaSource.cpp (+4) - (modified) clang/lib/Sema/SemaHLSL.cpp (+6) - (added) clang/test/CodeGenHLSL/builtins/InterlockedCompareExchangeFloatBitwise.hlsl (+43) - (modified) clang/test/CodeGenHLSL/builtins/RWBuffer-Interlocked.hlsl (+10) - (added) clang/test/CodeGenHLSL/builtins/RWByteAddressBuffer-InterlockedCompareExchangeFloatBitwise.hlsl (+32) - (added) clang/test/CodeGenHLSL/builtins/RasterizerOrderedByteAddressBuffer-InterlockedCompareExchangeFloatBitwise.hlsl (+25) - (added) clang/test/SemaHLSL/BuiltIns/ByteAddressBuffer-InterlockedCompareExchangeFloatBitwise-sm60.hlsl (+42) - (added) clang/test/SemaHLSL/BuiltIns/InterlockedCompareExchangeFloatBitwise-errors.hlsl (+119) ``````````diff diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td index af9a743716e6e..5b2c8bb06a594 100644 --- a/clang/include/clang/Basic/Builtins.td +++ b/clang/include/clang/Basic/Builtins.td @@ -5565,6 +5565,13 @@ def HLSLInterlockedCompareExchange : LangBuiltin<"HLSL_LANG"> { let Prototype = "void (...)"; } +def HLSLInterlockedCompareExchangeFloatBitwise : LangBuiltin<"HLSL_LANG"> { + let Spellings = ["__builtin_hlsl_interlocked_compare_exchange_float_bitwise"]; + // Prevent inadvertent float -> double arg promotion. + let Attributes = [NoThrow, CustomTypeChecking]; + let Prototype = "void (...)"; +} + def HLSLInterlockedCompareStore : LangBuiltin<"HLSL_LANG"> { let Spellings = ["__builtin_hlsl_interlocked_compare_store"]; // Prevent inadvertent float -> double arg promotion. diff --git a/clang/lib/CodeGen/CGHLSLBuiltins.cpp b/clang/lib/CodeGen/CGHLSLBuiltins.cpp index 1e0cb57307b2f..768df0c0157eb 100644 --- a/clang/lib/CodeGen/CGHLSLBuiltins.cpp +++ b/clang/lib/CodeGen/CGHLSLBuiltins.cpp @@ -361,9 +361,11 @@ static Value *handleInterlockedCompareOp(CodeGenFunction &CGF, // `cmpxchg` takes an integer or a pointer, so the float-bitwise operations // work on the bit pattern of the float. This is what those operations mean, // and DXIL and SPIR-V both need the integer form. + llvm::Type *FloatTy = nullptr; if (Compare->getType()->isFloatingPointTy()) { + FloatTy = Compare->getType(); llvm::Type *IntTy = - CGF.Builder.getIntNTy(Compare->getType()->getPrimitiveSizeInBits()); + CGF.Builder.getIntNTy(FloatTy->getPrimitiveSizeInBits()); Compare = CGF.Builder.CreateBitCast(Compare, IntTy); Val = CGF.Builder.CreateBitCast(Val, IntTy); DestAddr = DestAddr.withElementType(IntTy); @@ -380,6 +382,8 @@ static Value *handleInterlockedCompareOp(CodeGenFunction &CGF, // `cmpxchg` yields a { previous value, success } pair. HLSL reports only the // previous value, through the `original_value` reference parameter. Value *Original = CGF.Builder.CreateExtractValue(Pair, 0); + if (FloatTy) + Original = CGF.Builder.CreateBitCast(Original, FloatTy); LValue OrigLV = CGF.EmitLValue(E->getArg(3)); CGF.EmitStoreThroughLValue(RValue::get(Original), OrigLV); return Original; @@ -1527,6 +1531,7 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID, return handleInterlockedOp(*this, E, llvm::AtomicRMWInst::And); } case Builtin::BI__builtin_hlsl_interlocked_compare_exchange: + case Builtin::BI__builtin_hlsl_interlocked_compare_exchange_float_bitwise: case Builtin::BI__builtin_hlsl_interlocked_compare_store: case Builtin::BI__builtin_hlsl_interlocked_compare_store_float_bitwise: { return handleInterlockedCompareOp(*this, E); diff --git a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp index 6475aa6aa0fd1..2e51d138842aa 100644 --- a/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp +++ b/clang/lib/Sema/HLSLBuiltinTypeDeclBuilder.cpp @@ -1757,11 +1757,13 @@ BuiltinTypeDeclBuilder::addByteAddressBufferInterlockedMethods() { "InterlockedCompareExchange", AST.UnsignedIntTy, "__builtin_hlsl_interlocked_compare_exchange", /*WithOriginalValue=*/true); + addByteAddressBufferInterlockedCompareMethod( + "InterlockedCompareExchangeFloatBitwise", AST.FloatTy, + "__builtin_hlsl_interlocked_compare_exchange_float_bitwise", + /*WithOriginalValue=*/true); addByteAddressBufferInterlockedCompareMethod( "InterlockedCompareStore", AST.UnsignedIntTy, "__builtin_hlsl_interlocked_compare_store"); - // The float-bitwise compare reuses the 32-bit integer DXIL operation, so it - // needs no capability bits and works from SM 6.0. addByteAddressBufferInterlockedCompareMethod( "InterlockedCompareStoreFloatBitwise", AST.FloatTy, "__builtin_hlsl_interlocked_compare_store_float_bitwise"); diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index 7f51764248575..f473203df87b1 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -951,6 +951,10 @@ void HLSLExternalSemaSource::defineHLSLAtomicIntrinsics() { *SemaPtr, HLSLNamespace, "InterlockedCompareExchange", "__builtin_hlsl_interlocked_compare_exchange", AtomicOverloadShape::CompareExchange); + defineHLSLInterlockedCompareFunc( + *SemaPtr, HLSLNamespace, "InterlockedCompareExchangeFloatBitwise", + "__builtin_hlsl_interlocked_compare_exchange_float_bitwise", + AtomicOverloadShape::CompareExchange, /*FloatOnly=*/true); defineHLSLInterlockedCompareFunc(*SemaPtr, HLSLNamespace, "InterlockedCompareStore", "__builtin_hlsl_interlocked_compare_store", diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index d05c7e7a53c2b..90a355294f0db 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -4820,6 +4820,12 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { /*ReportsOriginalValue=*/true)) return true; break; + case Builtin::BI__builtin_hlsl_interlocked_compare_exchange_float_bitwise: + if (CheckInterlockedBuiltin(SemaRef, TheCall, /*MinArgs=*/4, /*MaxArgs=*/4, + InterlockedDest::Float, + /*ReportsOriginalValue=*/true)) + return true; + break; // Note these are llvm builtins that we want to catch invalid intrinsic // generation. Normal handling of these builtins will occur elsewhere. case Builtin::BI__builtin_elementwise_bitreverse: { diff --git a/clang/test/CodeGenHLSL/builtins/InterlockedCompareExchangeFloatBitwise.hlsl b/clang/test/CodeGenHLSL/builtins/InterlockedCompareExchangeFloatBitwise.hlsl new file mode 100644 index 0000000000000..42be35d40b967 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/InterlockedCompareExchangeFloatBitwise.hlsl @@ -0,0 +1,43 @@ +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.6-library %s -emit-llvm -disable-llvm-passes -o - | \ +// RUN: FileCheck %s --check-prefixes=CHECK,DXCHECK + +// RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -triple \ +// RUN: spirv-pc-vulkan-library %s -emit-llvm -disable-llvm-passes -o - | \ +// RUN: FileCheck %s --check-prefixes=CHECK,SPVCHECK + +// Test basic lowering of HLSL InterlockedCompareExchangeFloatBitwise to +// `cmpxchg monotonic`. `cmpxchg` takes an integer, so the float arguments +// become their bit patterns first, and the reported value becomes a float +// again before the store. + +groupshared float gs_f32; + +// CHECK-LABEL: define {{.*}}void @{{.*}}test_float +// CHECK: [[CMP:%.*]] = bitcast float %{{.*}} to i32 +// CHECK-NEXT: [[VAL:%.*]] = bitcast float %{{.*}} to i32 +// DXCHECK-NEXT: [[PAIR:%.*]] = cmpxchg ptr addrspace(3) {{.*}}@gs_f32{{.*}}, i32 [[CMP]], i32 [[VAL]] syncscope("workgroup") monotonic monotonic +// SPVCHECK-NEXT: [[PAIR:%.*]] = cmpxchg ptr addrspace(3) {{.*}}@gs_f32{{.*}}, i32 [[CMP]], i32 [[VAL]] syncscope("workgroup") monotonic monotonic +// CHECK-NEXT: [[RES:%.*]] = extractvalue { i32, i1 } [[PAIR]], 0 +// CHECK-NEXT: [[ORIG:%.*]] = bitcast i32 [[RES]] to float +// CHECK-NEXT: store float [[ORIG]], ptr %orig +export void test_float(float cmp, float v) { + float orig; + InterlockedCompareExchangeFloatBitwise(gs_f32, cmp, v, orig); +} + +// A device-address-space destination uses the "device" scope instead. +RWBuffer<float> Buf : register(u0); + +// CHECK-LABEL: define {{.*}}void @{{.*}}test_device +// CHECK: [[CMP:%.*]] = bitcast float %{{.*}} to i32 +// CHECK-NEXT: [[VAL:%.*]] = bitcast float %{{.*}} to i32 +// DXCHECK-NEXT: [[PAIR:%.*]] = cmpxchg ptr %{{.*}}, i32 [[CMP]], i32 [[VAL]] syncscope("device") monotonic monotonic +// SPVCHECK-NEXT: [[PAIR:%.*]] = cmpxchg ptr addrspace(11) %{{.*}}, i32 [[CMP]], i32 [[VAL]] syncscope("device") monotonic monotonic +// CHECK-NEXT: [[RES:%.*]] = extractvalue { i32, i1 } [[PAIR]], 0 +// CHECK-NEXT: [[ORIG:%.*]] = bitcast i32 [[RES]] to float +// CHECK-NEXT: store float [[ORIG]], ptr %orig +export void test_device(float cmp, float v) { + float orig; + InterlockedCompareExchangeFloatBitwise(Buf[0], cmp, v, orig); +} diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-Interlocked.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-Interlocked.hlsl index b85e40a9b1093..603e081df841e 100644 --- a/clang/test/CodeGenHLSL/builtins/RWBuffer-Interlocked.hlsl +++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-Interlocked.hlsl @@ -46,6 +46,10 @@ RWBuffer<float> FOut : register(u2); // DXCHECK: cmpxchg ptr %[[PTR11]], i32 1, i32 2 syncscope("device") monotonic monotonic // DXCHECK: %[[PTR12:.*]] = call {{.*}} @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_1_0_0t.i32(target("dx.TypedBuffer", float, 1, 0, 0) %{{.*}}, i32 %{{.*}}) // DXCHECK: cmpxchg ptr %[[PTR12]], i32 1065353216, i32 1073741824 syncscope("device") monotonic monotonic +// DXCHECK: %[[PTR13:.*]] = call {{.*}} @llvm.dx.resource.getpointer.p0.tdx.TypedBuffer_f32_1_0_0t.i32(target("dx.TypedBuffer", float, 1, 0, 0) %{{.*}}, i32 %{{.*}}) +// DXCHECK: %[[PAIR13:.*]] = cmpxchg ptr %[[PTR13]], i32 1065353216, i32 1073741824 syncscope("device") monotonic monotonic +// DXCHECK: %[[RES13:.*]] = extractvalue { i32, i1 } %[[PAIR13]], 0 +// DXCHECK: bitcast i32 %[[RES13]] to float // SPVCHECK: %[[PTR1:.*]] = call {{.*}} @llvm.spv.resource.getpointer.{{.*}}(target("spirv.SignedImage", i32, {{.*}}) %{{.*}}, i32 %{{.*}}) // SPVCHECK: atomicrmw add ptr addrspace(11) %[[PTR1]], i32 1 syncscope("device") monotonic // SPVCHECK: %[[PTR2:.*]] = call {{.*}} @llvm.spv.resource.getpointer.{{.*}}(target("spirv.SignedImage", i32, {{.*}}) %{{.*}}, i32 %{{.*}}) @@ -70,6 +74,10 @@ RWBuffer<float> FOut : register(u2); // SPVCHECK: cmpxchg ptr addrspace(11) %[[PTR11]], i32 1, i32 2 syncscope("device") monotonic monotonic // SPVCHECK: %[[PTR12:.*]] = call {{.*}} @llvm.spv.resource.getpointer.{{.*}}(target("spirv.Image", float, {{.*}}) %{{.*}}, i32 %{{.*}}) // SPVCHECK: cmpxchg ptr addrspace(11) %[[PTR12]], i32 1065353216, i32 1073741824 syncscope("device") monotonic monotonic +// SPVCHECK: %[[PTR13:.*]] = call {{.*}} @llvm.spv.resource.getpointer.{{.*}}(target("spirv.Image", float, {{.*}}) %{{.*}}, i32 %{{.*}}) +// SPVCHECK: %[[PAIR13:.*]] = cmpxchg ptr addrspace(11) %[[PTR13]], i32 1065353216, i32 1073741824 syncscope("device") monotonic monotonic +// SPVCHECK: %[[RES13:.*]] = extractvalue { i32, i1 } %[[PAIR13]], 0 +// SPVCHECK: bitcast i32 %[[RES13]] to float [shader("compute")] [numthreads(1,1,1)] void main(uint3 id : SV_DispatchThreadID) { @@ -86,4 +94,6 @@ void main(uint3 id : SV_DispatchThreadID) { InterlockedCompareStore(Out[id.x], 1, 2); InterlockedCompareExchange(Out[id.x], 1, 2, orig); InterlockedCompareStoreFloatBitwise(FOut[id.x], 1.0f, 2.0f); + float forig; + InterlockedCompareExchangeFloatBitwise(FOut[id.x], 1.0f, 2.0f, forig); } diff --git a/clang/test/CodeGenHLSL/builtins/RWByteAddressBuffer-InterlockedCompareExchangeFloatBitwise.hlsl b/clang/test/CodeGenHLSL/builtins/RWByteAddressBuffer-InterlockedCompareExchangeFloatBitwise.hlsl new file mode 100644 index 0000000000000..912565da3400e --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/RWByteAddressBuffer-InterlockedCompareExchangeFloatBitwise.hlsl @@ -0,0 +1,32 @@ +// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.6-library %s -emit-llvm -disable-llvm-passes -o - | \ +// RUN: FileCheck %s --check-prefixes=CHECK,DXCHECK + +// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple \ +// RUN: spirv-pc-vulkan1.3-library %s -emit-llvm -disable-llvm-passes -o - | \ +// RUN: FileCheck %s --check-prefixes=CHECK,SPVCHECK + +// Test that the RWByteAddressBuffer::InterlockedCompareExchangeFloatBitwise +// member method lowers to `resource_getpointer -> cmpxchg`, for both DXIL and +// SPIR-V targets. The float arguments become their bit patterns first, because +// `cmpxchg` takes an integer. The method takes the reported value by +// reference, so the pointer is loaded before the store. + +RWByteAddressBuffer BAB : register(u0); + +// CHECK-LABEL: define {{.*}}void @{{.*}}test_bab_float +// DXCHECK: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 0), ptr {{.*}} +// DXCHECK: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i8_1_0t.i32(target("dx.RawBuffer", i8, 1, 0) %[[HANDLE]], i32 %{{.*}}) +// SPVCHECK: %[[HANDLE:.*]] = load target("spirv.VulkanBuffer", [0 x i8], 12, 1), ptr {{.*}} +// SPVCHECK: %[[PTR:.*]] = call ptr addrspace(11) @llvm.spv.resource.getpointer.p11.tspirv.VulkanBuffer_a0i8_12_1t.i32(target("spirv.VulkanBuffer", [0 x i8], 12, 1) %[[HANDLE]], i32 %{{.*}}) +// CHECK: %[[CMP:.*]] = bitcast float %{{.*}} to i32 +// CHECK-NEXT: %[[VAL:.*]] = bitcast float %{{.*}} to i32 +// DXCHECK-NEXT: %[[PAIR:.*]] = cmpxchg ptr %[[PTR]], i32 %[[CMP]], i32 %[[VAL]] syncscope("device") monotonic monotonic +// SPVCHECK-NEXT: %[[PAIR:.*]] = cmpxchg ptr addrspace(11) %[[PTR]], i32 %[[CMP]], i32 %[[VAL]] syncscope("device") monotonic monotonic +// CHECK-NEXT: %[[RES:.*]] = extractvalue { i32, i1 } %[[PAIR]], 0 +// CHECK-NEXT: %[[ORIG:.*]] = bitcast i32 %[[RES]] to float +// CHECK-NEXT: %[[DEST:.*]] = load ptr, ptr %OriginalValue.addr +// CHECK-NEXT: store float %[[ORIG]], ptr %[[DEST]] +export void test_bab_float(uint off, float cmp, float v, out float orig) { + BAB.InterlockedCompareExchangeFloatBitwise(off, cmp, v, orig); +} diff --git a/clang/test/CodeGenHLSL/builtins/RasterizerOrderedByteAddressBuffer-InterlockedCompareExchangeFloatBitwise.hlsl b/clang/test/CodeGenHLSL/builtins/RasterizerOrderedByteAddressBuffer-InterlockedCompareExchangeFloatBitwise.hlsl new file mode 100644 index 0000000000000..67df534c00ae2 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/RasterizerOrderedByteAddressBuffer-InterlockedCompareExchangeFloatBitwise.hlsl @@ -0,0 +1,25 @@ +// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.6-library %s -emit-llvm -disable-llvm-passes -o - | \ +// RUN: FileCheck %s --check-prefixes=CHECK,DXCHECK + +// SPIR-V codegen for RasterizerOrderedByteAddressBuffer is not implemented +// yet (asserts in clang/lib/CodeGen/Targets/SPIR.cpp on +// `!ResAttrs.IsROV && "Rasterizer order views not implemented for SPIR-V yet"`). +// Add a `spirv-pc-vulkan1.3-library` RUN line here when SPIR-V ROV support +// lands. + +RasterizerOrderedByteAddressBuffer ROVB : register(u1); + +// CHECK-LABEL: define void @{{.*}}test_rovb_float +// DXCHECK: %[[HANDLE:.*]] = load target("dx.RawBuffer", i8, 1, 1), ptr {{.*}} +// DXCHECK: %[[PTR:.*]] = call ptr @llvm.dx.resource.getpointer.p0.tdx.RawBuffer_i8_1_1t.i32(target("dx.RawBuffer", i8, 1, 1) %[[HANDLE]], i32 %{{.*}}) +// DXCHECK: %[[CMP:.*]] = bitcast float %{{.*}} to i32 +// DXCHECK-NEXT: %[[VAL:.*]] = bitcast float %{{.*}} to i32 +// DXCHECK-NEXT: %[[PAIR:.*]] = cmpxchg ptr %[[PTR]], i32 %[[CMP]], i32 %[[VAL]] syncscope("device") monotonic monotonic +// DXCHECK-NEXT: %[[RES:.*]] = extractvalue { i32, i1 } %[[PAIR]], 0 +// DXCHECK-NEXT: %[[ORIG:.*]] = bitcast i32 %[[RES]] to float +// DXCHECK-NEXT: %[[DEST:.*]] = load ptr, ptr %OriginalValue.addr +// DXCHECK-NEXT: store float %[[ORIG]], ptr %[[DEST]] +export void test_rovb_float(uint off, float cmp, float v, out float orig) { + ROVB.InterlockedCompareExchangeFloatBitwise(off, cmp, v, orig); +} diff --git a/clang/test/SemaHLSL/BuiltIns/ByteAddressBuffer-InterlockedCompareExchangeFloatBitwise-sm60.hlsl b/clang/test/SemaHLSL/BuiltIns/ByteAddressBuffer-InterlockedCompareExchangeFloatBitwise-sm60.hlsl new file mode 100644 index 0000000000000..2adc6d1e1e552 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/ByteAddressBuffer-InterlockedCompareExchangeFloatBitwise-sm60.hlsl @@ -0,0 +1,42 @@ +// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header \ +// RUN: -triple dxil-pc-shadermodel6.0-library %s -fsyntax-only -verify \ +// RUN: -verify-ignore-unexpected=warning + +// The float-bitwise compare reuses the 32-bit integer DXIL operation, so it +// needs no capability bits and works from SM 6.0. The 64-bit compare-exchange +// needs SM 6.6. This file checks both halves, so it proves the two are gated +// differently. + +RWByteAddressBuffer BAB : register(u0); +RasterizerOrderedByteAddressBuffer ROVB : register(u1); +groupshared float gs_f32; +groupshared uint64_t gs_u64; + +void sm60_bab_float_bitwise_ok(uint off, float cmp, float v, out float orig) { + BAB.InterlockedCompareExchangeFloatBitwise(off, cmp, v, orig); +} + +void sm60_rovb_float_bitwise_ok(uint off, float cmp, float v, out float orig) { + ROVB.InterlockedCompareExchangeFloatBitwise(off, cmp, v, orig); +} + +void sm60_free_function_ok(float cmp, float v) { + float orig; + InterlockedCompareExchangeFloatBitwise(gs_f32, cmp, v, orig); +} + +void sm60_direct_builtin_ok(float cmp, float v) { + float orig; + __builtin_hlsl_interlocked_compare_exchange_float_bitwise(gs_f32, cmp, v, orig); +} + +void sm60_no_bab_compare_exchange64(uint off, uint64_t cmp, uint64_t v, + out uint64_t orig) { + BAB.InterlockedCompareExchange64(off, cmp, v, orig); + // expected-error@-1 {{no member named 'InterlockedCompareExchange64' in 'hlsl::RWByteAddressBuffer'}} +} + +void sm60_no_direct_builtin_u64(uint64_t cmp, uint64_t v, out uint64_t orig) { + __builtin_hlsl_interlocked_compare_exchange(gs_u64, cmp, v, orig); + // expected-error@-1 {{'__builtin_hlsl_interlocked_compare_exchange' requires shader model 6.6 or newer}} +} diff --git a/clang/test/SemaHLSL/BuiltIns/InterlockedCompareExchangeFloatBitwise-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/InterlockedCompareExchangeFloatBitwise-errors.hlsl new file mode 100644 index 0000000000000..934654c5f366d --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/InterlockedCompareExchangeFloatBitwise-errors.hlsl @@ -0,0 +1,119 @@ +// RUN: %clang_cc1 -std=hlsl202x -finclude-default-header \ +// RUN: -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only \ +// RUN: -disable-llvm-passes -verify + +// InterlockedCompareExchangeFloatBitwise compares the bit pattern of a 32-bit +// float, so it is provided as a float-only overload set (groupshared/device). +// It reports the previous value, so it has a single 4-argument form. + +groupshared float gs_f32; +groupshared int gs_i32; +groupshared double gs_f64; +groupshared half gs_f16; +struct S { float x; }; +groupshared S gs_s; + +void too_few(float cmp, float v) { + InterlockedCompareExchangeFloatBitwise(gs_f32, cmp, v); // expected-error{{no matching function for call to 'InterlockedCompareExchangeFloatBitwise'}} + // expected-note@*:* 2 {{candidate function}} +} + +void too_many(float cmp, float v, float extra) { + float orig; + InterlockedCompareExchangeFloatBitwise(gs_f32, cmp, v, orig, extra); // expected-error{{no matching function for call to 'InterlockedCompareExchangeFloatBitwise'}} + // expected-note@*:* 2 {{candidate function}} +} + +void local_dest(float cmp, float v) { + float dest; + float orig; + InterlockedCompareExchangeFloatBitwise(dest, cmp, v, orig); // expected-error{{no matching function for call to 'InterlockedCompareExchangeFloatBitwise'}} + // expected-note@*:* 2 {{candidate function}} +} + +// The bitwise compare is defined for 32-bit float alone, so there is no +// integer, half or double overload. +void int_dest(int cmp, int v) { + int orig; + InterlockedCompareExchangeFloatBitwise(gs_i32, cmp, v, orig); // expected-error{{no matching function for call to 'InterlockedCompareExchangeFloatBitwise'}} + // expected-note@*:* 2 {{candidate function}} +} + +void double_dest(double cmp, double v) { + double orig; + InterlockedCompareExchangeFloatBitwise(gs_f64, cmp, v, orig); // expected-error{{no matching function for call to 'InterlockedCompareExchangeFloatBitwise'}} + // expected-note@*:* 2 {{candidate function}} +} + +void half_dest(half cmp, half v) { + half orig; + InterlockedCompareExchangeFloatBitwise(gs_f16, cmp, v, orig); // expected-error{{no matching function for call to 'InterlockedCompareExchangeFloatBitwise'}} + // expected-note@*:* 2 {{candidate function}} +} + +void struct_dest(float... [truncated] `````````` </details> https://github.com/llvm/llvm-project/pull/222167 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
