fpetrogalli updated this revision to Diff 79734.
fpetrogalli added a comment.

Rebase plus apply clang format.


https://reviews.llvm.org/D27250

Files:
  lib/CodeGen/BackendUtil.cpp
  lib/CodeGen/CGCall.cpp
  lib/CodeGen/CGOpenMPRuntime.cpp
  lib/CodeGen/CGOpenMPRuntime.h
  test/OpenMP/declare_simd_no_definition.c
  test/OpenMP/declare_simd_no_definition.cpp

Index: test/OpenMP/declare_simd_no_definition.cpp
===================================================================
--- /dev/null
+++ test/OpenMP/declare_simd_no_definition.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -x c++ -emit-llvm %s -o - -femit-all-decls -verify| FileCheck %s
+// RUN: %clang_cc1 -verify -triple aarch64-linux-gnu -fopenmp -x c++ -emit-llvm %s -o - -femit-all-decls -verify| FileCheck %s --check-prefix=AARCH64
+// expected-no-diagnostics
+
+#pragma omp declare simd
+double f(double x);
+
+#pragma omp declare simd
+float f(float x);
+
+void aaa(double *x, double *y, int N) {
+  for (int i = 0; i < N; ++i) {
+    x[i] = f(y[i]);
+  }
+}
+
+void aaa(float *x, float *y, int N) {
+  for (int i = 0; i < N; ++i) {
+    x[i] = f(y[i]);
+  }
+}
+
+// CHECK-LABEL: define void @_Z3aaaPdS_i
+// CHECK-DAG: %call = call double @_Z1fd(double %{{[0-9]+}}) #[[attrD:[0-9]+]]
+
+// CHECK-LABEL: define void @_Z3aaaPfS_i
+// CHECK-DAG: %call = call float @_Z1ff(float %{{[0-9]+}}) #[[attrF:[0-9]+]]
+
+// CHECK-DAG: attributes #[[attrD]]
+// CHECK-DAG: _ZGVbM2v__Z1fd
+// CHECK-DAG: _ZGVbN2v__Z1fd
+// CHECK-DAG: _ZGVcM4v__Z1fd
+// CHECK-DAG: _ZGVcN4v__Z1fd
+// CHECK-DAG: _ZGVdM4v__Z1fd
+// CHECK-DAG: _ZGVdN4v__Z1fd
+// CHECK-DAG: _ZGVeM8v__Z1fd
+// CHECK-DAG: _ZGVeN8v__Z1fd
+
+// CHECK-DAG: attributes #[[attrF]]
+// CHECK-DAG: _ZGVbM4v__Z1ff
+// CHECK-DAG: _ZGVbN4v__Z1ff
+// CHECK-DAG: _ZGVcM8v__Z1ff
+// CHECK-DAG: _ZGVcN8v__Z1ff
+// CHECK-DAG: _ZGVdM8v__Z1ff
+// CHECK-DAG: _ZGVdN8v__Z1ff
+// CHECK-DAG: _ZGVeM16v__Z1ff
+// CHECK-DAG: _ZGVeN16v__Z1ff
+
+// AARCH64-DAG: @vec_prefix__VA64QM2v__Z1fd_vec_midfix__Z1fd_vec_postfix = external global <2 x double> (<2 x i64>, <2 x double>)
+// AARCH64-DAG: @vec_prefix__VA64QN2v__Z1fd_vec_midfix__Z1fd_vec_postfix = external global <2 x double> (<2 x double>)
+
+// AARCH64-DAG: @vec_prefix__VA64DM2v__Z1ff_vec_midfix__Z1ff_vec_postfix = external global <2 x float> (<2 x i32>, <2 x float>)
+// AARCH64-DAG: @vec_prefix__VA64QM4v__Z1ff_vec_midfix__Z1ff_vec_postfix = external global <4 x float> (<4 x i32>, <4 x float>)
+// AARCH64-DAG: @vec_prefix__VA64DN2v__Z1ff_vec_midfix__Z1ff_vec_postfix = external global <2 x float> (<2 x float>)
+// AARCH64-DAG: @vec_prefix__VA64QN4v__Z1ff_vec_midfix__Z1ff_vec_postfix = external global <4 x float> (<4 x float>)
Index: test/OpenMP/declare_simd_no_definition.c
===================================================================
--- /dev/null
+++ test/OpenMP/declare_simd_no_definition.c
@@ -0,0 +1,41 @@
+// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -x c -emit-llvm %s -o - -femit-all-decls -verify| FileCheck %s
+// RUN: %clang_cc1 -verify -triple aarch64-linux-gnu -fopenmp -x c -emit-llvm %s -o - -femit-all-decls -verify| FileCheck %s --check-prefix=AARCH64
+// expected-no-diagnostics
+
+#pragma omp declare simd
+double f(double x);
+
+void aaa(double *x, double *y, int N) {
+  for (int i = 0; i < N; ++i) {
+    x[i] = f(y[i]);
+  }
+}
+
+#pragma omp declare simd notinbranch
+#pragma omp declare simd uniform(y)
+double xpow(double x, double y);
+
+void bbb(double *x, double *y, int N) {
+  for (int i = 0; i < N; ++i) {
+    x[i] = xpow(y[i], N);
+  }
+}
+
+// CHECK-LABEL: define void @aaa
+// CHECK-DAG: %call = call double @f(double %{{[0-9]+}}) #[[attr:[0-9]+]]
+// CHECK: attributes #[[attr]]
+// CHECK-DAG: _ZGVbM2v_f
+// CHECK-DAG: _ZGVbN2v_f
+// CHECK-DAG: _ZGVcM4v_f
+// CHECK-DAG: _ZGVcN4v_f
+// CHECK-DAG: _ZGVdM4v_f
+// CHECK-DAG: _ZGVdN4v_f
+// CHECK-DAG: _ZGVeM8v_f
+// CHECK-DAG: _ZGVeN8v_f
+
+// AARCH64-DAG: @vec_prefix__VA64QM2v_f_vec_midfix_f_vec_postfix = external global <2 x double> (<2 x i64>, <2 x double>)
+// AARCH64-DAG: @vec_prefix__VA64QN2v_f_vec_midfix_f_vec_postfix = external global <2 x double> (<2 x double>)
+
+// AARCH64-DAG: @vec_prefix__VA64QM2vu_xpow_vec_midfix_xpow_vec_postfix = external global <2 x double> (<2 x i64>, <2 x double>, double)
+// AARCH64-DAG: @vec_prefix__VA64QN2vu_xpow_vec_midfix_xpow_vec_postfix = external global <2 x double> (<2 x double>, double)
+// AARCH64-DAG: @vec_prefix__VA64QN2vv_xpow_vec_midfix_xpow_vec_postfix = external global <2 x double> (<2 x double>, <2 x double>)
Index: lib/CodeGen/CGOpenMPRuntime.h
===================================================================
--- lib/CodeGen/CGOpenMPRuntime.h
+++ lib/CodeGen/CGOpenMPRuntime.h
@@ -1070,6 +1070,11 @@
   virtual void emitDeclareSimdFunction(const FunctionDecl *FD,
                                        llvm::Function *Fn);
 
+  /// Provides all the names of the vector variants associated to a
+  /// function \param FD marked with "declare simd'
+  virtual std::vector<std::string>
+  listAvailableVectorSignatures(const FunctionDecl *FD);
+
   /// Emit initialization for doacross loop nesting support.
   /// \param D Loop-based construct used in doacross nesting construct.
   virtual void emitDoacrossInit(CodeGenFunction &CGF,
Index: lib/CodeGen/CGOpenMPRuntime.cpp
===================================================================
--- lib/CodeGen/CGOpenMPRuntime.cpp
+++ lib/CodeGen/CGOpenMPRuntime.cpp
@@ -19,6 +19,7 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/StmtOpenMP.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/Analysis/TargetLibraryInfo.h"
 #include "llvm/Bitcode/BitcodeReader.h"
 #include "llvm/IR/CallSite.h"
 #include "llvm/IR/DerivedTypes.h"
@@ -6515,11 +6516,12 @@
   return C.getTypeSize(CDT);
 }
 
-static void
-emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::Function *Fn,
-                           const llvm::APSInt &VLENVal,
+static std::vector<std::string>
+emitX86DeclareSimdFunction(const FunctionDecl *FD, llvm::APSInt VLENVal,
                            ArrayRef<ParamAttrTy> ParamAttrs,
-                           OMPDeclareSimdDeclAttr::BranchStateTy State) {
+                           OMPDeclareSimdDeclAttr::BranchStateTy State,
+                           const StringRef MangledName) {
+  std::vector<std::string> OutVec;
   struct ISADataTy {
     char ISA;
     unsigned VecRegSize;
@@ -6581,14 +6583,144 @@
         if (!!ParamAttr.Alignment)
           Out << 'a' << ParamAttr.Alignment;
       }
-      Out << '_' << Fn->getName();
-      Fn->addFnAttr(Out.str());
+      Out << '_' << MangledName;
+      OutVec.push_back(Out.str());
+    }
+  }
+  return OutVec;
+}
+
+static llvm::VectorType *getAArch64MaskTy(const char ISA,
+                                          const unsigned LaneSizeInBits,
+                                          const unsigned VLEN,
+                                          llvm::LLVMContext &C) {
+
+  switch (LaneSizeInBits) {
+  case 64:
+    return llvm::VectorType::get(llvm::Type::getInt64Ty(C), VLEN);
+  case 32:
+    return llvm::VectorType::get(llvm::Type::getInt32Ty(C), VLEN);
+  case 16:
+    return llvm::VectorType::get(llvm::Type::getInt16Ty(C), VLEN);
+  case 8:
+    return llvm::VectorType::get(llvm::Type::getInt8Ty(C), VLEN);
+  default:
+    llvm_unreachable("Type is not supported");
+  }
+  return nullptr;
+}
+
+static void emitAArch64DeclareSimdFunction(
+    CodeGenModule &CGM, const FunctionDecl *FD, const llvm::APSInt &UserVLEN,
+    ArrayRef<ParamAttrTy> ParamAttrs,
+    OMPDeclareSimdDeclAttr::BranchStateTy State, const StringRef MangledName) {
+  struct ISADataTy {
+    char ISA;
+    unsigned VecRegSize;
+  };
+  // make this depend on the size of
+  const ISADataTy ISAData[] = {
+      {'Q', 128}, // NEON 128
+      {'D', 64},  // NEON 64
+  };
+  std::vector<char> Masked;
+  switch (State) {
+  case OMPDeclareSimdDeclAttr::BS_Undefined:
+    Masked = {'M', 'N'};
+    break;
+  case OMPDeclareSimdDeclAttr::BS_Notinbranch:
+    Masked = {'N'};
+    break;
+  case OMPDeclareSimdDeclAttr::BS_Inbranch:
+    Masked = {'M'};
+    break;
+  }
+
+  for (auto Mask : Masked) {
+    for (auto Data : ISAData) {
+      std::string Buffer;
+      llvm::raw_string_ostream Out(Buffer);
+      Out << "_VA64" << Data.ISA << Mask;
+      std::vector<llvm::Type *> Args;
+      auto VLEN = UserVLEN;
+
+      // Compute VLEN if the user hasn't provided one in the pragma.
+      if (!UserVLEN) {
+        auto CDTSize = evaluateCDTSize(FD, ParamAttrs);
+        VLEN = llvm::APSInt::getUnsigned(Data.VecRegSize / CDTSize);
+      }
+      // that's not a vector, skip
+      if (VLEN == 1)
+        continue;
+
+      // Add extra paramter if the function is Masked
+      if (Mask == 'M') {
+        auto MaskTy =
+            getAArch64MaskTy(Data.ISA, Data.VecRegSize / VLEN.getExtValue(),
+                             VLEN.getExtValue(), CGM.getLLVMContext());
+        Args.push_back(MaskTy);
+      }
+
+      Out << VLEN;
+      unsigned Pos = 0;
+      for (auto &ParamAttr : ParamAttrs) {
+        switch (ParamAttr.Kind) {
+        case LinearWithVarStride:
+          Out << 's' << ParamAttr.StrideOrArg;
+          break;
+        case Linear:
+          Out << 'l';
+          if (!!ParamAttr.StrideOrArg)
+            Out << ParamAttr.StrideOrArg;
+          break;
+        case Uniform:
+          Out << 'u';
+          break;
+        case Vector:
+          Out << 'v';
+          break;
+        }
+
+        if (!!ParamAttr.Alignment)
+          Out << 'a' << ParamAttr.Alignment;
+
+        llvm::Type *Ty = CGM.getTypes().ConvertType(
+            FD->getParamDecl(Pos)->getOriginalType());
+        llvm::Type *VecTy = llvm::VectorType::get(Ty, VLEN.getExtValue());
+        switch (ParamAttr.Kind) {
+        default:
+          Args.push_back(VecTy);
+          break;
+        case Uniform:
+          Args.push_back(Ty);
+          break;
+        }
+
+        ++Pos;
+      }
+      Out << '_' << MangledName;
+      std::string GlobalName =
+          llvm::TargetLibraryInfoImpl::mangle(Out.str(), MangledName);
+      llvm::Type *RetTy = CGM.getTypes().ConvertType(FD->getReturnType());
+      llvm::Type *VecRetTy = llvm::VectorType::get(RetTy, VLEN.getExtValue());
+      llvm::FunctionType *FTy = llvm::FunctionType::get(VecRetTy, Args, false);
+      CGM.getModule().getOrInsertGlobal(GlobalName, FTy);
     }
   }
 }
 
 void CGOpenMPRuntime::emitDeclareSimdFunction(const FunctionDecl *FD,
                                               llvm::Function *Fn) {
+
+  auto FunList = listAvailableVectorSignatures(FD);
+  for (auto &VectorName : FunList) {
+    std::string name = VectorName;
+    Fn->addFnAttr(name);
+  }
+}
+
+std::vector<std::string>
+CGOpenMPRuntime::listAvailableVectorSignatures(const FunctionDecl *FD) {
   ASTContext &C = CGM.getContext();
   FD = FD->getCanonicalDecl();
   // Map params to their positions in function decl.
@@ -6600,6 +6732,8 @@
     ParamPositions.insert({P->getCanonicalDecl(), ParamPos});
     ++ParamPos;
   }
+  std::vector<std::string> OutVec;
+  std::string MangledName = CGM.getMangledName(GlobalDecl(FD));
   for (auto *Attr : FD->specific_attrs<OMPDeclareSimdDeclAttr>()) {
     llvm::SmallVector<ParamAttrTy, 8> ParamAttrs(ParamPositions.size());
     // Mark uniform parameters.
@@ -6672,9 +6806,18 @@
       VLENVal = VLEN->EvaluateKnownConstInt(C);
     OMPDeclareSimdDeclAttr::BranchStateTy State = Attr->getBranchState();
     if (CGM.getTriple().getArch() == llvm::Triple::x86 ||
-        CGM.getTriple().getArch() == llvm::Triple::x86_64)
-      emitX86DeclareSimdFunction(FD, Fn, VLENVal, ParamAttrs, State);
+        CGM.getTriple().getArch() == llvm::Triple::x86_64) {
+      const auto Out = emitX86DeclareSimdFunction(FD, VLENVal, ParamAttrs,
+                                                  State, MangledName);
+      for (auto &VecName : Out)
+        OutVec.push_back(VecName);
+    }
+    if (CGM.getTriple().getArch() == llvm::Triple::aarch64) {
+      emitAArch64DeclareSimdFunction(CGM, FD, VLENVal, ParamAttrs, State,
+                                     MangledName);
+    }
   }
+  return OutVec;
 }
 
 namespace {
Index: lib/CodeGen/CGCall.cpp
===================================================================
--- lib/CodeGen/CGCall.cpp
+++ lib/CodeGen/CGCall.cpp
@@ -17,6 +17,7 @@
 #include "CGBlocks.h"
 #include "CGCXXABI.h"
 #include "CGCleanup.h"
+#include "CGOpenMPRuntime.h"
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
 #include "TargetInfo.h"
@@ -1663,6 +1664,15 @@
       const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn);
       if (Fn->isNoReturn() && !(AttrOnCallSite && MD && MD->isVirtual()))
         FuncAttrs.addAttribute(llvm::Attribute::NoReturn);
+
+      // TODO: this should work also when using -fopenmp-simd
+      if (getLangOpts().OpenMP && Fn->hasAttr<OMPDeclareSimdDeclAttr>() &&
+          !Fn->hasBody()) {
+        auto MangledNames =
+            CGOpenMPRuntime(*this).listAvailableVectorSignatures(Fn);
+        for (auto &MangledName : MangledNames)
+          FuncAttrs.addAttribute(MangledName);
+      }
     }
 
     // 'const', 'pure' and 'noalias' attributed functions are also nounwind.
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -306,6 +306,10 @@
   std::unique_ptr<TargetLibraryInfoImpl> TLII(
       createTLII(TargetTriple, CodeGenOpts));
 
+  if (LangOpts.OpenMP) {
+    TLII->addOpenMPVectorFunctions(TheModule);
+  }
+
   switch (Inlining) {
   case CodeGenOptions::NoInlining:
     break;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to