From 62d6beba976142a58c7c95afd84a5d632ab4cd84 Mon Sep 17 00:00:00 2001 From: Helena Kotas Date: Thu, 28 Mar 2024 14:41:33 -0700 Subject: [PATCH] [DXIL] Add lowering for `reversebits` and `trunc` (#86909) Add lowering of `llvm.bitreverse` and `llvm.trunc` intrinsics to DXIL ops. Fixes #86582 Fixes #86581 --- llvm/lib/Target/DirectX/DXIL.td | 6 +++++ llvm/test/CodeGen/DirectX/reversebits.ll | 31 ++++++++++++++++++++++++ llvm/test/CodeGen/DirectX/trunc.ll | 20 +++++++++++++++ llvm/test/CodeGen/DirectX/trunc_error.ll | 10 ++++++++ 4 files changed, 67 insertions(+) create mode 100644 llvm/test/CodeGen/DirectX/reversebits.ll create mode 100644 llvm/test/CodeGen/DirectX/trunc.ll create mode 100644 llvm/test/CodeGen/DirectX/trunc_error.ll diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index 1fd6f3ed044ecd..c5d7ee76275f86 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -292,6 +292,12 @@ def Round : DXILOpMapping<26, unary, int_round, def Floor : DXILOpMapping<27, unary, int_floor, "Returns the largest integer that is less than or equal to the input.", [llvm_halforfloat_ty, LLVMMatchType<0>]>; +def Trunc : DXILOpMapping<29, unary, int_trunc, + "Returns the specified value truncated to the integer component.", + [llvm_halforfloat_ty, LLVMMatchType<0>]>; +def Rbits : DXILOpMapping<30, unary, int_bitreverse, + "Returns the specified value with its bits reversed.", + [llvm_anyint_ty, LLVMMatchType<0>]>; def FMax : DXILOpMapping<35, binary, int_maxnum, "Float maximum. FMax(a,b) = a > b ? a : b">; def FMin : DXILOpMapping<36, binary, int_minnum, diff --git a/llvm/test/CodeGen/DirectX/reversebits.ll b/llvm/test/CodeGen/DirectX/reversebits.ll new file mode 100644 index 00000000000000..b6a7a1bc6152e3 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/reversebits.ll @@ -0,0 +1,31 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for reversebits are generated for all integer types. + +; Function Attrs: nounwind +define noundef i16 @test_bitreverse_short(i16 noundef %a) { +entry: +; CHECK:call i16 @dx.op.unary.i16(i32 30, i16 %{{.*}}) + %elt.bitreverse = call i16 @llvm.bitreverse.i16(i16 %a) + ret i16 %elt.bitreverse +} + +; Function Attrs: nounwind +define noundef i32 @test_bitreverse_int(i32 noundef %a) { +entry: +; CHECK:call i32 @dx.op.unary.i32(i32 30, i32 %{{.*}}) + %elt.bitreverse = call i32 @llvm.bitreverse.i32(i32 %a) + ret i32 %elt.bitreverse +} + +; Function Attrs: nounwind +define noundef i64 @test_bitreverse_long(i64 noundef %a) { +entry: +; CHECK:call i64 @dx.op.unary.i64(i32 30, i64 %{{.*}}) + %elt.bitreverse = call i64 @llvm.bitreverse.i64(i64 %a) + ret i64 %elt.bitreverse +} + +declare i16 @llvm.bitreverse.i16(i16) +declare i32 @llvm.bitreverse.i32(i32) +declare i64 @llvm.bitreverse.i64(i64) diff --git a/llvm/test/CodeGen/DirectX/trunc.ll b/llvm/test/CodeGen/DirectX/trunc.ll new file mode 100644 index 00000000000000..2072f28cef50a0 --- /dev/null +++ b/llvm/test/CodeGen/DirectX/trunc.ll @@ -0,0 +1,20 @@ +; RUN: opt -S -dxil-op-lower < %s | FileCheck %s + +; Make sure dxil operation function calls for trunc are generated for float and half. + +define noundef float @trunc_float(float noundef %a) { +entry: +; CHECK:call float @dx.op.unary.f32(i32 29, float %{{.*}}) + %elt.trunc = call float @llvm.trunc.f32(float %a) + ret float %elt.trunc +} + +define noundef half @trunc_half(half noundef %a) { +entry: +; CHECK:call half @dx.op.unary.f16(i32 29, half %{{.*}}) + %elt.trunc = call half @llvm.trunc.f16(half %a) + ret half %elt.trunc +} + +declare half @llvm.trunc.f16(half) +declare float @llvm.trunc.f32(float) diff --git a/llvm/test/CodeGen/DirectX/trunc_error.ll b/llvm/test/CodeGen/DirectX/trunc_error.ll new file mode 100644 index 00000000000000..751b0b94c280df --- /dev/null +++ b/llvm/test/CodeGen/DirectX/trunc_error.ll @@ -0,0 +1,10 @@ +; RUN: not opt -S -dxil-op-lower %s 2>&1 | FileCheck %s + +; DXIL operation trunc does not support double overload type +; CHECK: LLVM ERROR: Invalid Overload Type + +define noundef double @trunc_double(double noundef %a) { +entry: + %elt.trunc = call double @llvm.trunc.f64(double %a) + ret double %elt.trunc +}