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 #99134, though some SPIR-V changes still need to be made to complete the task. Below is how this PR addresses #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>
117 lines
4.4 KiB
LLVM
117 lines
4.4 KiB
LLVM
; 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
|
|
}
|