Files
clang-p2996/llvm/test/CodeGen/DirectX/length.ll
Joshua Batista ed5b0e1e69 Add length builtins and length HLSL function to DirectX Backend (#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 #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>
2024-08-02 21:16:24 -07:00

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
}