[clang] 01870d5 - [Clang] Add elementwise abs builtin.

Florian Hahn via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 27 13:04:11 PDT 2021


Author: Florian Hahn
Date: 2021-10-27T21:01:44+01:00
New Revision: 01870d51b848166eee59ed2e77be0199a561cf59

URL: https://github.com/llvm/llvm-project/commit/01870d51b848166eee59ed2e77be0199a561cf59
DIFF: https://github.com/llvm/llvm-project/commit/01870d51b848166eee59ed2e77be0199a561cf59.diff

LOG: [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

Added: 
    

Modified: 
    clang/include/clang/Basic/Builtins.def
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Sema/Sema.h
    clang/lib/CodeGen/CGBuiltin.cpp
    clang/lib/Sema/SemaChecking.cpp
    clang/test/CodeGen/builtins-elementwise-math.c
    clang/test/Sema/builtins-elementwise-math.c
    clang/test/SemaCXX/builtins-elementwise-math.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index b6967cc26af06..874bc655a00b7 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -643,6 +643,7 @@ BUILTIN(__builtin_alloca, "v*z"   , "Fn")
 BUILTIN(__builtin_alloca_with_align, "v*zIz", "Fn")
 BUILTIN(__builtin_call_with_static_chain, "v.", "nt")
 
+BUILTIN(__builtin_elementwise_abs, "v.", "nct")
 BUILTIN(__builtin_elementwise_max, "v.", "nct")
 BUILTIN(__builtin_elementwise_min, "v.", "nct")
 

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index ea030aad5d8df..09482d238ff3d 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -11306,7 +11306,8 @@ def err_builtin_launder_invalid_arg : Error<
 def err_builtin_invalid_arg_type: Error <
   "%ordinal0 argument must be a "
   "%select{vector, integer or floating point type|matrix|"
-   "pointer to a valid matrix element type}1 (was %2)">;
+   "pointer to a valid matrix element type|"
+   "signed integer or floating point type}1 (was %2)">;
 
 def err_builtin_matrix_disabled: Error<
   "matrix types extension is disabled. Pass -fenable-matrix to enable it">;

diff  --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 6bd5f4a35750d..b87532c51f630 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -12725,6 +12725,7 @@ class Sema final {
   bool CheckPPCMMAType(QualType Type, SourceLocation TypeLoc);
 
   bool SemaBuiltinElementwiseMath(CallExpr *TheCall);
+  bool SemaBuiltinElementwiseMathOneArg(CallExpr *TheCall);
 
   // Matrix builtin handling.
   ExprResult SemaBuiltinMatrixTranspose(CallExpr *TheCall,

diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index af6b496c604f1..02cba577a5420 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -3101,6 +3101,17 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID,
     return RValue::get(V);
   }
 
+  case Builtin::BI__builtin_elementwise_abs: {
+    Value *Op0 = EmitScalarExpr(E->getArg(0));
+    Value *Result;
+    if (Op0->getType()->isIntOrIntVectorTy())
+      Result = Builder.CreateBinaryIntrinsic(
+          llvm::Intrinsic::abs, Op0, Builder.getFalse(), nullptr, "elt.abs");
+    else
+      Result = Builder.CreateUnaryIntrinsic(llvm::Intrinsic::fabs, Op0, nullptr,
+                                            "elt.abs");
+    return RValue::get(Result);
+  }
   case Builtin::BI__builtin_elementwise_max: {
     Value *Op0 = EmitScalarExpr(E->getArg(0));
     Value *Op1 = EmitScalarExpr(E->getArg(1));

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 9d19a81ab23e7..83fb824cb14a6 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -1976,6 +1976,10 @@ Sema::CheckBuiltinFunctionCall(FunctionDecl *FDecl, unsigned BuiltinID,
     break;
   }
 
+  case Builtin::BI__builtin_elementwise_abs:
+    if (SemaBuiltinElementwiseMathOneArg(TheCall))
+      return ExprError();
+    break;
   case Builtin::BI__builtin_elementwise_min:
   case Builtin::BI__builtin_elementwise_max:
     if (SemaBuiltinElementwiseMath(TheCall))
@@ -16536,6 +16540,31 @@ static bool checkMathBuiltinElementType(Sema &S, SourceLocation Loc,
   return false;
 }
 
+bool Sema::SemaBuiltinElementwiseMathOneArg(CallExpr *TheCall) {
+  if (checkArgCount(*this, TheCall, 1))
+    return true;
+
+  ExprResult A = UsualUnaryConversions(TheCall->getArg(0));
+  SourceLocation ArgLoc = TheCall->getArg(0)->getBeginLoc();
+  if (A.isInvalid())
+    return true;
+
+  TheCall->setArg(0, A.get());
+  QualType TyA = A.get()->getType();
+  if (checkMathBuiltinElementType(*this, ArgLoc, TyA))
+    return true;
+
+  QualType EltTy = TyA;
+  if (auto *VecTy = EltTy->getAs<VectorType>())
+    EltTy = VecTy->getElementType();
+  if (EltTy->isUnsignedIntegerType())
+    return Diag(ArgLoc, diag::err_builtin_invalid_arg_type)
+           << 1 << /*signed integer or float ty*/ 3 << TyA;
+
+  TheCall->setType(TyA);
+  return false;
+}
+
 bool Sema::SemaBuiltinElementwiseMath(CallExpr *TheCall) {
   if (checkArgCount(*this, TheCall, 2))
     return true;

diff  --git a/clang/test/CodeGen/builtins-elementwise-math.c b/clang/test/CodeGen/builtins-elementwise-math.c
index e930039879b79..bfb162422c1b5 100644
--- a/clang/test/CodeGen/builtins-elementwise-math.c
+++ b/clang/test/CodeGen/builtins-elementwise-math.c
@@ -8,12 +8,54 @@ __attribute__((address_space(1))) int int_as_one;
 typedef int bar;
 bar b;
 
+void test_builtin_elementwise_abs(float f1, float f2, double d1, double d2,
+                                  float4 vf1, float4 vf2, si8 vi1, si8 vi2,
+                                  long long int i1, long long int i2, short si) {
+  // CHECK-LABEL: define void @test_builtin_elementwise_abs(
+  // CHECK:      [[F1:%.+]] = load float, float* %f1.addr, align 4
+  // CHECK-NEXT:  call float @llvm.fabs.f32(float [[F1]])
+  f2 = __builtin_elementwise_abs(f1);
+
+  // CHECK:      [[D1:%.+]] = load double, double* %d1.addr, align 8
+  // CHECK-NEXT: call double @llvm.fabs.f64(double [[D1]])
+  d2 = __builtin_elementwise_abs(d1);
+
+  // CHECK:      [[VF1:%.+]] = load <4 x float>, <4 x float>* %vf1.addr, align 16
+  // CHECK-NEXT: call <4 x float> @llvm.fabs.v4f32(<4 x float> [[VF1]])
+  vf2 = __builtin_elementwise_abs(vf1);
+
+  // CHECK:      [[I1:%.+]] = load i64, i64* %i1.addr, align 8
+  // CHECK-NEXT: call i64 @llvm.abs.i64(i64 [[I1]], i1 false)
+  i2 = __builtin_elementwise_abs(i1);
+
+  // CHECK:      [[VI1:%.+]] = load <8 x i16>, <8 x i16>* %vi1.addr, align 16
+  // CHECK-NEXT: call <8 x i16> @llvm.abs.v8i16(<8 x i16> [[VI1]], i1 false)
+  vi2 = __builtin_elementwise_abs(vi1);
+
+  // CHECK:      [[CVI2:%.+]] = load <8 x i16>, <8 x i16>* %cvi2, align 16
+  // CHECK-NEXT: call <8 x i16> @llvm.abs.v8i16(<8 x i16> [[CVI2]], i1 false)
+  const si8 cvi2 = vi2;
+  vi2 = __builtin_elementwise_abs(cvi2);
+
+  // CHECK:      [[IA1:%.+]] = load i32, i32 addrspace(1)* @int_as_one, align 4
+  // CHECK-NEXT: call i32 @llvm.abs.i32(i32 [[IA1]], i1 false)
+  b = __builtin_elementwise_abs(int_as_one);
+
+  // CHECK:   call i32 @llvm.abs.i32(i32 -10, i1 false)
+  b = __builtin_elementwise_abs(-10);
+
+  // CHECK:      [[SI:%.+]] = load i16, i16* %si.addr, align 2
+  // CHECK-NEXT: [[SI_EXT:%.+]] = sext i16 [[SI]] to i32
+  // CHECK-NEXT: [[RES:%.+]] = call i32 @llvm.abs.i32(i32 [[SI_EXT]], i1 false)
+  // CHECK-NEXT: = trunc i32 [[RES]] to i16
+  si = __builtin_elementwise_abs(si);
+}
+
 void test_builtin_elementwise_max(float f1, float f2, double d1, double d2,
                                   float4 vf1, float4 vf2, long long int i1,
                                   long long int i2, si8 vi1, si8 vi2,
                                   unsigned u1, unsigned u2, u4 vu1, u4 vu2) {
   // CHECK-LABEL: define void @test_builtin_elementwise_max(
-
   // CHECK:      [[F1:%.+]] = load float, float* %f1.addr, align 4
   // CHECK-NEXT: [[F2:%.+]] = load float, float* %f2.addr, align 4
   // CHECK-NEXT:  call float @llvm.maxnum.f32(float %0, float %1)

diff  --git a/clang/test/Sema/builtins-elementwise-math.c b/clang/test/Sema/builtins-elementwise-math.c
index 7c3c1aa0763a7..1825d0c684965 100644
--- a/clang/test/Sema/builtins-elementwise-math.c
+++ b/clang/test/Sema/builtins-elementwise-math.c
@@ -2,6 +2,7 @@
 
 typedef float float4 __attribute__((ext_vector_type(4)));
 typedef int int3 __attribute__((ext_vector_type(3)));
+typedef unsigned unsigned4 __attribute__((ext_vector_type(4)));
 
 struct Foo {
   char *p;
@@ -11,6 +12,26 @@ __attribute__((address_space(1))) int int_as_one;
 typedef int bar;
 bar b;
 
+void test_builtin_elementwise_abs(int i, double d, float4 v, int3 iv, unsigned u, unsigned4 uv) {
+  struct Foo s = __builtin_elementwise_abs(i);
+  // expected-error at -1 {{initializing 'struct Foo' with an expression of incompatible type 'int'}}
+
+  i = __builtin_elementwise_abs();
+  // expected-error at -1 {{too few arguments to function call, expected 1, have 0}}
+
+  i = __builtin_elementwise_abs(i, i);
+  // expected-error at -1 {{too many arguments to function call, expected 1, have 2}}
+
+  i = __builtin_elementwise_abs(v);
+  // expected-error at -1 {{assigning to 'int' from incompatible type 'float4' (vector of 4 'float' values)}}
+
+  u = __builtin_elementwise_abs(u);
+  // expected-error at -1 {{1st argument must be a signed integer or floating point type (was 'unsigned int')}}
+
+  uv = __builtin_elementwise_abs(uv);
+  // expected-error at -1 {{1st argument must be a signed integer or floating point type (was 'unsigned4' (vector of 4 'unsigned int' values))}}
+}
+
 void test_builtin_elementwise_max(int i, short s, double d, float4 v, int3 iv, int *p) {
   i = __builtin_elementwise_max(p, d);
   // expected-error at -1 {{arguments are of 
diff erent types ('int *' vs 'double')}}

diff  --git a/clang/test/SemaCXX/builtins-elementwise-math.cpp b/clang/test/SemaCXX/builtins-elementwise-math.cpp
index 4d552b7a17d05..fcf03d729620b 100644
--- a/clang/test/SemaCXX/builtins-elementwise-math.cpp
+++ b/clang/test/SemaCXX/builtins-elementwise-math.cpp
@@ -14,6 +14,13 @@ template <class T> struct is_const<const T> : true_type {};
 
 // expected-no-diagnostics
 
+void test_builtin_elementwise_abs() {
+  const int a = 2;
+  int b = 1;
+  static_assert(!is_const<decltype(__builtin_elementwise_abs(a))>::value);
+  static_assert(!is_const<decltype(__builtin_elementwise_abs(b))>::value);
+}
+
 void test_builtin_elementwise_max() {
   const int a = 2;
   int b = 1;


        


More information about the cfe-commits mailing list