https://github.com/raoanag updated https://github.com/llvm/llvm-project/pull/136026
>From 3221715ed9c06f6ef05414ae79a6e3bc576d4ba8 Mon Sep 17 00:00:00 2001 From: Anagha Rajendra Rao <anag...@microsoft.com> Date: Wed, 16 Apr 2025 11:47:27 -0700 Subject: [PATCH 1/4] Refract implementation --- clang/test/CodeGenHLSL/builtins/refract.hlsl | 92 +++++++++++++++++++ clang/test/CodeGenSPIRV/Builtins/refract.c | 32 +++++++ .../SemaHLSL/BuiltIns/refract-errors.hlsl | 74 +++++++++++++++ .../CodeGen/SPIRV/hlsl-intrinsics/refract.ll | 33 +++++++ 4 files changed, 231 insertions(+) create mode 100644 clang/test/CodeGenHLSL/builtins/refract.hlsl create mode 100644 clang/test/CodeGenSPIRV/Builtins/refract.c create mode 100644 clang/test/SemaHLSL/BuiltIns/refract-errors.hlsl create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/refract.ll diff --git a/clang/test/CodeGenHLSL/builtins/refract.hlsl b/clang/test/CodeGenHLSL/builtins/refract.hlsl new file mode 100644 index 0000000000000..4dc5b66251b62 --- /dev/null +++ b/clang/test/CodeGenHLSL/builtins/refract.hlsl @@ -0,0 +1,92 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s +// RUN: %clang_cc1 -finclude-default-header -triple \ +// RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ +// RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefix=SPVCHECK + +// CHECK-LABEL: define noundef nofpclass(nan inf) float @_Z18test_refract_floatff( +// CHECK-SAME: float noundef nofpclass(nan inf) [[I:%.*]], float noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[I]], 2.000000e+00 +// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[N]], [[N]] +// CHECK-NEXT: [[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP0]], [[MUL_I]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[I]], [[MUL2_I]] +// CHECK-NEXT: ret float [[SUB_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) float @_Z18test_refract_floatff( +// SPVCHECK-SAME: float noundef nofpclass(nan inf) [[I:%.*]], float noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[I]], 2.000000e+00 +// SPVCHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[N]], [[N]] +// SPVCHECK-NEXT: [[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP0]], [[MUL_I]] +// SPVCHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[I]], [[MUL2_I]] +// SPVCHECK-NEXT: ret float [[SUB_I]] +// +float test_refract_float(float I, float N, float eta) { + return refract(I, N, eta); +} + +// CHECK-LABEL: define noundef nofpclass(nan inf) <2 x float> @_Z19test_refract_float2Dv2_fS_( +// CHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[I:%.*]], <2 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v2f32(<2 x float> [[I]], <2 x float> [[N]]) +// CHECK-NEXT: [[DOTSCALAR:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], 2.000000e+00 +// CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x float> poison, float [[DOTSCALAR]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[TMP0]], <2 x float> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[MUL1_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> [[TMP1]], [[N]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x float> [[I]], [[MUL1_I]] +// CHECK-NEXT: ret <2 x float> [[SUB_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <2 x float> @_Z19test_refract_float2Dv2_fS_( +// SPVCHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[I:%.*]], <2 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[SPV_refract_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <2 x float> @llvm.spv.refract.v2f32(<2 x float> [[I]], <2 x float> [[N]]) +// SPVCHECK-NEXT: ret <2 x float> [[SPV_refract_I]] +// +float2 test_refract_float2(float2 I, float2 N, float eta) { + return refract(I, N, eta); +} + +// CHECK-LABEL: define noundef nofpclass(nan inf) <3 x float> @_Z19test_refract_float3Dv3_fS_( +// CHECK-SAME: <3 x float> noundef nofpclass(nan inf) [[I:%.*]], <3 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v3f32(<3 x float> [[I]], <3 x float> [[N]]) +// CHECK-NEXT: [[DOTSCALAR:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], 2.000000e+00 +// CHECK-NEXT: [[TMP0:%.*]] = insertelement <3 x float> poison, float [[DOTSCALAR]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <3 x float> [[TMP0]], <3 x float> poison, <3 x i32> zeroinitializer +// CHECK-NEXT: [[MUL1_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x float> [[TMP1]], [[N]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x float> [[I]], [[MUL1_I]] +// CHECK-NEXT: ret <3 x float> [[SUB_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <3 x float> @_Z19test_refract_float3Dv3_fS_( +// SPVCHECK-SAME: <3 x float> noundef nofpclass(nan inf) [[I:%.*]], <3 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[SPV_refract_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <3 x float> @llvm.spv.refract.v3f32(<3 x float> [[I]], <3 x float> [[N]]) +// SPVCHECK-NEXT: ret <3 x float> [[SPV_refract_I]] +// +float3 test_refract_float3(float3 I, float3 N, float eta) { + return refract(I, N, eta); +} + +// CHECK-LABEL: define noundef nofpclass(nan inf) <4 x float> @_Z19test_refract_float4Dv4_fS_( +// CHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[I:%.*]], <4 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v4f32(<4 x float> [[I]], <4 x float> [[N]]) +// CHECK-NEXT: [[DOTSCALAR:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], 2.000000e+00 +// CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x float> poison, float [[DOTSCALAR]], i64 0 +// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x float> [[TMP0]], <4 x float> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[MUL1_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x float> [[TMP1]], [[N]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x float> [[I]], [[MUL1_I]] +// CHECK-NEXT: ret <4 x float> [[SUB_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <4 x float> @_Z19test_refract_float4Dv4_fS_( +// SPVCHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[I:%.*]], <4 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[SPV_refract_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <4 x float> @llvm.spv.refract.v4f32(<4 x float> [[I]], <4 x float> [[N]]) +// SPVCHECK-NEXT: ret <4 x float> [[SPV_refract_I]] +// +float4 test_refract_float4(float4 I, float4 N, float eta) { + return refract(I, N, eta); +} diff --git a/clang/test/CodeGenSPIRV/Builtins/refract.c b/clang/test/CodeGenSPIRV/Builtins/refract.c new file mode 100644 index 0000000000000..06498554bd4d1 --- /dev/null +++ b/clang/test/CodeGenSPIRV/Builtins/refract.c @@ -0,0 +1,32 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 + +// RUN: %clang_cc1 -O1 -triple spirv-pc-vulkan-compute %s -emit-llvm -o - | FileCheck %s + +typedef float float2 __attribute__((ext_vector_type(2))); +typedef float float3 __attribute__((ext_vector_type(3))); +typedef float float4 __attribute__((ext_vector_type(4))); + +// CHECK-LABEL: define spir_func <2 x float> @test_refract_float2( +// CHECK-SAME: <2 x float> noundef [[X:%.*]], <2 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <2 x float> @llvm.spv.refract.v2f32(<2 x float> [[X]], <2 x float> [[Y]]) +// CHECK-NEXT: ret <2 x float> [[SPV_REFRACT]] +// +float2 test_refract_float2(float2 X, float2 Y, float eta) { return __builtin_spirv_refract(X, Y, eta); } + +// CHECK-LABEL: define spir_func <3 x float> @test_refract_float3( +// CHECK-SAME: <3 x float> noundef [[X:%.*]], <3 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <3 x float> @llvm.spv.refract.v3f32(<3 x float> [[X]], <3 x float> [[Y]]) +// CHECK-NEXT: ret <3 x float> [[SPV_REFRACT]] +// +float3 test_refract_float3(float3 X, float3 Y, float eta) { return __builtin_spirv_refract(X, Y, eta); } + +// CHECK-LABEL: define spir_func <4 x float> @test_refract_float4( +// CHECK-SAME: <4 x float> noundef [[X:%.*]], <4 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <4 x float> @llvm.spv.refract.v4f32(<4 x float> [[X]], <4 x float> [[Y]]) +// CHECK-NEXT: ret <4 x float> [[SPV_REFRACT]] +// +float4 test_refract_float4(float4 X, float4 Y, float eta) { return __builtin_spirv_refract(X, Y, eta); } + diff --git a/clang/test/SemaHLSL/BuiltIns/refract-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/refract-errors.hlsl new file mode 100644 index 0000000000000..eee913e6bb6e7 --- /dev/null +++ b/clang/test/SemaHLSL/BuiltIns/refract-errors.hlsl @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm-only -disable-llvm-passes -verify + +float test_no_second_arg(float3 p0) { + return refract(p0); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}} +} + +float test_no_third_arg(float3 p0) { + return refract(p0, p0); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}} +} + +float test_too_many_arg(float2 p0) { + return refract(p0, p0, p0, p0); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}} +} + +float test_double_inputs(double p0, double p1, double p2) { + return refract(p0, p1, p2); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} +} + +float test_int_inputs(int p0, int p1, int p2) { + return refract(p0, p1, p2); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored}} +} + +float1 test_vec1_inputs(float1 p0, float1 p1, float1 p2) { + return refract(p0, p1, p2); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 1>>'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with T = float1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, vector<float, 1>>'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, half>'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 1]: no type named 'Type' in 'hlsl::__detail::enable_if<false, float>'}} +} + +float3 test_mixed_datatype_inputs(float3 p0, float3 p1, half p2) { + return refract(p0, p1, p2); +} + +half3 test_mixed_datatype_inputs(half3 p0, half3 p1, float p2) { + return refract(p0, p1, p2); +} + +typedef float float5 __attribute__((ext_vector_type(5))); + +float5 test_vec5_inputs(float5 p0, float5 p1, float p2) { + return refract(p0, p1, p2); + // expected-error@-1 {{no matching function for call to 'refract'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: deduced conflicting types for parameter 'T' ('float5' (vector of 5 'float' values) vs. 'float')}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: deduced conflicting types for parameter 'T' ('float5' (vector of 5 'float' values) vs. 'float')}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, half>'}} + // expected-note@hlsl/hlsl_intrinsics.h:* {{candidate template ignored: substitution failure [with L = 5]: no type named 'Type' in 'hlsl::__detail::enable_if<false, float>'}} +} \ No newline at end of file diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/refract.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/refract.ll new file mode 100644 index 0000000000000..7dc6d24f651de --- /dev/null +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/refract.ll @@ -0,0 +1,33 @@ +; RUN: llc -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 %} + +; Make sure SPIRV operation function calls for refract are lowered correctly. + +; CHECK-DAG: %[[#op_ext_glsl:]] = OpExtInstImport "GLSL.std.450" +; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16 +; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4 +; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32 +; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4 + +define noundef <4 x half> @refract_half4(<4 x half> noundef %a, <4 x half> noundef %b, half %eta) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#vec4_float_16]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_16]] + ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]] refract %[[#arg0]] %[[#arg1]] + %spv.refract = call <4 x half> @llvm.spv.refract.f16(<4 x half> %a, <4 x half> %b) + ret <4 x half> %spv.refract +} + +define noundef <4 x float> @refract_float4(<4 x float> noundef %a, <4 x float> noundef %b, float %eta) { +entry: + ; CHECK: %[[#]] = OpFunction %[[#vec4_float_32]] None %[[#]] + ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]] + ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_32]] + ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]] refract %[[#arg0]] %[[#arg1]] + %spv.refract = call <4 x float> @llvm.spv.refract.f32(<4 x float> %a, <4 x float> %b) + ret <4 x float> %spv.refract +} + +declare <4 x half> @llvm.spv.refract.f16(<4 x half>, <4 x half>, half) +declare <4 x float> @llvm.spv.refract.f32(<4 x float>, <4 x float>, float) >From e9ba1cf031a0b87c66e8894050bb21f45d53f134 Mon Sep 17 00:00:00 2001 From: Anagha Rajendra Rao <anag...@microsoft.com> Date: Wed, 16 Apr 2025 13:48:06 -0700 Subject: [PATCH 2/4] Adding dxil tests --- clang/include/clang/Basic/BuiltinsSPIRV.td | 6 ++ clang/lib/CodeGen/TargetBuiltins/SPIR.cpp | 15 ++++ .../lib/Headers/hlsl/hlsl_intrinsic_helpers.h | 36 +++++++++ clang/lib/Headers/hlsl/hlsl_intrinsics.h | 77 +++++++++++++++++++ clang/lib/Sema/SemaSPIRV.cpp | 46 ++++++++++- clang/test/CodeGenHLSL/builtins/reflect.hlsl | 32 ++++++-- llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 + llvm/lib/IR/IRBuilder.cpp | 21 ++++- .../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 + 9 files changed, 227 insertions(+), 9 deletions(-) diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td b/clang/include/clang/Basic/BuiltinsSPIRV.td index 9f76d672cc7ce..c0f652b4f24e4 100644 --- a/clang/include/clang/Basic/BuiltinsSPIRV.td +++ b/clang/include/clang/Basic/BuiltinsSPIRV.td @@ -26,6 +26,12 @@ def SPIRVReflect : Builtin { let Prototype = "void(...)"; } +def SPIRVRefract : Builtin { + let Spellings = ["__builtin_spirv_refract"]; + let Attributes = [NoThrow, Const]; + let Prototype = "void(...)"; +} + def SPIRVSmoothStep : Builtin { let Spellings = ["__builtin_spirv_smoothstep"]; let Attributes = [NoThrow, Const, CustomTypeChecking]; diff --git a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp index 92e2c1c6da68f..5fedb9553699f 100644 --- a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp +++ b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp @@ -58,6 +58,21 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned BuiltinID, /*ReturnType=*/I->getType(), Intrinsic::spv_reflect, ArrayRef<Value *>{I, N}, nullptr, "spv.reflect"); } + case SPIRV::BI__builtin_spirv_refract: { + Value *I = EmitScalarExpr(E->getArg(0)); + Value *N = EmitScalarExpr(E->getArg(1)); + Value *eta = EmitScalarExpr(E->getArg(2)); + assert(E->getArg(0)->getType()->hasFloatingRepresentation() && + E->getArg(1)->getType()->hasFloatingRepresentation() && + E->getArg(2)->getType()->hasFloatingRepresentation() && + "refract operands must have a float representation"); + assert(E->getArg(0)->getType()->isVectorType() && + E->getArg(1)->getType()->isVectorType() && + "refract I and N operands must be a vector"); + return Builder.CreateIntrinsic( + /*ReturnType=*/I->getType(), Intrinsic::spv_refract, + ArrayRef<Value *>{I, N, eta}, nullptr, "spv.refract"); + } case SPIRV::BI__builtin_spirv_smoothstep: { Value *Min = EmitScalarExpr(E->getArg(0)); Value *Max = EmitScalarExpr(E->getArg(1)); diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h index 8cdd63d7e07bb..a1a8736f57a9e 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h @@ -58,6 +58,42 @@ constexpr vector<T, L> reflect_vec_impl(vector<T, L> I, vector<T, L> N) { #endif } +template <typename T> constexpr T refract_impl(T I, T N, T eta) { + T k = 1 - eta * eta * (1 - (N * I * N *I)); + if(k < 0) + return 0; + else + return (eta * I - (eta * N * I + sqrt(k)) * N); +} + +template <typename T, int L> +constexpr vector<T, L> refract_vec_impl(vector<T, L> I, vector<T, L> N, T eta) { +#if (__has_builtin(__builtin_spirv_refract)) + return __builtin_spirv_refract(I, N, eta); +#else + vector<T, L> k = 1 - eta * eta * (1 - dot(N, I) * dot(N, I)); + if(k < 0) + return 0; + else + return (eta * I - (eta * dot(N, I) + sqrt(k)) * N); +#endif +} + +/* +template <typename T, typename U> constexpr T refract_impl(T I, T N, U eta) { + return I - 2 * N * I * N; +} + +template <typename T, int L> +constexpr vector<T, L> refract_vec_impl(vector<T, L> I, vector<T, L> N) { +#if (__has_builtin(__builtin_spirv_refract)) + return __builtin_spirv_refract(I, N); +#else + return I - 2 * N * dot(I, N); +#endif +} +*/ + template <typename T> constexpr T fmod_impl(T X, T Y) { #if !defined(__DIRECTX__) return __builtin_elementwise_fmod(X, Y); diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index fd799b8d874ae..f632699a93824 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -323,6 +323,83 @@ reflect(__detail::HLSL_FIXED_VECTOR<float, L> I, return __detail::reflect_vec_impl(I, N); } +//===----------------------------------------------------------------------===// +// refract builtin +//===----------------------------------------------------------------------===// + +/// \fn T refract(T I, T N, T eta) +/// \brief Returns a refraction using an entering ray, \a I, a surface +/// normal, \a N and refraction index \a eta +/// \param I The entering ray. +/// \param N The surface normal. +/// \param eta The refraction index. +/// +/// The return value is a floating-point vector that represents the refraction +/// using the refraction index, \a eta, for the direction of the entering ray, \a I, +/// off a surface with the normal \a N. +/// +/// This function calculates the refraction vector using the following formulas: +/// k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I)) +/// if k < 0.0 the result is 0.0 +/// otherwise, the result is eta * I - (eta * dot(N, I) + sqrt(k)) * N +/// +/// I and N must already be normalized in order to achieve the desired result. +/// +/// I and N must be a scalar or vector whose component type is +/// floating-point. +/// +/// eta must be a 16-bit or 32-bit floating-point scalar. +/// +/// Result type, the type of I, and the type of N must all be the same type. + +template <typename T> +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value && + __detail::is_same<half, T>::value, + T> refract(T I, T N, T eta) { + return __detail::refract_impl(I, N, eta); +} + +/* +template <typename T, typename U> +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value && + __detail::is_same<half, T>::value, + T> refract(T I, T N, U eta) { + return __detail::refract_impl(I, N, eta); +} + +template <typename T, typename U> +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +const inline __detail::enable_if_t<__detail::is_arithmetic<U>::Value && + __detail::is_same<half, T>::value, + T> refract(T I, T N, U eta) { + return __detail::refract_impl(I, N, eta); +} +*/ + +template <typename T> +const inline __detail::enable_if_t< + __detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T> + refract(T I, T N, T eta) { + return __detail::refract_impl(I, N, eta); +} + +template <int L> +_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) +const inline __detail::HLSL_FIXED_VECTOR<half, L> refract( + __detail::HLSL_FIXED_VECTOR<half, L> I, + __detail::HLSL_FIXED_VECTOR<half, L> N, half eta) { + return __detail::refract_vec_impl(I, N, eta); +} + +template <int L> +const inline __detail::HLSL_FIXED_VECTOR<float, L> +refract(__detail::HLSL_FIXED_VECTOR<float, L> I, + __detail::HLSL_FIXED_VECTOR<float, L> N, float eta) { + return __detail::refract_vec_impl(I, N, eta); +} + //===----------------------------------------------------------------------===// // smoothstep builtin //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaSPIRV.cpp b/clang/lib/Sema/SemaSPIRV.cpp index 7131514d53421..fa6f28c87f7f4 100644 --- a/clang/lib/Sema/SemaSPIRV.cpp +++ b/clang/lib/Sema/SemaSPIRV.cpp @@ -69,6 +69,50 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID, TheCall->setType(RetTy); break; } + case SPIRV::BI__builtin_spirv_refract: { + if (SemaRef.checkArgCount(TheCall, 3)) + return true; + + ExprResult A = TheCall->getArg(0); + QualType ArgTyA = A.get()->getType(); + auto *VTyA = ArgTyA->getAs<VectorType>(); + if (VTyA == nullptr) { + SemaRef.Diag(A.get()->getBeginLoc(), + diag::err_typecheck_convert_incompatible) + << ArgTyA + << SemaRef.Context.getVectorType(ArgTyA, 2, VectorKind::Generic) << 1 + << 0 << 0; + return true; + } + + ExprResult B = TheCall->getArg(1); + QualType ArgTyB = B.get()->getType(); + auto *VTyB = ArgTyB->getAs<VectorType>(); + if (VTyB == nullptr) { + SemaRef.Diag(B.get()->getBeginLoc(), + diag::err_typecheck_convert_incompatible) + << ArgTyB + << SemaRef.Context.getVectorType(ArgTyB, 2, VectorKind::Generic) << 1 + << 0 << 0; + return true; + } + + ExprResult C = TheCall->getArg(2); + QualType ArgTyC = C.get()->getType(); + if (!ArgTyC->hasFloatingRepresentation()) { + SemaRef.Diag(C.get()->getBeginLoc(), + diag::err_builtin_invalid_arg_type) + << 3 << /* scalar or vector */ 5 << /* no int */ 0 << /* fp */ 1 + << ArgTyC; + return true; + } + + QualType RetTy = ArgTyA; + TheCall->setType(RetTy); + assert(RetTy == ArgTyA); + //assert(ArgTyB == ArgTyA); + break; + } case SPIRV::BI__builtin_spirv_reflect: { if (SemaRef.checkArgCount(TheCall, 2)) return true; @@ -89,7 +133,7 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID, QualType ArgTyB = B.get()->getType(); auto *VTyB = ArgTyB->getAs<VectorType>(); if (VTyB == nullptr) { - SemaRef.Diag(A.get()->getBeginLoc(), + SemaRef.Diag(B.get()->getBeginLoc(), diag::err_typecheck_convert_incompatible) << ArgTyB << SemaRef.Context.getVectorType(ArgTyB, 2, VectorKind::Generic) << 1 diff --git a/clang/test/CodeGenHLSL/builtins/reflect.hlsl b/clang/test/CodeGenHLSL/builtins/reflect.hlsl index 35ee059697c4b..34baf842a382c 100644 --- a/clang/test/CodeGenHLSL/builtins/reflect.hlsl +++ b/clang/test/CodeGenHLSL/builtins/reflect.hlsl @@ -6,14 +6,32 @@ // RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ // RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefix=SPVCHECK -// CHECK-LABEL: define noundef nofpclass(nan inf) half @_Z17test_reflect_halfDhDh( -// CHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-LABEL: define noundef nofpclass(nan inf) half @_Z17test_refract_halfDhDhDh( +// CHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[eta:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[I]], 0xH4000 -// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N]], [[N]] -// CHECK-NEXT: [[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0]], [[MUL_I]] -// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[I]], [[MUL2_I]] -// CHECK-NEXT: ret half [[SUB_I]] +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[eta]], [[eta]] +// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N:%.*]], %I +// CHECK_NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0:%.*]], [[TMP0:%.*]] +// CHECK_NEXT: [[SUB1_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[TMP1:%.*]] +// CHECK_NEXT: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half %mul.i, [[SUB1_I:%.*]] +// CHECK_NEXT: [[SUB5_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[MUL4_I:%.*]] +// CHECK_NEXT: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt half [[SUB5_I:%.*]], 0xH0000 +// CHECK_NEXT: br i1 [[CMP_I:%.*]], label %_ZN4hlsl8__detail12refract_implIDhEET_S2_S2_S2_.exit, label %if.else.i +// CHECK_NEXT: +// CHECK_NEXT: if.else.i: ; preds = %entry +// CHECK_NEXT: [[MUL6_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[eta]], %I +// CHECK_NEXT: [[MUL7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N:%.*]], %I +// CHECK_NEXT: [[MUL8_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[MUL7_I:%.*]], [[eta]] +// CHECK_NEXT: %2 = tail call reassoc nnan ninf nsz arcp afn half @llvm.sqrt.f16(half [[SUB5_I:%.*]]) +// CHECK_NEXT: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn half %2, [[MUL8_I:%.*]] +// CHECK_NEXT: [[MUL9_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[ADD_I:%.*]], [[N:%.*]] +// CHECK_NEXT: [[SUB10_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[MUL6_I:%.*]], [[MUL9_I:%.*]] +// CHECK_NEXT: br label %_ZN4hlsl8__detail12refract_implIDhEET_S2_S2_S2_.exit +// CHECK_NEXT: +// CHECK_NEXT: _ZN4hlsl8__detail12refract_implIDhEET_S2_S2_S2_.exit: ; preds = %entry, %if.else.i +// CHECK_NEXT: [[RETVAL_0_I:%.*]] = phi nsz half [ [[SUB10_I:%.*]], %if.else.i ], [ 0xH0000, %entry ] +// CHECK_NEXT: ret half [[RETVAL_0_I:%.*]] + // // SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) half @_Z17test_reflect_halfDhDh( // SPVCHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index 4389b86745d7f..17b41c16adcc1 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -72,6 +72,7 @@ let TargetPrefix = "spv" in { [IntrNoMem] >; def int_spv_length : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; def int_spv_normalize : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; + def int_spv_refract : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; def int_spv_reflect : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>; def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; def int_spv_saturate : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index 421b617a5fb7e..787236dfc4b70 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -919,8 +919,27 @@ CallInst *IRBuilderBase::CreateIntrinsic(Type *RetTy, Intrinsic::ID ID, SmallVector<Type *> ArgTys; ArgTys.reserve(Args.size()); - for (auto &I : Args) + int i =0; + Type * Ity; + Type * Nty; + Type * etaty; + + for (auto &I : Args) { + if(i ==0) + Ity = I->getType(); + if(i ==1) + Nty = I->getType(); + if(i ==2) + etaty = I->getType(); ArgTys.push_back(I->getType()); + i++; + } + //assert(Ity == RetTy); + //assert(Nty == RetTy); + assert(Nty == Ity); + + + FunctionType *FTy = FunctionType::get(RetTy, ArgTys, false); SmallVector<Type *> OverloadTys; Intrinsic::MatchIntrinsicTypesResult Res = diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp index 4f94d9c5ebb11..808e45c772baf 100644 --- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp +++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp @@ -3079,6 +3079,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register ResVReg, return selectExtInst(ResVReg, ResType, I, CL::fract, GL::Fract); case Intrinsic::spv_normalize: return selectExtInst(ResVReg, ResType, I, CL::normalize, GL::Normalize); + case Intrinsic::spv_refract: + return selectExtInst(ResVReg, ResType, I, GL::Refract); case Intrinsic::spv_reflect: return selectExtInst(ResVReg, ResType, I, GL::Reflect); case Intrinsic::spv_rsqrt: >From 73883f279e1f7729c39fd711fafacbf27dfe4cee Mon Sep 17 00:00:00 2001 From: Anagha Rajendra Rao <anag...@microsoft.com> Date: Tue, 22 Apr 2025 16:47:25 -0700 Subject: [PATCH 3/4] Update CodeGen checks --- clang/test/CodeGenHLSL/builtins/reflect.hlsl | 32 +- clang/test/CodeGenHLSL/builtins/refract.hlsl | 396 +++++++++++++++---- llvm/include/llvm/IR/IntrinsicsSPIRV.td | 2 +- 3 files changed, 338 insertions(+), 92 deletions(-) diff --git a/clang/test/CodeGenHLSL/builtins/reflect.hlsl b/clang/test/CodeGenHLSL/builtins/reflect.hlsl index 34baf842a382c..35ee059697c4b 100644 --- a/clang/test/CodeGenHLSL/builtins/reflect.hlsl +++ b/clang/test/CodeGenHLSL/builtins/reflect.hlsl @@ -6,32 +6,14 @@ // RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ // RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefix=SPVCHECK -// CHECK-LABEL: define noundef nofpclass(nan inf) half @_Z17test_refract_halfDhDhDh( -// CHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[eta:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-LABEL: define noundef nofpclass(nan inf) half @_Z17test_reflect_halfDhDh( +// CHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[eta]], [[eta]] -// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N:%.*]], %I -// CHECK_NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0:%.*]], [[TMP0:%.*]] -// CHECK_NEXT: [[SUB1_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[TMP1:%.*]] -// CHECK_NEXT: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half %mul.i, [[SUB1_I:%.*]] -// CHECK_NEXT: [[SUB5_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[MUL4_I:%.*]] -// CHECK_NEXT: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt half [[SUB5_I:%.*]], 0xH0000 -// CHECK_NEXT: br i1 [[CMP_I:%.*]], label %_ZN4hlsl8__detail12refract_implIDhEET_S2_S2_S2_.exit, label %if.else.i -// CHECK_NEXT: -// CHECK_NEXT: if.else.i: ; preds = %entry -// CHECK_NEXT: [[MUL6_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[eta]], %I -// CHECK_NEXT: [[MUL7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N:%.*]], %I -// CHECK_NEXT: [[MUL8_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[MUL7_I:%.*]], [[eta]] -// CHECK_NEXT: %2 = tail call reassoc nnan ninf nsz arcp afn half @llvm.sqrt.f16(half [[SUB5_I:%.*]]) -// CHECK_NEXT: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn half %2, [[MUL8_I:%.*]] -// CHECK_NEXT: [[MUL9_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[ADD_I:%.*]], [[N:%.*]] -// CHECK_NEXT: [[SUB10_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[MUL6_I:%.*]], [[MUL9_I:%.*]] -// CHECK_NEXT: br label %_ZN4hlsl8__detail12refract_implIDhEET_S2_S2_S2_.exit -// CHECK_NEXT: -// CHECK_NEXT: _ZN4hlsl8__detail12refract_implIDhEET_S2_S2_S2_.exit: ; preds = %entry, %if.else.i -// CHECK_NEXT: [[RETVAL_0_I:%.*]] = phi nsz half [ [[SUB10_I:%.*]], %if.else.i ], [ 0xH0000, %entry ] -// CHECK_NEXT: ret half [[RETVAL_0_I:%.*]] - +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[I]], 0xH4000 +// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N]], [[N]] +// CHECK-NEXT: [[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0]], [[MUL_I]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[I]], [[MUL2_I]] +// CHECK-NEXT: ret half [[SUB_I]] // // SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) half @_Z17test_reflect_halfDhDh( // SPVCHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { diff --git a/clang/test/CodeGenHLSL/builtins/refract.hlsl b/clang/test/CodeGenHLSL/builtins/refract.hlsl index 4dc5b66251b62..baeae1526545f 100644 --- a/clang/test/CodeGenHLSL/builtins/refract.hlsl +++ b/clang/test/CodeGenHLSL/builtins/refract.hlsl @@ -6,87 +6,351 @@ // RUN: spirv-unknown-vulkan-compute %s -fnative-half-type \ // RUN: -emit-llvm -O1 -o - | FileCheck %s --check-prefix=SPVCHECK -// CHECK-LABEL: define noundef nofpclass(nan inf) float @_Z18test_refract_floatff( -// CHECK-SAME: float noundef nofpclass(nan inf) [[I:%.*]], float noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-LABEL: define noundef nofpclass(nan inf) half @_Z17test_refract_halfDhDhDh( +// CHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[I]], 2.000000e+00 -// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[N]], [[N]] -// CHECK-NEXT: [[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP0]], [[MUL_I]] -// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[I]], [[MUL2_I]] -// CHECK-NEXT: ret float [[SUB_I]] -// -// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) float @_Z18test_refract_floatff( -// SPVCHECK-SAME: float noundef nofpclass(nan inf) [[I:%.*]], float noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[ETA]], [[ETA]] +// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N]], [[I]] +// CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0]], [[TMP0]] +// CHECK-NEXT: [[SUB1_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[TMP1]] +// CHECK-NEXT: [[MUL4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[MUL_I]], [[SUB1_I]] +// CHECK-NEXT: [[SUB5_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[MUL4_I]] +// CHECK-NEXT: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt half [[SUB5_I]], 0xH0000 +// CHECK-NEXT: br i1 [[CMP_I]], label %_ZN4hlsl8__detail12refract_implIDhEET_S2_S2_S2_.exit, label %if.else.i +// CHECK: if.else.i: ; preds = %entry +// CHECK-NEXT: [[MUL6_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[ETA]], [[I]] +// CHECK-NEXT: [[MUL7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N]], [[I]] +// CHECK-NEXT: [[MUL8_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[MUL7_I]], [[ETA]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call reassoc nnan ninf nsz arcp afn half @llvm.sqrt.f16(half [[SUB5_I]]) +// CHECK-NEXT: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn half [[TMP2]], [[MUL8_I]] +// CHECK-NEXT: [[MUL9_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[ADD_I]], [[N]] +// CHECK-NEXT: [[SUB10_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[MUL6_I]], [[MUL9_I]] +// CHECK-NEXT: br label %_ZN4hlsl8__detail12refract_implIDhEET_S2_S2_S2_.exit +// CHECK: _ZN4hlsl8__detail12refract_implIDhEET_S2_S2_S2_.exit: ; preds = %entry, %if.else.i +// CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi nsz half [ [[SUB10_I]], %if.else.i ], [ 0xH0000, %entry ] +// CHECK-NEXT: ret half [[RETVAL_0_I]] +// +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) half @_Z17test_refract_halfDhDhDh( +// SPVCHECK-SAME: half noundef nofpclass(nan inf) [[I:%.*]], half noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[ETA]], [[ETA]] +// SPVCHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N]], [[I]] +// SPVCHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[TMP0]], [[TMP0]] +// SPVCHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[TMP1]] +// SPVCHECK-NEXT: [[MUL_4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[MUL_I]], [[SUB_I]] +// SPVCHECK-NEXT: [[SUB5_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[MUL_4_I]] +// SPVCHECK-NEXT: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt half [[SUB5_I]], 0xH0000 +// SPVCHECK-NEXT: br i1 [[CMP_I]], label %_ZN4hlsl8__detail12refract_implIDhEET_S2_S2_S2_.exit, label %if.else.i +// SPVCHECK: if.else.i: ; preds = %entry +// SPVCHECK-NEXT: [[MUL_6_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[ETA]], [[I]] +// SPVCHECK-NEXT: [[MUL_7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[N]], [[I]] +// SPVCHECK-NEXT: [[MUL_8_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[MUL_7_I]], [[ETA]] +// SPVCHECK-NEXT: [[TMP2:%.*]] = tail call reassoc nnan ninf nsz arcp afn half @llvm.sqrt.f16(half [[SUB5_I]]) +// SPVCHECK-NEXT: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn half [[TMP2]], [[MUL_8_I]] +// SPVCHECK-NEXT: [[MUL_9_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[ADD_I]], [[N]] +// SPVCHECK-NEXT: [[SUB10_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half [[MUL_6_I]], [[MUL_9_I]] +// SPVCHECK-NEXT: br label %_ZN4hlsl8__detail12refract_implIDhEET_S2_S2_S2_.exit +// SPVCHECK: _ZN4hlsl8__detail12refract_implIDhEET_S2_S2_S2_.exit: ; preds = %entry, %if.else.i +// SPVCHECK-NEXT: [[RETVAL_0_I:%.*]] = phi nsz half [ [[SUB10_I]], %if.else.i ], [ 0xH0000, %entry ] +// SPVCHECK-NEXT: ret half [[RETVAL_0_I]] +// +half test_refract_half(half I, half N, half ETA) { + return refract(I, N, ETA); +} + +// CHECK-LABEL: define noundef nofpclass(nan inf) <2 x half> @_Z18test_refract_half2Dv2_DhS_S_ +// CHECK-SAME: <2 x half> noundef nofpclass(nan inf) [[I:%.*]], <2 x half> noundef nofpclass(nan inf) [[N:%.*]], <2 x half> noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <2 x half> [[ETA]], i64 0 +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[CAST_VTRUNC]], [[CAST_VTRUNC]] +// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v2f16(<2 x half> [[N]], <2 x half> [[I]]) +// CHECK-NEXT: [[MUL_2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[HLSL_DOT_I]], [[HLSL_DOT_I]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[MUL_2_I]] +// CHECK-NEXT: [[MUL_3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[MUL_I]], [[SUB_I]] +// CHECK-NEXT: [[SUB4_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[MUL_3_I]] +// CHECK-NEXT: [[CAST_VTRUNC_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt half [[SUB4_I]], 0xH0000 +// CHECK: br i1 [[CAST_VTRUNC_I]], label %_ZN4hlsl8__detail16refract_vec_implIDhLi2EEEDvT0__T_S3_S3_S2_.exit, label %if.else.i +// CHECK: if.else.i: ; preds = %entry +// CHECK-NEXT: [[SPLAT_SPLATINSERT_I:%.*]] = insertelement <2 x half> poison, half [[SUB4_I]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT_I:%.*]] = shufflevector <2 x half> [[SPLAT_SPLATINSERT_I]], <2 x half> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[SPLAT_SPLAT6_I:%.*]] = shufflevector <2 x half> [[ETA]], <2 x half> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[MUL_7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x half> [[SPLAT_SPLAT6_I]], [[I]] +// CHECK-NEXT: [[MUL_9_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[HLSL_DOT_I]], [[CAST_VTRUNC]] +// CHECK-NEXT: [[SPLAT_SPLATINSERT10_I:%.*]] = insertelement <2 x half> poison, half [[MUL_9_I]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT11_I:%.*]] = shufflevector <2 x half> [[SPLAT_SPLATINSERT10_I]], <2 x half> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn <2 x half> @llvm.sqrt.v2f16(<2 x half> [[SPLAT_SPLAT_I]]) +// CHECK-NEXT: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn <2 x half> [[TMP0]], [[SPLAT_SPLAT11_I]] +// CHECK-NEXT: [[MUL_12_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x half> [[ADD_I]], [[N]] +// CHECK-NEXT: [[SUB13_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x half> [[MUL_7_I]], [[MUL_12_I]] +// CHECK-NEXT: br label %_ZN4hlsl8__detail16refract_vec_implIDhLi2EEEDvT0__T_S3_S3_S2_.exit +// CHECK: _ZN4hlsl8__detail16refract_vec_implIDhLi2EEEDvT0__T_S3_S3_S2_.exit: ; preds = %entry, %if.else.i +// CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi nsz <2 x half> [ %sub13.i, %if.else.i ], [ zeroinitializer, %entry ] +// CHECK-NEXT: ret <2 x half> [[RETVAL_0_I]] + +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <2 x half> @_Z18test_refract_half2Dv2_DhS_S_( +// SPVCHECK-SAME: <2 x half> noundef nofpclass(nan inf) [[I:%.*]], <2 x half> noundef nofpclass(nan inf) [[N:%.*]], <2 x half> noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // SPVCHECK-NEXT: [[ENTRY:.*:]] -// SPVCHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[I]], 2.000000e+00 -// SPVCHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[N]], [[N]] -// SPVCHECK-NEXT: [[MUL2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP0]], [[MUL_I]] -// SPVCHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[I]], [[MUL2_I]] -// SPVCHECK-NEXT: ret float [[SUB_I]] -// -float test_refract_float(float I, float N, float eta) { - return refract(I, N, eta); +// SPVCHECK-NEXT: [[CAST_VTRUNC:%.*]] = extractelement <2 x half> [[ETA]], i64 0 +// SPVCHECK-NEXT: [[CONV_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[CAST_VTRUNC]] to double +// SPVCHECK-NEXT: [[SPV_REFRACT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <2 x half> @llvm.spv.refract.v2f16.f64(<2 x half> [[I]], <2 x half> [[N]], double [[CONV_I]]) +// SPVCHECK-NEXT: ret <2 x half> [[SPV_REFRACT_I]] +// +half2 test_refract_half2(half2 I, half2 N, half2 ETA) { + return refract(I, N, ETA); } -// CHECK-LABEL: define noundef nofpclass(nan inf) <2 x float> @_Z19test_refract_float2Dv2_fS_( -// CHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[I:%.*]], <2 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-LABEL: define noundef nofpclass(nan inf) <3 x half> @_Z18test_refract_half3Dv3_DhS_Dh( +// CHECK-SAME: <3 x half> noundef nofpclass(nan inf) [[I:%.*]], <3 x half> noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v2f32(<2 x float> [[I]], <2 x float> [[N]]) -// CHECK-NEXT: [[DOTSCALAR:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], 2.000000e+00 -// CHECK-NEXT: [[TMP0:%.*]] = insertelement <2 x float> poison, float [[DOTSCALAR]], i64 0 -// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <2 x float> [[TMP0]], <2 x float> poison, <2 x i32> zeroinitializer -// CHECK-NEXT: [[MUL1_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> [[TMP1]], [[N]] -// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x float> [[I]], [[MUL1_I]] -// CHECK-NEXT: ret <2 x float> [[SUB_I]] -// -// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <2 x float> @_Z19test_refract_float2Dv2_fS_( -// SPVCHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[I:%.*]], <2 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[ETA]], [[ETA]] +// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v3f16(<3 x half> [[N]], <3 x half> [[I]]) +// CHECK-NEXT: [[MUL_2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[HLSL_DOT_I]], [[HLSL_DOT_I]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[MUL_2_I]] +// CHECK-NEXT: [[MUL_3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[MUL_I]], [[SUB_I]] +// CHECK-NEXT: [[SUB4_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[MUL_3_I]] +// CHECK-NEXT: [[CAST_VTRUNC_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt half [[SUB4_I]], 0xH0000 +// CHECK: br i1 [[CAST_VTRUNC_I]], label %_ZN4hlsl8__detail16refract_vec_implIDhLi3EEEDvT0__T_S3_S3_S2_.exit, label %if.else.i +// CHECK: if.else.i: ; preds = %entry +// CHECK-NEXT: [[SPLAT_SPLATINSERT_I:%.*]] = insertelement <3 x half> poison, half [[SUB4_I]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT_I:%.*]] = shufflevector <3 x half> [[SPLAT_SPLATINSERT_I]], <3 x half> poison, <3 x i32> zeroinitializer +// CHECK-NEXT: [[SPLAT_SPLATINSERT5_I:%.*]] = insertelement <3 x half> poison, half [[ETA]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT6_I:%.*]] = shufflevector <3 x half> [[SPLAT_SPLATINSERT5_I]], <3 x half> poison, <3 x i32> zeroinitializer +// CHECK-NEXT: [[MUL_7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x half> [[SPLAT_SPLAT6_I]], [[I]] +// CHECK-NEXT: [[MUL_9_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[HLSL_DOT_I]], [[ETA]] +// CHECK-NEXT: [[SPLAT_SPLATINSERT10_I:%.*]] = insertelement <3 x half> poison, half [[MUL_9_I]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT11_I:%.*]] = shufflevector <3 x half> [[SPLAT_SPLATINSERT10_I]], <3 x half> poison, <3 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn <3 x half> @llvm.sqrt.v3f16(<3 x half> [[SPLAT_SPLAT_I]]) +// CHECK-NEXT: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn <3 x half> [[TMP0]], [[SPLAT_SPLAT11_I]] +// CHECK-NEXT: [[MUL_12_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x half> [[ADD_I]], [[N]] +// CHECK-NEXT: [[SUB13_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x half> [[MUL_7_I]], [[MUL_12_I]] +// CHECK: br label %_ZN4hlsl8__detail16refract_vec_implIDhLi3EEEDvT0__T_S3_S3_S2_.exit +// CHECK: _ZN4hlsl8__detail16refract_vec_implIDhLi3EEEDvT0__T_S3_S3_S2_.exit: ; preds = %entry, %if.else.i +// CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi nsz <3 x half> [ [[SUB13_I]], %if.else.i ], [ zeroinitializer, %entry ] +// CHECK-NEXT: ret <3 x half> [[RETVAL_0_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <3 x half> @_Z18test_refract_half3Dv3_DhS_Dh( +// SPVCHECK-SAME: <3 x half> noundef nofpclass(nan inf) [[I:%.*]], <3 x half> noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // SPVCHECK-NEXT: [[ENTRY:.*:]] -// SPVCHECK-NEXT: [[SPV_refract_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <2 x float> @llvm.spv.refract.v2f32(<2 x float> [[I]], <2 x float> [[N]]) -// SPVCHECK-NEXT: ret <2 x float> [[SPV_refract_I]] +// SPVCHECK-NEXT: [[CONV_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[ETA]] to double +// SPVCHECK-NEXT: [[SPV_REFRACT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <3 x half> @llvm.spv.refract.v3f16.f64(<3 x half> [[I]], <3 x half> [[N]], double [[CONV_I]]) +// SPVCHECK-NEXT: ret <3 x half> [[SPV_REFRACT_I]] // -float2 test_refract_float2(float2 I, float2 N, float eta) { - return refract(I, N, eta); +half3 test_refract_half3(half3 I, half3 N, half ETA) { + return refract(I, N, ETA); } -// CHECK-LABEL: define noundef nofpclass(nan inf) <3 x float> @_Z19test_refract_float3Dv3_fS_( -// CHECK-SAME: <3 x float> noundef nofpclass(nan inf) [[I:%.*]], <3 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-LABEL: define noundef nofpclass(nan inf) <4 x half> @_Z18test_refract_half4Dv4_DhS_Dh( +// CHECK-SAME: <4 x half> noundef nofpclass(nan inf) [[I:%.*]], <4 x half> noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v3f32(<3 x float> [[I]], <3 x float> [[N]]) -// CHECK-NEXT: [[DOTSCALAR:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], 2.000000e+00 -// CHECK-NEXT: [[TMP0:%.*]] = insertelement <3 x float> poison, float [[DOTSCALAR]], i64 0 -// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <3 x float> [[TMP0]], <3 x float> poison, <3 x i32> zeroinitializer -// CHECK-NEXT: [[MUL1_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x float> [[TMP1]], [[N]] -// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x float> [[I]], [[MUL1_I]] -// CHECK-NEXT: ret <3 x float> [[SUB_I]] -// -// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <3 x float> @_Z19test_refract_float3Dv3_fS_( -// SPVCHECK-SAME: <3 x float> noundef nofpclass(nan inf) [[I:%.*]], <3 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[ETA]], [[ETA]] +// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn half @llvm.dx.fdot.v4f16(<4 x half> [[N]], <4 x half> [[I]]) +// CHECK-NEXT: [[MUL_2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[HLSL_DOT_I]], [[HLSL_DOT_I]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[MUL_2_I]] +// CHECK-NEXT: [[MUL_3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[MUL_I]], [[SUB_I]] +// CHECK-NEXT: [[SUB4_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn half 0xH3C00, [[MUL_3_I]] +// CHECK-NEXT: [[CAST_VTRUNC_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt half [[SUB4_I]], 0xH0000 +// CHECK: br i1 [[CAST_VTRUNC_I]], label %_ZN4hlsl8__detail16refract_vec_implIDhLi4EEEDvT0__T_S3_S3_S2_.exit, label %if.else.i +// CHECK: if.else.i: ; preds = %entry +// CHECK-NEXT: [[SPLAT_SPLATINSERT_I:%.*]] = insertelement <4 x half> poison, half [[SUB4_I]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT_I:%.*]] = shufflevector <4 x half> [[SPLAT_SPLATINSERT_I]], <4 x half> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[SPLAT_SPLATINSERT5_I:%.*]] = insertelement <4 x half> poison, half [[ETA]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT6_I:%.*]] = shufflevector <4 x half> [[SPLAT_SPLATINSERT5_I]], <4 x half> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[MUL_7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x half> [[SPLAT_SPLAT6_I]], [[I]] +// CHECK-NEXT: [[MUL_9_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn half [[HLSL_DOT_I]], [[ETA]] +// CHECK-NEXT: [[SPLAT_SPLATINSERT10_I:%.*]] = insertelement <4 x half> poison, half [[MUL_9_I]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT11_I:%.*]] = shufflevector <4 x half> [[SPLAT_SPLATINSERT10_I]], <4 x half> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn <4 x half> @llvm.sqrt.v4f16(<4 x half> [[SPLAT_SPLAT_I]]) +// CHECK-NEXT: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn <4 x half> [[TMP0]], [[SPLAT_SPLAT11_I]] +// CHECK-NEXT: [[MUL_12_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x half> [[ADD_I]], [[N]] +// CHECK-NEXT: [[SUB13_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x half> [[MUL_7_I]], [[MUL_12_I]] +// CHECK: br label %_ZN4hlsl8__detail16refract_vec_implIDhLi4EEEDvT0__T_S3_S3_S2_.exit +// CHECK: _ZN4hlsl8__detail16refract_vec_implIDhLi4EEEDvT0__T_S3_S3_S2_.exit: ; preds = %entry, %if.else.i +// CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi nsz <4 x half> [ [[SUB13_I]], %if.else.i ], [ zeroinitializer, %entry ] +// CHECK-NEXT: ret <4 x half> [[RETVAL_0_I]] + +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <4 x half> @_Z18test_refract_half4Dv4_DhS_Dh( +// SPVCHECK-SAME: <4 x half> noundef nofpclass(nan inf) [[I:%.*]], <4 x half> noundef nofpclass(nan inf) [[N:%.*]], half noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // SPVCHECK-NEXT: [[ENTRY:.*:]] -// SPVCHECK-NEXT: [[SPV_refract_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <3 x float> @llvm.spv.refract.v3f32(<3 x float> [[I]], <3 x float> [[N]]) -// SPVCHECK-NEXT: ret <3 x float> [[SPV_refract_I]] +// SPVCHECK-NEXT: [[CONV_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn half [[ETA]] to double +// SPVCHECK-NEXT: [[SPV_REFRACT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <4 x half> @llvm.spv.refract.v4f16.f64(<4 x half> [[I]], <4 x half> [[N]], double [[CONV_I]]) +// SPVCHECK-NEXT: ret <4 x half> [[SPV_REFRACT_I]] // -float3 test_refract_float3(float3 I, float3 N, float eta) { - return refract(I, N, eta); +half4 test_refract_half4(half4 I, half4 N, half ETA) { + return refract(I, N, ETA); } -// CHECK-LABEL: define noundef nofpclass(nan inf) <4 x float> @_Z19test_refract_float4Dv4_fS_( -// CHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[I:%.*]], <4 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-LABEL: define noundef nofpclass(nan inf) float @_Z18test_refract_floatfff( +// CHECK-SAME: float noundef nofpclass(nan inf) [[I:%.*]], float noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v4f32(<4 x float> [[I]], <4 x float> [[N]]) -// CHECK-NEXT: [[DOTSCALAR:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], 2.000000e+00 -// CHECK-NEXT: [[TMP0:%.*]] = insertelement <4 x float> poison, float [[DOTSCALAR]], i64 0 -// CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x float> [[TMP0]], <4 x float> poison, <4 x i32> zeroinitializer -// CHECK-NEXT: [[MUL1_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x float> [[TMP1]], [[N]] -// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x float> [[I]], [[MUL1_I]] -// CHECK-NEXT: ret <4 x float> [[SUB_I]] -// -// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <4 x float> @_Z19test_refract_float4Dv4_fS_( -// SPVCHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[I:%.*]], <4 x float> noundef nofpclass(nan inf) [[N:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[ETA]], [[ETA]] +// CHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[N]], [[I]] +// CHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP0]], [[TMP0]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 1.000000e+00, [[TMP1]] +// CHECK-NEXT: [[MUL_4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[MUL_I]], [[SUB_I]] +// CHECK-NEXT: [[SUB5_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 1.000000e+00, [[MUL_4_I]] +// CHECK-NEXT: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt float [[SUB5_I]], 0.000000e+00 +// CHECK: br i1 [[CMP_I]], label %_ZN4hlsl8__detail12refract_implIfEET_S2_S2_S2_.exit, label %if.else.i +// CHECK: if.else.i: ; preds = %entry +// CHECK-NEXT: [[MUL_6_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[ETA]], [[I]] +// CHECK-NEXT: [[MUL_7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[N]], [[I]] +// CHECK-NEXT: [[MUL_8_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[MUL_7_I]], [[ETA]] +// CHECK-NEXT: [[TMP2:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.sqrt.f32(float [[SUB5_I]]) +// CHECK-NEXT: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP2]], [[MUL_8_I]] +// CHECK-NEXT: [[MUL_9_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[ADD_I]], [[N]] +// CHECK-NEXT: [[SUB10_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MUL_6_I]], [[MUL_9_I]] +// CHECK: br label %_ZN4hlsl8__detail12refract_implIfEET_S2_S2_S2_.exit +// CHECK: _ZN4hlsl8__detail12refract_implIfEET_S2_S2_S2_.exit: ; preds = %entry, %if.else.i +// CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi nsz float [ [[SUB10_I]], %if.else.i ], [ 0.000000e+00, %entry ] +// CHECK-NEXT: ret float [[RETVAL_0_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) float @_Z18test_refract_floatfff( +// SPVCHECK-SAME: float noundef nofpclass(nan inf) [[I:%.*]], float noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // SPVCHECK-NEXT: [[ENTRY:.*:]] -// SPVCHECK-NEXT: [[SPV_refract_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <4 x float> @llvm.spv.refract.v4f32(<4 x float> [[I]], <4 x float> [[N]]) -// SPVCHECK-NEXT: ret <4 x float> [[SPV_refract_I]] +// SPVCHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[ETA]], [[ETA]] +// SPVCHECK-NEXT: [[TMP0:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[N]], [[I]] +// SPVCHECK-NEXT: [[TMP1:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[TMP0]], [[TMP0]] +// SPVCHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 1.000000e+00, [[TMP1]] +// SPVCHECK-NEXT: [[MUL_4_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[MUL_I]], [[SUB_I]] +// SPVCHECK-NEXT: [[SUB5_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 1.000000e+00, [[MUL_4_I]] +// SPVCHECK-NEXT: [[CMP_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt float [[SUB5_I]], 0.000000e+00 +// SPVCHECK-NEXT: br i1 [[CMP_I]], label %_ZN4hlsl8__detail12refract_implIfEET_S2_S2_S2_.exit, label %if.else.i + +// SPVCHECK: if.else.i: ; preds = %entry +// SPVCHECK-NEXT: [[MUL_6_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[ETA]], [[I]] +// SPVCHECK-NEXT: [[MUL_7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[N]], [[I]] +// SPVCHECK-NEXT: [[MUL_8_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[MUL_7_I]], [[ETA]] +// SPVCHECK-NEXT: [[TMP2:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.sqrt.f32(float [[SUB5_I]]) +// SPVCHECK-NEXT: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn float [[TMP2]], [[MUL_8_I]] +// SPVCHECK-NEXT: [[MUL_9_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[ADD_I]], [[N]] +// SPVCHECK-NEXT: [[SUB10_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float [[MUL_6_I]], [[MUL_9_I]] +// SPVCHECK-NEXT: br label %_ZN4hlsl8__detail12refract_implIfEET_S2_S2_S2_.exit +// SPVCHECK: _ZN4hlsl8__detail12refract_implIfEET_S2_S2_S2_.exit: ; preds = %entry, %if.else.i +// SPVCHECK-NEXT: [[RETVAL_0_I:%.*]] = phi nsz float [ [[SUB10_I]], %if.else.i ], [ 0.000000e+00, %entry ] +// SPVCHECK-NEXT: ret float [[RETVAL_0_I]] // -float4 test_refract_float4(float4 I, float4 N, float eta) { - return refract(I, N, eta); +float test_refract_float(float I, float N, float ETA) { + return refract(I, N, ETA); } + +// CHECK-LABEL: define noundef nofpclass(nan inf) <2 x float> @_Z19test_refract_float2Dv2_fS_f( +// CHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[I:%.*]], <2 x float> noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[ETA]], [[ETA]] +// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v2f32(<2 x float> [[N]], <2 x float> [[I]]) +// CHECK-NEXT: [[MUL_2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], [[HLSL_DOT_I]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 1.000000e+00, [[MUL_2_I]] +// CHECK-NEXT: [[MUL_3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[MUL_I]], [[SUB_I]] +// CHECK-NEXT: [[SUB4_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 1.000000e+00, [[MUL_3_I]] +// CHECK-NEXT: [[CAST_VTRUNC_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt float [[SUB4_I]], 0.000000e+00 +// CHECK-NEXT: br i1 [[CAST_VTRUNC_I]], label %_ZN4hlsl8__detail16refract_vec_implIfLi2EEEDvT0__T_S3_S3_S2_.exit, label %if.else.i +// CHECK: if.else.i: ; preds = %entry +// CHECK-NEXT: [[SPLAT_SPLATINSERT_I:%.*]] = insertelement <2 x float> poison, float [[SUB4_I]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT_I:%.*]] = shufflevector <2 x float> [[SPLAT_SPLATINSERT_I]], <2 x float> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[SPLAT_SPLATINSERT5_I:%.*]] = insertelement <2 x float> poison, float [[ETA]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT6_I:%.*]] = shufflevector <2 x float> [[SPLAT_SPLATINSERT5_I]], <2 x float> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[MUL_7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> [[SPLAT_SPLAT6_I]], [[I]] +// CHECK-NEXT: [[MUL_9_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], [[ETA]] +// CHECK-NEXT: [[SPLAT_SPLATINSERT10_I:%.*]] = insertelement <2 x float> poison, float [[MUL_9_I]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT11_I:%.*]] = shufflevector <2 x float> [[SPLAT_SPLATINSERT10_I]], <2 x float> poison, <2 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn <2 x float> @llvm.sqrt.v2f32(<2 x float> [[SPLAT_SPLAT_I]]) +// CHECK-NEXT: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn <2 x float> [[TMP0]], [[SPLAT_SPLAT11_I]] +// CHECK-NEXT: [[MUL_12_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <2 x float> [[ADD_I]], [[N]] +// CHECK-NEXT: [[SUB13_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <2 x float> [[MUL_7_I]], [[MUL_12_I]] +// CHECK-NEXT: br label %_ZN4hlsl8__detail16refract_vec_implIfLi2EEEDvT0__T_S3_S3_S2_.exit +// CHECK: _ZN4hlsl8__detail16refract_vec_implIfLi2EEEDvT0__T_S3_S3_S2_.exit: ; preds = %entry, %if.else.i +// CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi nsz <2 x float> [ [[SUB13_I]], %if.else.i ], [ zeroinitializer, %entry ] +// CHECK-NEXT: ret <2 x float> [[RETVAL_0_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <2 x float> @_Z19test_refract_float2Dv2_fS_f( +// SPVCHECK-SAME: <2 x float> noundef nofpclass(nan inf) [[I:%.*]], <2 x float> noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[CONV_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[ETA]] to double +// SPVCHECK-NEXT: [[SPV_REFRACT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <2 x float> @llvm.spv.refract.v2f32.f64(<2 x float> [[I]], <2 x float> [[N]], double [[CONV_I]]) +// SPVCHECK-NEXT: ret <2 x float> [[SPV_REFRACT_I]] +// +float2 test_refract_float2(float2 I, float2 N, float ETA) { + return refract(I, N, ETA); +} + +// CHECK-LABEL: define noundef nofpclass(nan inf) <3 x float> @_Z19test_refract_float3Dv3_fS_f( +// CHECK-SAME: <3 x float> noundef nofpclass(nan inf) [[I:%.*]], <3 x float> noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[ETA]], [[ETA]] +// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v3f32(<3 x float> [[N]], <3 x float> [[I]]) +// CHECK-NEXT: [[MUL_2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], [[HLSL_DOT_I]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 1.000000e+00, [[MUL_2_I]] +// CHECK-NEXT: [[MUL_3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[MUL_I]], [[SUB_I]] +// CHECK-NEXT: [[SUB4_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 1.000000e+00, [[MUL_3_I]] +// CHECK-NEXT: [[CAST_VTRUNC_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt float [[SUB4_I]], 0.000000e+00 +// CHECK-NEXT: br i1 [[CAST_VTRUNC_I]], label %_ZN4hlsl8__detail16refract_vec_implIfLi3EEEDvT0__T_S3_S3_S2_.exit, label %if.else.i +// CHECK: if.else.i: ; preds = %entry +// CHECK-NEXT: [[SPLAT_SPLATINSERT_I:%.*]] = insertelement <3 x float> poison, float [[SUB4_I]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT_I:%.*]] = shufflevector <3 x float> [[SPLAT_SPLATINSERT_I]], <3 x float> poison, <3 x i32> zeroinitializer +// CHECK-NEXT: [[SPLAT_SPLATINSERT5_I:%.*]] = insertelement <3 x float> poison, float [[ETA]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT6_I:%.*]] = shufflevector <3 x float> [[SPLAT_SPLATINSERT5_I]], <3 x float> poison, <3 x i32> zeroinitializer +// CHECK-NEXT: [[MUL_7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x float> [[SPLAT_SPLAT6_I]], [[I]] +// CHECK-NEXT: [[MUL_9_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], [[ETA]] +// CHECK-NEXT: [[SPLAT_SPLATINSERT10_I:%.*]] = insertelement <3 x float> poison, float [[MUL_9_I]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT11_I:%.*]] = shufflevector <3 x float> [[SPLAT_SPLATINSERT10_I]], <3 x float> poison, <3 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn <3 x float> @llvm.sqrt.v3f32(<3 x float> [[SPLAT_SPLAT_I]]) +// CHECK-NEXT: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn <3 x float> [[TMP0]], [[SPLAT_SPLAT11_I]] +// CHECK-NEXT: [[MUL_12_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <3 x float> [[ADD_I]], [[N]] +// CHECK-NEXT: [[SUB13_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <3 x float> [[MUL_7_I]], [[MUL_12_I]] +// CHECK-NEXT: br label %_ZN4hlsl8__detail16refract_vec_implIfLi3EEEDvT0__T_S3_S3_S2_.exit +// CHECK: _ZN4hlsl8__detail16refract_vec_implIfLi3EEEDvT0__T_S3_S3_S2_.exit: ; preds = %entry, %if.else.i +// CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi nsz <3 x float> [ [[SUB13_I]], %if.else.i ], [ zeroinitializer, %entry ] +// CHECK-NEXT: ret <3 x float> [[RETVAL_0_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <3 x float> @_Z19test_refract_float3Dv3_fS_f( +// SPVCHECK-SAME: <3 x float> noundef nofpclass(nan inf) [[I:%.*]], <3 x float> noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[CONV_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[ETA]] to double +// SPVCHECK-NEXT: [[SPV_REFRACT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <3 x float> @llvm.spv.refract.v3f32.f64(<3 x float> [[I]], <3 x float> [[N]], double [[CONV_I]]) +// SPVCHECK-NEXT: ret <3 x float> [[SPV_REFRACT_I]] +// +float3 test_refract_float3(float3 I, float3 N, float ETA) { + return refract(I, N, ETA); +} + +// CHECK-LABEL: define noundef nofpclass(nan inf) <4 x float> @_Z19test_refract_float4Dv4_fS_f +// CHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[I:%.*]], <4 x float> noundef nofpclass(nan inf) [[N:%.*]], float noundef nofpclass(nan inf) [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-NEXT: [[ENTRY:.*:]] +// CHECK-NEXT: [[MUL_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[ETA]], [[ETA]] +// CHECK-NEXT: [[HLSL_DOT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn float @llvm.dx.fdot.v4f32(<4 x float> [[N]], <4 x float> [[I]]) +// CHECK-NEXT: [[MUL_2_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], [[HLSL_DOT_I]] +// CHECK-NEXT: [[SUB_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 1.000000e+00, [[MUL_2_I]] +// CHECK-NEXT: [[MUL_3_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[MUL_I]], [[SUB_I]] +// CHECK-NEXT: [[SUB4_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn float 1.000000e+00, [[MUL_3_I]] +// CHECK-NEXT: [[CAST_VTRUNC_I:%.*]] = fcmp reassoc nnan ninf nsz arcp afn olt float [[SUB4_I]], 0.000000e+00 +// CHECK-NEXT: br i1 [[CAST_VTRUNC_I]], label %_ZN4hlsl8__detail16refract_vec_implIfLi4EEEDvT0__T_S3_S3_S2_.exit, label %if.else.i +// CHECK: if.else.i: ; preds = %entry +// CHECK-NEXT: [[SPLAT_SPLATINSERT_I:%.*]] = insertelement <4 x float> poison, float [[SUB4_I]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT_I:%.*]] = shufflevector <4 x float> [[SPLAT_SPLATINSERT_I]], <4 x float> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[SPLAT_SPLATINSERT5_I:%.*]] = insertelement <4 x float> poison, float [[ETA]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT6_I:%.*]] = shufflevector <4 x float> [[SPLAT_SPLATINSERT5_I]], <4 x float> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[MUL_7_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x float> [[SPLAT_SPLAT6_I]], [[I]] +// CHECK-NEXT: [[MUL_9_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn float [[HLSL_DOT_I]], [[ETA]] +// CHECK-NEXT: [[SPLAT_SPLATINSERT10_I:%.*]] = insertelement <4 x float> poison, float [[MUL_9_I]], i64 0 +// CHECK-NEXT: [[SPLAT_SPLAT11_I:%.*]] = shufflevector <4 x float> [[SPLAT_SPLATINSERT10_I]], <4 x float> poison, <4 x i32> zeroinitializer +// CHECK-NEXT: [[TMP0:%.*]] = tail call reassoc nnan ninf nsz arcp afn <4 x float> @llvm.sqrt.v4f32(<4 x float> [[SPLAT_SPLAT_I]]) +// CHECK-NEXT: [[ADD_I:%.*]] = fadd reassoc nnan ninf nsz arcp afn <4 x float> [[TMP0]], [[SPLAT_SPLAT11_I]] +// CHECK-NEXT: [[MUL_12_I:%.*]] = fmul reassoc nnan ninf nsz arcp afn <4 x float> [[ADD_I]], [[N]] +// CHECK-NEXT: [[SUB13_I:%.*]] = fsub reassoc nnan ninf nsz arcp afn <4 x float> [[MUL_7_I]], [[MUL_12_I]] +// CHECK-NEXT: br label %_ZN4hlsl8__detail16refract_vec_implIfLi4EEEDvT0__T_S3_S3_S2_.exit +// CHECK: _ZN4hlsl8__detail16refract_vec_implIfLi4EEEDvT0__T_S3_S3_S2_.exit: ; preds = %entry, %if.else.i +// CHECK-NEXT: [[RETVAL_0_I:%.*]] = phi nsz <4 x float> [ [[SUB13_I]], %if.else.i ], [ zeroinitializer, %entry ] +// CHECK-NEXT: ret <4 x float> [[RETVAL_0_I]] +// +// SPVCHECK-LABEL: define spir_func noundef nofpclass(nan inf) <4 x float> @_Z19test_refract_float4Dv4_fS_f( +// SPVCHECK-SAME: <4 x float> noundef nofpclass(nan inf) [[I]], <4 x float> noundef nofpclass(nan inf) [[N]], float noundef nofpclass(nan inf) [[ETA]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// SPVCHECK-NEXT: [[ENTRY:.*:]] +// SPVCHECK-NEXT: [[CONV_I:%.*]] = fpext reassoc nnan ninf nsz arcp afn float [[ETA]] to double +// SPVCHECK-NEXT: [[SPV_REFRACT_I:%.*]] = tail call reassoc nnan ninf nsz arcp afn noundef <4 x float> @llvm.spv.refract.v4f32.f64(<4 x float> [[I]], <4 x float> [[N]], double [[CONV_I]]) +// SPVCHECK-NEXT: ret <4 x float> [[SPV_REFRACT_I]] +// +float4 test_refract_float4(float4 I, float4 N, float ETA) { + return refract(I, N, ETA); +} \ No newline at end of file diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td b/llvm/include/llvm/IR/IntrinsicsSPIRV.td index 17b41c16adcc1..79569388f915d 100644 --- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td +++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td @@ -72,7 +72,7 @@ let TargetPrefix = "spv" in { [IntrNoMem] >; def int_spv_length : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; def int_spv_normalize : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; - def int_spv_refract : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>; + def int_spv_refract : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>, llvm_anyfloat_ty], [IntrNoMem]>; def int_spv_reflect : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>; def int_spv_rsqrt : DefaultAttrsIntrinsic<[LLVMMatchType<0>], [llvm_anyfloat_ty], [IntrNoMem]>; def int_spv_saturate : DefaultAttrsIntrinsic<[llvm_anyfloat_ty], [LLVMMatchType<0>], [IntrNoMem]>; >From 49455010d82f29a70ea76ac54b3a519caac55a38 Mon Sep 17 00:00:00 2001 From: Anagha Rajendra Rao <anag...@microsoft.com> Date: Mon, 28 Apr 2025 16:39:20 -0700 Subject: [PATCH 4/4] fix tests --- .../lib/Headers/hlsl/hlsl_intrinsic_helpers.h | 15 ---------- clang/lib/Headers/hlsl/hlsl_intrinsics.h | 18 ------------ clang/lib/Sema/SemaSPIRV.cpp | 1 - clang/test/CodeGenSPIRV/Builtins/refract.c | 21 ++++++++------ .../test/SemaSPIRV/BuiltIns/refract-errors.c | 28 +++++++++++++++++++ llvm/lib/IR/IRBuilder.cpp | 21 +------------- .../CodeGen/SPIRV/hlsl-intrinsics/refract.ll | 28 +++++++++++-------- 7 files changed, 57 insertions(+), 75 deletions(-) create mode 100644 clang/test/SemaSPIRV/BuiltIns/refract-errors.c diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h index a1a8736f57a9e..2395a36e07642 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h @@ -79,21 +79,6 @@ constexpr vector<T, L> refract_vec_impl(vector<T, L> I, vector<T, L> N, T eta) { #endif } -/* -template <typename T, typename U> constexpr T refract_impl(T I, T N, U eta) { - return I - 2 * N * I * N; -} - -template <typename T, int L> -constexpr vector<T, L> refract_vec_impl(vector<T, L> I, vector<T, L> N) { -#if (__has_builtin(__builtin_spirv_refract)) - return __builtin_spirv_refract(I, N); -#else - return I - 2 * N * dot(I, N); -#endif -} -*/ - template <typename T> constexpr T fmod_impl(T X, T Y) { #if !defined(__DIRECTX__) return __builtin_elementwise_fmod(X, Y); diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index f632699a93824..d76f26a529538 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -360,24 +360,6 @@ const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value && return __detail::refract_impl(I, N, eta); } -/* -template <typename T, typename U> -_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) -const inline __detail::enable_if_t<__detail::is_arithmetic<T>::Value && - __detail::is_same<half, T>::value, - T> refract(T I, T N, U eta) { - return __detail::refract_impl(I, N, eta); -} - -template <typename T, typename U> -_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) -const inline __detail::enable_if_t<__detail::is_arithmetic<U>::Value && - __detail::is_same<half, T>::value, - T> refract(T I, T N, U eta) { - return __detail::refract_impl(I, N, eta); -} -*/ - template <typename T> const inline __detail::enable_if_t< __detail::is_arithmetic<T>::Value && __detail::is_same<float, T>::value, T> diff --git a/clang/lib/Sema/SemaSPIRV.cpp b/clang/lib/Sema/SemaSPIRV.cpp index fa6f28c87f7f4..2ad2089323cc3 100644 --- a/clang/lib/Sema/SemaSPIRV.cpp +++ b/clang/lib/Sema/SemaSPIRV.cpp @@ -110,7 +110,6 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned BuiltinID, QualType RetTy = ArgTyA; TheCall->setType(RetTy); assert(RetTy == ArgTyA); - //assert(ArgTyB == ArgTyA); break; } case SPIRV::BI__builtin_spirv_reflect: { diff --git a/clang/test/CodeGenSPIRV/Builtins/refract.c b/clang/test/CodeGenSPIRV/Builtins/refract.c index 06498554bd4d1..5a3beb23a4ed2 100644 --- a/clang/test/CodeGenSPIRV/Builtins/refract.c +++ b/clang/test/CodeGenSPIRV/Builtins/refract.c @@ -7,26 +7,29 @@ typedef float float3 __attribute__((ext_vector_type(3))); typedef float float4 __attribute__((ext_vector_type(4))); // CHECK-LABEL: define spir_func <2 x float> @test_refract_float2( -// CHECK-SAME: <2 x float> noundef [[X:%.*]], <2 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { +// CHECK-SAME: <2 x float> noundef [[I:%.*]], <2 x float> noundef [[N:%.*]], float noundef [[ETA:%.*]]) local_unnamed_addr #[[ATTR0:[0-9]+]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <2 x float> @llvm.spv.refract.v2f32(<2 x float> [[X]], <2 x float> [[Y]]) +// CHECK-NEXT: [[CONV:%.*]] = fpext float [[ETA]] to double +// CHECK: [[SPV_REFRACT:%.*]] = tail call <2 x float> @llvm.spv.refract.v2f32.f64(<2 x float> [[I]], <2 x float> [[N]], double [[CONV]]) // CHECK-NEXT: ret <2 x float> [[SPV_REFRACT]] // -float2 test_refract_float2(float2 X, float2 Y, float eta) { return __builtin_spirv_refract(X, Y, eta); } +float2 test_refract_float2(float2 I, float2 N, float eta) { return __builtin_spirv_refract(I, N, eta); } // CHECK-LABEL: define spir_func <3 x float> @test_refract_float3( -// CHECK-SAME: <3 x float> noundef [[X:%.*]], <3 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-SAME: <3 x float> noundef [[I:%.*]], <3 x float> noundef [[N:%.*]], float noundef [[ETA:%.*]]) local_unnamed_addr #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <3 x float> @llvm.spv.refract.v3f32(<3 x float> [[X]], <3 x float> [[Y]]) +// CHECK-NEXT: [[CONV:%.*]] = fpext float [[ETA]] to double +// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <3 x float> @llvm.spv.refract.v3f32.f64(<3 x float> [[I]], <3 x float> [[N]], double [[CONV]]) // CHECK-NEXT: ret <3 x float> [[SPV_REFRACT]] // -float3 test_refract_float3(float3 X, float3 Y, float eta) { return __builtin_spirv_refract(X, Y, eta); } +float3 test_refract_float3(float3 I, float3 N, float eta) { return __builtin_spirv_refract(I, N, eta); } // CHECK-LABEL: define spir_func <4 x float> @test_refract_float4( -// CHECK-SAME: <4 x float> noundef [[X:%.*]], <4 x float> noundef [[Y:%.*]]) local_unnamed_addr #[[ATTR0]] { +// CHECK-SAME: <4 x float> noundef [[I:%.*]], <4 x float> noundef [[N:%.*]], float noundef [[ETA:%.*]]) local_unnamed_addr #[[ATTR0]] { // CHECK-NEXT: [[ENTRY:.*:]] -// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <4 x float> @llvm.spv.refract.v4f32(<4 x float> [[X]], <4 x float> [[Y]]) +// CHECK-NEXT: [[CONV:%.*]] = fpext float [[ETA]] to double +// CHECK-NEXT: [[SPV_REFRACT:%.*]] = tail call <4 x float> @llvm.spv.refract.v4f32.f64(<4 x float> [[I]], <4 x float> [[N]], double [[CONV]]) // CHECK-NEXT: ret <4 x float> [[SPV_REFRACT]] // -float4 test_refract_float4(float4 X, float4 Y, float eta) { return __builtin_spirv_refract(X, Y, eta); } +float4 test_refract_float4(float4 I, float4 N, float eta) { return __builtin_spirv_refract(I, N, eta); } diff --git a/clang/test/SemaSPIRV/BuiltIns/refract-errors.c b/clang/test/SemaSPIRV/BuiltIns/refract-errors.c new file mode 100644 index 0000000000000..1baea9dca303e --- /dev/null +++ b/clang/test/SemaSPIRV/BuiltIns/refract-errors.c @@ -0,0 +1,28 @@ +// RUN: %clang_cc1 %s -triple spirv-pc-vulkan-compute -verify + +typedef float float2 __attribute__((ext_vector_type(2))); + +float2 test_no_second_arg(float2 p0) { + return __builtin_spirv_refract(p0); + // expected-error@-1 {{too few arguments to function call, expected 3, have 1}} +} + +float2 test_too_few_arg(float2 p0) { + return __builtin_spirv_refract(p0, p0); + // expected-error@-1 {{too few arguments to function call, expected 3, have 2}} +} + +float2 test_too_many_arg(float2 p0, float p1) { + return __builtin_spirv_refract(p0, p0, p1, p1); + // expected-error@-1 {{too many arguments to function call, expected 3, have 4}} +} + +float test_double_scalar_inputs(double p0, double p1, double p2) { + return __builtin_spirv_refract(p0, p1, p2); + // expected-error@-1 {{passing 'double' to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(double)))) double' (vector of 2 'double' values)}} +} + +float test_int_scalar_inputs(int p0, int p1, int p2) { + return __builtin_spirv_refract(p0, p1, p2); + // expected-error@-1 {{passing 'int' to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(int)))) int' (vector of 2 'int' values)}} +} diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp index 787236dfc4b70..421b617a5fb7e 100644 --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -919,27 +919,8 @@ CallInst *IRBuilderBase::CreateIntrinsic(Type *RetTy, Intrinsic::ID ID, SmallVector<Type *> ArgTys; ArgTys.reserve(Args.size()); - int i =0; - Type * Ity; - Type * Nty; - Type * etaty; - - for (auto &I : Args) { - if(i ==0) - Ity = I->getType(); - if(i ==1) - Nty = I->getType(); - if(i ==2) - etaty = I->getType(); + for (auto &I : Args) ArgTys.push_back(I->getType()); - i++; - } - //assert(Ity == RetTy); - //assert(Nty == RetTy); - assert(Nty == Ity); - - - FunctionType *FTy = FunctionType::get(RetTy, ArgTys, false); SmallVector<Type *> OverloadTys; Intrinsic::MatchIntrinsicTypesResult Res = diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/refract.ll b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/refract.ll index 7dc6d24f651de..48b40dd8ba15a 100644 --- a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/refract.ll +++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/refract.ll @@ -7,27 +7,31 @@ ; CHECK-DAG: %[[#float_16:]] = OpTypeFloat 16 ; CHECK-DAG: %[[#vec4_float_16:]] = OpTypeVector %[[#float_16]] 4 ; CHECK-DAG: %[[#float_32:]] = OpTypeFloat 32 +; CHECK-DAG: %[[#float_64:]] = OpTypeFloat 64 ; CHECK-DAG: %[[#vec4_float_32:]] = OpTypeVector %[[#float_32]] 4 -define noundef <4 x half> @refract_half4(<4 x half> noundef %a, <4 x half> noundef %b, half %eta) { +define noundef <4 x half> @refract_half(<4 x half> noundef %I, <4 x half> noundef %N, half noundef %ETA) { entry: ; CHECK: %[[#]] = OpFunction %[[#vec4_float_16]] None %[[#]] ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]] ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_16]] - ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]] refract %[[#arg0]] %[[#arg1]] - %spv.refract = call <4 x half> @llvm.spv.refract.f16(<4 x half> %a, <4 x half> %b) - ret <4 x half> %spv.refract + ; CHECK: %[[#arg2_float_16:]] = OpFunctionParameter %[[#float_16:]] + ; CHECK: %[[#arg2:]] = OpFConvert %[[#float_64:]] %[[#arg2_float_16:]] + ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]] Refract %[[#arg0]] %[[#arg1]] %[[#arg2]] + %conv.i = fpext reassoc nnan ninf nsz arcp afn half %ETA to double + %spv.refract.i = tail call reassoc nnan ninf nsz arcp afn noundef <4 x half> @llvm.spv.refract.v4f16.f64(<4 x half> %I, <4 x half> %N, double %conv.i) + ret <4 x half> %spv.refract.i } -define noundef <4 x float> @refract_float4(<4 x float> noundef %a, <4 x float> noundef %b, float %eta) { +define noundef <4 x float> @refract_float4(<4 x float> noundef %I, <4 x float> noundef %N, float noundef %ETA) { entry: + %conv.i = fpext reassoc nnan ninf nsz arcp afn float %ETA to double ; CHECK: %[[#]] = OpFunction %[[#vec4_float_32]] None %[[#]] ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]] ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_32]] - ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]] refract %[[#arg0]] %[[#arg1]] - %spv.refract = call <4 x float> @llvm.spv.refract.f32(<4 x float> %a, <4 x float> %b) - ret <4 x float> %spv.refract -} - -declare <4 x half> @llvm.spv.refract.f16(<4 x half>, <4 x half>, half) -declare <4 x float> @llvm.spv.refract.f32(<4 x float>, <4 x float>, float) + ; CHECK: %[[#arg2_float_32:]] = OpFunctionParameter %[[#float_32:]] + ; CHECK: %[[#arg2:]] = OpFConvert %[[#float_64:]] %[[#arg2_float_32:]] + ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]] Refract %[[#arg0]] %[[#arg1]] %[[#arg2]] + %spv.refract.i = tail call reassoc nnan ninf nsz arcp afn noundef <4 x float> @llvm.spv.refract.v4f32.f64(<4 x float> %I, <4 x float> %N, double %conv.i) + ret <4 x float> %spv.refract.i +} \ No newline at end of file _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits