[clang] [llvm] [HLSL] Implement the `degrees` intrinsic (PR #111209)
Finn Plummer via cfe-commits
cfe-commits at lists.llvm.org
Thu Oct 10 11:59:45 PDT 2024
https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/111209
>From 398dcb5c1a354c12d4d43af152f6d3e14f001274 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 2 Oct 2024 13:30:33 -0700
Subject: [PATCH 1/3] [HLSL] Implementation the `degrees` intrinsic
- add degrees builtin
- link degrees api in hlsl_intrinsics.h
- add degrees intrinsic to IntrinsicDirectX.td
- add degrees intrinsic to IntrinsicSPIRV.td
- add lowering from clang builtin to dx/spv intrinsics in
CGBuiltin.cpp
- add semantic checks to SemaHLSL.cpp
- add expansion of directx intrinsic to llvm fmul for DirectX in
DXILIntrinsicExpansion.cpp
- add mapping to spir-v intrinsic in SPIRVInstructionSelector.cpp
- add test coverage:
- degrees.hlsl -> check hlsl lowering to dx/spv degrees intrinsics
- degrees-errors.hlsl/half-float-only-errors ->
check semantic warnings
- hlsl-intrinsics/degrees.ll -> check lowering of spir-v
degrees intrinsic to SPIR-V backend
- DirectX/degrees.ll -> check expansion and scalarization of
directx degrees intrinsic to fmul
---
clang/include/clang/Basic/Builtins.td | 6 ++
clang/lib/CodeGen/CGBuiltin.cpp | 11 +++
clang/lib/CodeGen/CGHLSLRuntime.h | 1 +
clang/lib/Headers/hlsl/hlsl_intrinsics.h | 30 ++++++++
clang/lib/Sema/SemaHLSL.cpp | 1 +
clang/test/CodeGenHLSL/builtins/degrees.hlsl | 64 +++++++++++++++++
.../SemaHLSL/BuiltIns/degrees-errors.hlsl | 26 +++++++
.../BuiltIns/half-float-only-errors.hlsl | 1 +
llvm/include/llvm/IR/IntrinsicsDirectX.td | 1 +
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 +
.../Target/DirectX/DXILIntrinsicExpansion.cpp | 12 ++++
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 +
llvm/test/CodeGen/DirectX/degrees.ll | 54 +++++++++++++++
.../CodeGen/SPIRV/hlsl-intrinsics/degrees.ll | 68 +++++++++++++++++++
llvm/test/CodeGen/SPIRV/opencl/degrees.ll | 50 ++++++++++++++
15 files changed, 328 insertions(+)
create mode 100644 clang/test/CodeGenHLSL/builtins/degrees.hlsl
create mode 100644 clang/test/SemaHLSL/BuiltIns/degrees-errors.hlsl
create mode 100644 llvm/test/CodeGen/DirectX/degrees.ll
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees.ll
create mode 100644 llvm/test/CodeGen/SPIRV/opencl/degrees.ll
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 5b504666365b32..44142298987f12 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4739,6 +4739,12 @@ def HLSLClamp : LangBuiltin<"HLSL_LANG"> {
let Prototype = "void(...)";
}
+def HLSLDegrees : LangBuiltin<"HLSL_LANG"> {
+ let Spellings = ["__builtin_hlsl_elementwise_degrees"];
+ let Attributes = [NoThrow, Const];
+ let Prototype = "void(...)";
+}
+
def HLSLDotProduct : LangBuiltin<"HLSL_LANG"> {
let Spellings = ["__builtin_hlsl_dot"];
let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index c864714182e019..0f824fc2c4431a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18740,6 +18740,17 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
CGM.getHLSLRuntime().getNormalizeIntrinsic(), ArrayRef<Value *>{X},
nullptr, "hlsl.normalize");
}
+ case Builtin::BI__builtin_hlsl_elementwise_degrees: {
+ Value *X = EmitScalarExpr(E->getArg(0));
+
+ assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
+ "degree operand must have a float representation");
+
+ return Builder.CreateIntrinsic(
+ /*ReturnType=*/X->getType(),
+ CGM.getHLSLRuntime().getDegreesIntrinsic(),
+ ArrayRef<Value *>{X}, nullptr, "hlsl.degrees");
+ }
case Builtin::BI__builtin_hlsl_elementwise_frac: {
Value *Op0 = EmitScalarExpr(E->getArg(0));
if (!E->getArg(0)->getType()->hasFloatingRepresentation())
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index a8aabca7348ffb..966111a9600017 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -74,6 +74,7 @@ class CGHLSLRuntime {
GENERATE_HLSL_INTRINSIC_FUNCTION(All, all)
GENERATE_HLSL_INTRINSIC_FUNCTION(Any, any)
+ GENERATE_HLSL_INTRINSIC_FUNCTION(Degrees, degrees)
GENERATE_HLSL_INTRINSIC_FUNCTION(Frac, frac)
GENERATE_HLSL_INTRINSIC_FUNCTION(Length, length)
GENERATE_HLSL_INTRINSIC_FUNCTION(Lerp, lerp)
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index d28f204e352de5..07004a48f96128 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -766,6 +766,36 @@ uint64_t3 countbits(uint64_t3);
_HLSL_BUILTIN_ALIAS(__builtin_elementwise_popcount)
uint64_t4 countbits(uint64_t4);
+//===----------------------------------------------------------------------===//
+// degrees builtins
+//===----------------------------------------------------------------------===//
+
+/// \fn T degrees(T x)
+/// \brief Converts the specified value from radians to degrees.
+/// \param x The specified input value.
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_degrees)
+half degrees(half);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_degrees)
+half2 degrees(half2);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_degrees)
+half3 degrees(half3);
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_degrees)
+half4 degrees(half4);
+
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_degrees)
+float degrees(float);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_degrees)
+float2 degrees(float2);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_degrees)
+float3 degrees(float3);
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_degrees)
+float4 degrees(float4);
+
//===----------------------------------------------------------------------===//
// dot product builtins
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 5eda22f560c9d2..7e971e9fc92e05 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -1861,6 +1861,7 @@ bool SemaHLSL::CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) {
return true;
break;
}
+ case Builtin::BI__builtin_hlsl_elementwise_degrees:
case Builtin::BI__builtin_hlsl_elementwise_rsqrt:
case Builtin::BI__builtin_hlsl_elementwise_frac: {
if (CheckFloatOrHalfRepresentations(&SemaRef, TheCall))
diff --git a/clang/test/CodeGenHLSL/builtins/degrees.hlsl b/clang/test/CodeGenHLSL/builtins/degrees.hlsl
new file mode 100644
index 00000000000000..b861be2e79fa2c
--- /dev/null
+++ b/clang/test/CodeGenHLSL/builtins/degrees.hlsl
@@ -0,0 +1,64 @@
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
+// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
+// RUN: --check-prefixes=CHECK,NATIVE_HALF \
+// RUN: -DFNATTRS=noundef -DTARGET=dx
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
+// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \
+// RUN: -DFNATTRS=noundef -DTARGET=dx
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
+// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
+// RUN: --check-prefixes=CHECK,NATIVE_HALF \
+// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
+// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
+// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \
+// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
+
+// NATIVE_HALF: define [[FNATTRS]] half @
+// NATIVE_HALF: %hlsl.degrees = call half @llvm.[[TARGET]].degrees.f16(
+// NATIVE_HALF: ret half %hlsl.degrees
+// NO_HALF: define [[FNATTRS]] float @
+// NO_HALF: %hlsl.degrees = call float @llvm.[[TARGET]].degrees.f32(
+// NO_HALF: ret float %hlsl.degrees
+half test_degrees_half(half p0) { return degrees(p0); }
+// NATIVE_HALF: define [[FNATTRS]] <2 x half> @
+// NATIVE_HALF: %hlsl.degrees = call <2 x half> @llvm.[[TARGET]].degrees.v2f16
+// NATIVE_HALF: ret <2 x half> %hlsl.degrees
+// NO_HALF: define [[FNATTRS]] <2 x float> @
+// NO_HALF: %hlsl.degrees = call <2 x float> @llvm.[[TARGET]].degrees.v2f32(
+// NO_HALF: ret <2 x float> %hlsl.degrees
+half2 test_degrees_half2(half2 p0) { return degrees(p0); }
+// NATIVE_HALF: define [[FNATTRS]] <3 x half> @
+// NATIVE_HALF: %hlsl.degrees = call <3 x half> @llvm.[[TARGET]].degrees.v3f16
+// NATIVE_HALF: ret <3 x half> %hlsl.degrees
+// NO_HALF: define [[FNATTRS]] <3 x float> @
+// NO_HALF: %hlsl.degrees = call <3 x float> @llvm.[[TARGET]].degrees.v3f32(
+// NO_HALF: ret <3 x float> %hlsl.degrees
+half3 test_degrees_half3(half3 p0) { return degrees(p0); }
+// NATIVE_HALF: define [[FNATTRS]] <4 x half> @
+// NATIVE_HALF: %hlsl.degrees = call <4 x half> @llvm.[[TARGET]].degrees.v4f16
+// NATIVE_HALF: ret <4 x half> %hlsl.degrees
+// NO_HALF: define [[FNATTRS]] <4 x float> @
+// NO_HALF: %hlsl.degrees = call <4 x float> @llvm.[[TARGET]].degrees.v4f32(
+// NO_HALF: ret <4 x float> %hlsl.degrees
+half4 test_degrees_half4(half4 p0) { return degrees(p0); }
+
+// CHECK: define [[FNATTRS]] float @
+// CHECK: %hlsl.degrees = call float @llvm.[[TARGET]].degrees.f32(
+// CHECK: ret float %hlsl.degrees
+float test_degrees_float(float p0) { return degrees(p0); }
+// CHECK: define [[FNATTRS]] <2 x float> @
+// CHECK: %hlsl.degrees = call <2 x float> @llvm.[[TARGET]].degrees.v2f32
+// CHECK: ret <2 x float> %hlsl.degrees
+float2 test_degrees_float2(float2 p0) { return degrees(p0); }
+// CHECK: define [[FNATTRS]] <3 x float> @
+// CHECK: %hlsl.degrees = call <3 x float> @llvm.[[TARGET]].degrees.v3f32
+// CHECK: ret <3 x float> %hlsl.degrees
+float3 test_degrees_float3(float3 p0) { return degrees(p0); }
+// CHECK: define [[FNATTRS]] <4 x float> @
+// CHECK: %hlsl.degrees = call <4 x float> @llvm.[[TARGET]].degrees.v4f32
+// CHECK: ret <4 x float> %hlsl.degrees
+float4 test_degrees_float4(float4 p0) { return degrees(p0); }
diff --git a/clang/test/SemaHLSL/BuiltIns/degrees-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/degrees-errors.hlsl
new file mode 100644
index 00000000000000..e39ffda4696940
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/degrees-errors.hlsl
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected
+
+float test_too_few_arg() {
+ return __builtin_hlsl_elementwise_degrees();
+ // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+}
+
+float2 test_too_many_arg(float2 p0) {
+ return __builtin_hlsl_elementwise_degrees(p0, p0);
+ // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+}
+
+float builtin_bool_to_float_type_promotion(bool p1) {
+ return __builtin_hlsl_elementwise_degrees(p1);
+ // expected-error at -1 {{passing 'bool' to parameter of incompatible type 'float'}}
+}
+
+float builtin_degrees_int_to_float_promotion(int p1) {
+ return __builtin_hlsl_elementwise_degrees(p1);
+ // expected-error at -1 {{passing 'int' to parameter of incompatible type 'float'}}
+}
+
+float2 builtin_degrees_int2_to_float2_promotion(int2 p1) {
+ return __builtin_hlsl_elementwise_degrees(p1);
+ // expected-error at -1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl
index 0c1f7022bad609..c12a230ea6f4eb 100644
--- a/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl
@@ -17,6 +17,7 @@
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_tan
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_tanh
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_trunc
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -DTEST_FUNC=__builtin_hlsl_elementwise_degrees
double test_double_builtin(double p0) {
return TEST_FUNC(p0);
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 81d7e55047c77c..caacb65ac18837 100644
--- a/llvm/include/llvm/IR/IntrinsicsDirectX.td
+++ b/llvm/include/llvm/IR/IntrinsicsDirectX.td
@@ -70,6 +70,7 @@ def int_dx_udot :
[IntrNoMem, Commutative] >;
def int_dx_frac : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>;
+def int_dx_degrees : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;
def int_dx_isinf : DefaultAttrsIntrinsic<[LLVMScalarOrSameVectorWidth<0, llvm_i1_ty>],
[llvm_anyfloat_ty], [IntrNoMem]>;
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index efe19f5a8370e5..ee61793bbea241 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -61,6 +61,7 @@ let TargetPrefix = "spv" in {
def int_spv_thread_id : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem, IntrWillReturn]>;
def int_spv_all : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>;
def int_spv_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty], [IntrNoMem]>;
+ def int_spv_degrees : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_lerp : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem] >;
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index fca5af9d19141e..0cb0dc4c48e541 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -55,6 +55,7 @@ static bool isIntrinsicExpansion(Function &F) {
case Intrinsic::dx_any:
case Intrinsic::dx_clamp:
case Intrinsic::dx_uclamp:
+ case Intrinsic::dx_degrees:
case Intrinsic::dx_lerp:
case Intrinsic::dx_length:
case Intrinsic::dx_normalize:
@@ -444,6 +445,14 @@ static Value *expandClampIntrinsic(CallInst *Orig,
{MaxCall, Max}, nullptr, "dx.min");
}
+static Value *expandDegreesIntrinsic(CallInst *Orig) {
+ Value *X = Orig->getOperand(0);
+ Type *Ty = X->getType();
+ IRBuilder<> Builder(Orig);
+ Value *DegreesRatio = ConstantFP::get(Ty, 180.0 * llvm::numbers::inv_pi);
+ return Builder.CreateFMul(X, DegreesRatio);
+}
+
static Value *expandSignIntrinsic(CallInst *Orig) {
Value *X = Orig->getOperand(0);
Type *Ty = X->getType();
@@ -500,6 +509,9 @@ static bool expandIntrinsic(Function &F, CallInst *Orig) {
case Intrinsic::dx_clamp:
Result = expandClampIntrinsic(Orig, IntrinsicId);
break;
+ case Intrinsic::dx_degrees:
+ Result = expandDegreesIntrinsic(Orig);
+ break;
case Intrinsic::dx_lerp:
Result = expandLerpIntrinsic(Orig);
break;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index c1a0cd9837d146..103103050d412c 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -2504,6 +2504,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
return selectExtInst(ResVReg, ResType, I, CL::mix, GL::FMix);
case Intrinsic::spv_length:
return selectExtInst(ResVReg, ResType, I, CL::length, GL::Length);
+ case Intrinsic::spv_degrees:
+ return selectExtInst(ResVReg, ResType, I, CL::degrees, GL::Degrees);
case Intrinsic::spv_frac:
return selectExtInst(ResVReg, ResType, I, CL::fract, GL::Fract);
case Intrinsic::spv_normalize:
diff --git a/llvm/test/CodeGen/DirectX/degrees.ll b/llvm/test/CodeGen/DirectX/degrees.ll
new file mode 100644
index 00000000000000..3cc4edadaa5e93
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/degrees.ll
@@ -0,0 +1,54 @@
+; RUN: opt -S -dxil-intrinsic-expansion -scalarizer -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library %s | FileCheck %s
+
+; Make sure dxil op function calls for degrees are expanded and lowered as fmul for float and half.
+
+define noundef half @degrees_half(half noundef %a) {
+; CHECK-LABEL: define noundef half @degrees_half(
+; CHECK-SAME: half noundef [[A:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[DX_DEGREES1:%.*]] = fmul half [[A]], 0xH5329
+; CHECK-NEXT: ret half [[DX_DEGREES1]]
+;
+entry:
+ %dx.degrees = call half @llvm.dx.degrees.f16(half %a)
+ ret half %dx.degrees
+}
+
+define noundef float @degrees_float(float noundef %a) #0 {
+; CHECK-LABEL: define noundef float @degrees_float(
+; CHECK-SAME: float noundef [[A:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[DX_DEGREES1:%.*]] = fmul float [[A]], 0x404CA5DC20000000
+; CHECK-NEXT: ret float [[DX_DEGREES1]]
+;
+entry:
+ %dx.degrees = call float @llvm.dx.degrees.f32(float %a)
+ ret float %dx.degrees
+}
+
+define noundef <4 x float> @degrees_float4(<4 x float> noundef %a) #0 {
+; CHECK-LABEL: define noundef <4 x float> @degrees_float4(
+; CHECK-SAME: <4 x float> noundef [[A:%.*]]) {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: [[A_I0:%.*]] = extractelement <4 x float> [[A]], i64 0
+; CHECK-NEXT: [[DOTI04:%.*]] = fmul float [[A_I0]], 0x404CA5DC20000000
+; CHECK-NEXT: [[A_I1:%.*]] = extractelement <4 x float> [[A]], i64 1
+; CHECK-NEXT: [[DOTI13:%.*]] = fmul float [[A_I1]], 0x404CA5DC20000000
+; CHECK-NEXT: [[A_I2:%.*]] = extractelement <4 x float> [[A]], i64 2
+; CHECK-NEXT: [[DOTI22:%.*]] = fmul float [[A_I2]], 0x404CA5DC20000000
+; CHECK-NEXT: [[A_I3:%.*]] = extractelement <4 x float> [[A]], i64 3
+; CHECK-NEXT: [[DOTI31:%.*]] = fmul float [[A_I3]], 0x404CA5DC20000000
+; CHECK-NEXT: [[DOTUPTO0:%.*]] = insertelement <4 x float> poison, float [[DOTI04]], i64 0
+; CHECK-NEXT: [[DOTUPTO1:%.*]] = insertelement <4 x float> [[DOTUPTO0]], float [[DOTI13]], i64 1
+; CHECK-NEXT: [[DOTUPTO2:%.*]] = insertelement <4 x float> [[DOTUPTO1]], float [[DOTI22]], i64 2
+; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x float> [[DOTUPTO2]], float [[DOTI31]], i64 3
+; CHECK-NEXT: ret <4 x float> [[TMP0]]
+;
+entry:
+ %2 = call <4 x float> @llvm.dx.degrees.v4f32(<4 x float> %a)
+ ret <4 x float> %2
+}
+
+declare half @llvm.dx.degrees.f16(half)
+declare float @llvm.dx.degrees.f32(float)
+declare <4 x float> @llvm.dx.degrees.v4f32(<4 x float>)
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees.ll
new file mode 100644
index 00000000000000..ce648e0e51ba2c
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees.ll
@@ -0,0 +1,68 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450"
+
+; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
+; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
+; CHECK-DAG: %[[#float_64:]] = OpTypeFloat 64
+
+; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4
+; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4
+; CHECK-DAG: %[[#vec4_float_64:]] = OpTypeVector %[[#float_64]] 4
+
+define noundef float @degrees_float(float noundef %a) {
+entry:
+; CHECK: %[[#float_32_arg:]] = OpFunctionParameter %[[#float_32]]
+; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_glsl]] Degrees %[[#float_32_arg]]
+ %elt.degrees = call float @llvm.spv.degrees.f32(float %a)
+ ret float %elt.degrees
+}
+
+define noundef half @degrees_half(half noundef %a) {
+entry:
+; CHECK: %[[#float_16_arg:]] = OpFunctionParameter %[[#float_16]]
+; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_glsl]] Degrees %[[#float_16_arg]]
+ %elt.degrees = call half @llvm.spv.degrees.f16(half %a)
+ ret half %elt.degrees
+}
+
+define noundef double @degrees_double(double noundef %a) {
+entry:
+; CHECK: %[[#float_64_arg:]] = OpFunctionParameter %[[#float_64]]
+; CHECK: %[[#]] = OpExtInst %[[#float_64]] %[[#op_ext_glsl]] Degrees %[[#float_64_arg]]
+ %elt.degrees = call double @llvm.spv.degrees.f64(double %a)
+ ret double %elt.degrees
+}
+
+define noundef <4 x float> @degrees_float_vector(<4 x float> noundef %a) {
+entry:
+; CHECK: %[[#vec4_float_32_arg:]] = OpFunctionParameter %[[#vec4_float_32]]
+; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]] Degrees %[[#vec4_float_32_arg]]
+ %elt.degrees = call <4 x float> @llvm.spv.degrees.v4f32(<4 x float> %a)
+ ret <4 x float> %elt.degrees
+}
+
+define noundef <4 x half> @degrees_half_vector(<4 x half> noundef %a) {
+entry:
+; CHECK: %[[#vec4_float_16_arg:]] = OpFunctionParameter %[[#vec4_float_16]]
+; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]] Degrees %[[#vec4_float_16_arg]]
+ %elt.degrees = call <4 x half> @llvm.spv.degrees.v4f16(<4 x half> %a)
+ ret <4 x half> %elt.degrees
+}
+
+define noundef <4 x double> @degrees_double_vector(<4 x double> noundef %a) {
+entry:
+; CHECK: %[[#vec4_float_64_arg:]] = OpFunctionParameter %[[#vec4_float_64]]
+; CHECK: %[[#]] = OpExtInst %[[#vec4_float_64]] %[[#op_ext_glsl]] Degrees %[[#vec4_float_64_arg]]
+ %elt.degrees = call <4 x double> @llvm.spv.degrees.v4f64(<4 x double> %a)
+ ret <4 x double> %elt.degrees
+}
+
+declare half @llvm.spv.degrees.f16(half)
+declare float @llvm.spv.degrees.f32(float)
+declare double @llvm.spv.degrees.f64(double)
+
+declare <4 x float> @llvm.spv.degrees.v4f32(<4 x float>)
+declare <4 x half> @llvm.spv.degrees.v4f16(<4 x half>)
+declare <4 x double> @llvm.spv.degrees.v4f64(<4 x double>)
diff --git a/llvm/test/CodeGen/SPIRV/opencl/degrees.ll b/llvm/test/CodeGen/SPIRV/opencl/degrees.ll
new file mode 100644
index 00000000000000..88f97835fe7194
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/opencl/degrees.ll
@@ -0,0 +1,50 @@
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv64-unknown-unknown %s -o - | FileCheck %s
+; RUN: llc -verify-machineinstrs -O0 -mtriple=spirv32-unknown-unknown %s -o - | FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv64-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv32-unknown-unknown %s -o - -filetype=obj | spirv-val %}
+
+; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "OpenCL.std"
+
+; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32
+; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16
+
+; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4
+; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4
+
+declare half @llvm.spv.degrees.f16(half)
+declare float @llvm.spv.degrees.f32(float)
+
+declare <4 x float> @llvm.spv.degrees.v4f32(<4 x float>)
+declare <4 x half> @llvm.spv.degrees.v4f16(<4 x half>)
+
+define noundef float @degrees_float(float noundef %a) {
+entry:
+; CHECK: %[[#float_32_arg:]] = OpFunctionParameter %[[#float_32]]
+; CHECK: %[[#]] = OpExtInst %[[#float_32]] %[[#op_ext_glsl]] degrees %[[#float_32_arg]]
+ %elt.degrees = call float @llvm.spv.degrees.f32(float %a)
+ ret float %elt.degrees
+}
+
+define noundef half @degrees_half(half noundef %a) {
+entry:
+; CHECK: %[[#float_16_arg:]] = OpFunctionParameter %[[#float_16]]
+; CHECK: %[[#]] = OpExtInst %[[#float_16]] %[[#op_ext_glsl]] degrees %[[#float_16_arg]]
+ %elt.degrees = call half @llvm.spv.degrees.f16(half %a)
+ ret half %elt.degrees
+}
+
+define noundef <4 x float> @degrees_float_vector(<4 x float> noundef %a) {
+entry:
+; CHECK: %[[#vec4_float_32_arg:]] = OpFunctionParameter %[[#vec4_float_32]]
+; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]] degrees %[[#vec4_float_32_arg]]
+ %elt.degrees = call <4 x float> @llvm.spv.degrees.v4f32(<4 x float> %a)
+ ret <4 x float> %elt.degrees
+}
+
+define noundef <4 x half> @degrees_half_vector(<4 x half> noundef %a) {
+entry:
+; CHECK: %[[#vec4_float_16_arg:]] = OpFunctionParameter %[[#vec4_float_16]]
+; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]] degrees %[[#vec4_float_16_arg]]
+ %elt.degrees = call <4 x half> @llvm.spv.degrees.v4f16(<4 x half> %a)
+ ret <4 x half> %elt.degrees
+}
>From f7f55b9613775f4e77acf50b3a3ea13d09252c1f Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 9 Oct 2024 13:54:20 -0700
Subject: [PATCH 2/3] review comments:
improve testcases:
- remove flags that were not needed
- improve readability of FileCheck variables
- add CHECK-LABEL to spirv check
---
clang/test/CodeGenHLSL/builtins/degrees.hlsl | 8 ++---
.../SemaHLSL/BuiltIns/degrees-errors.hlsl | 2 +-
llvm/test/CodeGen/DirectX/degrees.ll | 34 +++++++++----------
.../CodeGen/SPIRV/hlsl-intrinsics/degrees.ll | 6 ++++
4 files changed, 28 insertions(+), 22 deletions(-)
diff --git a/clang/test/CodeGenHLSL/builtins/degrees.hlsl b/clang/test/CodeGenHLSL/builtins/degrees.hlsl
index b861be2e79fa2c..9e131f4badc19a 100644
--- a/clang/test/CodeGenHLSL/builtins/degrees.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/degrees.hlsl
@@ -1,18 +1,18 @@
-// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: %clang_cc1 -finclude-default-header -triple \
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
// RUN: --check-prefixes=CHECK,NATIVE_HALF \
// RUN: -DFNATTRS=noundef -DTARGET=dx
-// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: %clang_cc1 -finclude-default-header -triple \
// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \
// RUN: -DFNATTRS=noundef -DTARGET=dx
-// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: %clang_cc1 -finclude-default-header -triple \
// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \
// RUN: --check-prefixes=CHECK,NATIVE_HALF \
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
-// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \
+// RUN: %clang_cc1 -finclude-default-header -triple \
// RUN: spirv-unknown-vulkan-compute %s -emit-llvm -disable-llvm-passes \
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF \
// RUN: -DFNATTRS="spir_func noundef" -DTARGET=spv
diff --git a/clang/test/SemaHLSL/BuiltIns/degrees-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/degrees-errors.hlsl
index e39ffda4696940..9e981f6973572d 100644
--- a/clang/test/SemaHLSL/BuiltIns/degrees-errors.hlsl
+++ b/clang/test/SemaHLSL/BuiltIns/degrees-errors.hlsl
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify -verify-ignore-unexpected
+// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -emit-llvm-only -disable-llvm-passes -verify
float test_too_few_arg() {
return __builtin_hlsl_elementwise_degrees();
diff --git a/llvm/test/CodeGen/DirectX/degrees.ll b/llvm/test/CodeGen/DirectX/degrees.ll
index 3cc4edadaa5e93..b38ac13d5f24e2 100644
--- a/llvm/test/CodeGen/DirectX/degrees.ll
+++ b/llvm/test/CodeGen/DirectX/degrees.ll
@@ -17,9 +17,9 @@ entry:
define noundef float @degrees_float(float noundef %a) #0 {
; CHECK-LABEL: define noundef float @degrees_float(
; CHECK-SAME: float noundef [[A:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[DX_DEGREES1:%.*]] = fmul float [[A]], 0x404CA5DC20000000
-; CHECK-NEXT: ret float [[DX_DEGREES1]]
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[DEGREES:%.*]] = fmul float [[A]], 0x404CA5DC20000000
+; CHECK-NEXT: ret float [[DEGREES]]
;
entry:
%dx.degrees = call float @llvm.dx.degrees.f32(float %a)
@@ -29,20 +29,20 @@ entry:
define noundef <4 x float> @degrees_float4(<4 x float> noundef %a) #0 {
; CHECK-LABEL: define noundef <4 x float> @degrees_float4(
; CHECK-SAME: <4 x float> noundef [[A:%.*]]) {
-; CHECK-NEXT: [[ENTRY:.*:]]
-; CHECK-NEXT: [[A_I0:%.*]] = extractelement <4 x float> [[A]], i64 0
-; CHECK-NEXT: [[DOTI04:%.*]] = fmul float [[A_I0]], 0x404CA5DC20000000
-; CHECK-NEXT: [[A_I1:%.*]] = extractelement <4 x float> [[A]], i64 1
-; CHECK-NEXT: [[DOTI13:%.*]] = fmul float [[A_I1]], 0x404CA5DC20000000
-; CHECK-NEXT: [[A_I2:%.*]] = extractelement <4 x float> [[A]], i64 2
-; CHECK-NEXT: [[DOTI22:%.*]] = fmul float [[A_I2]], 0x404CA5DC20000000
-; CHECK-NEXT: [[A_I3:%.*]] = extractelement <4 x float> [[A]], i64 3
-; CHECK-NEXT: [[DOTI31:%.*]] = fmul float [[A_I3]], 0x404CA5DC20000000
-; CHECK-NEXT: [[DOTUPTO0:%.*]] = insertelement <4 x float> poison, float [[DOTI04]], i64 0
-; CHECK-NEXT: [[DOTUPTO1:%.*]] = insertelement <4 x float> [[DOTUPTO0]], float [[DOTI13]], i64 1
-; CHECK-NEXT: [[DOTUPTO2:%.*]] = insertelement <4 x float> [[DOTUPTO1]], float [[DOTI22]], i64 2
-; CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x float> [[DOTUPTO2]], float [[DOTI31]], i64 3
-; CHECK-NEXT: ret <4 x float> [[TMP0]]
+; CHECK-NEXT: entry:
+; CHECK-NEXT: [[A0:%.*]] = extractelement <4 x float> [[A]], i64 0
+; CHECK-NEXT: [[DEGREES_A0:%.*]] = fmul float [[A0]], 0x404CA5DC20000000
+; CHECK-NEXT: [[A1:%.*]] = extractelement <4 x float> [[A]], i64 1
+; CHECK-NEXT: [[DEGREES_A1:%.*]] = fmul float [[A1]], 0x404CA5DC20000000
+; CHECK-NEXT: [[A2:%.*]] = extractelement <4 x float> [[A]], i64 2
+; CHECK-NEXT: [[DEGREES_A2:%.*]] = fmul float [[A2]], 0x404CA5DC20000000
+; CHECK-NEXT: [[A3:%.*]] = extractelement <4 x float> [[A]], i64 3
+; CHECK-NEXT: [[DEGREES_A3:%.*]] = fmul float [[A3]], 0x404CA5DC20000000
+; CHECK-NEXT: [[INSERT_0:%.*]] = insertelement <4 x float> poison, float [[DEGREES_A0]], i64 0
+; CHECK-NEXT: [[INSERT_1:%.*]] = insertelement <4 x float> [[INSERT_0]], float [[DEGREES_A1]], i64 1
+; CHECK-NEXT: [[INSERT_2:%.*]] = insertelement <4 x float> [[INSERT_1]], float [[DEGREES_A2]], i64 2
+; CHECK-NEXT: [[RES:%.*]] = insertelement <4 x float> [[INSERT_2]], float [[DEGREES_A3]], i64 3
+; CHECK-NEXT: ret <4 x float> [[RES]]
;
entry:
%2 = call <4 x float> @llvm.dx.degrees.v4f32(<4 x float> %a)
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees.ll
index ce648e0e51ba2c..58383b72757eb9 100644
--- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees.ll
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees.ll
@@ -11,6 +11,7 @@
; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4
; CHECK-DAG: %[[#vec4_float_64:]] = OpTypeVector %[[#float_64]] 4
+; CHECK-LABEL: Begin function degrees_float
define noundef float @degrees_float(float noundef %a) {
entry:
; CHECK: %[[#float_32_arg:]] = OpFunctionParameter %[[#float_32]]
@@ -19,6 +20,7 @@ entry:
ret float %elt.degrees
}
+; CHECK-LABEL: Begin function degrees_half
define noundef half @degrees_half(half noundef %a) {
entry:
; CHECK: %[[#float_16_arg:]] = OpFunctionParameter %[[#float_16]]
@@ -27,6 +29,7 @@ entry:
ret half %elt.degrees
}
+; CHECK-LABEL: Begin function degrees_double
define noundef double @degrees_double(double noundef %a) {
entry:
; CHECK: %[[#float_64_arg:]] = OpFunctionParameter %[[#float_64]]
@@ -35,6 +38,7 @@ entry:
ret double %elt.degrees
}
+; CHECK-LABEL: Begin function degrees_float_vector
define noundef <4 x float> @degrees_float_vector(<4 x float> noundef %a) {
entry:
; CHECK: %[[#vec4_float_32_arg:]] = OpFunctionParameter %[[#vec4_float_32]]
@@ -43,6 +47,7 @@ entry:
ret <4 x float> %elt.degrees
}
+; CHECK-LABEL: Begin function degrees_half_vector
define noundef <4 x half> @degrees_half_vector(<4 x half> noundef %a) {
entry:
; CHECK: %[[#vec4_float_16_arg:]] = OpFunctionParameter %[[#vec4_float_16]]
@@ -51,6 +56,7 @@ entry:
ret <4 x half> %elt.degrees
}
+; CHECK-LABEL: Begin function degrees_double_vector
define noundef <4 x double> @degrees_double_vector(<4 x double> noundef %a) {
entry:
; CHECK: %[[#vec4_float_64_arg:]] = OpFunctionParameter %[[#vec4_float_64]]
>From b7a20c9a217400d44d5b84df771a4d47d5f89bba Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Thu, 10 Oct 2024 11:56:58 -0700
Subject: [PATCH 3/3] clang format
---
clang/lib/CodeGen/CGBuiltin.cpp | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 23ea78337d6651..ff678ee04f9c2a 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18759,11 +18759,10 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
Value *X = EmitScalarExpr(E->getArg(0));
assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
- "degree operand must have a float representation");
+ "degree operand must have a float representation");
return Builder.CreateIntrinsic(
- /*ReturnType=*/X->getType(),
- CGM.getHLSLRuntime().getDegreesIntrinsic(),
+ /*ReturnType=*/X->getType(), CGM.getHLSLRuntime().getDegreesIntrinsic(),
ArrayRef<Value *>{X}, nullptr, "hlsl.degrees");
}
case Builtin::BI__builtin_hlsl_elementwise_frac: {
More information about the cfe-commits
mailing list