[OpenMP] support depend clause for taskwait directive, by Deepak

Eachempati.

This patch adds clang (parsing, sema, serialization, codegen) support for the 'depend' clause on the 'taskwait' directive.

Reviewed By: ABataev

Differential Revision: https://reviews.llvm.org/D113540
This commit is contained in:
Alexey Bataev 2021-11-19 05:59:40 -08:00
parent 8b76d33c59
commit 80256605f8
17 changed files with 214 additions and 47 deletions

View File

@ -147,7 +147,7 @@ implementation.
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| task extension | task affinity | :part:`not upstream` | https://github.com/jklinkenberg/openmp/tree/task-affinity |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| task extension | clause: depend on the taskwait construct | :part:`worked on` | |
| task extension | clause: depend on the taskwait construct | :part:`mostly done` | D113540 (regular codegen only) |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
| task extension | depend objects and detachable tasks | :good:`done` | |
+------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+

View File

@ -2569,15 +2569,20 @@ public:
/// \param C AST context.
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending Location of the directive.
/// \param Clauses List of clauses.
///
static OMPTaskwaitDirective *
Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
static OMPTaskwaitDirective *Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses);
/// Creates an empty directive.
///
/// \param C AST context.
/// \param NumClauses Number of clauses.
///
static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C, EmptyShell);
static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C,
unsigned NumClauses, EmptyShell);
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPTaskwaitDirectiveClass;

View File

@ -10599,6 +10599,8 @@ def err_omp_depend_sink_unexpected_expr : Error<
"unexpected expression: number of expressions is larger than the number of associated loops">;
def err_omp_depend_sink_expected_plus_minus : Error<
"expected '+' or '-' operation">;
def err_omp_taskwait_depend_mutexinoutset_not_allowed : Error<
"'mutexinoutset' modifier not allowed in 'depend' clause on 'taskwait' directive">;
def err_omp_depend_sink_source_not_allowed : Error<
"'depend(%select{source|sink:vec}0)' clause%select{|s}0 cannot be mixed with 'depend(%select{sink:vec|source}0)' clause%select{s|}0">;
def err_omp_depend_zero_length_array_section_not_allowed : Error<

View File

@ -10753,7 +10753,8 @@ public:
StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
SourceLocation EndLoc);
/// Called on well-formed '\#pragma omp taskwait'.
StmtResult ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,
StmtResult ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
SourceLocation EndLoc);
/// Called on well-formed '\#pragma omp taskgroup'.
StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,

View File

@ -739,15 +739,19 @@ OMPBarrierDirective *OMPBarrierDirective::CreateEmpty(const ASTContext &C,
return new (C) OMPBarrierDirective();
}
OMPTaskwaitDirective *OMPTaskwaitDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc) {
return new (C) OMPTaskwaitDirective(StartLoc, EndLoc);
OMPTaskwaitDirective *
OMPTaskwaitDirective::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses) {
return createDirective<OMPTaskwaitDirective>(
C, Clauses, /*AssociatedStmt=*/nullptr, /*NumChildren=*/0, StartLoc,
EndLoc);
}
OMPTaskwaitDirective *OMPTaskwaitDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
EmptyShell) {
return new (C) OMPTaskwaitDirective();
return createEmptyDirective<OMPTaskwaitDirective>(C, NumClauses);
}
OMPTaskgroupDirective *OMPTaskgroupDirective::Create(

View File

@ -6264,21 +6264,51 @@ Address CGOpenMPRuntime::getTaskReductionItem(CodeGenFunction &CGF,
SharedLVal.getAlignment());
}
void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
SourceLocation Loc) {
void CGOpenMPRuntime::emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc,
const OMPTaskDataTy &Data) {
if (!CGF.HaveInsertPoint())
return;
if (CGF.CGM.getLangOpts().OpenMPIRBuilder) {
if (CGF.CGM.getLangOpts().OpenMPIRBuilder && Data.Dependences.empty()) {
// TODO: Need to support taskwait with dependences in the OpenMPIRBuilder.
OMPBuilder.createTaskwait(CGF.Builder);
} else {
// Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
// global_tid);
llvm::Value *Args[] = {emitUpdateLocation(CGF, Loc), getThreadID(CGF, Loc)};
// Ignore return result until untied tasks are supported.
CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction(
CGM.getModule(), OMPRTL___kmpc_omp_taskwait),
Args);
llvm::Value *ThreadID = getThreadID(CGF, Loc);
llvm::Value *UpLoc = emitUpdateLocation(CGF, Loc);
auto &M = CGM.getModule();
Address DependenciesArray = Address::invalid();
llvm::Value *NumOfElements;
std::tie(NumOfElements, DependenciesArray) =
emitDependClause(CGF, Data.Dependences, Loc);
llvm::Value *DepWaitTaskArgs[6];
if (!Data.Dependences.empty()) {
DepWaitTaskArgs[0] = UpLoc;
DepWaitTaskArgs[1] = ThreadID;
DepWaitTaskArgs[2] = NumOfElements;
DepWaitTaskArgs[3] = DependenciesArray.getPointer();
DepWaitTaskArgs[4] = CGF.Builder.getInt32(0);
DepWaitTaskArgs[5] = llvm::ConstantPointerNull::get(CGF.VoidPtrTy);
CodeGenFunction::RunCleanupsScope LocalScope(CGF);
// Build void __kmpc_omp_wait_deps(ident_t *, kmp_int32 gtid,
// kmp_int32 ndeps, kmp_depend_info_t *dep_list, kmp_int32
// ndeps_noalias, kmp_depend_info_t *noalias_dep_list); if dependence info
// is specified.
CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_wait_deps),
DepWaitTaskArgs);
} else {
// Build call kmp_int32 __kmpc_omp_taskwait(ident_t *loc, kmp_int32
// global_tid);
llvm::Value *Args[] = {UpLoc, ThreadID};
// Ignore return result until untied tasks are supported.
CGF.EmitRuntimeCall(
OMPBuilder.getOrCreateRuntimeFunction(M, OMPRTL___kmpc_omp_taskwait),
Args);
}
}
if (auto *Region = dyn_cast_or_null<CGOpenMPRegionInfo>(CGF.CapturedStmtInfo))
@ -13044,7 +13074,8 @@ Address CGOpenMPSIMDRuntime::getTaskReductionItem(CodeGenFunction &CGF,
}
void CGOpenMPSIMDRuntime::emitTaskwaitCall(CodeGenFunction &CGF,
SourceLocation Loc) {
SourceLocation Loc,
const OMPTaskDataTy &Data) {
llvm_unreachable("Not supported in SIMD-only mode");
}

View File

@ -1547,7 +1547,8 @@ public:
LValue SharedLVal);
/// Emit code for 'taskwait' directive.
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc);
virtual void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc,
const OMPTaskDataTy &Data);
/// Emit code for 'cancellation point' construct.
/// \param CancelRegion Region kind for which the cancellation point must be
@ -2385,7 +2386,8 @@ public:
LValue SharedLVal) override;
/// Emit code for 'taskwait' directive.
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc) override;
void emitTaskwaitCall(CodeGenFunction &CGF, SourceLocation Loc,
const OMPTaskDataTy &Data) override;
/// Emit code for 'cancellation point' construct.
/// \param CancelRegion Region kind for which the cancellation point must be

View File

@ -4845,7 +4845,14 @@ void CodeGenFunction::EmitOMPBarrierDirective(const OMPBarrierDirective &S) {
}
void CodeGenFunction::EmitOMPTaskwaitDirective(const OMPTaskwaitDirective &S) {
CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc());
OMPTaskDataTy Data;
// Build list of dependences
for (const auto *C : S.getClausesOfKind<OMPDependClause>()) {
OMPTaskDataTy::DependData &DD =
Data.Dependences.emplace_back(C->getDependencyKind(), C->getModifier());
DD.DepExprs.append(C->varlist_begin(), C->varlist_end());
}
CGM.getOpenMPRuntime().emitTaskwaitCall(*this, S.getBeginLoc(), Data);
}
void CodeGenFunction::EmitOMPTaskgroupDirective(

View File

@ -6046,11 +6046,9 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(
Res = ActOnOpenMPBarrierDirective(StartLoc, EndLoc);
break;
case OMPD_taskwait:
assert(ClausesWithImplicit.empty() &&
"No clauses are allowed for 'omp taskwait' directive");
assert(AStmt == nullptr &&
"No associated statement allowed for 'omp taskwait' directive");
Res = ActOnOpenMPTaskwaitDirective(StartLoc, EndLoc);
Res = ActOnOpenMPTaskwaitDirective(ClausesWithImplicit, StartLoc, EndLoc);
break;
case OMPD_taskgroup:
Res = ActOnOpenMPTaskgroupDirective(ClausesWithImplicit, AStmt, StartLoc,
@ -10467,9 +10465,10 @@ StmtResult Sema::ActOnOpenMPBarrierDirective(SourceLocation StartLoc,
return OMPBarrierDirective::Create(Context, StartLoc, EndLoc);
}
StmtResult Sema::ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc,
StmtResult Sema::ActOnOpenMPTaskwaitDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation StartLoc,
SourceLocation EndLoc) {
return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc);
return OMPTaskwaitDirective::Create(Context, StartLoc, EndLoc, Clauses);
}
StmtResult Sema::ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses,
@ -18444,6 +18443,11 @@ Sema::ActOnOpenMPDependClause(Expr *DepModifier, OpenMPDependClauseKind DepKind,
<< "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
return nullptr;
}
if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
DepKind == OMPC_DEPEND_mutexinoutset) {
Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
return nullptr;
}
if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
DSAStack->getCurrentDirective() == OMPD_depobj) &&
(DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||

View File

@ -2416,6 +2416,8 @@ void ASTStmtReader::VisitOMPBarrierDirective(OMPBarrierDirective *D) {
void ASTStmtReader::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
Record.skipInts(1);
VisitOMPExecutableDirective(D);
}
@ -3313,7 +3315,8 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
case STMT_OMP_TASKWAIT_DIRECTIVE:
S = OMPTaskwaitDirective::CreateEmpty(Context, Empty);
S = OMPTaskwaitDirective::CreateEmpty(
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
case STMT_OMP_TASKGROUP_DIRECTIVE:

View File

@ -2380,6 +2380,7 @@ void ASTStmtWriter::VisitOMPBarrierDirective(OMPBarrierDirective *D) {
void ASTStmtWriter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
VisitStmt(D);
Record.push_back(D->getNumClauses());
VisitOMPExecutableDirective(D);
Code = serialization::STMT_OMP_TASKWAIT_DIRECTIVE;
}

View File

@ -1,10 +1,10 @@
// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp-simd -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp-simd -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ast-print %s | FileCheck %s
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -x c++ -std=c++11 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp-simd -fopenmp-version=50 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s
// expected-no-diagnostics
#ifndef HEADER
@ -16,20 +16,26 @@ template <class T>
T tmain(T argc) {
static T a;
#pragma omp taskwait
#pragma omp taskwait depend(in:a, argc)
return a + argc;
}
// CHECK: static T a;
// CHECK-NEXT: #pragma omp taskwait{{$}}
// CHECK-NEXT: #pragma omp taskwait depend(in : a,argc){{$}}
// CHECK: static int a;
// CHECK-NEXT: #pragma omp taskwait
// CHECK-NEXT: #pragma omp taskwait depend(in : a,argc){{$}}
// CHECK: static char a;
// CHECK-NEXT: #pragma omp taskwait
// CHECK-NEXT: #pragma omp taskwait depend(in : a,argc){{$}}
int main(int argc, char **argv) {
static int a;
// CHECK: static int a;
#pragma omp taskwait
#pragma omp taskwait depend(out:a, argc)
// CHECK-NEXT: #pragma omp taskwait
// CHECK-NEXT: #pragma omp taskwait depend(out : a,argc)
return tmain(argc) + tmain(argv[0][0]) + a;
}

View File

@ -0,0 +1,38 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp -x c++ -emit-llvm %s -o - | FileCheck %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin10 -fopenmp-simd -x c++ -emit-llvm %s -o - | FileCheck --check-prefix SIMD-ONLY0 %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -emit-pch -o %t %s
// RUN: %clang_cc1 -fopenmp-simd -x c++ -triple x86_64-apple-darwin10 -include-pch %t -verify %s -emit-llvm -o - | FileCheck --check-prefix SIMD-ONLY0 %s
// SIMD-ONLY0-NOT: {{__kmpc|__tgt}}
// expected-no-diagnostics
#ifndef HEADER
#define HEADER
void foo() {}
template <class T>
T tmain(T &argc) {
static T a;
#pragma omp taskwait depend(in:argc)
return a + argc;
}
int main(int argc, char **argv) {
int n = 0;
#pragma omp task shared(n,argc) depend(out:n)
n = argc;
return tmain(n);
}
// CHECK-LABEL: @main
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%{{.+}}* @{{.+}})
// CHECK: [[ALLOC:%.+]] = call i8* @__kmpc_omp_task_alloc(%{{.+}}* @{{.+}}, i32 [[GTID]], i32 1, i64 40, i64 16, i32 (i32, i8*)* bitcast (i32 (i32, %{{.+}}*)* @{{.+}} to i32 (i32, i8*)*))
// CHECK: %{{.+}} = call i32 @__kmpc_omp_task_with_deps(%{{.+}}* @{{.+}}, i32 [[GTID]], i8* [[ALLOC]], i32 1, i8* %{{[0-9]*}}, i32 0, i8* null)
// CHECK-LABEL: tmain
// CHECK: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(%{{.+}}* @{{.+}})
// CHECK: call void @__kmpc_omp_wait_deps(%{{.+}}* @{{.+}}, i32 [[GTID]], i32 1, i8* %{{.}}, i32 0, i8* null)
#endif

View File

@ -0,0 +1,62 @@
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=50 -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=50 -ferror-limit 100 -o - -std=c++11 %s -Wuninitialized
void foo() {
}
bool foobool(int argc) {
return argc;
}
struct S1; // expected-note {{declared here}}
class vector {
public:
int operator[](int index) { return 0; }
};
int main(int argc, char **argv, char *env[]) {
vector vec;
typedef float V __attribute__((vector_size(16)));
V a;
auto arr = x; // expected-error {{use of undeclared identifier 'x'}}
#pragma omp taskwait depend // expected-error {{expected '(' after 'depend'}}
#pragma omp taskwait depend ( // expected-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after dependency type - ignoring}}
#pragma omp taskwait depend () // expected-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}}
#pragma omp taskwait depend (argc // expected-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp taskwait depend (source : argc) // expected-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
#pragma omp taskwait depend (source) // expected-error {{expected expression}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
#pragma omp taskwait depend(mutexinoutset: argc) // expected-error{{'mutexinoutset' modifier not allowed in 'depend' clause on 'taskwait' directive}}
#pragma omp taskwait depend (in : argc)) // expected-warning {{extra tokens at the end of '#pragma omp taskwait' are ignored}}
#pragma omp taskwait depend (out: ) // expected-error {{expected expression}}
#pragma omp taskwait depend (inout : foobool(argc)), depend (in, argc) // expected-error {{expected addressable lvalue expression, array element, array section or array shaping expression}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected expression}}
#pragma omp taskwait depend (out :S1) // expected-error {{'S1' does not refer to a value}}
#pragma omp taskwait depend(in : argv[1][1] = '2')
#pragma omp taskwait depend (in : vec[1]) // expected-error {{expected addressable lvalue expression, array element, array section or array shaping expression}}
#pragma omp taskwait depend (in : argv[0])
#pragma omp taskwait depend (in : ) // expected-error {{expected expression}}
#pragma omp taskwait depend (in : main)
#pragma omp taskwait depend(in : a[0]) // expected-error{{expected addressable lvalue expression, array element, array section or array shaping expression}}
#pragma omp taskwait depend (in : vec[1:2]) // expected-error {{ value is not an array or pointer}}
#pragma omp taskwait depend (in : argv[ // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
#pragma omp taskwait depend (in : argv[: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
#pragma omp taskwait depend (in : argv[:] // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}} expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp taskwait depend (in : argv[argc: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
#pragma omp taskwait depend (in : argv[argc:argc] // expected-error {{expected ')'}} expected-note {{to match this '('}}
#pragma omp taskwait depend (in : argv[0:-1]) // expected-error {{section length is evaluated to a negative value -1}}
#pragma omp taskwait depend (in : argv[-1:0]) // expected-error {{zero-length array section is not allowed in 'depend' clause}}
#pragma omp taskwait depend (in : argv[:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
#pragma omp taskwait depend (in : argv[3:4:1]) // expected-error {{expected ']'}} expected-note {{to match this '['}}
#pragma omp taskwait depend(in:a[0:1]) // expected-error {{subscripted value is not an array or pointer}}
#pragma omp taskwait depend(in:argv[argv[:2]:1]) // expected-error {{OpenMP array section is not allowed here}}
#pragma omp taskwait depend(in:argv[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is not an array}}
#pragma omp taskwait depend(in:env[0:][:]) // expected-error {{section length is unspecified and cannot be inferred because subscripted value is an array of unknown bound}}
#pragma omp taskwait depend(in : argv[ : argc][1 : argc - 1])
#pragma omp taskwait depend(in : arr[0])
foo();
return 0;
}

View File

@ -1,10 +1,11 @@
// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 %s -Wuninitialized
// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ferror-limit 100 %s -Wuninitialized
// RUN: %clang_cc1 -verify -fopenmp-simd -ferror-limit 100 %s -Wuninitialized
// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=45 -ferror-limit 100 %s -Wuninitialized
template <class T>
T tmain(T argc) {
#pragma omp taskwait allocate(argc) // expected-error {{unexpected OpenMP clause 'allocate' in directive '#pragma omp taskwait'}}
#pragma omp taskwait depend(in:argc) // expected-error {{unexpected OpenMP clause 'depend' in directive '#pragma omp taskwait'}}
;
#pragma omp taskwait untied // expected-error {{unexpected OpenMP clause 'untied' in directive '#pragma omp taskwait'}}
#pragma omp taskwait unknown // expected-warning {{extra tokens at the end of '#pragma omp taskwait' are ignored}}

View File

@ -7,10 +7,9 @@
// icc does not yet support taskwait with depend clause
// XFAIL: icc
// clang does not yet support taskwait with depend clause
// clang-12 introduced parsing, but no codegen
// update expected result when codegen in clang was added
// XFAIL: clang
// support for taskwait with depend clause introduced in clang-14
// UNSUPPORTED: clang-5, clang-6, clang-6, clang-8, clang-9, clang-10, clang-11,
// clang-12, clang-13
#include "callback.h"
#include <omp.h>

View File

@ -1,11 +1,12 @@
// RUN: %libomp-compile-and-run
// UNSUPPORTED: gcc-4, gcc-5, gcc-6, gcc-7, gcc-8
// clang does not yet support taskwait with depend clause
// clang-12 introduced parsing, but no codegen
// TODO: update expected result when codegen in clang is added
// support for taskwait with depend clause introduced in clang-14
// UNSUPPORTED: clang-5, clang-6, clang-6, clang-8, clang-9, clang-10, clang-11,
// clang-12, clang-13
// icc does not yet support taskwait with depend clause
// TODO: update expected result when support for icc is added
// XFAIL: clang, icc
// XFAIL: icc
#include <stdio.h>
#include <stdlib.h>