Hi hfinkel, rsmith, doug.gregor, ABataev, rjmccall,

Please review codegen of the ‘aligned’ clause for the ‘omp simd’ directive.
It uses @llvm.assume intrinsic to specify alignment hints in LLVM IR.

http://reviews.llvm.org/D5499

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  lib/CodeGen/CGStmtOpenMP.cpp
  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: test/OpenMP/for_simd_aligned_messages.cpp
===================================================================
--- test/OpenMP/for_simd_aligned_messages.cpp
+++ test/OpenMP/for_simd_aligned_messages.cpp
@@ -39,6 +39,7 @@
   // expected-error@+1 {{expected variable name}}
   #pragma omp for simd aligned(B::bfoo())
   for (int i = 0; i < 10; ++i) ;
+  // expected-warning@+1 {{requested alignment value is not power of 2 - ignored}}
   #pragma omp for simd aligned(B::ib,B:C1+C2)
   for (int i = 0; i < 10; ++i) ;
 }
@@ -122,7 +123,7 @@
   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 {{requested alignment value is not power of 2 - ignored}}
   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: test/OpenMP/simd_aligned_messages.cpp
===================================================================
--- test/OpenMP/simd_aligned_messages.cpp
+++ test/OpenMP/simd_aligned_messages.cpp
@@ -39,6 +39,7 @@
   // expected-error@+1 {{expected variable name}}
   #pragma omp simd aligned(B::bfoo())
   for (int i = 0; i < 10; ++i) ;
+  // expected-warning@+1 {{requested alignment value is not power of 2 - ignored}}
   #pragma omp simd aligned(B::ib,B:C1+C2)
   for (int i = 0; i < 10; ++i) ;
 }
@@ -122,7 +123,7 @@
   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 {{requested alignment value is not power of 2 - ignored}}
   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: test/OpenMP/parallel_for_simd_aligned_messages.cpp
===================================================================
--- test/OpenMP/parallel_for_simd_aligned_messages.cpp
+++ test/OpenMP/parallel_for_simd_aligned_messages.cpp
@@ -39,6 +39,7 @@
   // expected-error@+1 {{expected variable name}}
   #pragma omp parallel for simd aligned(B::bfoo())
   for (int i = 0; i < 10; ++i) ;
+  // expected-warning@+1 {{requested alignment value is not power of 2 - ignored}}
   #pragma omp parallel for simd aligned(B::ib,B:C1+C2)
   for (int i = 0; i < 10; ++i) ;
 }
@@ -122,7 +123,7 @@
   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 {{requested alignment value is not power of 2 - ignored}}
   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: test/OpenMP/simd_metadata.c
===================================================================
--- test/OpenMP/simd_metadata.c
+++ test/OpenMP/simd_metadata.c
@@ -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]], 7
+// 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;
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -7176,6 +7176,9 @@
 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<
+  "requested alignment value is not power of 2 - ignored">,
+  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: lib/Sema/SemaOpenMP.cpp
===================================================================
--- lib/Sema/SemaOpenMP.cpp
+++ lib/Sema/SemaOpenMP.cpp
@@ -2842,6 +2842,11 @@
         << 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: lib/CodeGen/CGStmtOpenMP.cpp
===================================================================
--- lib/CodeGen/CGStmtOpenMP.cpp
+++ lib/CodeGen/CGStmtOpenMP.cpp
@@ -48,6 +48,41 @@
   EmitRuntimeCall(RTLFn, Args);
 }
 
+static void EmitOMPAlignedClause(CodeGenFunction &CGF,
+                                 const OMPAlignedClause &Clause,
+                                 unsigned Safelen = 2) {
+  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()) {
+    llvm::Value *PtrValue = CGF.EmitScalarExpr(E);
+    unsigned PrefAlignment = ClauseAlignment;
+    if (PrefAlignment == 0) {
+      // OpenMP [2.8.1, Description]
+      // If no optional parameter isspecified, implementation-defined default
+      // alignments for SIMD instructions on the target platforms are assumed.
+      const Type *Ty = E->getType().getNonReferenceType().getTypePtr();
+      assert((Ty->isPointerType() || Ty->isArrayType()) &&
+             "unexpected type in OpenMP 'aligned' clause");
+      if (Ty->isPointerType())
+        Ty = Ty->getPointeeType().getTypePtr();
+      else
+        Ty = Ty->getArrayElementTypeNoTypeQual();
+      auto &C = CGF.getContext();
+      if (Ty->isBuiltinType())
+        Ty = C.getVectorType(QualType(Ty, 0), Safelen,
+                             VectorType::GenericVector).getTypePtr();
+      PrefAlignment = static_cast<unsigned>(
+          C.toCharUnitsFromBits(C.getPreferredTypeAlign(Ty)).getQuantity());
+    }
+    assert(llvm::isPowerOf2_32(PrefAlignment) && "alignment is not power of 2");
+    CGF.EmitAlignmentAssumption(PtrValue, PrefAlignment);
+  }
+}
+
 void CodeGenFunction::EmitOMPSimdDirective(const OMPSimdDirective &S) {
   const CapturedStmt *CS = cast<CapturedStmt>(S.getAssociatedStmt());
   const Stmt *Body = CS->getCapturedStmt();
@@ -66,6 +101,11 @@
       LoopStack.setParallel(false);
       break;
     }
+    case OMPC_aligned: {
+      // FIXME: Passing safelen.
+      EmitOMPAlignedClause(*this, cast<OMPAlignedClause>(*C));
+      break;
+    }
     default:
       // Not handled yet
       ;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to