mirror of
https://github.com/intel/llvm.git
synced 2026-02-08 00:50:03 +08:00
[OPENMP] Codegen of the ‘aligned’ clause for the ‘omp simd’ directive.
Differential Revision: http://reviews.llvm.org/D5499 llvm-svn: 218660
This commit is contained in:
@@ -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"
|
||||
|
||||
@@ -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
|
||||
;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user