]> granicus.if.org Git - clang/commitdiff
[OPENMP] Codegen of the ‘aligned’ clause for the ‘omp simd’ directive.
authorAlexander Musman <alexander.musman@gmail.com>
Tue, 30 Sep 2014 05:29:28 +0000 (05:29 +0000)
committerAlexander Musman <alexander.musman@gmail.com>
Tue, 30 Sep 2014 05:29:28 +0000 (05:29 +0000)
Differential Revision: http://reviews.llvm.org/D5499

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218660 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/CodeGen/CGStmtOpenMP.cpp
lib/CodeGen/TargetInfo.cpp
lib/CodeGen/TargetInfo.h
lib/Sema/SemaOpenMP.cpp
test/OpenMP/for_simd_aligned_messages.cpp
test/OpenMP/parallel_for_simd_aligned_messages.cpp
test/OpenMP/simd_aligned_messages.cpp
test/OpenMP/simd_metadata.c

index d41f1ccb40eaaaca60be059816048f23d629cf23..93c800b5f927a45326c8bb3a48b4757c62ccf4e4 100644 (file)
@@ -7187,6 +7187,9 @@ def err_omp_linear_expected_int_or_ptr : Error<
 def warn_omp_linear_step_zero : Warning<
   "zero linear step (%0 %select{|and other variables in clause }1should probably be const)">,
   InGroup<OpenMPClauses>;
+def warn_omp_alignment_not_power_of_two : Warning<
+  "aligned clause will be ignored because the requested alignment is not a power of 2">,
+  InGroup<OpenMPClauses>;
 def err_omp_aligned_expected_array_or_ptr : Error<
   "argument of aligned clause should be array"
   "%select{ or pointer|, pointer, reference to array or reference to pointer}1"
index 24bbfed1afa7ea2d2e99601ee9867e8081a8e8ee..199322318b9280878f4bcb8227f9e659b94a2d83 100644 (file)
@@ -16,6 +16,7 @@
 #include "CodeGenModule.h"
 #include "clang/AST/Stmt.h"
 #include "clang/AST/StmtOpenMP.h"
+#include "TargetInfo.h"
 using namespace clang;
 using namespace CodeGen;
 
@@ -48,6 +49,32 @@ void CodeGenFunction::EmitOMPParallelDirective(const OMPParallelDirective &S) {
   EmitRuntimeCall(RTLFn, Args);
 }
 
+static void EmitOMPAlignedClause(CodeGenFunction &CGF, CodeGenModule &CGM,
+                                 const OMPAlignedClause &Clause) {
+  unsigned ClauseAlignment = 0;
+  if (auto AlignmentExpr = Clause.getAlignment()) {
+    auto AlignmentCI =
+        cast<llvm::ConstantInt>(CGF.EmitScalarExpr(AlignmentExpr));
+    ClauseAlignment = static_cast<unsigned>(AlignmentCI->getZExtValue());
+  }
+  for (auto E : Clause.varlists()) {
+    unsigned Alignment = ClauseAlignment;
+    if (Alignment == 0) {
+      // OpenMP [2.8.1, Description]
+      // If no optional parameter isspecified, implementation-defined default
+      // alignments for SIMD instructions on the target platforms are assumed.
+      Alignment = CGM.getTargetCodeGenInfo().getOpenMPSimdDefaultAlignment(
+          E->getType());
+    }
+    assert((Alignment == 0 || llvm::isPowerOf2_32(Alignment)) &&
+           "alignment is not power of 2");
+    if (Alignment != 0) {
+      llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
+      CGF.EmitAlignmentAssumption(PtrValue, Alignment);
+    }
+  }
+}
+
 void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
   const CapturedStmt *CS = cast<CapturedStmt>(S.getAssociatedStmt());
   const Stmt *Body = CS->getCapturedStmt();
@@ -66,6 +93,9 @@ void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
       LoopStack.setParallel(false);
       break;
     }
+    case OMPC_aligned:
+      EmitOMPAlignedClause(*this, CGM, cast<OMPAlignedClause>(*C));
+      break;
     default:
       // Not handled yet
       ;
index 58d66b7bb10e40cfdfcb89a8a4a74397782d5869..2b62d999d308d35eb524209573d7628987c9e4bb 100644 (file)
@@ -1437,9 +1437,10 @@ public:
 };
 
 class X86_64TargetCodeGenInfo : public TargetCodeGenInfo {
+  bool HasAVX;
 public:
   X86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool HasAVX)
-      : TargetCodeGenInfo(new X86_64ABIInfo(CGT, HasAVX)) {}
+      : TargetCodeGenInfo(new X86_64ABIInfo(CGT, HasAVX)), HasAVX(HasAVX) {}
 
   const X86_64ABIInfo &getABIInfo() const {
     return static_cast<const X86_64ABIInfo&>(TargetCodeGenInfo::getABIInfo());
@@ -1499,6 +1500,9 @@ public:
     return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
   }
 
+  unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
+    return HasAVX ? 32 : 16;
+  }
 };
 
 static std::string qualifyWindowsLibrary(llvm::StringRef Lib) {
@@ -1530,9 +1534,10 @@ public:
 };
 
 class WinX86_64TargetCodeGenInfo : public TargetCodeGenInfo {
+  bool HasAVX;
 public:
-  WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT)
-    : TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)) {}
+  WinX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool HasAVX)
+    : TargetCodeGenInfo(new WinX86_64ABIInfo(CGT)), HasAVX(HasAVX) {}
 
   int getDwarfEHStackPointer(CodeGen::CodeGenModule &CGM) const override {
     return 7;
@@ -1559,6 +1564,10 @@ public:
                                llvm::SmallString<32> &Opt) const override {
     Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
   }
+
+  unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
+    return HasAVX ? 32 : 16;
+  }
 };
 
 }
@@ -2909,9 +2918,14 @@ class NaClX86_64ABIInfo : public ABIInfo {
 };
 
 class NaClX86_64TargetCodeGenInfo : public TargetCodeGenInfo  {
+  bool HasAVX;
  public:
-  NaClX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool HasAVX)
-      : TargetCodeGenInfo(new NaClX86_64ABIInfo(CGT, HasAVX)) {}
+   NaClX86_64TargetCodeGenInfo(CodeGen::CodeGenTypes &CGT, bool HasAVX)
+       : TargetCodeGenInfo(new NaClX86_64ABIInfo(CGT, HasAVX)), HasAVX(HasAVX) {
+   }
+   unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
+     return HasAVX ? 32 : 16;
+   }
 };
 
 }
@@ -6981,13 +6995,14 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() {
 
     switch (Triple.getOS()) {
     case llvm::Triple::Win32:
-      return *(TheTargetCodeGenInfo = new WinX86_64TargetCodeGenInfo(Types));
+      return *(TheTargetCodeGenInfo =
+                   new WinX86_64TargetCodeGenInfo(Types, HasAVX));
     case llvm::Triple::NaCl:
-      return *(TheTargetCodeGenInfo = new NaClX86_64TargetCodeGenInfo(Types,
-                                                                      HasAVX));
+      return *(TheTargetCodeGenInfo =
+                   new NaClX86_64TargetCodeGenInfo(Types, HasAVX));
     default:
-      return *(TheTargetCodeGenInfo = new X86_64TargetCodeGenInfo(Types,
-                                                                  HasAVX));
+      return *(TheTargetCodeGenInfo =
+                   new X86_64TargetCodeGenInfo(Types, HasAVX));
     }
   }
   case llvm::Triple::hexagon:
index f14965009d9413da69bba18fa809b50e7cf7daa4..cc469d69e3905f70af9401613831cf37a8772568 100644 (file)
@@ -218,6 +218,13 @@ public:
   virtual void getDetectMismatchOption(llvm::StringRef Name,
                                        llvm::StringRef Value,
                                        llvm::SmallString<32> &Opt) const {}
+
+  /// Gets the target-specific default alignment used when an 'aligned' clause
+  /// is used with a 'simd' OpenMP directive without specifying a specific
+  /// alignment.
+  virtual unsigned getOpenMPSimdDefaultAlignment(QualType Type) const {
+    return 0;
+  }
 };
 }
 
index ece5316187d0311415c0b6ab5706f785724bc607..d8627434a1649c0459707167a88f23fe0b64ea03 100644 (file)
@@ -2842,6 +2842,11 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
         << getOpenMPClauseName(CKind) << E->getSourceRange();
     return ExprError();
   }
+  if (CKind == OMPC_aligned && !Result.isPowerOf2()) {
+    Diag(E->getExprLoc(), diag::warn_omp_alignment_not_power_of_two)
+        << E->getSourceRange();
+    return ExprError();
+  }
   return ICE;
 }
 
index 6d35eb863dce451d6f82dc3f1be4b9a1b46e3e4a..70131d5e5a35f8702f1befc43f735d2e4abc22ff 100644 (file)
@@ -39,6 +39,7 @@ void test_aligned_colons(int *&rp)
   // expected-error@+1 {{expected variable name}}
   #pragma omp for simd aligned(B::bfoo())
   for (int i = 0; i < 10; ++i) ;
+  // expected-warning@+1 {{aligned clause will be ignored because the requested alignment is not a power of 2}}
   #pragma omp for simd aligned(B::ib,B:C1+C2)
   for (int i = 0; i < 10; ++i) ;
 }
@@ -122,7 +123,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
   for (I k = 0; k < argc; ++k) ++k;
   #pragma omp for simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
   for (I k = 0; k < argc; ++k) ++k;
-  #pragma omp for simd aligned (argc : 5)
+  #pragma omp for simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
   for (I k = 0; k < argc; ++k) ++k;
   #pragma omp for simd aligned (S1) // expected-error {{'S1' does not refer to a value}}
   for (I k = 0; k < argc; ++k) ++k;
index a1b37f809353ec8c0313f11c5afd4b4b7b8ef97b..ea4ec21f28a948943decfd4a49b243e3cb7b7e79 100644 (file)
@@ -39,6 +39,7 @@ void test_aligned_colons(int *&rp)
   // expected-error@+1 {{expected variable name}}
   #pragma omp parallel for simd aligned(B::bfoo())
   for (int i = 0; i < 10; ++i) ;
+  // expected-warning@+1 {{aligned clause will be ignored because the requested alignment is not a power of 2}}
   #pragma omp parallel for simd aligned(B::ib,B:C1+C2)
   for (int i = 0; i < 10; ++i) ;
 }
@@ -122,7 +123,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
   for (I k = 0; k < argc; ++k) ++k;
   #pragma omp parallel for simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
   for (I k = 0; k < argc; ++k) ++k;
-  #pragma omp parallel for simd aligned (argc : 5)
+  #pragma omp parallel for simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
   for (I k = 0; k < argc; ++k) ++k;
   #pragma omp parallel for simd aligned (S1) // expected-error {{'S1' does not refer to a value}}
   for (I k = 0; k < argc; ++k) ++k;
index 84cf40c1731b46607f9289457e62bc3690ee378b..dfa6b541c909da767b6158274f468890e7dde1e6 100644 (file)
@@ -39,6 +39,7 @@ void test_aligned_colons(int *&rp)
   // expected-error@+1 {{expected variable name}}
   #pragma omp simd aligned(B::bfoo())
   for (int i = 0; i < 10; ++i) ;
+  // expected-warning@+1 {{aligned clause will be ignored because the requested alignment is not a power of 2}}
   #pragma omp simd aligned(B::ib,B:C1+C2)
   for (int i = 0; i < 10; ++i) ;
 }
@@ -122,7 +123,7 @@ template<class I, class C> int foomain(I argc, C **argv) {
   for (I k = 0; k < argc; ++k) ++k;
   #pragma omp simd aligned (argc > 0 ? argv[1] : argv[2]) // expected-error {{expected variable name}}
   for (I k = 0; k < argc; ++k) ++k;
-  #pragma omp simd aligned (argc : 5)
+  #pragma omp simd aligned (argc : 5) // expected-warning {{aligned clause will be ignored because the requested alignment is not a power of 2}}
   for (I k = 0; k < argc; ++k) ++k;
   #pragma omp simd aligned (S1) // expected-error {{'S1' does not refer to a value}}
   for (I k = 0; k < argc; ++k) ++k;
index a0588adf7dad46006ba2ce9e5b9f63f3591f4b7b..cc2e19d5dd97220dea0338f7e03ea883a7dfb67d 100644 (file)
@@ -1,10 +1,22 @@
-// RUN: %clang_cc1 -fopenmp=libiomp5 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -fopenmp=libiomp5 -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
 
-void h1(float *c, float *a, float *b, int size)
+void h1(float *c, float *a, double b[], int size)
 {
 // CHECK-LABEL: define void @h1
   int t = 0;
-#pragma omp simd safelen(16) linear(t)
+#pragma omp simd safelen(16) linear(t) aligned(c:32) aligned(a,b)
+// CHECK:         [[C_PTRINT:%.+]] = ptrtoint
+// CHECK-NEXT:    [[C_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[C_PTRINT]], 31
+// CHECK-NEXT:    [[C_MASKCOND:%.+]] = icmp eq i{{[0-9]+}} [[C_MASKEDPTR]], 0
+// CHECK-NEXT:    call void @llvm.assume(i1 [[C_MASKCOND]])
+// CHECK:         [[A_PTRINT:%.+]] = ptrtoint
+// CHECK-NEXT:    [[A_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[A_PTRINT]], 15
+// CHECK-NEXT:    [[A_MASKCOND:%.+]] = icmp eq i{{[0-9]+}} [[A_MASKEDPTR]], 0
+// CHECK-NEXT:    call void @llvm.assume(i1 [[A_MASKCOND]])
+// CHECK:         [[B_PTRINT:%.+]] = ptrtoint
+// CHECK-NEXT:    [[B_MASKEDPTR:%.+]] = and i{{[0-9]+}} [[B_PTRINT]], 15
+// CHECK-NEXT:    [[B_MASKCOND:%.+]] = icmp eq i{{[0-9]+}} [[B_MASKEDPTR]], 0
+// CHECK-NEXT:    call void @llvm.assume(i1 [[B_MASKCOND]])
   for (int i = 0; i < size; ++i) {
     c[i] = a[i] * a[i] + b[i] * b[t];
     ++t;