forked from llvm/llvm-project
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add length builtins and length HLSL function to DirectX Backend (llvm…
…#101256) This PR adds the length intrinsic and an HLSL function that uses it. The SPIRV implementation is left for a future PR. This PR addresses llvm#99134, though some SPIR-V changes still need to be made to complete the task. Below is how this PR addresses llvm#99134. - "Implement `length` clang builtin" was done by defining `HLSLL ength` in Builtins.td - "Link `length` clang builtin with hlsl_intrinsics.h" was done by using the alias attribute to make `length` an alias of `__builtin_hlsl_elementwise_length` in hlsl_intrinsics.h - "Add sema checks for `length` to `CheckHLSLBuiltinFunctionCall` in `SemaChecking.cpp` " was done, but in this case not in SemaChecking.cpp, rather SemaHLSL.cpp. A case was added to the builtin to check for semantic failures, and set `TheCall` up to have the right return type. - "Add codegen for `length` to `EmitHLSLBuiltinExpr` in `CGBuiltin.cpp`" was done. For scalars, fabs is emitted, otherwise, length is emitted. - "Add codegen tests to `clang/test/CodeGenHLSL/builtins/length.hlsl` was done to test that `length` in HLSL emits the right intrinsic. - "Add sema tests to `clang/test/SemaHLSL/BuiltIns/length-errors.hlsl`" was done to test for diagnostics emitted in SemaHLSL.cpp - "Create the `int_dx_length` intrinsic in `IntrinsicsDirectX.td`" was done. Specifying return types and parameter types was difficult, but `idot` was used for reference, and `llvm\include\llvm\IR\Intrinsics.td` contains all the ways to express return / parameter types. - "Create an intrinsic expansion of `int_dx_length` in `llvm/lib/Target/DirectX/DXILIntrinsicExpansion.cpp`" was done, and was mostly derived by looking at `TranslateLength` in `HLOperationLower.cpp` in the DXC codebase. - "Create the `length.ll` and `length_errors.ll` tests in `llvm/test/CodeGen/DirectX/`" was done by taking the DXIL output of `clang/test/CodeGenHLSL/builtins/length.hlsl` and running `opt -S -dxil-intrinsic-expansion` and ` opt -S -dxil-op-lower` on it, checking for how the length intrinsic was either expanded or lowered. - "Create the `int_spv_length` intrinsic in `IntrinsicsSPIRV.td`" was done by copying `IntrinsicsDirectX.td`. --------- Co-authored-by: Justin Bogner <mail@justinbogner.com>
- Loading branch information
1 parent
6a72bb7
commit 39ebc22
Showing
14 changed files
with
357 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ | ||
// RUN: dxil-pc-shadermodel6.3-library %s -fnative-half-type \ | ||
// RUN: -emit-llvm -disable-llvm-passes -o - | FileCheck %s \ | ||
// RUN: --check-prefixes=CHECK,NATIVE_HALF | ||
// RUN: %clang_cc1 -finclude-default-header -x hlsl -triple \ | ||
// RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ | ||
// RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF | ||
|
||
// NATIVE_HALF: define noundef half @ | ||
// NATIVE_HALF: call half @llvm.fabs.f16(half | ||
// NO_HALF: call float @llvm.fabs.f32(float | ||
// NATIVE_HALF: ret half | ||
// NO_HALF: ret float | ||
half test_length_half(half p0) | ||
{ | ||
return length(p0); | ||
} | ||
// NATIVE_HALF: define noundef half @ | ||
// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v2f16 | ||
// NO_HALF: %hlsl.length = call float @llvm.dx.length.v2f32( | ||
// NATIVE_HALF: ret half %hlsl.length | ||
// NO_HALF: ret float %hlsl.length | ||
half test_length_half2(half2 p0) | ||
{ | ||
return length(p0); | ||
} | ||
// NATIVE_HALF: define noundef half @ | ||
// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v3f16 | ||
// NO_HALF: %hlsl.length = call float @llvm.dx.length.v3f32( | ||
// NATIVE_HALF: ret half %hlsl.length | ||
// NO_HALF: ret float %hlsl.length | ||
half test_length_half3(half3 p0) | ||
{ | ||
return length(p0); | ||
} | ||
// NATIVE_HALF: define noundef half @ | ||
// NATIVE_HALF: %hlsl.length = call half @llvm.dx.length.v4f16 | ||
// NO_HALF: %hlsl.length = call float @llvm.dx.length.v4f32( | ||
// NATIVE_HALF: ret half %hlsl.length | ||
// NO_HALF: ret float %hlsl.length | ||
half test_length_half4(half4 p0) | ||
{ | ||
return length(p0); | ||
} | ||
|
||
// CHECK: define noundef float @ | ||
// CHECK: call float @llvm.fabs.f32(float | ||
// CHECK: ret float | ||
float test_length_float(float p0) | ||
{ | ||
return length(p0); | ||
} | ||
// CHECK: define noundef float @ | ||
// CHECK: %hlsl.length = call float @llvm.dx.length.v2f32( | ||
// CHECK: ret float %hlsl.length | ||
float test_length_float2(float2 p0) | ||
{ | ||
return length(p0); | ||
} | ||
// CHECK: define noundef float @ | ||
// CHECK: %hlsl.length = call float @llvm.dx.length.v3f32( | ||
// CHECK: ret float %hlsl.length | ||
float test_length_float3(float3 p0) | ||
{ | ||
return length(p0); | ||
} | ||
// CHECK: define noundef float @ | ||
// CHECK: %hlsl.length = call float @llvm.dx.length.v4f32( | ||
// CHECK: ret float %hlsl.length | ||
float test_length_float4(float4 p0) | ||
{ | ||
return length(p0); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -verify-ignore-unexpected | ||
|
||
void test_too_few_arg() | ||
{ | ||
return __builtin_hlsl_length(); | ||
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}} | ||
} | ||
|
||
void test_too_many_arg(float2 p0) | ||
{ | ||
return __builtin_hlsl_length(p0, p0); | ||
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}} | ||
} | ||
|
||
bool builtin_bool_to_float_type_promotion(bool p1) | ||
{ | ||
return __builtin_hlsl_length(p1); | ||
// expected-error@-1 {passing 'bool' to parameter of incompatible type 'float'}} | ||
} | ||
|
||
bool builtin_length_int_to_float_promotion(int p1) | ||
{ | ||
return __builtin_hlsl_length(p1); | ||
// expected-error@-1 {{passing 'int' to parameter of incompatible type 'float'}} | ||
} | ||
|
||
bool2 builtin_length_int2_to_float2_promotion(int2 p1) | ||
{ | ||
return __builtin_hlsl_length(p1); | ||
// expected-error@-1 {{passing 'int2' (aka 'vector<int, 2>') to parameter of incompatible type '__attribute__((__vector_size__(2 * sizeof(float)))) float' (vector of 2 'float' values)}} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
; RUN: opt -S -dxil-intrinsic-expansion < %s | FileCheck %s --check-prefixes=CHECK,EXPCHECK | ||
; RUN: opt -S -dxil-op-lower -mtriple=dxil-pc-shadermodel6.3-library < %s | FileCheck %s --check-prefixes=CHECK,DOPCHECK | ||
|
||
; Make sure dxil operation function calls for length are generated for half/float. | ||
|
||
declare half @llvm.fabs.f16(half) | ||
declare half @llvm.dx.length.v2f16(<2 x half>) | ||
declare half @llvm.dx.length.v3f16(<3 x half>) | ||
declare half @llvm.dx.length.v4f16(<4 x half>) | ||
|
||
declare float @llvm.fabs.f32(float) | ||
declare float @llvm.dx.length.v2f32(<2 x float>) | ||
declare float @llvm.dx.length.v3f32(<3 x float>) | ||
declare float @llvm.dx.length.v4f32(<4 x float>) | ||
|
||
define noundef half @test_length_half2(<2 x half> noundef %p0) { | ||
entry: | ||
; CHECK: extractelement <2 x half> %{{.*}}, i64 0 | ||
; CHECK: fmul half %{{.*}}, %{{.*}} | ||
; CHECK: extractelement <2 x half> %{{.*}}, i64 1 | ||
; CHECK: fmul half %{{.*}}, %{{.*}} | ||
; CHECK: fadd half %{{.*}}, %{{.*}} | ||
; EXPCHECK: call half @llvm.sqrt.f16(half %{{.*}}) | ||
; DOPCHECK: call half @dx.op.unary.f16(i32 24, half %{{.*}}) | ||
|
||
%hlsl.length = call half @llvm.dx.length.v2f16(<2 x half> %p0) | ||
ret half %hlsl.length | ||
} | ||
|
||
define noundef half @test_length_half3(<3 x half> noundef %p0) { | ||
entry: | ||
; CHECK: extractelement <3 x half> %{{.*}}, i64 0 | ||
; CHECK: fmul half %{{.*}}, %{{.*}} | ||
; CHECK: extractelement <3 x half> %{{.*}}, i64 1 | ||
; CHECK: fmul half %{{.*}}, %{{.*}} | ||
; CHECK: fadd half %{{.*}}, %{{.*}} | ||
; CHECK: extractelement <3 x half> %{{.*}}, i64 2 | ||
; CHECK: fmul half %{{.*}}, %{{.*}} | ||
; CHECK: fadd half %{{.*}}, %{{.*}} | ||
; EXPCHECK: call half @llvm.sqrt.f16(half %{{.*}}) | ||
; DOPCHECK: call half @dx.op.unary.f16(i32 24, half %{{.*}}) | ||
|
||
%hlsl.length = call half @llvm.dx.length.v3f16(<3 x half> %p0) | ||
ret half %hlsl.length | ||
} | ||
|
||
define noundef half @test_length_half4(<4 x half> noundef %p0) { | ||
entry: | ||
; CHECK: extractelement <4 x half> %{{.*}}, i64 0 | ||
; CHECK: fmul half %{{.*}}, %{{.*}} | ||
; CHECK: extractelement <4 x half> %{{.*}}, i64 1 | ||
; CHECK: fmul half %{{.*}}, %{{.*}} | ||
; CHECK: fadd half %{{.*}}, %{{.*}} | ||
; CHECK: extractelement <4 x half> %{{.*}}, i64 2 | ||
; CHECK: fmul half %{{.*}}, %{{.*}} | ||
; CHECK: fadd half %{{.*}}, %{{.*}} | ||
; CHECK: extractelement <4 x half> %{{.*}}, i64 3 | ||
; CHECK: fmul half %{{.*}}, %{{.*}} | ||
; CHECK: fadd half %{{.*}}, %{{.*}} | ||
; EXPCHECK: call half @llvm.sqrt.f16(half %{{.*}}) | ||
; DOPCHECK: call half @dx.op.unary.f16(i32 24, half %{{.*}}) | ||
|
||
%hlsl.length = call half @llvm.dx.length.v4f16(<4 x half> %p0) | ||
ret half %hlsl.length | ||
} | ||
|
||
define noundef float @test_length_float2(<2 x float> noundef %p0) { | ||
entry: | ||
; CHECK: extractelement <2 x float> %{{.*}}, i64 0 | ||
; CHECK: fmul float %{{.*}}, %{{.*}} | ||
; CHECK: extractelement <2 x float> %{{.*}}, i64 1 | ||
; CHECK: fmul float %{{.*}}, %{{.*}} | ||
; CHECK: fadd float %{{.*}}, %{{.*}} | ||
; EXPCHECK: call float @llvm.sqrt.f32(float %{{.*}}) | ||
; DOPCHECK: call float @dx.op.unary.f32(i32 24, float %{{.*}}) | ||
|
||
%hlsl.length = call float @llvm.dx.length.v2f32(<2 x float> %p0) | ||
ret float %hlsl.length | ||
} | ||
|
||
define noundef float @test_length_float3(<3 x float> noundef %p0) { | ||
entry: | ||
; CHECK: extractelement <3 x float> %{{.*}}, i64 0 | ||
; CHECK: fmul float %{{.*}}, %{{.*}} | ||
; CHECK: extractelement <3 x float> %{{.*}}, i64 1 | ||
; CHECK: fmul float %{{.*}}, %{{.*}} | ||
; CHECK: fadd float %{{.*}}, %{{.*}} | ||
; CHECK: extractelement <3 x float> %{{.*}}, i64 2 | ||
; CHECK: fmul float %{{.*}}, %{{.*}} | ||
; CHECK: fadd float %{{.*}}, %{{.*}} | ||
; EXPCHECK: call float @llvm.sqrt.f32(float %{{.*}}) | ||
; DOPCHECK: call float @dx.op.unary.f32(i32 24, float %{{.*}}) | ||
|
||
%hlsl.length = call float @llvm.dx.length.v3f32(<3 x float> %p0) | ||
ret float %hlsl.length | ||
} | ||
|
||
define noundef float @test_length_float4(<4 x float> noundef %p0) { | ||
entry: | ||
; CHECK: extractelement <4 x float> %{{.*}}, i64 0 | ||
; CHECK: fmul float %{{.*}}, %{{.*}} | ||
; CHECK: extractelement <4 x float> %{{.*}}, i64 1 | ||
; CHECK: fmul float %{{.*}}, %{{.*}} | ||
; CHECK: fadd float %{{.*}}, %{{.*}} | ||
; CHECK: extractelement <4 x float> %{{.*}}, i64 2 | ||
; CHECK: fmul float %{{.*}}, %{{.*}} | ||
; CHECK: fadd float %{{.*}}, %{{.*}} | ||
; CHECK: extractelement <4 x float> %{{.*}}, i64 3 | ||
; CHECK: fmul float %{{.*}}, %{{.*}} | ||
; CHECK: fadd float %{{.*}}, %{{.*}} | ||
; EXPCHECK: call float @llvm.sqrt.f32(float %{{.*}}) | ||
; DOPCHECK: call float @dx.op.unary.f32(i32 24, float %{{.*}}) | ||
|
||
%hlsl.length = call float @llvm.dx.length.v4f32(<4 x float> %p0) | ||
ret float %hlsl.length | ||
} |
Oops, something went wrong.