diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -9050,6 +9050,10 @@ } bool ASTContext::canBuiltinBeRedeclared(const FunctionDecl *FD) const { + // Allow redecl custom type checking builtin for HLSL. + if (LangOpts.HLSL && FD->getBuiltinID() != Builtin::NotBuiltin && + BuiltinInfo.hasCustomTypechecking(FD->getBuiltinID())) + return true; return BuiltinInfo.canBeRedeclared(FD->getBuiltinID()); } diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h b/clang/lib/Headers/hlsl/hlsl_intrinsics.h --- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h +++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h @@ -13,13 +13,51 @@ __attribute__((clang_builtin_alias(__builtin_hlsl_wave_active_count_bits))) uint WaveActiveCountBits(bool bBit); -__attribute__((clang_builtin_alias(__builtin_abs))) int abs(int In); -__attribute__((clang_builtin_alias(__builtin_labs))) int64_t abs(int64_t In); -__attribute__((clang_builtin_alias(__builtin_fabsf))) float abs(float In); -__attribute__((clang_builtin_alias(__builtin_fabs))) double abs(double In); - #ifdef __HLSL_ENABLE_16_BIT -__attribute__((clang_builtin_alias(__builtin_fabsf16))) half abs(half In); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +int16_t abs(int16_t); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +int16_t2 abs(int16_t2); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +int16_t3 abs(int16_t3); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +int16_t4 abs(int16_t4); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) half abs(half); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +half2 abs(half2); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +half3 abs(half3); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +half4 abs(half4); #endif +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) int abs(int); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) int2 abs(int2); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) int3 abs(int3); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) int4 abs(int4); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) float +abs(float); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +float2 abs(float2); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +float3 abs(float3); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +float4 abs(float4); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +int64_t abs(int64_t); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +int64_t2 abs(int64_t2); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +int64_t3 abs(int64_t3); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +int64_t4 abs(int64_t4); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) double +abs(double); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +double2 abs(double2); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +double3 abs(double3); +__attribute__((clang_builtin_alias(__builtin_elementwise_abs))) +double4 abs(double4); + #endif //_HLSL_HLSL_INTRINSICS_H_ diff --git a/clang/test/CodeGenHLSL/builtins/abs.hlsl b/clang/test/CodeGenHLSL/builtins/abs.hlsl --- a/clang/test/CodeGenHLSL/builtins/abs.hlsl +++ b/clang/test/CodeGenHLSL/builtins/abs.hlsl @@ -1,57 +1,138 @@ // RUN: %clang_cc1 -std=hlsl2021 -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: -emit-llvm -disable-llvm-passes -O3 -o - | FileCheck %s // RUN: %clang_cc1 -std=hlsl2021 -finclude-default-header -x hlsl -triple \ // RUN: dxil-pc-shadermodel6.3-library %s -emit-llvm -disable-llvm-passes \ -// RUN: -o - | FileCheck %s --check-prefix=NO_HALF +// RUN: -D__HLSL_ENABLE_16_BIT -o - | FileCheck %s --check-prefix=NO_HALF -float abs_float(float X) { - return abs(X); +// CHECK: define noundef signext i16 @ +// FIXME: int16_t is promoted to i32 now. Change to abs.i16 once it is fixed. +// CHECK: call i32 @llvm.abs.i32( +int16_t test_abs_int16_t ( int16_t p0 ) { + return abs ( p0 ); } - -// CHECK: define noundef float @"?abs_float@@YAMM@Z"( -// CHECK: call float @llvm.fabs.f32(float %0) - -double abs_double(double X) { - return abs(X); +// CHECK: define noundef <2 x i16> @ +// CHECK: call <2 x i16> @llvm.abs.v2i16( +int16_t2 test_abs_int16_t2 ( int16_t2 p0 ) { + return abs ( p0 ); } - -// CHECK: define noundef double @"?abs_double@@YANN@Z"( -// CHECK: call double @llvm.fabs.f64(double %0) - -half abs_half(half X) { - return abs(X); +// CHECK: define noundef <3 x i16> @ +// CHECK: call <3 x i16> @llvm.abs.v3i16( +int16_t3 test_abs_int16_t3 ( int16_t3 p0 ) { + return abs ( p0 ); } - -// CHECK: define noundef half @"?abs_half@@YA$f16@$f16@@Z"( -// CHECK: call half @llvm.fabs.f16(half %0) -// NO_HALF: define noundef float @"?abs_half@@YA$halff@$halff@@Z"( +// CHECK: define noundef <4 x i16> @ +// CHECK: call <4 x i16> @llvm.abs.v4i16( +int16_t4 test_abs_int16_t4 ( int16_t4 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef half @ +// CHECK: call half @llvm.fabs.f16( +// NO_HALF: define noundef float @"?test_abs_half@@YA$halff@$halff@@Z"( // NO_HALF: call float @llvm.fabs.f32(float %0) - -int abs_int(int X) { - return abs(X); +half test_abs_half ( half p0 ) { + return abs ( p0 ); } - -// NO_HALF: define noundef i32 @"?abs_int@@YAHH@Z"(i32 -// CHECK: define noundef i32 @"?abs_int@@YAHH@Z"(i32 -// CHECK: [[A_ADDR:%.*]] = alloca i32, align 4 -// CHECK-NEXT: store i32 [[A:%.*]], ptr [[A_ADDR]], align 4 -// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A_ADDR]], align 4 -// CHECK-NEXT: [[NEG:%.*]] = sub nsw i32 0, [[TMP0]] -// CHECK-NEXT: [[ABSCOND:%.*]] = icmp slt i32 [[TMP0]], 0 -// CHECK-NEXT: [[ABS:%.*]] = select i1 [[ABSCOND]], i32 [[NEG]], i32 [[TMP0]] -// CHECK-NEXT: ret i32 [[ABS]] - -int64_t abs_int64(int64_t X) { - return abs(X); +// CHECK: define noundef <2 x half> @ +// CHECK: call <2 x half> @llvm.fabs.v2f16( +// NO_HALF: define noundef <2 x float> @"?test_abs_half2@@YAT?$__vector@$halff@$01@__clang@@T12@@Z"( +// NO_HALF: call <2 x float> @llvm.fabs.v2f32( +half2 test_abs_half2 ( half2 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <3 x half> @ +// CHECK: call <3 x half> @llvm.fabs.v3f16( +// NO_HALF: define noundef <3 x float> @"?test_abs_half3@@YAT?$__vector@$halff@$02@__clang@@T12@@Z"( +// NO_HALF: call <3 x float> @llvm.fabs.v3f32( +half3 test_abs_half3 ( half3 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <4 x half> @ +// CHECK: call <4 x half> @llvm.fabs.v4f16( +// NO_HALF: define noundef <4 x float> @"?test_abs_half4@@YAT?$__vector@$halff@$03@__clang@@T12@@Z"( +// NO_HALF: call <4 x float> @llvm.fabs.v4f32( +half4 test_abs_half4 ( half4 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef i32 @ +// CHECK: call i32 @llvm.abs.i32( +// NO_HALF: define noundef i32 @"?test_abs_int@@YAHH@Z" +int test_abs_int ( int p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <2 x i32> @ +// CHECK: call <2 x i32> @llvm.abs.v2i32( +int2 test_abs_int2 ( int2 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <3 x i32> @ +// CHECK: call <3 x i32> @llvm.abs.v3i32( +int3 test_abs_int3 ( int3 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <4 x i32> @ +// CHECK: call <4 x i32> @llvm.abs.v4i32( +int4 test_abs_int4 ( int4 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef float @ +// CHECK: call float @llvm.fabs.f32( +float test_abs_float ( float p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <2 x float> @ +// CHECK: call <2 x float> @llvm.fabs.v2f32( +float2 test_abs_float2 ( float2 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <3 x float> @ +// CHECK: call <3 x float> @llvm.fabs.v3f32( +float3 test_abs_float3 ( float3 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <4 x float> @ +// CHECK: call <4 x float> @llvm.fabs.v4f32( +float4 test_abs_float4 ( float4 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef i64 @ +// CHECK: call i64 @llvm.abs.i64( +int64_t test_abs_int64_t ( int64_t p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <2 x i64> @ +// CHECK: call <2 x i64> @llvm.abs.v2i64( +int64_t2 test_abs_int64_t2 ( int64_t2 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <3 x i64> @ +// CHECK: call <3 x i64> @llvm.abs.v3i64( +int64_t3 test_abs_int64_t3 ( int64_t3 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <4 x i64> @ +// CHECK: call <4 x i64> @llvm.abs.v4i64( +int64_t4 test_abs_int64_t4 ( int64_t4 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef double @ +// CHECK: call double @llvm.fabs.f64( +double test_abs_double ( double p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <2 x double> @ +// CHECK: call <2 x double> @llvm.fabs.v2f64( +double2 test_abs_double2 ( double2 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <3 x double> @ +// CHECK: call <3 x double> @llvm.fabs.v3f64( +double3 test_abs_double3 ( double3 p0 ) { + return abs ( p0 ); +} +// CHECK: define noundef <4 x double> @ +// CHECK: call <4 x double> @llvm.fabs.v4f64( +double4 test_abs_double4 ( double4 p0 ) { + return abs ( p0 ); } - -// CHECK: define noundef i64 @"?abs_int64@@YAJJ@Z"(i64 -// CHECK: [[A_ADDR:%.*]] = alloca i64, align 8 -// CHECK-NEXT: store i64 [[A:%.*]], ptr [[A_ADDR]], align 8 -// CHECK-NEXT: [[TMP0:%.*]] = load i64, ptr [[A_ADDR]], align 8 -// CHECK-NEXT: [[NEG:%.*]] = sub nsw i64 0, [[TMP0]] -// CHECK-NEXT: [[ABSCOND:%.*]] = icmp slt i64 [[TMP0]], 0 -// CHECK-NEXT: [[ABS:%.*]] = select i1 [[ABSCOND]], i64 [[NEG]], i64 [[TMP0]] -// CHECK-NEXT: ret i64 [[ABS]]