From: Alexander Musman Date: Tue, 30 Sep 2014 05:29:28 +0000 (+0000) Subject: [OPENMP] Codegen of the ‘aligned’ clause for the ‘omp simd’ directive. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e0d26d6fa7dee8cbef088c49f61a6fe3b1b957a8;p=clang [OPENMP] Codegen of the ‘aligned’ clause for the ‘omp simd’ directive. Differential Revision: http://reviews.llvm.org/D5499 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@218660 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index d41f1ccb40..93c800b5f9 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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; +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; 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" diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp index 24bbfed1af..199322318b 100644 --- a/lib/CodeGen/CGStmtOpenMP.cpp +++ b/lib/CodeGen/CGStmtOpenMP.cpp @@ -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(CGF.EmitScalarExpr(AlignmentExpr)); + ClauseAlignment = static_cast(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(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(*C)); + break; default: // Not handled yet ; diff --git a/lib/CodeGen/TargetInfo.cpp b/lib/CodeGen/TargetInfo.cpp index 58d66b7bb1..2b62d999d3 100644 --- a/lib/CodeGen/TargetInfo.cpp +++ b/lib/CodeGen/TargetInfo.cpp @@ -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(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: diff --git a/lib/CodeGen/TargetInfo.h b/lib/CodeGen/TargetInfo.h index f14965009d..cc469d69e3 100644 --- a/lib/CodeGen/TargetInfo.h +++ b/lib/CodeGen/TargetInfo.h @@ -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; + } }; } diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp index ece5316187..d8627434a1 100644 --- a/lib/Sema/SemaOpenMP.cpp +++ b/lib/Sema/SemaOpenMP.cpp @@ -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; } diff --git a/test/OpenMP/for_simd_aligned_messages.cpp b/test/OpenMP/for_simd_aligned_messages.cpp index 6d35eb863d..70131d5e5a 100644 --- a/test/OpenMP/for_simd_aligned_messages.cpp +++ b/test/OpenMP/for_simd_aligned_messages.cpp @@ -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 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; diff --git a/test/OpenMP/parallel_for_simd_aligned_messages.cpp b/test/OpenMP/parallel_for_simd_aligned_messages.cpp index a1b37f8093..ea4ec21f28 100644 --- a/test/OpenMP/parallel_for_simd_aligned_messages.cpp +++ b/test/OpenMP/parallel_for_simd_aligned_messages.cpp @@ -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 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; diff --git a/test/OpenMP/simd_aligned_messages.cpp b/test/OpenMP/simd_aligned_messages.cpp index 84cf40c173..dfa6b541c9 100644 --- a/test/OpenMP/simd_aligned_messages.cpp +++ b/test/OpenMP/simd_aligned_messages.cpp @@ -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 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; diff --git a/test/OpenMP/simd_metadata.c b/test/OpenMP/simd_metadata.c index a0588adf7d..cc2e19d5dd 100644 --- a/test/OpenMP/simd_metadata.c +++ b/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]], 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;