[clang] [llvm] [HLSL] Implement the `degrees` intrinsic (PR #111209)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 4 15:38:09 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen
Author: Finn Plummer (inbelic)
<details>
<summary>Changes</summary>
- 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
---
Patch is 21.70 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/111209.diff
14 Files Affected:
- (modified) clang/include/clang/Basic/Builtins.td (+6)
- (modified) clang/lib/CodeGen/CGBuiltin.cpp (+11)
- (modified) clang/lib/CodeGen/CGHLSLRuntime.h (+1)
- (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+30)
- (modified) clang/lib/Sema/SemaHLSL.cpp (+1)
- (added) clang/test/CodeGenHLSL/builtins/degrees.hlsl (+64)
- (added) clang/test/SemaHLSL/BuiltIns/degrees-errors.hlsl (+37)
- (modified) clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl (+1)
- (modified) llvm/include/llvm/IR/IntrinsicsDirectX.td (+1)
- (modified) llvm/include/llvm/IR/IntrinsicsSPIRV.td (+1)
- (modified) llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp (+12)
- (modified) llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp (+22)
- (added) llvm/test/CodeGen/DirectX/degrees.ll (+54)
- (added) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/degrees.ll (+68)
``````````diff
diff --git a/clang/include/clang/Basic/Builtins.td b/clang/include/clang/Basic/Builtins.td
index 8090119e512fbb..910d90cb3fbc7e 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4709,6 +4709,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 da3eca73bfb575..ecaff0f83b76f3 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -18715,6 +18715,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 810a16d75f0228..0fac48378379cc 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -736,6 +736,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 43cc6c81ae5cb0..d46f8778272d0f 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..16f3ece6cee3a8
--- /dev/null
+++ b/clang/test/SemaHLSL/BuiltIns/degrees-errors.hlsl
@@ -0,0 +1,37 @@
+// 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)}}
+}
+
+// builtins are variadic functions and so are subject to DefaultVariadicArgumentPromotion
+half builtin_degrees_half_scalar (half p0) {
+ return __builtin_hlsl_elementwise_degrees(p0);
+ // expected-error at -1 {{passing 'double' to parameter of incompatible type 'float'}}
+}
+
+float builtin_degrees_float_scalar (float p0) {
+ return __builtin_hlsl_elementwise_degrees(p0);
+ // expected-error at -1 {{passing 'double' to parameter of incompatible type 'float'}}
+}
diff --git a/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl
index 1841f60568b568..ed0d3dae99c8a5 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
double2 test_double_builtin(double2 p0) {
return TEST_FUNC(p0);
diff --git a/llvm/include/llvm/IR/IntrinsicsDirectX.td b/llvm/include/llvm/IR/IntrinsicsDirectX.td
index 555877e7aaf0e5..c930a0ccd1f72a 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]>;
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 7ff3d58690ba75..da5ffd3e70cfa0 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]>;
def int_spv_any : DefaultAttrsIntrinsic<[llvm_i1_ty], [llvm_any_ty]>;
+ def int_spv_degrees : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]>;
def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty]>;
def int_spv_lerp : Intrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem, IntrWillReturn] >;
diff --git a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
index 926cbe97f24fda..8d3417ea5c7c00 100644
--- a/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
+++ b/llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp
@@ -45,6 +45,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:
@@ -434,6 +435,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();
@@ -490,6 +499,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 7a565249a342d1..e75ef181057758 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -157,6 +157,9 @@ class SPIRVInstructionSelector : public InstructionSelector {
bool selectLength(Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;
+ bool selectDegrees(Register ResVReg, const SPIRVType *ResType,
+ MachineInstr &I) const;
+
bool selectFrac(Register ResVReg, const SPIRVType *ResType,
MachineInstr &I) const;
@@ -1643,6 +1646,23 @@ bool SPIRVInstructionSelector::selectLength(Register ResVReg,
.constrainAllUses(TII, TRI, RBI);
}
+bool SPIRVInstructionSelector::selectDegrees(Register ResVReg,
+ const SPIRVType *ResType,
+ MachineInstr &I) const {
+
+ assert(I.getNumOperands() == 3);
+ assert(I.getOperand(2).isReg());
+ MachineBasicBlock &BB = *I.getParent();
+
+ return BuildMI(BB, I, I.getDebugLoc(), TII.get(SPIRV::OpExtInst))
+ .addDef(ResVReg)
+ .addUse(GR.getSPIRVTypeID(ResType))
+ .addImm(static_cast<uint32_t>(SPIRV::InstructionSet::GLSL_std_450))
+ .addImm(GL::Degrees)
+ .addUse(I.getOperand(2).getReg())
+ .constrainAllUses(TII, TRI, RBI);
+}
+
bool SPIRVInstructionSelector::selectFrac(Register ResVReg,
const SPIRVType *ResType,
MachineInstr &I) const {
@@ -2625,6 +2645,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg,
return selectFmix(ResVReg, ResType, I);
case Intrinsic::spv_length:
return selectLength(ResVReg, ResType, I);
+ case Intrinsic::spv_degrees:
+ return selectDegrees(ResVReg, ResType, I);
case Intrinsic::spv_frac:
return selectFrac(ResVReg, ResType, I);
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
+}
+
+d...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/111209
More information about the cfe-commits
mailing list