https://github.com/farzonl created https://github.com/llvm/llvm-project/pull/87078
fixes #86999 >From bbb30f792bb9fb28f68079146783d6e8d1f0682b Mon Sep 17 00:00:00 2001 From: Farzon Lotfi <farzonlo...@microsoft.com> Date: Fri, 29 Mar 2024 10:44:37 -0400 Subject: [PATCH] [HLSL][DXIL] HLSL's `round` should follow `roundeven` behavior fixes #86999 --- clang/lib/Headers/hlsl/hlsl_intrinsics.h | 16 +++---- clang/lib/Sema/SemaChecking.cpp | 1 + clang/test/CodeGenHLSL/builtins/round.hlsl | 48 +++++++++---------- .../BuiltIns/half-float-only-errors.hlsl | 1 + llvm/lib/Target/DirectX/DXIL.td | 2 +- llvm/test/CodeGen/DirectX/round.ll | 35 +++++--------- llvm/test/CodeGen/DirectX/round_error.ll | 4 +- 7 files changed, 50 insertions(+), 57 deletions(-) diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h index a34e72402c0e64..9fb6204f90c9a8 100644 --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -1248,25 +1248,25 @@ float4 rsqrt(float4); /// rounded to the nearest even value. _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) half round(half); _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) half2 round(half2); _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) half3 round(half3); _HLSL_16BIT_AVAILABILITY(shadermodel, 6.2) -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) half4 round(half4); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) float round(float); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) float2 round(float2); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) float3 round(float3); -_HLSL_BUILTIN_ALIAS(__builtin_elementwise_round) +_HLSL_BUILTIN_ALIAS(__builtin_elementwise_roundeven) float4 round(float4); //===----------------------------------------------------------------------===// diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 2e4e18a3ebf759..2684535d8e53d1 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5650,6 +5650,7 @@ bool Sema::CheckHLSLBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall) { case Builtin::BI__builtin_elementwise_log2: case Builtin::BI__builtin_elementwise_log10: case Builtin::BI__builtin_elementwise_pow: + case Builtin::BI__builtin_elementwise_roundeven: case Builtin::BI__builtin_elementwise_sin: case Builtin::BI__builtin_elementwise_sqrt: case Builtin::BI__builtin_elementwise_trunc: { diff --git a/clang/test/CodeGenHLSL/builtins/round.hlsl b/clang/test/CodeGenHLSL/builtins/round.hlsl index b9f35bd3712d18..33d761dbdfbeae 100644 --- a/clang/test/CodeGenHLSL/builtins/round.hlsl +++ b/clang/test/CodeGenHLSL/builtins/round.hlsl @@ -7,47 +7,47 @@ // RUN: -o - | FileCheck %s --check-prefixes=CHECK,NO_HALF // NATIVE_HALF: define noundef half @ -// NATIVE_HALF: %elt.round = call half @llvm.round.f16( -// NATIVE_HALF: ret half %elt.round +// NATIVE_HALF: %elt.roundeven = call half @llvm.roundeven.f16( +// NATIVE_HALF: ret half %elt.roundeven // NO_HALF: define noundef float @"?test_round_half@@YA$halff@$halff@@Z"( -// NO_HALF: %elt.round = call float @llvm.round.f32( -// NO_HALF: ret float %elt.round +// NO_HALF: %elt.roundeven = call float @llvm.roundeven.f32( +// NO_HALF: ret float %elt.roundeven half test_round_half(half p0) { return round(p0); } // NATIVE_HALF: define noundef <2 x half> @ -// NATIVE_HALF: %elt.round = call <2 x half> @llvm.round.v2f16 -// NATIVE_HALF: ret <2 x half> %elt.round +// NATIVE_HALF: %elt.roundeven = call <2 x half> @llvm.roundeven.v2f16 +// NATIVE_HALF: ret <2 x half> %elt.roundeven // NO_HALF: define noundef <2 x float> @ -// NO_HALF: %elt.round = call <2 x float> @llvm.round.v2f32( -// NO_HALF: ret <2 x float> %elt.round +// NO_HALF: %elt.roundeven = call <2 x float> @llvm.roundeven.v2f32( +// NO_HALF: ret <2 x float> %elt.roundeven half2 test_round_half2(half2 p0) { return round(p0); } // NATIVE_HALF: define noundef <3 x half> @ -// NATIVE_HALF: %elt.round = call <3 x half> @llvm.round.v3f16 -// NATIVE_HALF: ret <3 x half> %elt.round +// NATIVE_HALF: %elt.roundeven = call <3 x half> @llvm.roundeven.v3f16 +// NATIVE_HALF: ret <3 x half> %elt.roundeven // NO_HALF: define noundef <3 x float> @ -// NO_HALF: %elt.round = call <3 x float> @llvm.round.v3f32( -// NO_HALF: ret <3 x float> %elt.round +// NO_HALF: %elt.roundeven = call <3 x float> @llvm.roundeven.v3f32( +// NO_HALF: ret <3 x float> %elt.roundeven half3 test_round_half3(half3 p0) { return round(p0); } // NATIVE_HALF: define noundef <4 x half> @ -// NATIVE_HALF: %elt.round = call <4 x half> @llvm.round.v4f16 -// NATIVE_HALF: ret <4 x half> %elt.round +// NATIVE_HALF: %elt.roundeven = call <4 x half> @llvm.roundeven.v4f16 +// NATIVE_HALF: ret <4 x half> %elt.roundeven // NO_HALF: define noundef <4 x float> @ -// NO_HALF: %elt.round = call <4 x float> @llvm.round.v4f32( -// NO_HALF: ret <4 x float> %elt.round +// NO_HALF: %elt.roundeven = call <4 x float> @llvm.roundeven.v4f32( +// NO_HALF: ret <4 x float> %elt.roundeven half4 test_round_half4(half4 p0) { return round(p0); } // CHECK: define noundef float @ -// CHECK: %elt.round = call float @llvm.round.f32( -// CHECK: ret float %elt.round +// CHECK: %elt.roundeven = call float @llvm.roundeven.f32( +// CHECK: ret float %elt.roundeven float test_round_float(float p0) { return round(p0); } // CHECK: define noundef <2 x float> @ -// CHECK: %elt.round = call <2 x float> @llvm.round.v2f32 -// CHECK: ret <2 x float> %elt.round +// CHECK: %elt.roundeven = call <2 x float> @llvm.roundeven.v2f32 +// CHECK: ret <2 x float> %elt.roundeven float2 test_round_float2(float2 p0) { return round(p0); } // CHECK: define noundef <3 x float> @ -// CHECK: %elt.round = call <3 x float> @llvm.round.v3f32 -// CHECK: ret <3 x float> %elt.round +// CHECK: %elt.roundeven = call <3 x float> @llvm.roundeven.v3f32 +// CHECK: ret <3 x float> %elt.roundeven float3 test_round_float3(float3 p0) { return round(p0); } // CHECK: define noundef <4 x float> @ -// CHECK: %elt.round = call <4 x float> @llvm.round.v4f32 -// CHECK: ret <4 x float> %elt.round +// CHECK: %elt.roundeven = call <4 x float> @llvm.roundeven.v4f32 +// CHECK: ret <4 x float> %elt.roundeven float4 test_round_float4(float4 p0) { return round(p0); } diff --git a/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl index c56986b7f86225..98c02c38675f4e 100644 --- a/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl +++ b/clang/test/SemaHLSL/BuiltIns/half-float-only-errors.hlsl @@ -8,6 +8,7 @@ // RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_log10 // RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sin // RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_sqrt +// RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_roundeven // RUN: %clang_cc1 -finclude-default-header -triple dxil-pc-shadermodel6.6-library %s -fnative-half-type -emit-llvm -disable-llvm-passes -verify -DTEST_FUNC=__builtin_elementwise_trunc double2 test_double_builtin(double2 p0) { diff --git a/llvm/lib/Target/DirectX/DXIL.td b/llvm/lib/Target/DirectX/DXIL.td index c5d7ee76275f86..a131bcc7dafe9a 100644 --- a/llvm/lib/Target/DirectX/DXIL.td +++ b/llvm/lib/Target/DirectX/DXIL.td @@ -285,7 +285,7 @@ def RSqrt : DXILOpMapping<25, unary, int_dx_rsqrt, "Returns the reciprocal of the square root of the specified value." "rsqrt(x) = 1 / sqrt(x).", [llvm_halforfloat_ty, LLVMMatchType<0>]>; -def Round : DXILOpMapping<26, unary, int_round, +def Round : DXILOpMapping<26, unary, int_roundeven, "Returns the input rounded to the nearest integer" "within a floating-point type.", [llvm_halforfloat_ty, LLVMMatchType<0>]>; diff --git a/llvm/test/CodeGen/DirectX/round.ll b/llvm/test/CodeGen/DirectX/round.ll index 5d53a794b763a6..e0a3772ebca8fa 100644 --- a/llvm/test/CodeGen/DirectX/round.ll +++ b/llvm/test/CodeGen/DirectX/round.ll @@ -1,31 +1,22 @@ ; RUN: opt -S -dxil-op-lower < %s | FileCheck %s ; Make sure dxil operation function calls for round are generated for float and half. -; CHECK:call float @dx.op.unary.f32(i32 26, float %{{.*}}) -; CHECK:call half @dx.op.unary.f16(i32 26, half %{{.*}}) -target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64" -target triple = "dxil-pc-shadermodel6.7-library" - -; Function Attrs: noinline nounwind optnone -define noundef float @round_float(float noundef %a) #0 { +; CHECK-LABEL: round_half +define noundef half @round_half(half noundef %a) { entry: - %a.addr = alloca float, align 4 - store float %a, ptr %a.addr, align 4 - %0 = load float, ptr %a.addr, align 4 - %elt.round = call float @llvm.round.f32(float %0) - ret float %elt.round +; CHECK: call half @dx.op.unary.f16(i32 26, half %{{.*}}) + %elt.roundeven = call half @llvm.roundeven.f16(half %a) + ret half %elt.roundeven } -; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn -declare float @llvm.round.f32(float) #1 - -; Function Attrs: noinline nounwind optnone -define noundef half @round_half(half noundef %a) #0 { +; CHECK-LABEL: round_float +define noundef float @round_float(float noundef %a) { entry: - %a.addr = alloca half, align 2 - store half %a, ptr %a.addr, align 2 - %0 = load half, ptr %a.addr, align 2 - %elt.round = call half @llvm.round.f16(half %0) - ret half %elt.round +; CHECK: call float @dx.op.unary.f32(i32 26, float %{{.*}}) + %elt.roundeven = call float @llvm.roundeven.f32(float %a) + ret float %elt.roundeven } + +declare half @llvm.roundeven.f16(half) +declare float @llvm.roundeven.f32(float) diff --git a/llvm/test/CodeGen/DirectX/round_error.ll b/llvm/test/CodeGen/DirectX/round_error.ll index 3bd87b2bbf0200..2d27fbb5ee20de 100644 --- a/llvm/test/CodeGen/DirectX/round_error.ll +++ b/llvm/test/CodeGen/DirectX/round_error.ll @@ -8,6 +8,6 @@ entry: %a.addr = alloca double, align 8 store double %a, ptr %a.addr, align 8 %0 = load double, ptr %a.addr, align 8 - %elt.round = call double @llvm.round.f64(double %0) - ret double %elt.round + %elt.roundeven = call double @llvm.roundeven.f64(double %0) + ret double %elt.roundeven } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits