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; +def warn_omp_alignment_not_power_of_two : Warning< + "requested alignment value is not power of 2 - ignored">, + InGroup; 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/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(CGF.EmitScalarExpr(AlignmentExpr)); + ClauseAlignment = static_cast(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( + 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(S.getAssociatedStmt()); const Stmt *Body = CS->getCapturedStmt(); @@ -66,6 +101,11 @@ LoopStack.setParallel(false); break; } + case OMPC_aligned: { + // FIXME: Passing safelen. + EmitOMPAlignedClause(*this, cast(*C)); + break; + } default: // Not handled yet ; 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: 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/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_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/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;