koops updated this revision to Diff 512381.
koops added a comment.
Moving the code to SemaOpenMP.cpp from CodeGen.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D144634/new/
https://reviews.llvm.org/D144634
Files:
clang/include/clang/AST/StmtOpenMP.h
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Parse/Parser.h
clang/lib/AST/StmtOpenMP.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/test/OpenMP/loop_bind_codegen.cpp
Index: clang/test/OpenMP/loop_bind_codegen.cpp
===================================================================
--- /dev/null
+++ clang/test/OpenMP/loop_bind_codegen.cpp
@@ -0,0 +1,132 @@
+// Copyright 2020 Hewlett Packard Enterprise Development LP
+
+// expected-no-diagnostics
+#ifndef HEADER
+#define HEADER
+// RUN: %clang_cc1 -DCK1 -verify -fopenmp -x c++ %s -emit-llvm -o - | FileCheck %s
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s
+
+
+/*
+#include <stdio.h>
+#include <assert.h>
+#include <pthread.h>
+#include <omp.h>
+*/
+
+#define NNN 50
+int aaa[NNN];
+
+void parallel_loop() {
+ #pragma omp parallel
+ {
+ #pragma omp loop bind(parallel)
+ for (int j = 0 ; j < NNN ; j++) {
+ aaa[j] = j*NNN;
+ }
+ }
+}
+
+
+void teams_loop() {
+ #pragma omp teams
+ {
+ #pragma omp loop bind(teams)
+ for (int j = 0 ; j < NNN ; j++) {
+ aaa[j] = j*NNN;
+ }
+ }
+}
+
+void thread_loop() {
+ #pragma omp parallel
+ {
+ #pragma omp loop bind(thread)
+ for (int j = 0 ; j < NNN ; j++) {
+ aaa[j] = j*NNN;
+ }
+ }
+}
+
+void thread_loop2() {
+ #pragma omp loop bind(thread)
+ for (int j = 0 ; j < NNN ; j++) {
+ aaa[j] = j*NNN;
+ }
+}
+
+int main() {
+ parallel_loop();
+ teams_loop();
+ thread_loop();
+ thread_loop2();
+
+ return 0;
+}
+#endif
+// CHECK-LABEL: define {{[^@]+}}@_Z13parallel_loopv
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @3, i32 0, ptr @.omp_outlined.)
+// CHECK-NEXT: ret void
+// CHECK-LABEL: define {{[^@]+}}@.omp_outlined
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[TMP:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[J:%.*]] = alloca i32, align 4
+// CHECK: call void @__kmpc_for_static_init_4(ptr @1, i32 %1, i32 34, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK-LABEL: cond.true:
+// CHECK-NEXT: br label [[COND_END:%.*]]
+// CHECK-LABEL: cond.false:
+// CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
+// CHECK-NEXT: br label [[COND_END]]
+// CHECK: omp.inner.for.cond:
+// CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4
+// CHECK: omp.inner.for.body:
+// CHECK: omp.loop.exit:
+// CHECK-NEXT: call void @__kmpc_for_static_fini(ptr @1, i32 %1)
+// CHECK-NEXT: call void @__kmpc_barrier(ptr @2, i32 %1)
+// CHECK-NEXT: ret void
+//
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z10teams_loopv
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_teams(ptr @3, i32 0, ptr @.omp_outlined..1)
+// CHECK-NEXT: ret void
+//
+// CHECK-LABEL: define {{[^@]+}}@.omp_outlined
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[DOTGLOBAL_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[DOTBOUND_TID__ADDR:%.*]] = alloca ptr, align 8
+// CHECK-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[TMP:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTOMP_LB:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTOMP_UB:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTOMP_STRIDE:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTOMP_IS_LAST:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[J:%.*]] = alloca i32, align 4
+// CHECK: call void @__kmpc_for_static_init_4(ptr @4, i32 %1, i32 92, ptr [[DOTOMP_IS_LAST]], ptr [[DOTOMP_LB]], ptr [[DOTOMP_UB]], ptr [[DOTOMP_STRIDE]], i32 1, i32 1)
+// CHECK-LABEL: cond.true:
+// CHECK-NEXT: br label [[COND_END:%.*]]
+// CHECK-LABEL: cond.false:
+// CHECK-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTOMP_UB]], align 4
+// CHECK-NEXT: br label [[COND_END]]
+// CHECK: omp.inner.for.cond:
+// CHECK-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4
+// CHECK: omp.inner.for.body:
+// CHECK: omp.loop.exit:
+// CHECK-NEXT: call void @__kmpc_for_static_fini(ptr @4, i32 %1)
+// CHECK-NEXT: ret void
+//
+// CHECK-LABEL: define {{[^@]+}}@_Z11thread_loopv()
+// CHECK-NEXT: entry:
+// CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @3, i32 0, ptr @.omp_outlined.)
+// CHECK-LABEL: define {{[^@]+}}@.omp_outlined
+// CHECK: omp.inner.for.cond:
+//
+// CHECK-LABEL: @main{{.*}}
Index: clang/lib/Sema/SemaOpenMP.cpp
===================================================================
--- clang/lib/Sema/SemaOpenMP.cpp
+++ clang/lib/Sema/SemaOpenMP.cpp
@@ -635,6 +635,11 @@
const SharingMapTy *Top = getTopOfStackOrNull();
return Top ? Top->Directive : OMPD_unknown;
}
+ void setCurrentDirective(OpenMPDirectiveKind newDK) {
+ SharingMapTy *Top = (SharingMapTy *)getTopOfStackOrNull();
+ assert(Top != NULL);
+ Top->Directive = newDK;
+ }
/// Returns directive kind at specified level.
OpenMPDirectiveKind getDirective(unsigned Level) const {
assert(!isStackEmpty() && "No directive at specified level.");
@@ -6116,6 +6121,7 @@
if (const OMPBindClause *BC =
OMPExecutableDirective::getSingleClause<OMPBindClause>(Clauses))
BindKind = BC->getBindKind();
+
// First check CancelRegion which is then used in checkNestingOfRegions.
if (checkCancelRegion(*this, Kind, CancelRegion, StartLoc) ||
checkNestingOfRegions(*this, DSAStack, Kind, DirName, CancelRegion,
@@ -6127,10 +6133,75 @@
isOpenMPTargetDataManagementDirective(Kind)))
Diag(StartLoc, diag::warn_hip_omp_target_directives);
+ llvm::SmallVector<OMPClause *, 8> ClausesWithoutBind;
+ bool UseClausesWithoutBind = false;
+
+ // Restricting to "#pragma omp loop bind"
+ if (Kind == OMPD_loop) {
+ if (BindKind == OMPC_BIND_unknown) {
+ // Setting the enclosing teams or parallel construct for the loop
+ // directive without bind clause.
+ BindKind = OMPC_BIND_thread; // Default bind(thread) if binding is unknown
+
+ const OpenMPDirectiveKind parentDirective =
+ DSAStack->getParentDirective();
+ if (parentDirective == OMPD_unknown) {
+ Diag(DSAStack->getDefaultDSALocation(),
+ diag::err_omp_bind_required_on_loop);
+ } else if (parentDirective == OMPD_parallel ||
+ parentDirective == OMPD_target_parallel) {
+ BindKind = OMPC_BIND_parallel;
+ } else if (parentDirective == OMPD_teams ||
+ parentDirective == OMPD_target_teams) {
+ BindKind = OMPC_BIND_teams;
+ }
+ } else {
+ // bind clause is present, so we should set flag indicating to only
+ // use the clauses that aren't the bind clause for the new directive that
+ // loop is lowered to.
+ UseClausesWithoutBind = true;
+ }
+
+ for (OMPClause *C : Clauses) {
+ // Spec restriction : bind(teams) and reduction not permitted.
+ if ((BindKind == OMPC_BIND_teams) &&
+ (C->getClauseKind() == llvm::omp::Clause::OMPC_reduction))
+ Diag(SourceLocation(), diag::error_loop_reduction_clause);
+
+ // A new Vector ClausesWithoutBind, which does not contain the bind
+ // clause, for passing to new directive.
+ if (C->getClauseKind() != llvm::omp::Clause::OMPC_bind) {
+ ClausesWithoutBind.push_back(C);
+ }
+ }
+
+ switch (BindKind) {
+ case OMPC_BIND_parallel:
+ Kind = OMPD_for;
+ DSAStack->setCurrentDirective(OMPD_for);
+ break;
+ case OMPC_BIND_teams:
+ Kind = OMPD_distribute;
+ DSAStack->setCurrentDirective(OMPD_distribute);
+ break;
+ case OMPC_BIND_thread:
+ Kind = OMPD_simd;
+ DSAStack->setCurrentDirective(OMPD_simd);
+ break;
+ case OMPC_BIND_unknown:
+ break;
+ }
+ }
+
llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit;
VarsWithInheritedDSAType VarsWithInheritedDSA;
bool ErrorFound = false;
- ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
+ if (UseClausesWithoutBind) {
+ ClausesWithImplicit.append(ClausesWithoutBind.begin(),
+ ClausesWithoutBind.end());
+ } else {
+ ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
+ }
if (AStmt && !CurContext->isDependentContext() && Kind != OMPD_atomic &&
Kind != OMPD_critical && Kind != OMPD_section && Kind != OMPD_master &&
Kind != OMPD_masked && !isOpenMPLoopTransformationDirective(Kind)) {
Index: clang/lib/AST/StmtOpenMP.cpp
===================================================================
--- clang/lib/AST/StmtOpenMP.cpp
+++ clang/lib/AST/StmtOpenMP.cpp
@@ -2340,6 +2340,10 @@
Dir->setDependentInits(Exprs.DependentInits);
Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
+
+ Dir->LoopParamInit(C, StartLoc, EndLoc, CollapsedNum, Clauses, AssociatedStmt,
+ Exprs);
+
return Dir;
}
@@ -2351,6 +2355,14 @@
numLoopChildren(CollapsedNum, OMPD_loop), CollapsedNum);
}
+void OMPGenericLoopDirective::LoopParamInit(
+ const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
+ unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs) {
+ this->LoopDirCrParmV = new LoopDirCrParam(C, StartLoc, EndLoc, CollapsedNum,
+ Clauses, AssociatedStmt, Exprs);
+}
+
OMPTeamsGenericLoopDirective *OMPTeamsGenericLoopDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
Index: clang/include/clang/Parse/Parser.h
===================================================================
--- clang/include/clang/Parse/Parser.h
+++ clang/include/clang/Parse/Parser.h
@@ -1102,6 +1102,8 @@
void checkCompoundToken(SourceLocation FirstTokLoc,
tok::TokenKind FirstTokKind, CompoundToken Op);
+ void SetExecutableFlags(unsigned ExecFlags);
+
public:
//===--------------------------------------------------------------------===//
// Scope manipulation
@@ -1134,6 +1136,10 @@
}
}
+ void SetExecutableFlags(unsigned ExecFlags) {
+ Self->SetExecutableFlags(ExecFlags);
+ }
+
// Exit - Exit the scope associated with this object now, rather
// than waiting until the object is destroyed.
void Exit() {
Index: clang/include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9786,6 +9786,11 @@
def warn_loop_ctrl_binds_to_inner : Warning<
"'%0' is bound to current loop, GCC binds it to the enclosing loop">,
InGroup<GccCompat>;
+def err_omp_bind_required_on_loop : Error<
+ "expected 'bind' clause for loop construct without an enclosing OpenMP "
+ "construct">;
+def error_loop_reduction_clause : Error<
+ "reduction clause not handled with '#pragma omp loop bind(teams)'">;
def warn_break_binds_to_switch : Warning<
"'break' is bound to loop, GCC binds it to switch">,
InGroup<GccCompat>;
Index: clang/include/clang/AST/StmtOpenMP.h
===================================================================
--- clang/include/clang/AST/StmtOpenMP.h
+++ clang/include/clang/AST/StmtOpenMP.h
@@ -5945,6 +5945,30 @@
unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt, const HelperExprs &Exprs);
+ struct LoopDirCrParam {
+ const ASTContext *C;
+ SourceLocation StartLoc;
+ SourceLocation EndLoc;
+ unsigned CollapsedNum;
+ ArrayRef<OMPClause *> Clauses;
+ Stmt *AssociatedStmt;
+ const HelperExprs Exprs;
+
+ LoopDirCrParam(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned CollapsedNum,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs)
+ : C(&C), StartLoc(StartLoc), EndLoc(EndLoc), CollapsedNum(CollapsedNum),
+ Clauses(Clauses), AssociatedStmt(AssociatedStmt), Exprs(Exprs) {}
+ };
+
+ void LoopParamInit(const ASTContext &C, SourceLocation StartLoc,
+ SourceLocation EndLoc, unsigned CollapsedNum,
+ ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
+ const HelperExprs &Exprs);
+
+ struct LoopDirCrParam *LoopDirCrParmV;
+
/// Creates an empty directive with a place for \a NumClauses clauses.
///
/// \param C AST context.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits