https://github.com/Icohedron updated https://github.com/llvm/llvm-project/pull/189445
>From 1e9ea7daf333e9935e91dbff4291121df3de5a58 Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Mon, 30 Mar 2026 10:29:19 -0700 Subject: [PATCH 1/5] Fix 16-bit Shader Model availability for Wave intrinsics This commit fixes 16-bit Shader Model availability for HLSL wave intrinsics. Wave intrinsics require Shader Model 6.0, but many Wave intrinsics were missing the annotation specifying it. Furthermore, there wasn't an easy way to specify Shader Model 6.0 availability while maintaining the requirement for Shader Model 6.2 when 16-bit types is enabled and the overload uses half types. To fix the issue, this commit extends _HLSL_16BIT_AVAILABILITY to accept a 3rd optional argument that specifies the Shader Model availability when 16-bit types is disabled. Assisted-by: GitHub Copilot --- clang/include/clang/Basic/HLSLIntrinsics.td | 8 ++++ .../lib/Headers/hlsl/hlsl_alias_intrinsics.h | 5 ++- clang/utils/TableGen/HLSLEmitter.cpp | 40 +++++-------------- 3 files changed, 22 insertions(+), 31 deletions(-) diff --git a/clang/include/clang/Basic/HLSLIntrinsics.td b/clang/include/clang/Basic/HLSLIntrinsics.td index bc4dc56a46b5b..d05516ac49861 100644 --- a/clang/include/clang/Basic/HLSLIntrinsics.td +++ b/clang/include/clang/Basic/HLSLIntrinsics.td @@ -1578,6 +1578,7 @@ def hlsl_wave_active_all_equal_16bit : let ReturnType = VaryingShape<BoolTy>; let VaryingTypes = [HalfTy, Int16Ty, UInt16Ty]; let IsConvergent = 1; + let Availability = SM6_0; let VaryingMatDims = []; } @@ -1702,6 +1703,7 @@ def hlsl_wave_active_max : }]; let VaryingTypes = AllNumericTypes; let IsConvergent = 1; + let Availability = SM6_0; let VaryingMatDims = []; } @@ -1714,6 +1716,7 @@ def hlsl_wave_active_min : }]; let VaryingTypes = AllNumericTypes; let IsConvergent = 1; + let Availability = SM6_0; let VaryingMatDims = []; } @@ -1727,6 +1730,7 @@ def hlsl_wave_active_product : }]; let VaryingTypes = AllNumericTypes; let IsConvergent = 1; + let Availability = SM6_0; let VaryingMatDims = []; } @@ -1739,6 +1743,7 @@ def hlsl_wave_active_sum : }]; let VaryingTypes = AllNumericTypes; let IsConvergent = 1; + let Availability = SM6_0; let VaryingMatDims = []; } @@ -1801,6 +1806,7 @@ def hlsl_wave_prefix_product : }]; let VaryingTypes = AllNumericTypes; let IsConvergent = 1; + let Availability = SM6_0; let VaryingMatDims = []; } @@ -1813,6 +1819,7 @@ def hlsl_wave_prefix_sum : }]; let VaryingTypes = AllNumericTypes; let IsConvergent = 1; + let Availability = SM6_0; let VaryingMatDims = []; } @@ -1828,5 +1835,6 @@ the specified wave. let Args = [Varying, UIntTy]; let VaryingTypes = AllTypesWithBool; let IsConvergent = 1; + let Availability = SM6_0; let VaryingMatDims = []; } diff --git a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h index b2480b30f4a26..3ee56b597da30 100644 --- a/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_alias_intrinsics.h @@ -25,7 +25,7 @@ namespace hlsl { availability(platform, introduced = version, environment = stage))) #ifdef __HLSL_ENABLE_16_BIT -#define _HLSL_16BIT_AVAILABILITY(platform, version) \ +#define _HLSL_16BIT_AVAILABILITY(platform, version, ...) \ __attribute__((availability(platform, introduced = version))) #define _HLSL_16BIT_AVAILABILITY_STAGE(platform, version, stage) \ __attribute__(( \ @@ -33,7 +33,8 @@ namespace hlsl { #define _HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT() \ _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) #else -#define _HLSL_16BIT_AVAILABILITY(environment, version) +#define _HLSL_16BIT_AVAILABILITY(platform, version, ...) \ + __VA_OPT__(_HLSL_AVAILABILITY(platform, __VA_ARGS__)) #define _HLSL_16BIT_AVAILABILITY_STAGE(environment, version, stage) #define _HLSL_16BIT_AVAILABILITY_SHADERMODEL_DEFAULT() #endif diff --git a/clang/utils/TableGen/HLSLEmitter.cpp b/clang/utils/TableGen/HLSLEmitter.cpp index d115c35af5f6d..ce77c84d0ffcc 100644 --- a/clang/utils/TableGen/HLSLEmitter.cpp +++ b/clang/utils/TableGen/HLSLEmitter.cpp @@ -145,9 +145,12 @@ struct TypeInfo { static void emitAvailability(raw_ostream &OS, StringRef Version, bool Use16Bit = false) { - if (Use16Bit) - OS << "_HLSL_16BIT_AVAILABILITY(shadermodel, " << Version << ")\n"; - else + if (Use16Bit) { + OS << "_HLSL_16BIT_AVAILABILITY(shadermodel, " << SM6_2; + if (!Version.empty()) + OS << ", " << Version; + OS << ")\n"; + } else OS << "_HLSL_AVAILABILITY(shadermodel, " << Version << ")\n"; } @@ -397,32 +400,11 @@ static void buildWorklist(const Record *R, if (AvailabilityIsAtLeastSM6_2) { Item.Availability = Availability; } else { - Item.Availability = SM6_2; Item.Use16BitAvail = IsCond16Bit; - - // Note: If Availability = x where x < 6.2 and a half type is used, - // neither _HLSL_AVAILABILITY(shadermodel, x) nor - // _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) are correct: - // - // _HLSL_AVAILABILITY(shadermodel, x) will set the availbility for the - // half overload to x even when 16-bit types are enabled, but x < 6.2 - // and 6.2 is required for 16-bit half. - // - // _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) will set the - // availability for the half overload to 6.2 when 16-bit types are - // enabled, but there will be no availability set when 16-bit types - // are not enabled. - // - // A possible solution to this is to make _HLSL_16BIT_AVAILABILITY - // accept 3 args: (shadermodel, X, Y) where X is the availability for - // the 16-bit half type overload (which will typically be 6.2), and Y is - // the availability for the non-16-bit half overload. However, this - // situation does not currently arise, so we just assert below that this - // case will never occur. - assert( - !(IsCond16Bit && !Availability.empty()) && - "Can not handle availability for an intrinsic using half types and" - " which has an explicit shader model requirement older than 6.2"); + if (IsCond16Bit) + Item.Availability = Availability; + else + Item.Availability = SM6_2; } } else { Item.Availability = Availability; @@ -486,7 +468,7 @@ static void emitWorklistOverloads(raw_ostream &OS, const OverloadContext &Ctx, } auto EmitAvail = [&]() { - if (!Item.Availability.empty()) + if (!Item.Availability.empty() || Item.Use16BitAvail) emitAvailability(OS, Item.Availability, Item.Use16BitAvail); }; >From cff4d138f83cbfe3292847b2589ea6f8016ee8ad Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Mon, 30 Mar 2026 11:49:09 -0700 Subject: [PATCH 2/5] Add tests to ensure the 6.0 availability is enforced --- .../SemaHLSL/WaveBuiltinAvailability.hlsl | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl b/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl index 9c136ae497424..88cfd6056ef32 100644 --- a/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl +++ b/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl @@ -1,10 +1,38 @@ // RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel5.0-library -verify %s -// WaveActiveCountBits is unavailable before ShaderModel 6.0. +// Wave intrinsics are unavailable before ShaderModel 6.0. [shader("compute")] [numthreads(8,8,1)] void foo() { - // expected-error@#site {{'WaveActiveCountBits' is only available on Shader Model 6.0 or newer}} + // expected-error@#WaveActiveCountBits {{'WaveActiveCountBits' is only available on Shader Model 6.0 or newer}} // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* {{'WaveActiveCountBits' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} - unsigned tmp = hlsl::WaveActiveCountBits(1); // #site + unsigned tmp = hlsl::WaveActiveCountBits(1); // #WaveActiveCountBits + + // expected-error@#WaveActiveMax {{'WaveActiveMax' is only available on Shader Model 6.0 or newer}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* {{'WaveActiveMax' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + float a = hlsl::WaveActiveMax(1.0f); // #WaveActiveMax + + // expected-error@#WaveActiveMin {{'WaveActiveMin' is only available on Shader Model 6.0 or newer}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* {{'WaveActiveMin' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + float b = hlsl::WaveActiveMin(1.0f); // #WaveActiveMin + + // expected-error@#WaveActiveProduct {{'WaveActiveProduct' is only available on Shader Model 6.0 or newer}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* {{'WaveActiveProduct' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + float c = hlsl::WaveActiveProduct(1.0f); // #WaveActiveProduct + + // expected-error@#WaveActiveSum {{'WaveActiveSum' is only available on Shader Model 6.0 or newer}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* {{'WaveActiveSum' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + float d = hlsl::WaveActiveSum(1.0f); // #WaveActiveSum + + // expected-error@#WavePrefixProduct {{'WavePrefixProduct' is only available on Shader Model 6.0 or newer}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* {{'WavePrefixProduct' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + float e = hlsl::WavePrefixProduct(1.0f); // #WavePrefixProduct + + // expected-error@#WavePrefixSum {{'WavePrefixSum' is only available on Shader Model 6.0 or newer}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* {{'WavePrefixSum' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + float f = hlsl::WavePrefixSum(1.0f); // #WavePrefixSum + + // expected-error@#WaveReadLaneAt {{'WaveReadLaneAt' is only available on Shader Model 6.0 or newer}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* {{'WaveReadLaneAt' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + float g = hlsl::WaveReadLaneAt(1.0f, 0u); // #WaveReadLaneAt } >From 29e91e1eeddc04db48b0084ac6622b4a4f423bf7 Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Mon, 30 Mar 2026 11:56:37 -0700 Subject: [PATCH 3/5] Exercise half type overloads in the WaveBuiltinAvailability test --- clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl b/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl index 88cfd6056ef32..5741b81832ad0 100644 --- a/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl +++ b/clang/test/SemaHLSL/WaveBuiltinAvailability.hlsl @@ -35,4 +35,15 @@ void foo() { // expected-error@#WaveReadLaneAt {{'WaveReadLaneAt' is only available on Shader Model 6.0 or newer}} // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* {{'WaveReadLaneAt' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} float g = hlsl::WaveReadLaneAt(1.0f, 0u); // #WaveReadLaneAt + + // Test that half overloads (which map to float without native half) also + // have the correct SM 6.0 availability via the _HLSL_16BIT_AVAILABILITY + // fallback path. + // expected-error@#WaveActiveMax_half {{'WaveActiveMax' is only available on Shader Model 6.0 or newer}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* {{'WaveActiveMax' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + half h = hlsl::WaveActiveMax((half)1.0); // #WaveActiveMax_half + + // expected-error@#WaveReadLaneAt_half {{'WaveReadLaneAt' is only available on Shader Model 6.0 or newer}} + // expected-note@hlsl/hlsl_alias_intrinsics_gen.inc:* {{'WaveReadLaneAt' has been marked as being introduced in Shader Model 6.0 here, but the deployment target is Shader Model 5.0}} + half i = hlsl::WaveReadLaneAt((half)1.0, 0u); // #WaveReadLaneAt_half } >From a8cbcdcb435a7892f137f98afedec930be161fb7 Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Mon, 30 Mar 2026 12:08:44 -0700 Subject: [PATCH 4/5] Exercise new _HLSL_16BIT_AVAILABILITY in TableGen test --- clang/test/TableGen/hlsl-intrinsics.td | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/clang/test/TableGen/hlsl-intrinsics.td b/clang/test/TableGen/hlsl-intrinsics.td index e7dff7be97a39..3b741cf69f157 100644 --- a/clang/test/TableGen/hlsl-intrinsics.td +++ b/clang/test/TableGen/hlsl-intrinsics.td @@ -208,25 +208,27 @@ def test_08_avail_ge62 : HLSLBuiltin<"availfunc", "__builtin_availfunc"> { // ALIAS-NOT: availfunc //===----------------------------------------------------------------------===// -// Explicit availability (< SM6.2) with 16-bit integer types: the ifdef guard -// and _HLSL_AVAILABILITY(shadermodel, 6.2) are used for int16_t regardless of -// the intrinsic's stated availability, because 16-bit types require SM6.2. -// Note: half (IsConditionally16Bit) cannot be used here — the emitter asserts -// because neither _HLSL_AVAILABILITY nor _HLSL_16BIT_AVAILABILITY can correctly -// express availability for half when the intrinsic's SM < 6.2. -// Exercises: Availability < SM6.2 with Is16Bit types. +// Explicit availability (< SM6.2) with 16-bit types: int16_t gets the ifdef +// guard and _HLSL_AVAILABILITY(shadermodel, 6.2) regardless of the intrinsic's +// stated availability, because 16-bit types require SM6.2. Half gets a 3-arg +// _HLSL_16BIT_AVAILABILITY so that 16-bit half uses SM6.2 availability while +// the non-16-bit float fallback uses the intrinsic's original availability. +// Exercises: Availability < SM6.2 with Is16Bit and IsConditionally16Bit types. //===----------------------------------------------------------------------===// def test_08b_avail_lt62 : HLSLBuiltin<"availlt62", "__builtin_availlt62"> { let Args = [Varying]; let ReturnType = Varying; let VaryingScalar = 1; - let VaryingTypes = [Int16Ty, IntTy]; + let VaryingTypes = [HalfTy, Int16Ty, IntTy]; let Availability = SM6_1; } // ALIAS-LABEL: // availlt62 overloads -// ALIAS-NEXT: #ifdef __HLSL_ENABLE_16_BIT +// ALIAS-NEXT: _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2, 6.1) +// ALIAS-NEXT: _HLSL_BUILTIN_ALIAS(__builtin_availlt62) +// ALIAS-NEXT: half availlt62(half); +// ALIAS: #ifdef __HLSL_ENABLE_16_BIT // ALIAS-NEXT: _HLSL_AVAILABILITY(shadermodel, 6.2) // ALIAS-NEXT: _HLSL_BUILTIN_ALIAS(__builtin_availlt62) // ALIAS-NEXT: int16_t availlt62(int16_t); >From dc46d5a74e0c4a3a70f6baab223b7d48c6b6b3bd Mon Sep 17 00:00:00 2001 From: Deric Cheung <[email protected]> Date: Mon, 30 Mar 2026 13:26:43 -0700 Subject: [PATCH 5/5] Combine WaveActiveAllEqual definitions into one --- clang/include/clang/Basic/HLSLIntrinsics.td | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/clang/include/clang/Basic/HLSLIntrinsics.td b/clang/include/clang/Basic/HLSLIntrinsics.td index d05516ac49861..e2b34cae60137 100644 --- a/clang/include/clang/Basic/HLSLIntrinsics.td +++ b/clang/include/clang/Basic/HLSLIntrinsics.td @@ -1564,19 +1564,7 @@ group. Otherwise, the result is false. \return True if all values across all lanes are equal, false otherwise }]; let ReturnType = VaryingShape<BoolTy>; - let VaryingTypes = [IntTy, UIntTy, FloatTy, Int64Ty, UInt64Ty, DoubleTy]; - let IsConvergent = 1; - let Availability = SM6_0; - let VaryingMatDims = []; -} - -// WaveActiveAllEqual — half and 16-bit integer types. The 6.2 availability -// annotations for the half and 16-bit types are emitted automatically. -def hlsl_wave_active_all_equal_16bit : - HLSLOneArgBuiltin<"WaveActiveAllEqual", - "__builtin_hlsl_wave_active_all_equal"> { - let ReturnType = VaryingShape<BoolTy>; - let VaryingTypes = [HalfTy, Int16Ty, UInt16Ty]; + let VaryingTypes = AllNumericTypes; let IsConvergent = 1; let Availability = SM6_0; let VaryingMatDims = []; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
