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"
#include "CodeGenModule.h"
#include "clang/AST/Stmt.h"
#include "clang/AST/StmtOpenMP.h"
+#include "TargetInfo.h"
using namespace clang;
using namespace CodeGen;
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();
LoopStack.setParallel(false);
break;
}
+ case OMPC_aligned:
+ EmitOMPAlignedClause(*this, CGM, cast<OMPAlignedClause>(*C));
+ break;
default:
// Not handled yet
;
};
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());
return llvm::ConstantInt::get(CGM.Int32Ty, Sig);
}
+ unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
+ return HasAVX ? 32 : 16;
+ }
};
static std::string qualifyWindowsLibrary(llvm::StringRef Lib) {
};
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;
llvm::SmallString<32> &Opt) const override {
Opt = "/FAILIFMISMATCH:\"" + Name.str() + "=" + Value.str() + "\"";
}
+
+ unsigned getOpenMPSimdDefaultAlignment(QualType) const override {
+ return HasAVX ? 32 : 16;
+ }
};
}
};
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;
+ }
};
}
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:
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;
+ }
};
}
<< 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;
}
// 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) ;
}
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;
// 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) ;
}
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;
// 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) ;
}
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;
-// 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;