[HLSL] [clang] Add vector version of abs for HLSL

Add vector version of abs as
```
__attribute__((clang_builtin_alias(__builtin_elementwise_abs)))
int2 abs (int2 );
__attribute__((clang_builtin_alias(__builtin_elementwise_abs)))
int3 abs (int3 );
```
To make this work.
Allowed custom type checking builtins to be recelareable.

Reviewed By: RKSimon

Differential Revision: https://reviews.llvm.org/D133737
This commit is contained in:
Xiang Li 2022-09-12 15:58:32 -07:00
parent 71b12030b9
commit edbf36c5e9
3 changed files with 174 additions and 51 deletions

View File

@ -9050,6 +9050,10 @@ TypedefDecl *ASTContext::getBuiltinMSVaListDecl() const {
}
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());
}

View File

@ -13,13 +13,51 @@ __attribute__((availability(shadermodel, introduced = 6.0)))
__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_

View File

@ -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]]