[clang] [llvm] User/raoanag/refract (PR #136026)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 22 16:48:12 PDT 2025
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 <anagrao at microsoft.com>
Date: Wed, 16 Apr 2025 11:47:27 -0700
Subject: [PATCH 1/3] 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 at -1 {{no matching function for call to 'refract'}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 1 was provided}}
+ // expected-note at 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 at -1 {{no matching function for call to 'refract'}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 2 were provided}}
+ // expected-note at 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 at -1 {{no matching function for call to 'refract'}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate function template not viable: requires 3 arguments, but 4 were provided}}
+ // expected-note at 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 at -1 {{no matching function for call to 'refract'}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+}
+
+float test_int_inputs(int p0, int p1, int p2) {
+ return refract(p0, p1, p2);
+ // expected-error at -1 {{no matching function for call to 'refract'}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored}}
+}
+
+float1 test_vec1_inputs(float1 p0, float1 p1, float1 p2) {
+ return refract(p0, p1, p2);
+ // expected-error at -1 {{no matching function for call to 'refract'}}
+ // expected-note at 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 at 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 at 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 at 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 at -1 {{no matching function for call to 'refract'}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: deduced conflicting types for parameter 'T' ('float5' (vector of 5 'float' values) vs. 'float')}}
+ // expected-note at hlsl/hlsl_intrinsics.h:* {{candidate template ignored: deduced conflicting types for parameter 'T' ('float5' (vector of 5 'float' values) vs. 'float')}}
+ // expected-note at 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 at 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 <anagrao at microsoft.com>
Date: Wed, 16 Apr 2025 13:48:06 -0700
Subject: [PATCH 2/3] 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 <anagrao at microsoft.com>
Date: Tue, 22 Apr 2025 16:47:25 -0700
Subject: [PATCH 3/3] 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]>;
More information about the llvm-commits
mailing list