Skip to content

Commit 2823377

Browse files
committed
[Clang] Add elementwise abs builtin.
This patch implements __builtin_elementwise_abs as specified in D111529. Reviewed By: aaron.ballman, scanon Differential Revision: https://reviews.llvm.org/D111986 (cherry-picked from 01870d5)
1 parent bfd3cb1 commit 2823377

File tree

8 files changed

+115
-2
lines changed

8 files changed

+115
-2
lines changed

clang/include/clang/Basic/Builtins.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,6 +645,7 @@ BUILTIN(__builtin_alloca, "v*z" , "Fn")
645645
BUILTIN(__builtin_alloca_with_align, "v*zIz", "Fn")
646646
BUILTIN(__builtin_call_with_static_chain, "v.", "nt")
647647

648+
BUILTIN(__builtin_elementwise_abs, "v.", "nct")
648649
BUILTIN(__builtin_elementwise_max, "v.", "nct")
649650
BUILTIN(__builtin_elementwise_min, "v.", "nct")
650651

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11355,7 +11355,8 @@ def err_builtin_launder_invalid_arg : Error<
1135511355
def err_builtin_invalid_arg_type: Error <
1135611356
"%ordinal0 argument must be a "
1135711357
"%select{vector, integer or floating point type|matrix|"
11358-
"pointer to a valid matrix element type}1 (was %2)">;
11358+
"pointer to a valid matrix element type|"
11359+
"signed integer or floating point type}1 (was %2)">;
1135911360

1136011361
def err_builtin_matrix_disabled: Error<
1136111362
"matrix types extension is disabled. Pass -fenable-matrix to enable it">;

clang/include/clang/Sema/Sema.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12679,6 +12679,7 @@ class Sema final {
1267912679
bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc);
1268012680

1268112681
bool SemaBuiltinElementwiseMath(CallExpr *TheCall);
12682+
bool SemaBuiltinElementwiseMathOneArg(CallExpr *TheCall);
1268212683

1268312684
// Matrix builtin handling.
1268412685
ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall,

clang/lib/CodeGen/CGBuiltin.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3101,6 +3101,17 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
31013101
return RValue::get(V);
31023102
}
31033103

3104+
case Builtin::BI__builtin_elementwise_abs: {
3105+
Value *Op0 = EmitScalarExpr(E->getArg(0));
3106+
Value *Result;
3107+
if (Op0->getType()->isIntOrIntVectorTy())
3108+
Result = Builder.CreateBinaryIntrinsic(
3109+
llvm::Intrinsic::abs, Op0, Builder.getFalse(), nullptr, "elt.abs");
3110+
else
3111+
Result = Builder.CreateUnaryIntrinsic(llvm::Intrinsic::fabs, Op0, nullptr,
3112+
"elt.abs");
3113+
return RValue::get(Result);
3114+
}
31043115
case Builtin::BI__builtin_elementwise_max: {
31053116
Value *Op0 = EmitScalarExpr(E->getArg(0));
31063117
Value *Op1 = EmitScalarExpr(E->getArg(1));

clang/lib/Sema/SemaChecking.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,6 +2288,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
22882288
break;
22892289
}
22902290

2291+
case Builtin::BI__builtin_elementwise_abs:
2292+
if (SemaBuiltinElementwiseMathOneArg(TheCall))
2293+
return ExprError();
2294+
break;
22912295
case Builtin::BI__builtin_elementwise_min:
22922296
case Builtin::BI__builtin_elementwise_max:
22932297
if (SemaBuiltinElementwiseMath(TheCall))
@@ -16755,6 +16759,31 @@ static bool checkMathBuiltinElementType(Sema &S, SourceLocation Loc,
1675516759
return false;
1675616760
}
1675716761

16762+
bool Sema::SemaBuiltinElementwiseMathOneArg(CallExpr *TheCall) {
16763+
if (checkArgCount(*this, TheCall, 1))
16764+
return true;
16765+
16766+
ExprResult A = UsualUnaryConversions(TheCall->getArg(0));
16767+
SourceLocation ArgLoc = TheCall->getArg(0)->getBeginLoc();
16768+
if (A.isInvalid())
16769+
return true;
16770+
16771+
TheCall->setArg(0, A.get());
16772+
QualType TyA = A.get()->getType();
16773+
if (checkMathBuiltinElementType(*this, ArgLoc, TyA))
16774+
return true;
16775+
16776+
QualType EltTy = TyA;
16777+
if (auto *VecTy = EltTy->getAs<VectorType>())
16778+
EltTy = VecTy->getElementType();
16779+
if (EltTy->isUnsignedIntegerType())
16780+
return Diag(ArgLoc, diag::err_builtin_invalid_arg_type)
16781+
<< 1 << /*signed integer or float ty*/ 3 << TyA;
16782+
16783+
TheCall->setType(TyA);
16784+
return false;
16785+
}
16786+
1675816787
bool Sema::SemaBuiltinElementwiseMath(CallExpr *TheCall) {
1675916788
if (checkArgCount(*this, TheCall, 2))
1676016789
return true;

clang/test/CodeGen/builtins-elementwise-math.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,54 @@ __attribute__((address_space(1))) int int_as_one;
88
typedef int bar;
99
bar b;
1010

11+
void test_builtin_elementwise_abs(float f1, float f2, double d1, double d2,
12+
float4 vf1, float4 vf2, si8 vi1, si8 vi2,
13+
long long int i1, long long int i2, short si) {
14+
// CHECK-LABEL: define void @test_builtin_elementwise_abs(
15+
// CHECK: [[F1:%.+]] = load float, float* %f1.addr, align 4
16+
// CHECK-NEXT: call float @llvm.fabs.f32(float [[F1]])
17+
f2 = __builtin_elementwise_abs(f1);
18+
19+
// CHECK: [[D1:%.+]] = load double, double* %d1.addr, align 8
20+
// CHECK-NEXT: call double @llvm.fabs.f64(double [[D1]])
21+
d2 = __builtin_elementwise_abs(d1);
22+
23+
// CHECK: [[VF1:%.+]] = load <4 x float>, <4 x float>* %vf1.addr, align 16
24+
// CHECK-NEXT: call <4 x float> @llvm.fabs.v4f32(<4 x float> [[VF1]])
25+
vf2 = __builtin_elementwise_abs(vf1);
26+
27+
// CHECK: [[I1:%.+]] = load i64, i64* %i1.addr, align 8
28+
// CHECK-NEXT: call i64 @llvm.abs.i64(i64 [[I1]], i1 false)
29+
i2 = __builtin_elementwise_abs(i1);
30+
31+
// CHECK: [[VI1:%.+]] = load <8 x i16>, <8 x i16>* %vi1.addr, align 16
32+
// CHECK-NEXT: call <8 x i16> @llvm.abs.v8i16(<8 x i16> [[VI1]], i1 false)
33+
vi2 = __builtin_elementwise_abs(vi1);
34+
35+
// CHECK: [[CVI2:%.+]] = load <8 x i16>, <8 x i16>* %cvi2, align 16
36+
// CHECK-NEXT: call <8 x i16> @llvm.abs.v8i16(<8 x i16> [[CVI2]], i1 false)
37+
const si8 cvi2 = vi2;
38+
vi2 = __builtin_elementwise_abs(cvi2);
39+
40+
// CHECK: [[IA1:%.+]] = load i32, i32 addrspace(1)* @int_as_one, align 4
41+
// CHECK-NEXT: call i32 @llvm.abs.i32(i32 [[IA1]], i1 false)
42+
b = __builtin_elementwise_abs(int_as_one);
43+
44+
// CHECK: call i32 @llvm.abs.i32(i32 -10, i1 false)
45+
b = __builtin_elementwise_abs(-10);
46+
47+
// CHECK: [[SI:%.+]] = load i16, i16* %si.addr, align 2
48+
// CHECK-NEXT: [[SI_EXT:%.+]] = sext i16 [[SI]] to i32
49+
// CHECK-NEXT: [[RES:%.+]] = call i32 @llvm.abs.i32(i32 [[SI_EXT]], i1 false)
50+
// CHECK-NEXT: = trunc i32 [[RES]] to i16
51+
si = __builtin_elementwise_abs(si);
52+
}
53+
1154
void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
1255
float4 vf1, float4 vf2, long long int i1,
1356
long long int i2, si8 vi1, si8 vi2,
1457
unsigned u1, unsigned u2, u4 vu1, u4 vu2) {
1558
// CHECK-LABEL: define void @test_builtin_elementwise_max(
16-
1759
// CHECK: [[F1:%.+]] = load float, float* %f1.addr, align 4
1860
// CHECK-NEXT: [[F2:%.+]] = load float, float* %f2.addr, align 4
1961
// CHECK-NEXT: call float @llvm.maxnum.f32(float %0, float %1)

clang/test/Sema/builtins-elementwise-math.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
typedef float float4 __attribute__((ext_vector_type(4)));
44
typedef int int3 __attribute__((ext_vector_type(3)));
5+
typedef unsigned unsigned4 __attribute__((ext_vector_type(4)));
56

67
struct Foo {
78
char *p;
@@ -11,6 +12,26 @@ __attribute__((address_space(1))) int int_as_one;
1112
typedef int bar;
1213
bar b;
1314

15+
void test_builtin_elementwise_abs(int i, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) {
16+
struct Foo s = __builtin_elementwise_abs(i);
17+
// expected-error@-1 {{initializing 'struct Foo' with an expression of incompatible type 'int'}}
18+
19+
i = __builtin_elementwise_abs();
20+
// expected-error@-1 {{too few arguments to function call, expected 1, have 0}}
21+
22+
i = __builtin_elementwise_abs(i, i);
23+
// expected-error@-1 {{too many arguments to function call, expected 1, have 2}}
24+
25+
i = __builtin_elementwise_abs(v);
26+
// expected-error@-1 {{assigning to 'int' from incompatible type 'float4' (vector of 4 'float' values)}}
27+
28+
u = __builtin_elementwise_abs(u);
29+
// expected-error@-1 {{1st argument must be a signed integer or floating point type (was 'unsigned int')}}
30+
31+
uv = __builtin_elementwise_abs(uv);
32+
// expected-error@-1 {{1st argument must be a signed integer or floating point type (was 'unsigned4' (vector of 4 'unsigned int' values))}}
33+
}
34+
1435
void test_builtin_elementwise_max(int i, short s, double d, float4 v, int3 iv, int *p) {
1536
i = __builtin_elementwise_max(p, d);
1637
// expected-error@-1 {{arguments are of different types ('int *' vs 'double')}}

clang/test/SemaCXX/builtins-elementwise-math.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,13 @@ template <class T> struct is_const<const T> : true_type {};
1414

1515
// expected-no-diagnostics
1616

17+
void test_builtin_elementwise_abs() {
18+
const int a = 2;
19+
int b = 1;
20+
static_assert(!is_const<decltype(__builtin_elementwise_abs(a))>::value);
21+
static_assert(!is_const<decltype(__builtin_elementwise_abs(b))>::value);
22+
}
23+
1724
void test_builtin_elementwise_max() {
1825
const int a = 2;
1926
int b = 1;

0 commit comments

Comments
 (0)