[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/kmpeng closed https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/farzonl approved this pull request. https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/kmpeng edited https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/kmpeng edited https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/kmpeng edited https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/kmpeng updated
https://github.com/llvm/llvm-project/pull/135878
>From 115b4f8e6276c4dd19e66136a5ad01b6b22f7586 Mon Sep 17 00:00:00 2001
From: kmpeng
Date: Mon, 7 Apr 2025 14:46:07 -0700
Subject: [PATCH 1/5] create int_spv_faceforward intrinsic, create faceforward
lowering & map to int_spv_faceforward, create SPIR-V backend test case
---
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 +
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 ++
.../SPIRV/hlsl-intrinsics/faceforward.ll | 35 +++
3 files changed, 38 insertions(+)
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 4389b86745d7f..77cca0a58424f 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -67,6 +67,7 @@ let TargetPrefix = "spv" in {
def int_spv_cross : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
[LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_degrees : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_distance : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>;
+ def int_spv_faceforward : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_lerp : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem] >;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 79f6b43f3aded..8304077f049a3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -3083,6 +3083,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register
ResVReg,
return selectExtInst(ResVReg, ResType, I, CL::length, GL::Length);
case Intrinsic::spv_degrees:
return selectExtInst(ResVReg, ResType, I, CL::degrees, GL::Degrees);
+ case Intrinsic::spv_faceforward:
+return selectExtInst(ResVReg, ResType, I, GL::FaceForward);
case Intrinsic::spv_frac:
return selectExtInst(ResVReg, ResType, I, CL::fract, GL::Fract);
case Intrinsic::spv_normalize:
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
new file mode 100644
index 0..4b34adc88c0f2
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
@@ -0,0 +1,35 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o - |
FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o -
-filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; Make sure SPIRV operation function calls for faceforward 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> @faceforward_half4(<4 x half> noundef %a, <4 x half>
noundef %b, <4 x half> noundef %c) {
+entry:
+ ; CHECK: %[[#]] = OpFunction %[[#vec4_float_16]] None %[[#]]
+ ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]]
FaceForward %[[#arg0]] %[[#arg1]] %[[#arg2]]
+ %spv.faceforward = call <4 x half> @llvm.spv.faceforward.f16(<4 x half> %a,
<4 x half> %b, <4 x half> %c)
+ ret <4 x half> %spv.faceforward
+}
+
+define noundef <4 x float> @faceforward_float4(<4 x float> noundef %a, <4 x
float> noundef %b, <4 x float> noundef %c) {
+entry:
+ ; CHECK: %[[#]] = OpFunction %[[#vec4_float_32]] None %[[#]]
+ ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]]
FaceForward %[[#arg0]] %[[#arg1]] %[[#arg2]]
+ %spv.faceforward = call <4 x float> @llvm.spv.faceforward.f32(<4 x float>
%a, <4 x float> %b, <4 x float> %c)
+ ret <4 x float> %spv.faceforward
+}
+
+declare <4 x half> @llvm.spv.faceforward.f16(<4 x half>, <4 x half>, <4 x
half>)
+declare <4 x float> @llvm.spv.faceforward.f32(<4 x float>, <4 x float>, <4 x
float>)
>From ae11724e49658d9b6c51556746618e7817835d27 Mon Sep 17 00:00:00 2001
From: kmpeng
Date: Thu, 10 Apr 2025 14:55:17 -0700
Subject: [PATCH 2/5] implemented `faceforward` in `hlsl.Intrinsics.h` an
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/kmpeng edited https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -0,0 +1,63 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o - |
FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o -
-filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; TODO(#136344): This test currently fails when --target-env vulkan1.3 is
specified.
+; XFAIL: spirv-tools
farzonl wrote:
we can't xfail a new test
https://github.com/llvm/llvm-project/pull/135878
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/kmpeng edited https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -105,35 +136,27 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned
BuiltinID,
if (SemaRef.checkArgCount(TheCall, 3))
return true;
-// check if the all arguments have floating representation
-for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {
- ExprResult Arg = TheCall->getArg(i);
- QualType ArgTy = Arg.get()->getType();
- if (!ArgTy->hasFloatingRepresentation()) {
-SemaRef.Diag(Arg.get()->getBeginLoc(),
- diag::err_builtin_invalid_arg_type)
-<< i + 1 << /* scalar or vector */ 5 << /* no int */ 0 << /* fp */
1
-<< ArgTy;
-return true;
- }
-}
+if (CheckAllArgsHaveFloatRepresentation(&SemaRef, TheCall))
+ return true;
-// check if all arguments are of the same type
-ExprResult A = TheCall->getArg(0);
-ExprResult B = TheCall->getArg(1);
-ExprResult C = TheCall->getArg(2);
-if (!(SemaRef.getASTContext().hasSameUnqualifiedType(A.get()->getType(),
- B.get()->getType()) &&
- SemaRef.getASTContext().hasSameUnqualifiedType(A.get()->getType(),
- C.get()->getType(
{
- SemaRef.Diag(TheCall->getBeginLoc(),
- diag::err_vec_builtin_incompatible_vector)
- << TheCall->getDirectCallee() << /*useAllTerminology*/ true
- << SourceRange(A.get()->getBeginLoc(), C.get()->getEndLoc());
+if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
kmpeng wrote:
Code updated to only check the first value for float representation
https://github.com/llvm/llvm-project/pull/135878
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -126,6 +126,24 @@ template constexpr vector lit_impl(T
NDotL, T NDotH, T M) {
return Result;
}
+template constexpr T faceforward_impl(T N, T I, T Ng) {
kmpeng wrote:
You're right. Removed vector implementation
https://github.com/llvm/llvm-project/pull/135878
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -0,0 +1,35 @@ +// 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))); + kmpeng wrote: Added half tests https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/kmpeng updated
https://github.com/llvm/llvm-project/pull/135878
>From d953d95867574dd575cf098668554dfa8e7ffad5 Mon Sep 17 00:00:00 2001
From: kmpeng
Date: Mon, 7 Apr 2025 14:46:07 -0700
Subject: [PATCH 1/4] create int_spv_faceforward intrinsic, create faceforward
lowering & map to int_spv_faceforward, create SPIR-V backend test case
---
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 +
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 ++
.../SPIRV/hlsl-intrinsics/faceforward.ll | 35 +++
3 files changed, 38 insertions(+)
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 4389b86745d7f..77cca0a58424f 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -67,6 +67,7 @@ let TargetPrefix = "spv" in {
def int_spv_cross : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
[LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_degrees : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_distance : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>;
+ def int_spv_faceforward : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_lerp : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem] >;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 79f6b43f3aded..8304077f049a3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -3083,6 +3083,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register
ResVReg,
return selectExtInst(ResVReg, ResType, I, CL::length, GL::Length);
case Intrinsic::spv_degrees:
return selectExtInst(ResVReg, ResType, I, CL::degrees, GL::Degrees);
+ case Intrinsic::spv_faceforward:
+return selectExtInst(ResVReg, ResType, I, GL::FaceForward);
case Intrinsic::spv_frac:
return selectExtInst(ResVReg, ResType, I, CL::fract, GL::Fract);
case Intrinsic::spv_normalize:
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
new file mode 100644
index 0..4b34adc88c0f2
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
@@ -0,0 +1,35 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o - |
FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o -
-filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; Make sure SPIRV operation function calls for faceforward 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> @faceforward_half4(<4 x half> noundef %a, <4 x half>
noundef %b, <4 x half> noundef %c) {
+entry:
+ ; CHECK: %[[#]] = OpFunction %[[#vec4_float_16]] None %[[#]]
+ ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]]
FaceForward %[[#arg0]] %[[#arg1]] %[[#arg2]]
+ %spv.faceforward = call <4 x half> @llvm.spv.faceforward.f16(<4 x half> %a,
<4 x half> %b, <4 x half> %c)
+ ret <4 x half> %spv.faceforward
+}
+
+define noundef <4 x float> @faceforward_float4(<4 x float> noundef %a, <4 x
float> noundef %b, <4 x float> noundef %c) {
+entry:
+ ; CHECK: %[[#]] = OpFunction %[[#vec4_float_32]] None %[[#]]
+ ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]]
FaceForward %[[#arg0]] %[[#arg1]] %[[#arg2]]
+ %spv.faceforward = call <4 x float> @llvm.spv.faceforward.f32(<4 x float>
%a, <4 x float> %b, <4 x float> %c)
+ ret <4 x float> %spv.faceforward
+}
+
+declare <4 x half> @llvm.spv.faceforward.f16(<4 x half>, <4 x half>, <4 x
half>)
+declare <4 x float> @llvm.spv.faceforward.f32(<4 x float>, <4 x float>, <4 x
float>)
>From 9966b0cf1d12dd5db1907d7d99c8d812a75349c0 Mon Sep 17 00:00:00 2001
From: kmpeng
Date: Thu, 10 Apr 2025 14:55:17 -0700
Subject: [PATCH 2/4] implemented `faceforward` in `hlsl.Intrinsics.h` an
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/kmpeng updated
https://github.com/llvm/llvm-project/pull/135878
>From 69aee464d31dcf585c355808053b0c4d1c7d7f3c Mon Sep 17 00:00:00 2001
From: kmpeng
Date: Mon, 7 Apr 2025 14:46:07 -0700
Subject: [PATCH 1/4] create int_spv_faceforward intrinsic, create faceforward
lowering & map to int_spv_faceforward, create SPIR-V backend test case
---
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 +
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 ++
.../SPIRV/hlsl-intrinsics/faceforward.ll | 35 +++
3 files changed, 38 insertions(+)
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 4389b86745d7f..77cca0a58424f 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -67,6 +67,7 @@ let TargetPrefix = "spv" in {
def int_spv_cross : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
[LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_degrees : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_distance : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>;
+ def int_spv_faceforward : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_lerp : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem] >;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 79f6b43f3aded..8304077f049a3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -3083,6 +3083,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register
ResVReg,
return selectExtInst(ResVReg, ResType, I, CL::length, GL::Length);
case Intrinsic::spv_degrees:
return selectExtInst(ResVReg, ResType, I, CL::degrees, GL::Degrees);
+ case Intrinsic::spv_faceforward:
+return selectExtInst(ResVReg, ResType, I, GL::FaceForward);
case Intrinsic::spv_frac:
return selectExtInst(ResVReg, ResType, I, CL::fract, GL::Fract);
case Intrinsic::spv_normalize:
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
new file mode 100644
index 0..4b34adc88c0f2
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
@@ -0,0 +1,35 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o - |
FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o -
-filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; Make sure SPIRV operation function calls for faceforward 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> @faceforward_half4(<4 x half> noundef %a, <4 x half>
noundef %b, <4 x half> noundef %c) {
+entry:
+ ; CHECK: %[[#]] = OpFunction %[[#vec4_float_16]] None %[[#]]
+ ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]]
FaceForward %[[#arg0]] %[[#arg1]] %[[#arg2]]
+ %spv.faceforward = call <4 x half> @llvm.spv.faceforward.f16(<4 x half> %a,
<4 x half> %b, <4 x half> %c)
+ ret <4 x half> %spv.faceforward
+}
+
+define noundef <4 x float> @faceforward_float4(<4 x float> noundef %a, <4 x
float> noundef %b, <4 x float> noundef %c) {
+entry:
+ ; CHECK: %[[#]] = OpFunction %[[#vec4_float_32]] None %[[#]]
+ ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]]
FaceForward %[[#arg0]] %[[#arg1]] %[[#arg2]]
+ %spv.faceforward = call <4 x float> @llvm.spv.faceforward.f32(<4 x float>
%a, <4 x float> %b, <4 x float> %c)
+ ret <4 x float> %spv.faceforward
+}
+
+declare <4 x half> @llvm.spv.faceforward.f16(<4 x half>, <4 x half>, <4 x
half>)
+declare <4 x float> @llvm.spv.faceforward.f32(<4 x float>, <4 x float>, <4 x
float>)
>From 06324ca82d3c593c801bf602b8f58683d13e738f Mon Sep 17 00:00:00 2001
From: kmpeng
Date: Thu, 10 Apr 2025 14:55:17 -0700
Subject: [PATCH 2/4] implemented `faceforward` in `hlsl.Intrinsics.h` an
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/farzonl edited https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -105,35 +136,27 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned
BuiltinID,
if (SemaRef.checkArgCount(TheCall, 3))
return true;
-// check if the all arguments have floating representation
-for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {
- ExprResult Arg = TheCall->getArg(i);
- QualType ArgTy = Arg.get()->getType();
- if (!ArgTy->hasFloatingRepresentation()) {
-SemaRef.Diag(Arg.get()->getBeginLoc(),
- diag::err_builtin_invalid_arg_type)
-<< i + 1 << /* scalar or vector */ 5 << /* no int */ 0 << /* fp */
1
-<< ArgTy;
-return true;
- }
-}
+if (CheckAllArgsHaveFloatRepresentation(&SemaRef, TheCall))
+ return true;
-// check if all arguments are of the same type
-ExprResult A = TheCall->getArg(0);
-ExprResult B = TheCall->getArg(1);
-ExprResult C = TheCall->getArg(2);
-if (!(SemaRef.getASTContext().hasSameUnqualifiedType(A.get()->getType(),
- B.get()->getType()) &&
- SemaRef.getASTContext().hasSameUnqualifiedType(A.get()->getType(),
- C.get()->getType(
{
- SemaRef.Diag(TheCall->getBeginLoc(),
- diag::err_vec_builtin_incompatible_vector)
- << TheCall->getDirectCallee() << /*useAllTerminology*/ true
- << SourceRange(A.get()->getBeginLoc(), C.get()->getEndLoc());
+if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
kmpeng wrote:
You're right, it would be better to just check the first value then do
`CheckAllArgsHaveSameType`.
The only caveat I can think of would be that it would change the error messages
for tests, e.g. the error message for
```
float test_int_scalar_inputs2(float p0, int p1, int p2)
```
would change from `2nd argument must be a scalar or vector of floating-point
types (was 'int')` to `all arguments to '__builtin_spirv_faceforward' must have
the same type`, which I think is fine.
If we want to make this change for `smoothstep` though, we would probably want
to do it in a separate PR right?
https://github.com/llvm/llvm-project/pull/135878
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -105,35 +136,27 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned
BuiltinID,
if (SemaRef.checkArgCount(TheCall, 3))
return true;
-// check if the all arguments have floating representation
-for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {
- ExprResult Arg = TheCall->getArg(i);
- QualType ArgTy = Arg.get()->getType();
- if (!ArgTy->hasFloatingRepresentation()) {
-SemaRef.Diag(Arg.get()->getBeginLoc(),
- diag::err_builtin_invalid_arg_type)
-<< i + 1 << /* scalar or vector */ 5 << /* no int */ 0 << /* fp */
1
-<< ArgTy;
-return true;
- }
-}
+if (CheckAllArgsHaveFloatRepresentation(&SemaRef, TheCall))
+ return true;
-// check if all arguments are of the same type
-ExprResult A = TheCall->getArg(0);
-ExprResult B = TheCall->getArg(1);
-ExprResult C = TheCall->getArg(2);
-if (!(SemaRef.getASTContext().hasSameUnqualifiedType(A.get()->getType(),
- B.get()->getType()) &&
- SemaRef.getASTContext().hasSameUnqualifiedType(A.get()->getType(),
- C.get()->getType(
{
- SemaRef.Diag(TheCall->getBeginLoc(),
- diag::err_vec_builtin_incompatible_vector)
- << TheCall->getDirectCallee() << /*useAllTerminology*/ true
- << SourceRange(A.get()->getBeginLoc(), C.get()->getEndLoc());
+if (CheckAllArgsHaveSameType(&SemaRef, TheCall))
farzonl wrote:
do we need to do CheckAllArgsHaveSameType and
CheckAllArgsHaveFloatRepresentation. Two loops over arguments seems
unnecesary. Seems like we can just check if the first value has a float
representation then do CheckAllArgsHaveSameType
https://github.com/llvm/llvm-project/pull/135878
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -0,0 +1,35 @@ +// 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))); + farzonl wrote: if you want to do half testing you should be able to do this ```cpp typedef _Float16 half; typedef half half2 __attribute__((ext_vector_type(2))); ``` https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/farzonl edited https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/farzonl edited https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -126,6 +126,24 @@ template constexpr vector lit_impl(T
NDotL, T NDotH, T M) {
return Result;
}
+template constexpr T faceforward_impl(T N, T I, T Ng) {
farzonl wrote:
So in cases like length and distance I know why we had a scalar and vector
version of the implementation function.
In those two cases the return type was different than the argument types. In
other cases like reflect it also made sense to do two seperate functions
because the scalar case did not call the spirv builtin. In this case the return
and argument types are the same and both the vector ans scalar cases call the
spirv builtin so why do we need two seperate templatized functions?
https://github.com/llvm/llvm-project/pull/135878
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/farzonl edited https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/kmpeng updated
https://github.com/llvm/llvm-project/pull/135878
>From 69aee464d31dcf585c355808053b0c4d1c7d7f3c Mon Sep 17 00:00:00 2001
From: kmpeng
Date: Mon, 7 Apr 2025 14:46:07 -0700
Subject: [PATCH 1/3] create int_spv_faceforward intrinsic, create faceforward
lowering & map to int_spv_faceforward, create SPIR-V backend test case
---
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 +
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 ++
.../SPIRV/hlsl-intrinsics/faceforward.ll | 35 +++
3 files changed, 38 insertions(+)
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 4389b86745d7f..77cca0a58424f 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -67,6 +67,7 @@ let TargetPrefix = "spv" in {
def int_spv_cross : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
[LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_degrees : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_distance : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>;
+ def int_spv_faceforward : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_lerp : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem] >;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 79f6b43f3aded..8304077f049a3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -3083,6 +3083,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register
ResVReg,
return selectExtInst(ResVReg, ResType, I, CL::length, GL::Length);
case Intrinsic::spv_degrees:
return selectExtInst(ResVReg, ResType, I, CL::degrees, GL::Degrees);
+ case Intrinsic::spv_faceforward:
+return selectExtInst(ResVReg, ResType, I, GL::FaceForward);
case Intrinsic::spv_frac:
return selectExtInst(ResVReg, ResType, I, CL::fract, GL::Fract);
case Intrinsic::spv_normalize:
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
new file mode 100644
index 0..4b34adc88c0f2
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
@@ -0,0 +1,35 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o - |
FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o -
-filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; Make sure SPIRV operation function calls for faceforward 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> @faceforward_half4(<4 x half> noundef %a, <4 x half>
noundef %b, <4 x half> noundef %c) {
+entry:
+ ; CHECK: %[[#]] = OpFunction %[[#vec4_float_16]] None %[[#]]
+ ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]]
FaceForward %[[#arg0]] %[[#arg1]] %[[#arg2]]
+ %spv.faceforward = call <4 x half> @llvm.spv.faceforward.f16(<4 x half> %a,
<4 x half> %b, <4 x half> %c)
+ ret <4 x half> %spv.faceforward
+}
+
+define noundef <4 x float> @faceforward_float4(<4 x float> noundef %a, <4 x
float> noundef %b, <4 x float> noundef %c) {
+entry:
+ ; CHECK: %[[#]] = OpFunction %[[#vec4_float_32]] None %[[#]]
+ ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]]
FaceForward %[[#arg0]] %[[#arg1]] %[[#arg2]]
+ %spv.faceforward = call <4 x float> @llvm.spv.faceforward.f32(<4 x float>
%a, <4 x float> %b, <4 x float> %c)
+ ret <4 x float> %spv.faceforward
+}
+
+declare <4 x half> @llvm.spv.faceforward.f16(<4 x half>, <4 x half>, <4 x
half>)
+declare <4 x float> @llvm.spv.faceforward.f32(<4 x float>, <4 x float>, <4 x
float>)
>From 06324ca82d3c593c801bf602b8f58683d13e738f Mon Sep 17 00:00:00 2001
From: kmpeng
Date: Thu, 10 Apr 2025 14:55:17 -0700
Subject: [PATCH 2/3] implemented `faceforward` in `hlsl.Intrinsics.h` an
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -214,6 +214,53 @@ const inline double4 dst(double4 Src0, double4 Src1) {
return __detail::dst_impl(Src0, Src1);
}
+//===--===//
+// faceforward builtin
+//===--===//
+
+/// \fn T faceforward(T N, T I, T Ng)
+/// \brief Flips the surface-normal (if needed) to face in a direction opposite
+/// to \a I. Returns the result in \a N.
kmpeng wrote:
Ah yeah, that's makes it much more clear. Code updated, thanks!
https://github.com/llvm/llvm-project/pull/135878
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -137,6 +137,42 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned
BuiltinID,
TheCall->setType(RetTy);
break;
}
+ case SPIRV::BI__builtin_spirv_faceforward: {
+if (SemaRef.checkArgCount(TheCall, 3))
+ return true;
+
+// check if all arguments have floating representation
+for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {
+ ExprResult Arg = TheCall->getArg(i);
+ QualType ArgTy = Arg.get()->getType();
+ if (!ArgTy->hasFloatingRepresentation()) {
+SemaRef.Diag(Arg.get()->getBeginLoc(),
+ diag::err_builtin_invalid_arg_type)
+<< i + 1 << /* scalar or vector */ 5 << /* no int */ 0 << /* fp */
1
kmpeng wrote:
Code updated
https://github.com/llvm/llvm-project/pull/135878
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -0,0 +1,94 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ kmpeng wrote: Code updated https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/kmpeng edited https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -137,6 +137,42 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned
BuiltinID,
TheCall->setType(RetTy);
break;
}
+ case SPIRV::BI__builtin_spirv_faceforward: {
+if (SemaRef.checkArgCount(TheCall, 3))
+ return true;
+
+// check if all arguments have floating representation
+for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {
+ ExprResult Arg = TheCall->getArg(i);
+ QualType ArgTy = Arg.get()->getType();
+ if (!ArgTy->hasFloatingRepresentation()) {
+SemaRef.Diag(Arg.get()->getBeginLoc(),
+ diag::err_builtin_invalid_arg_type)
+<< i + 1 << /* scalar or vector */ 5 << /* no int */ 0 << /* fp */
1
+<< ArgTy;
+return true;
+ }
+}
+
+// check if all arguments are of the same type
+ExprResult A = TheCall->getArg(0);
+ExprResult B = TheCall->getArg(1);
+ExprResult C = TheCall->getArg(2);
+if (!(SemaRef.getASTContext().hasSameUnqualifiedType(A.get()->getType(),
kmpeng wrote:
Code updated
https://github.com/llvm/llvm-project/pull/135878
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -214,6 +214,53 @@ const inline double4 dst(double4 Src0, double4 Src1) {
return __detail::dst_impl(Src0, Src1);
}
+//===--===//
+// faceforward builtin
+//===--===//
+
+/// \fn T faceforward(T N, T I, T Ng)
+/// \brief Flips the surface-normal (if needed) to face in a direction opposite
+/// to \a I. Returns the result in \a N.
inbelic wrote:
I assume this is copied from the docs, but "returns the result in N" is quite
confusing to me. Maybe it was meant to be "Returns the result in terms of N" or
the like?
https://github.com/llvm/llvm-project/pull/135878
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -0,0 +1,94 @@ +// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ inbelic wrote: ```suggestion // RUN: %clang_cc1 -finclude-default-header -triple \ ``` `-x` just specifies the file extension, since the file is `.hlsl` it should naturally detect and use it as expected. https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -137,6 +137,42 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned
BuiltinID,
TheCall->setType(RetTy);
break;
}
+ case SPIRV::BI__builtin_spirv_faceforward: {
+if (SemaRef.checkArgCount(TheCall, 3))
+ return true;
+
+// check if all arguments have floating representation
+for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {
+ ExprResult Arg = TheCall->getArg(i);
+ QualType ArgTy = Arg.get()->getType();
+ if (!ArgTy->hasFloatingRepresentation()) {
+SemaRef.Diag(Arg.get()->getBeginLoc(),
+ diag::err_builtin_invalid_arg_type)
+<< i + 1 << /* scalar or vector */ 5 << /* no int */ 0 << /* fp */
1
inbelic wrote:
```suggestion
<< /* ordinal */ i + 1 << /* scalar or vector */ 5 << /* no int */
0 << /* fp */ 1
```
I think this for loop is the exact same as the smoothstep function? We could
probably move it to a common function then.
https://github.com/llvm/llvm-project/pull/135878
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
@@ -137,6 +137,42 @@ bool SemaSPIRV::CheckSPIRVBuiltinFunctionCall(unsigned
BuiltinID,
TheCall->setType(RetTy);
break;
}
+ case SPIRV::BI__builtin_spirv_faceforward: {
+if (SemaRef.checkArgCount(TheCall, 3))
+ return true;
+
+// check if all arguments have floating representation
+for (unsigned i = 0; i < TheCall->getNumArgs(); ++i) {
+ ExprResult Arg = TheCall->getArg(i);
+ QualType ArgTy = Arg.get()->getType();
+ if (!ArgTy->hasFloatingRepresentation()) {
+SemaRef.Diag(Arg.get()->getBeginLoc(),
+ diag::err_builtin_invalid_arg_type)
+<< i + 1 << /* scalar or vector */ 5 << /* no int */ 0 << /* fp */
1
+<< ArgTy;
+return true;
+ }
+}
+
+// check if all arguments are of the same type
+ExprResult A = TheCall->getArg(0);
+ExprResult B = TheCall->getArg(1);
+ExprResult C = TheCall->getArg(2);
+if (!(SemaRef.getASTContext().hasSameUnqualifiedType(A.get()->getType(),
inbelic wrote:
Same here, could be common function. See the `CheckAllArgsHaveTheSameType` in
`SemaHLSL`. You could probably just copy paste that into this file. I think we
previously decided to NOT move them to a common place so I wouldn't worry about
doing that.
https://github.com/llvm/llvm-project/pull/135878
___
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/inbelic commented: Just a collection of nits. LGTM https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/inbelic edited https://github.com/llvm/llvm-project/pull/135878 ___ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/kmpeng updated
https://github.com/llvm/llvm-project/pull/135878
>From 69aee464d31dcf585c355808053b0c4d1c7d7f3c Mon Sep 17 00:00:00 2001
From: kmpeng
Date: Mon, 7 Apr 2025 14:46:07 -0700
Subject: [PATCH 1/2] create int_spv_faceforward intrinsic, create faceforward
lowering & map to int_spv_faceforward, create SPIR-V backend test case
---
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 +
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 ++
.../SPIRV/hlsl-intrinsics/faceforward.ll | 35 +++
3 files changed, 38 insertions(+)
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 4389b86745d7f..77cca0a58424f 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -67,6 +67,7 @@ let TargetPrefix = "spv" in {
def int_spv_cross : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
[LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_degrees : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_distance : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>;
+ def int_spv_faceforward : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_lerp : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem] >;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 79f6b43f3aded..8304077f049a3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -3083,6 +3083,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register
ResVReg,
return selectExtInst(ResVReg, ResType, I, CL::length, GL::Length);
case Intrinsic::spv_degrees:
return selectExtInst(ResVReg, ResType, I, CL::degrees, GL::Degrees);
+ case Intrinsic::spv_faceforward:
+return selectExtInst(ResVReg, ResType, I, GL::FaceForward);
case Intrinsic::spv_frac:
return selectExtInst(ResVReg, ResType, I, CL::fract, GL::Fract);
case Intrinsic::spv_normalize:
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
new file mode 100644
index 0..4b34adc88c0f2
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
@@ -0,0 +1,35 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o - |
FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o -
-filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; Make sure SPIRV operation function calls for faceforward 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> @faceforward_half4(<4 x half> noundef %a, <4 x half>
noundef %b, <4 x half> noundef %c) {
+entry:
+ ; CHECK: %[[#]] = OpFunction %[[#vec4_float_16]] None %[[#]]
+ ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_16]] %[[#op_ext_glsl]]
FaceForward %[[#arg0]] %[[#arg1]] %[[#arg2]]
+ %spv.faceforward = call <4 x half> @llvm.spv.faceforward.f16(<4 x half> %a,
<4 x half> %b, <4 x half> %c)
+ ret <4 x half> %spv.faceforward
+}
+
+define noundef <4 x float> @faceforward_float4(<4 x float> noundef %a, <4 x
float> noundef %b, <4 x float> noundef %c) {
+entry:
+ ; CHECK: %[[#]] = OpFunction %[[#vec4_float_32]] None %[[#]]
+ ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#arg2:]] = OpFunctionParameter %[[#vec4_float_32]]
+ ; CHECK: %[[#]] = OpExtInst %[[#vec4_float_32]] %[[#op_ext_glsl]]
FaceForward %[[#arg0]] %[[#arg1]] %[[#arg2]]
+ %spv.faceforward = call <4 x float> @llvm.spv.faceforward.f32(<4 x float>
%a, <4 x float> %b, <4 x float> %c)
+ ret <4 x float> %spv.faceforward
+}
+
+declare <4 x half> @llvm.spv.faceforward.f16(<4 x half>, <4 x half>, <4 x
half>)
+declare <4 x float> @llvm.spv.faceforward.f32(<4 x float>, <4 x float>, <4 x
float>)
>From 06324ca82d3c593c801bf602b8f58683d13e738f Mon Sep 17 00:00:00 2001
From: kmpeng
Date: Thu, 10 Apr 2025 14:55:17 -0700
Subject: [PATCH 2/2] implemented `faceforward` in `hlsl.Intrinsics.h` an
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
llvmbot wrote:
@llvm/pr-subscribers-clang-codegen
Author: Kaitlin Peng (kmpeng)
Changes
Resolves #99114. There will be a follow-up PR on pattern matching later.
Tasks completed:
- Implement `faceforward` in `hlsl_intrinsics.h`/`hlsl_intrinsic_helpers.h`
- Implement `faceforward` SPIR-V target builtin in
`clang/include/clang/Basic/BuiltinsSPIRV.td`
- Add a SPIR-V fast path in `hlsl_intrinsic_helpers.h`
- Add sema checks for `faceforward` to `CheckSPIRVBuiltinFunctionCall` in
`clang/lib/Sema/SemaSPIRV.cpp`
- Add codegen for SPIR-V `faceforward` builtin to `EmitSPIRVBuiltinExpr` in
`SPIR.cpp`
- Add HLSL codegen tests to `clang/test/CodeGenHLSL/builtins/faceforward.hlsl`
- Add SPIRV builtin codegen tests to
`clang/test/CodeGenSPIRV/Builtins/faceforward.c`
- Add sema tests to `clang/test/SemaHLSL/BuiltIns/faceforward-errors.hlsl`
- Add spirv sema tests to `clang/test/SemaSPIRV/BuiltIns/faceforward-errors.c`
- Create the `int_spv_faceforward` intrinsic in `IntrinsicsSPIRV.td`
- In `SPIRVInstructionSelector.cpp` create the `faceforward` lowering and map
it to `int_spv_faceforward` in `SPIRVInstructionSelector::selectIntrinsic`
- Create SPIR-V backend test case in
`llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll`
Incomplete tasks:
- Create SPIR-V backend test case in
`llvm/test/CodeGen/SPIRV/opencl/faceforward.ll`
- Not applicable because the OpenCL SPIR-V extended instruction set does not
include a `faceforward` function
---
Patch is 27.53 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/135878.diff
12 Files Affected:
- (modified) clang/include/clang/Basic/BuiltinsSPIRV.td (+6)
- (modified) clang/lib/CodeGen/TargetBuiltins/SPIR.cpp (+12)
- (modified) clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h (+18)
- (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+47)
- (modified) clang/lib/Sema/SemaSPIRV.cpp (+36)
- (added) clang/test/CodeGenHLSL/builtins/faceforward.hlsl (+94)
- (added) clang/test/CodeGenSPIRV/Builtins/faceforward.c (+35)
- (added) clang/test/SemaHLSL/BuiltIns/faceforward-errors.hlsl (+39)
- (added) clang/test/SemaSPIRV/BuiltIns/faceforward-errors.c (+54)
- (modified) llvm/include/llvm/IR/IntrinsicsSPIRV.td (+1)
- (modified) llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp (+2)
- (added) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll (+60)
``diff
diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td
b/clang/include/clang/Basic/BuiltinsSPIRV.td
index 9f76d672cc7ce..cc0c2f960f8d2 100644
--- a/clang/include/clang/Basic/BuiltinsSPIRV.td
+++ b/clang/include/clang/Basic/BuiltinsSPIRV.td
@@ -31,3 +31,9 @@ def SPIRVSmoothStep : Builtin {
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Prototype = "void(...)";
}
+
+def SPIRVFaceForward : Builtin {
+ let Spellings = ["__builtin_spirv_faceforward"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
diff --git a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
index 92e2c1c6da68f..c1bcc9ae084d0 100644
--- a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
@@ -71,6 +71,18 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned
BuiltinID,
ArrayRef{Min, Max, X}, /*FMFSource=*/nullptr,
"spv.smoothstep");
}
+ case SPIRV::BI__builtin_spirv_faceforward: {
+Value *N = EmitScalarExpr(E->getArg(0));
+Value *I = EmitScalarExpr(E->getArg(1));
+Value *Ng = EmitScalarExpr(E->getArg(2));
+assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
+ E->getArg(1)->getType()->hasFloatingRepresentation() &&
+ E->getArg(2)->getType()->hasFloatingRepresentation() &&
+ "FaceForward operands must have a float representation");
+return Builder.CreateIntrinsic(
+/*ReturnType=*/N->getType(), Intrinsic::spv_smoothstep,
+ArrayRef{N, I, Ng}, /*FMFSource=*/nullptr, "spv.faceforward");
+ }
}
return nullptr;
}
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
index 3a8a9b6fa2a45..b2332419dc034 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
@@ -126,6 +126,24 @@ template constexpr vector lit_impl(T
NDotL, T NDotH, T M) {
return Result;
}
+template constexpr T faceforward_impl(T N, T I, T Ng) {
+#if (__has_builtin(__builtin_spirv_faceforward))
+ return __builtin_spirv_faceforward(N, I, Ng);
+#else
+ return select(I * Ng < 0, N, -N);
+#endif
+}
+
+template
+constexpr vector faceforward_vec_impl(vector N, vector I,
+vector Ng) {
+#if (__has_builtin(__builtin_spirv_faceforward))
+ return __builtin_spirv_faceforward(N, I, Ng);
+#else
+ return select(dot(I, Ng) < 0, N, -N);
+#endif
+}
+
} // namespace __detail
} // namespace hlsl
diff --git a/clang/lib/Headers/hlsl/
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
llvmbot wrote:
@llvm/pr-subscribers-backend-spir-v
Author: Kaitlin Peng (kmpeng)
Changes
Resolves #99114. There will be a follow-up PR on pattern matching later.
Tasks completed:
- Implement `faceforward` in `hlsl_intrinsics.h`/`hlsl_intrinsic_helpers.h`
- Implement `faceforward` SPIR-V target builtin in
`clang/include/clang/Basic/BuiltinsSPIRV.td`
- Add a SPIR-V fast path in `hlsl_intrinsic_helpers.h`
- Add sema checks for `faceforward` to `CheckSPIRVBuiltinFunctionCall` in
`clang/lib/Sema/SemaSPIRV.cpp`
- Add codegen for SPIR-V `faceforward` builtin to `EmitSPIRVBuiltinExpr` in
`SPIR.cpp`
- Add HLSL codegen tests to `clang/test/CodeGenHLSL/builtins/faceforward.hlsl`
- Add SPIRV builtin codegen tests to
`clang/test/CodeGenSPIRV/Builtins/faceforward.c`
- Add sema tests to `clang/test/SemaHLSL/BuiltIns/faceforward-errors.hlsl`
- Add spirv sema tests to `clang/test/SemaSPIRV/BuiltIns/faceforward-errors.c`
- Create the `int_spv_faceforward` intrinsic in `IntrinsicsSPIRV.td`
- In `SPIRVInstructionSelector.cpp` create the `faceforward` lowering and map
it to `int_spv_faceforward` in `SPIRVInstructionSelector::selectIntrinsic`
- Create SPIR-V backend test case in
`llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll`
Incomplete tasks:
- Create SPIR-V backend test case in
`llvm/test/CodeGen/SPIRV/opencl/faceforward.ll`
- Not applicable because the OpenCL SPIR-V extended instruction set does not
include a `faceforward` function
---
Patch is 27.53 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/135878.diff
12 Files Affected:
- (modified) clang/include/clang/Basic/BuiltinsSPIRV.td (+6)
- (modified) clang/lib/CodeGen/TargetBuiltins/SPIR.cpp (+12)
- (modified) clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h (+18)
- (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+47)
- (modified) clang/lib/Sema/SemaSPIRV.cpp (+36)
- (added) clang/test/CodeGenHLSL/builtins/faceforward.hlsl (+94)
- (added) clang/test/CodeGenSPIRV/Builtins/faceforward.c (+35)
- (added) clang/test/SemaHLSL/BuiltIns/faceforward-errors.hlsl (+39)
- (added) clang/test/SemaSPIRV/BuiltIns/faceforward-errors.c (+54)
- (modified) llvm/include/llvm/IR/IntrinsicsSPIRV.td (+1)
- (modified) llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp (+2)
- (added) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll (+60)
``diff
diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td
b/clang/include/clang/Basic/BuiltinsSPIRV.td
index 9f76d672cc7ce..cc0c2f960f8d2 100644
--- a/clang/include/clang/Basic/BuiltinsSPIRV.td
+++ b/clang/include/clang/Basic/BuiltinsSPIRV.td
@@ -31,3 +31,9 @@ def SPIRVSmoothStep : Builtin {
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Prototype = "void(...)";
}
+
+def SPIRVFaceForward : Builtin {
+ let Spellings = ["__builtin_spirv_faceforward"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
diff --git a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
index 92e2c1c6da68f..c1bcc9ae084d0 100644
--- a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
@@ -71,6 +71,18 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned
BuiltinID,
ArrayRef{Min, Max, X}, /*FMFSource=*/nullptr,
"spv.smoothstep");
}
+ case SPIRV::BI__builtin_spirv_faceforward: {
+Value *N = EmitScalarExpr(E->getArg(0));
+Value *I = EmitScalarExpr(E->getArg(1));
+Value *Ng = EmitScalarExpr(E->getArg(2));
+assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
+ E->getArg(1)->getType()->hasFloatingRepresentation() &&
+ E->getArg(2)->getType()->hasFloatingRepresentation() &&
+ "FaceForward operands must have a float representation");
+return Builder.CreateIntrinsic(
+/*ReturnType=*/N->getType(), Intrinsic::spv_smoothstep,
+ArrayRef{N, I, Ng}, /*FMFSource=*/nullptr, "spv.faceforward");
+ }
}
return nullptr;
}
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
index 3a8a9b6fa2a45..b2332419dc034 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
@@ -126,6 +126,24 @@ template constexpr vector lit_impl(T
NDotL, T NDotH, T M) {
return Result;
}
+template constexpr T faceforward_impl(T N, T I, T Ng) {
+#if (__has_builtin(__builtin_spirv_faceforward))
+ return __builtin_spirv_faceforward(N, I, Ng);
+#else
+ return select(I * Ng < 0, N, -N);
+#endif
+}
+
+template
+constexpr vector faceforward_vec_impl(vector N, vector I,
+vector Ng) {
+#if (__has_builtin(__builtin_spirv_faceforward))
+ return __builtin_spirv_faceforward(N, I, Ng);
+#else
+ return select(dot(I, Ng) < 0, N, -N);
+#endif
+}
+
} // namespace __detail
} // namespace hlsl
diff --git a/clang/lib/Headers/hlsl
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
llvmbot wrote:
@llvm/pr-subscribers-llvm-ir
@llvm/pr-subscribers-backend-x86
@llvm/pr-subscribers-hlsl
Author: Kaitlin Peng (kmpeng)
Changes
Resolves #99114. There will be a follow-up PR on pattern matching later.
Tasks completed:
- Implement `faceforward` in `hlsl_intrinsics.h`/`hlsl_intrinsic_helpers.h`
- Implement `faceforward` SPIR-V target builtin in
`clang/include/clang/Basic/BuiltinsSPIRV.td`
- Add a SPIR-V fast path in `hlsl_intrinsic_helpers.h`
- Add sema checks for `faceforward` to `CheckSPIRVBuiltinFunctionCall` in
`clang/lib/Sema/SemaSPIRV.cpp`
- Add codegen for SPIR-V `faceforward` builtin to `EmitSPIRVBuiltinExpr` in
`SPIR.cpp`
- Add HLSL codegen tests to `clang/test/CodeGenHLSL/builtins/faceforward.hlsl`
- Add SPIRV builtin codegen tests to
`clang/test/CodeGenSPIRV/Builtins/faceforward.c`
- Add sema tests to `clang/test/SemaHLSL/BuiltIns/faceforward-errors.hlsl`
- Add spirv sema tests to `clang/test/SemaSPIRV/BuiltIns/faceforward-errors.c`
- Create the `int_spv_faceforward` intrinsic in `IntrinsicsSPIRV.td`
- In `SPIRVInstructionSelector.cpp` create the `faceforward` lowering and map
it to `int_spv_faceforward` in `SPIRVInstructionSelector::selectIntrinsic`
- Create SPIR-V backend test case in
`llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll`
Incomplete tasks:
- Create SPIR-V backend test case in
`llvm/test/CodeGen/SPIRV/opencl/faceforward.ll`
- Not applicable because the OpenCL SPIR-V extended instruction set does not
include a `faceforward` function
---
Patch is 27.53 KiB, truncated to 20.00 KiB below, full version:
https://github.com/llvm/llvm-project/pull/135878.diff
12 Files Affected:
- (modified) clang/include/clang/Basic/BuiltinsSPIRV.td (+6)
- (modified) clang/lib/CodeGen/TargetBuiltins/SPIR.cpp (+12)
- (modified) clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h (+18)
- (modified) clang/lib/Headers/hlsl/hlsl_intrinsics.h (+47)
- (modified) clang/lib/Sema/SemaSPIRV.cpp (+36)
- (added) clang/test/CodeGenHLSL/builtins/faceforward.hlsl (+94)
- (added) clang/test/CodeGenSPIRV/Builtins/faceforward.c (+35)
- (added) clang/test/SemaHLSL/BuiltIns/faceforward-errors.hlsl (+39)
- (added) clang/test/SemaSPIRV/BuiltIns/faceforward-errors.c (+54)
- (modified) llvm/include/llvm/IR/IntrinsicsSPIRV.td (+1)
- (modified) llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp (+2)
- (added) llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll (+60)
``diff
diff --git a/clang/include/clang/Basic/BuiltinsSPIRV.td
b/clang/include/clang/Basic/BuiltinsSPIRV.td
index 9f76d672cc7ce..cc0c2f960f8d2 100644
--- a/clang/include/clang/Basic/BuiltinsSPIRV.td
+++ b/clang/include/clang/Basic/BuiltinsSPIRV.td
@@ -31,3 +31,9 @@ def SPIRVSmoothStep : Builtin {
let Attributes = [NoThrow, Const, CustomTypeChecking];
let Prototype = "void(...)";
}
+
+def SPIRVFaceForward : Builtin {
+ let Spellings = ["__builtin_spirv_faceforward"];
+ let Attributes = [NoThrow, Const, CustomTypeChecking];
+ let Prototype = "void(...)";
+}
diff --git a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
index 92e2c1c6da68f..c1bcc9ae084d0 100644
--- a/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/SPIR.cpp
@@ -71,6 +71,18 @@ Value *CodeGenFunction::EmitSPIRVBuiltinExpr(unsigned
BuiltinID,
ArrayRef{Min, Max, X}, /*FMFSource=*/nullptr,
"spv.smoothstep");
}
+ case SPIRV::BI__builtin_spirv_faceforward: {
+Value *N = EmitScalarExpr(E->getArg(0));
+Value *I = EmitScalarExpr(E->getArg(1));
+Value *Ng = EmitScalarExpr(E->getArg(2));
+assert(E->getArg(0)->getType()->hasFloatingRepresentation() &&
+ E->getArg(1)->getType()->hasFloatingRepresentation() &&
+ E->getArg(2)->getType()->hasFloatingRepresentation() &&
+ "FaceForward operands must have a float representation");
+return Builder.CreateIntrinsic(
+/*ReturnType=*/N->getType(), Intrinsic::spv_smoothstep,
+ArrayRef{N, I, Ng}, /*FMFSource=*/nullptr, "spv.faceforward");
+ }
}
return nullptr;
}
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
index 3a8a9b6fa2a45..b2332419dc034 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsic_helpers.h
@@ -126,6 +126,24 @@ template constexpr vector lit_impl(T
NDotL, T NDotH, T M) {
return Result;
}
+template constexpr T faceforward_impl(T N, T I, T Ng) {
+#if (__has_builtin(__builtin_spirv_faceforward))
+ return __builtin_spirv_faceforward(N, I, Ng);
+#else
+ return select(I * Ng < 0, N, -N);
+#endif
+}
+
+template
+constexpr vector faceforward_vec_impl(vector N, vector I,
+vector Ng) {
+#if (__has_builtin(__builtin_spirv_faceforward))
+ return __builtin_spirv_faceforward(N, I, Ng);
+#else
+ return select(dot(I, Ng) < 0, N, -N);
+#endif
+}
+
} // namespace __detail
} //
[clang] [llvm] [HLSL] Implement the `faceforward` intrinsic (PR #135878)
https://github.com/kmpeng created
https://github.com/llvm/llvm-project/pull/135878
Resolves #99114. There will be a follow-up PR on pattern matching later.
Tasks completed:
- Implement `faceforward` in `hlsl_intrinsics.h`/`hlsl_intrinsic_helpers.h`
- Implement `faceforward` SPIR-V target builtin in
`clang/include/clang/Basic/BuiltinsSPIRV.td`
- Add a SPIR-V fast path in `hlsl_intrinsic_helpers.h`
- Add sema checks for `faceforward` to `CheckSPIRVBuiltinFunctionCall` in
`clang/lib/Sema/SemaSPIRV.cpp`
- Add codegen for SPIR-V `faceforward` builtin to `EmitSPIRVBuiltinExpr` in
`SPIR.cpp`
- Add HLSL codegen tests to `clang/test/CodeGenHLSL/builtins/faceforward.hlsl`
- Add SPIRV builtin codegen tests to
`clang/test/CodeGenSPIRV/Builtins/faceforward.c`
- Add sema tests to `clang/test/SemaHLSL/BuiltIns/faceforward-errors.hlsl`
- Add spirv sema tests to `clang/test/SemaSPIRV/BuiltIns/faceforward-errors.c`
- Create the `int_spv_faceforward` intrinsic in `IntrinsicsSPIRV.td`
- In `SPIRVInstructionSelector.cpp` create the `faceforward` lowering and map
it to `int_spv_faceforward` in `SPIRVInstructionSelector::selectIntrinsic`
- Create SPIR-V backend test case in
`llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll`
Incomplete tasks:
- Create SPIR-V backend test case in
`llvm/test/CodeGen/SPIRV/opencl/faceforward.ll`
- Not applicable because the OpenCL SPIR-V extended instruction set does not
include a `faceforward` function
>From fc4bb1c5747cb26fafab8bffa53c7b21e377d09e Mon Sep 17 00:00:00 2001
From: kmpeng
Date: Mon, 7 Apr 2025 14:46:07 -0700
Subject: [PATCH 1/2] create int_spv_faceforward intrinsic, create faceforward
lowering & map to int_spv_faceforward, create SPIR-V backend test case
---
llvm/include/llvm/IR/IntrinsicsSPIRV.td | 1 +
.../Target/SPIRV/SPIRVInstructionSelector.cpp | 2 ++
.../SPIRV/hlsl-intrinsics/faceforward.ll | 35 +++
3 files changed, 38 insertions(+)
create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
diff --git a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
index 4389b86745d7f..77cca0a58424f 100644
--- a/llvm/include/llvm/IR/IntrinsicsSPIRV.td
+++ b/llvm/include/llvm/IR/IntrinsicsSPIRV.td
@@ -67,6 +67,7 @@ let TargetPrefix = "spv" in {
def int_spv_cross : DefaultAttrsIntrinsic<[llvm_anyfloat_ty],
[LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_degrees : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_distance : DefaultAttrsIntrinsic<[LLVMVectorElementType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>], [IntrNoMem]>;
+ def int_spv_faceforward : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>, LLVMMatchType<0>], [IntrNoMem]>;
def int_spv_frac : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty], [IntrNoMem]>;
def int_spv_lerp : DefaultAttrsIntrinsic<[LLVMMatchType<0>],
[llvm_anyfloat_ty, LLVMMatchType<0>,LLVMMatchType<0>],
[IntrNoMem] >;
diff --git a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
index 79f6b43f3aded..8304077f049a3 100644
--- a/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
+++ b/llvm/lib/Target/SPIRV/SPIRVInstructionSelector.cpp
@@ -3083,6 +3083,8 @@ bool SPIRVInstructionSelector::selectIntrinsic(Register
ResVReg,
return selectExtInst(ResVReg, ResType, I, CL::length, GL::Length);
case Intrinsic::spv_degrees:
return selectExtInst(ResVReg, ResType, I, CL::degrees, GL::Degrees);
+ case Intrinsic::spv_faceforward:
+return selectExtInst(ResVReg, ResType, I, GL::FaceForward);
case Intrinsic::spv_frac:
return selectExtInst(ResVReg, ResType, I, CL::fract, GL::Fract);
case Intrinsic::spv_normalize:
diff --git a/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
new file mode 100644
index 0..4b34adc88c0f2
--- /dev/null
+++ b/llvm/test/CodeGen/SPIRV/hlsl-intrinsics/faceforward.ll
@@ -0,0 +1,35 @@
+; RUN: llc -O0 -verify-machineinstrs -mtriple=spirv-unknown-unknown %s -o - |
FileCheck %s
+; RUN: %if spirv-tools %{ llc -O0 -mtriple=spirv-unknown-unknown %s -o -
-filetype=obj | spirv-val --target-env vulkan1.3 %}
+
+; Make sure SPIRV operation function calls for faceforward 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> @faceforward_half4(<4 x half> noundef %a, <4 x half>
noundef %b, <4 x half> noundef %c) {
+entry:
+ ; CHECK: %[[#]] = OpFunction %[[#vec4_float_16]] None %[[#]]
+ ; CHECK: %[[#arg0:]] = OpFunctionParameter %[[#vec4_float_16]]
+ ; CHECK: %[[#arg1:]] = OpFunctionParameter %[[#vec4_fl
