Author: Urvi Rav Date: 2025-05-02T10:29:57+05:30 New Revision: 35e743d4bf1960a9ea982227a6159325784c56b9
URL: https://github.com/llvm/llvm-project/commit/35e743d4bf1960a9ea982227a6159325784c56b9 DIFF: https://github.com/llvm/llvm-project/commit/35e743d4bf1960a9ea982227a6159325784c56b9.diff LOG: default clause replaced by otherwise clause for metadirective in OpenMP 5.2 (#128640) This PR replaces the `default` clause with the `otherwise` clause for the `metadirective` in OpenMP. The `otherwise` clause serves as a fallback condition when no directive from the when clauses is selected. In the `when` clause, context selectors define traits evaluated to determine the directive to be applied. The previous merge was reverted due to a failing test case, which has now been resolved. --------- Co-authored-by: urvi-rav <urvi....@hpe.com> Added: clang/test/OpenMP/metadirective_default.cpp Modified: clang/docs/OpenMPSupport.rst clang/include/clang/Basic/DiagnosticParseKinds.td clang/lib/Parse/ParseOpenMP.cpp clang/test/OpenMP/metadirective_ast_print.c clang/test/OpenMP/metadirective_messages.cpp clang/test/OpenMP/metadirective_otherwise.cpp Removed: ################################################################################ diff --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst index f39987caf5c43..d6507071d4693 100644 --- a/clang/docs/OpenMPSupport.rst +++ b/clang/docs/OpenMPSupport.rst @@ -207,7 +207,7 @@ implementation. +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ | misc | library shutdown (omp_pause_resource[_all]) | :good:`done` | D55078 | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ -| misc | metadirectives | :part:`mostly done` | D91944 | +| misc | metadirectives | :part:`mostly done` | D91944, https://github.com/llvm/llvm-project/pull/128640 | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ | misc | conditional modifier for lastprivate clause | :good:`done` | | +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+ diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 72e765bcb800d..49ac27c915cbf 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1668,6 +1668,8 @@ def err_omp_expected_colon : Error<"missing ':' in %0">; def err_omp_missing_comma : Error< "missing ',' after %0">; def err_omp_expected_context_selector : Error<"expected valid context selector in %0">; +def warn_omp_default_deprecated : Warning<"'default' clause for" + " 'metadirective' is deprecated; use 'otherwise' instead">, InGroup<Deprecated>; def err_omp_requires_out_inout_depend_type : Error< "reserved locator 'omp_all_memory' requires 'out' or 'inout' " "dependency types">; diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 6fe2137435cd3..42051fff70eb8 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -2759,6 +2759,15 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( OpenMPClauseKind CKind = Tok.isAnnotation() ? OMPC_unknown : getOpenMPClauseKind(PP.getSpelling(Tok)); + // Check if the clause is unrecognized. + if (CKind == OMPC_unknown) + Diag(Tok, diag::err_omp_expected_clause) << "metadirective"; + if (getLangOpts().OpenMP < 52 && CKind == OMPC_otherwise) + Diag(Tok, diag::err_omp_unexpected_clause) + << getOpenMPClauseName(CKind) << "metadirective"; + if (CKind == OMPC_default && getLangOpts().OpenMP >= 52) + Diag(Tok, diag::warn_omp_default_deprecated); + SourceLocation Loc = ConsumeToken(); // Parse '('. @@ -2785,6 +2794,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective( return Directive; } } + // Skip Directive for now. We will parse directive in the second iteration int paren = 0; while (Tok.isNot(tok::r_paren) || paren != 0) { diff --git a/clang/test/OpenMP/metadirective_ast_print.c b/clang/test/OpenMP/metadirective_ast_print.c index 851f08ce37ee7..638dbae1bc774 100644 --- a/clang/test/OpenMP/metadirective_ast_print.c +++ b/clang/test/OpenMP/metadirective_ast_print.c @@ -1,19 +1,149 @@ -// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-unknown-linux-gnu -x c -std=c99 -ast-print %s -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp -triple x86_64-unknown-linux-gnu -x c -std=c99 -ast-print %s -o - | FileCheck %s --check-prefix=DEFAULT -// RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-unknown-linux-gnu -x c -std=c99 -ast-print %s -o - | FileCheck %s +// RUN: %clang_cc1 -verify -fopenmp-simd -triple x86_64-unknown-linux-gnu -x c -std=c99 -ast-print %s -o - | FileCheck %s --check-prefix=DEFAULT -// RUN: %clang_cc1 -verify -fopenmp -triple amdgcn-amd-amdhsa -x c -std=c99 -ast-print %s -o - | FileCheck %s --check-prefix=CHECK-AMDGCN +// RUN: %clang_cc1 -verify -fopenmp -triple amdgcn-amd-amdhsa -x c -std=c99 -ast-print %s -o - | FileCheck %s --check-prefix=DEFAULT-AMDGCN -// RUN: %clang_cc1 -verify -fopenmp-simd -triple amdgcn-amd-amdhsa -x c -std=c99 -ast-print %s -o - | FileCheck %s --check-prefix=CHECK-AMDGCN +// RUN: %clang_cc1 -verify -fopenmp-simd -triple amdgcn-amd-amdhsa -x c -std=c99 -ast-print %s -o - | FileCheck %s --check-prefix=DEFAULT-AMDGCN + +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=52 -DOMP52 -triple x86_64-unknown-linux-gnu -x c -std=c99 -ast-print %s -o - | FileCheck %s --check-prefix=OMP52 + +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=52 -DOMP52 -triple x86_64-unknown-linux-gnu -x c -std=c99 -ast-print %s -o - | FileCheck %s --check-prefix=OMP52 + +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=52 -DOMP52 -triple amdgcn-amd-amdhsa -x c -std=c99 -ast-print %s -o - | FileCheck %s --check-prefix=OMP52-AMDGCN + +// RUN: %clang_cc1 -verify -fopenmp-simd -fopenmp-version=52 -DOMP52 -triple amdgcn-amd-amdhsa -x c -std=c99 -ast-print %s -o - | FileCheck %s --check-prefix=OMP52-AMDGCN // expected-no-diagnostics #ifndef HEADER #define HEADER +#ifdef OMP52 void bar(void); #define N 10 -void foo(void) { +void foo1(void) { +#pragma omp metadirective when(device = {kind(cpu)} \ + : parallel) otherwise() + bar(); +#pragma omp metadirective when(implementation = {vendor(score(0) \ + : llvm)}, \ + device = {kind(cpu)} \ + : parallel) otherwise(target teams) + bar(); +#pragma omp metadirective when(device = {kind(gpu)} \ + : target teams) when(implementation = {vendor(llvm)} \ + : parallel) otherwise() + bar(); +#pragma omp metadirective otherwise(target) when(implementation = {vendor(score(5) \ + : llvm)}, \ + device = {kind(cpu, host)} \ + : parallel) + bar(); +#pragma omp metadirective when(user = {condition(N > 10)} \ + : target) when(user = {condition(N == 10)} \ + : parallel) + bar(); +#pragma omp metadirective when(device = {kind(host)} \ + : parallel for) + for (int i = 0; i < 100; i++) + ; +#pragma omp metadirective when(implementation = {extension(match_all)} \ + : parallel) otherwise(parallel for) + for (int i = 0; i < 100; i++) + ; +#pragma omp metadirective when(implementation = {extension(match_any)} \ + : parallel) otherwise(parallel for) + for (int i = 0; i < 100; i++) + ; +#pragma omp metadirective when(implementation = {extension(match_none)} \ + : parallel) otherwise(parallel for) + for (int i = 0; i < 100; i++) + ; + +// Test metadirective with nested OpenMP directive. + int array[16]; + #pragma omp metadirective when(user = {condition(1)} \ + : parallel for) + for (int i = 0; i < 16; i++) { + #pragma omp simd + for (int j = 0; j < 16; j++) + array[i] = i; + } + +#pragma omp metadirective when(device={arch("amdgcn")}: \ + teams distribute parallel for)\ + otherwise(parallel for) + for (int i = 0; i < 100; i++) + ; + +#pragma omp metadirective when(implementation = {extension(match_all)} \ + : nothing) otherwise(parallel for) + for (int i = 0; i < 16; i++) + ; + +#pragma omp metadirective when(implementation = {extension(match_any)} \ + : parallel) otherwise(nothing) + for (int i = 0; i < 16; i++) + ; + + +#pragma omp metadirective when(user = {condition(0)} \ + : parallel for) + for (int i=0; i<10; i++) + ; +#pragma omp metadirective when(user = {condition(0)} \ + : parallel for) when(implementation = {extension(match_none)} \ + : parallel) otherwise(parallel for) + for (int i=0; i<10; i++) + ; + + +#pragma omp metadirective when(user = {condition(1)} \ + : parallel for) + for (int i=0; i<10; i++) + ; +#pragma omp metadirective when(user = {condition(1)} \ + : parallel for) when(implementation = {extension(match_none)} \ + : parallel) otherwise(parallel for) + for (int i=0; i<10; i++) + ; +} + +// OMP52: void bar(void); +// OMP52: void foo1(void) +// OMP52-NEXT: #pragma omp parallel +// OMP52-NEXT: bar() +// OMP52-NEXT: #pragma omp parallel +// OMP52-NEXT: bar() +// OMP52-NEXT: #pragma omp parallel +// OMP52-NEXT: bar() +// OMP52-NEXT: #pragma omp parallel +// OMP52-NEXT: bar() +// OMP52-NEXT: #pragma omp parallel +// OMP52-NEXT: bar() +// OMP52-NEXT: #pragma omp parallel for +// OMP52-NEXT: for (int i = 0; i < 100; i++) +// OMP52: #pragma omp parallel +// OMP52-NEXT: for (int i = 0; i < 100; i++) +// OMP52: #pragma omp parallel for +// OMP52-NEXT: for (int i = 0; i < 100; i++) +// OMP52: #pragma omp parallel +// OMP52-NEXT: for (int i = 0; i < 100; i++) +// OMP52: #pragma omp parallel for +// OMP52-NEXT: for (int i = 0; i < 16; i++) { +// OMP52-NEXT: #pragma omp simd +// OMP52-NEXT: for (int j = 0; j < 16; j++) +// OMP52-AMDGCN: #pragma omp teams distribute parallel for +// OMP52-AMDGCN-NEXT: for (int i = 0; i < 100; i++) +// OMP52: for (int i = 0; i < 16; i++) +// OMP52: for (int i = 0; i < 16; i++) + +#else +void bar(void); + +#define N 10 +void foo2(void) { #pragma omp metadirective when(device = {kind(cpu)} \ : parallel) default() bar(); @@ -78,10 +208,7 @@ void foo(void) { for (int i = 0; i < 16; i++) ; -#pragma omp metadirective when(user = {condition(0)} \ - : parallel for) otherwise() - for (int i=0; i<10; i++) - ; + #pragma omp metadirective when(user = {condition(0)} \ : parallel for) for (int i=0; i<10; i++) @@ -92,10 +219,7 @@ void foo(void) { for (int i=0; i<10; i++) ; -#pragma omp metadirective when(user = {condition(1)} \ - : parallel for) otherwise() - for (int i=0; i<10; i++) - ; + #pragma omp metadirective when(user = {condition(1)} \ : parallel for) for (int i=0; i<10; i++) @@ -105,35 +229,49 @@ void foo(void) { : parallel) default(parallel for) for (int i=0; i<10; i++) ; +#if _OPENMP >= 202111 + #pragma omp metadirective when(user = {condition(0)} \ + : parallel for) otherwise() + for (int i=0; i<10; i++) + ; + + #pragma omp metadirective when(user = {condition(1)} \ + : parallel for) otherwise() + for (int i=0; i<10; i++) + ; +#endif } -// CHECK: void bar(void); -// CHECK: void foo(void) -// CHECK-NEXT: #pragma omp parallel -// CHECK-NEXT: bar() -// CHECK-NEXT: #pragma omp parallel -// CHECK-NEXT: bar() -// CHECK-NEXT: #pragma omp parallel -// CHECK-NEXT: bar() -// CHECK-NEXT: #pragma omp parallel -// CHECK-NEXT: bar() -// CHECK-NEXT: #pragma omp parallel -// CHECK-NEXT: bar() -// CHECK-NEXT: #pragma omp parallel for -// CHECK-NEXT: for (int i = 0; i < 100; i++) -// CHECK: #pragma omp parallel -// CHECK-NEXT: for (int i = 0; i < 100; i++) -// CHECK: #pragma omp parallel for -// CHECK-NEXT: for (int i = 0; i < 100; i++) -// CHECK: #pragma omp parallel -// CHECK-NEXT: for (int i = 0; i < 100; i++) -// CHECK: #pragma omp parallel for -// CHECK-NEXT: for (int i = 0; i < 16; i++) { -// CHECK-NEXT: #pragma omp simd -// CHECK-NEXT: for (int j = 0; j < 16; j++) -// CHECK-AMDGCN: #pragma omp teams distribute parallel for -// CHECK-AMDGCN-NEXT: for (int i = 0; i < 100; i++) -// CHECK: for (int i = 0; i < 16; i++) -// CHECK: for (int i = 0; i < 16; i++) +// DEFAULT: void bar(void); +// DEFAULT: void foo2(void) +// DEFAULT-NEXT: #pragma omp parallel +// DEFAULT-NEXT: bar() +// DEFAULT-NEXT: #pragma omp parallel +// DEFAULT-NEXT: bar() +// DEFAULT-NEXT: #pragma omp parallel +// DEFAULT-NEXT: bar() +// DEFAULT-NEXT: #pragma omp parallel +// DEFAULT-NEXT: bar() +// DEFAULT-NEXT: #pragma omp parallel +// DEFAULT-NEXT: bar() +// DEFAULT-NEXT: #pragma omp parallel for +// DEFAULT-NEXT: for (int i = 0; i < 100; i++) +// DEFAULT: #pragma omp parallel +// DEFAULT-NEXT: for (int i = 0; i < 100; i++) +// DEFAULT: #pragma omp parallel for +// DEFAULT-NEXT: for (int i = 0; i < 100; i++) +// DEFAULT: #pragma omp parallel +// DEFAULT-NEXT: for (int i = 0; i < 100; i++) +// DEFAULT: #pragma omp parallel for +// DEFAULT-NEXT: for (int i = 0; i < 16; i++) { +// DEFAULT-NEXT: #pragma omp simd +// DEFAULT-NEXT: for (int j = 0; j < 16; j++) +// DEFAULT-AMDGCN: #pragma omp teams distribute parallel for +// DEFAULT-AMDGCN-NEXT: for (int i = 0; i < 100; i++) +// DEFAULT: for (int i = 0; i < 16; i++) +// DEFAULT: for (int i = 0; i < 16; i++) + #endif +#endif + diff --git a/clang/test/OpenMP/metadirective_default.cpp b/clang/test/OpenMP/metadirective_default.cpp new file mode 100644 index 0000000000000..ab269f41b9380 --- /dev/null +++ b/clang/test/OpenMP/metadirective_default.cpp @@ -0,0 +1,198 @@ +// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-linux -emit-llvm %s -o - | FileCheck %s +// expected-no-diagnostics + +#ifndef HEADER +#define HEADER + +void func1() { + +#pragma omp metadirective when(user = {condition(0)} \ + : parallel for) + for (int i = 0; i < 100; i++) + ; + +#pragma omp metadirective when(user = {condition(0)} \ + : parallel for) \ + when(implementation = {extension(match_none)} \ + : parallel) default(parallel for) + + for (int i = 0; i < 100; i++) + ; + + +} + +// CHECK-LABEL: define dso_local void @_Z5func1v() +// CHECK: entry +// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store i32 0, ptr [[I]], align 4 +// CHECK-NEXT: br label %[[FOR_COND:.*]] +// CHECK: [[FOR_COND]]: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I]], align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 100 +// CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END:.*]] +// CHECK: [[FOR_BODY]]: +// CHECK-NEXT: br label %[[FOR_INC:.*]] +// CHECK: [[FOR_INC]]: +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[I]], align 4 +// CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 +// CHECK-NEXT: store i32 [[INC]], ptr [[I]], align 4 +// CHECK-NEXT: br label %[[FOR_COND]], !llvm.loop [[LOOP3:![0-9]+]] +// CHECK: [[FOR_END]]: +// CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @1, i32 0, ptr @_Z5func1v.omp_outlined) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define internal void @_Z5func1v.omp_outlined +// CHECK-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], +// CHECK-SAME: ptr noalias noundef [[DOTBOUND_TID_:%.*]]) +// CHECK-NEXT: entry +// CHECK-NEXT: [[GLOB_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[BOUND_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[GLOB_TID__ADDR]], align 8 +// CHECK-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[BOUND_TID__ADDR]], align 8 +// CHECK-NEXT: store i32 0, ptr [[I]], align 4 +// CHECK-NEXT: br label %for.cond +// CHECK:for.cond: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I]], align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 100 +// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// CHECK:for.body: +// CHECK-NEXT: br label [[FOR_INC:%.*]] +// CHECK:for.inc: +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[I]], align 4 +// CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 +// CHECK-NEXT: store i32 [[INC]], ptr [[I]], align 4 +// CHECK-NEXT: br label [[FOR_COND:%.*]] +// CHECK:for.end: +// CHECK-NEXT: ret void +// CHECK-NEXT:} + +void func2() { + +#pragma omp metadirective when(user = {condition(1)} \ + : parallel for) + for (int i = 0; i < 100; i++) + ; +} + +// CHECK-LABEL: define dso_local void @_Z5func2v() +// CHECK: entry +// CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2:[0-9]+]], i32 0, ptr @_Z5func2v.omp_outlined) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define internal void @_Z5func2v.omp_outlined +// CHECK-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], +// CHECK-SAME: ptr noalias noundef [[DOTBOUND_TID_:%.*]]) +// CHECK-NEXT: entry +// CHECK-NEXT: [[GLOB_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[BOUND_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK: [[OMP_IV:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[TMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[OMP_LB:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[OMP_UB:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[OMP_STRIDE:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[OMP_IS_LAST:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[GLOB_TID__ADDR]], align 8 +// CHECK-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[BOUND_TID__ADDR]], align 8 +// CHECK: store i32 0, ptr [[OMP_LB:%.*]], align 4 +// CHECK-NEXT: store i32 99, ptr [[OMP_UB:%.*]], align 4 +// CHECK-NEXT: store i32 1, ptr [[OMP_STRIDE:%.*]], align 4 +// CHECK-NEXT: store i32 0, ptr [[OMP_IS_LAST:%.*]], align 4 +// CHECK-NEXT: [[TID_PTR:%.*]] = load ptr, ptr [[GLOBAL_TID_ADDR:%.*]], align 8 +// CHECK-NEXT: [[TID_VAL:%.*]] = load i32, ptr [[TID_PTR]], align 4 +// CHECK-NEXT: call void @__kmpc_for_static_init_4(ptr @2, i32 [[TID_VAL]], i32 34, ptr [[OMP_IS_LAST]], ptr [[OMP_LB]], ptr [[OMP_UB]], ptr [[OMP_STRIDE]], i32 1, i32 1) +// CHECK-NEXT: [[UB_VAL:%.*]] = load i32, ptr [[OMP_UB]], align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[UB_VAL]], 99 +// CHECK-NEXT: br i1 [[CMP]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]] +// CHECK: cond.true: +// CHECK-NEXT: br label [[COND_END:%.*]] + +// CHECK:cond.false: +// CHECK-NEXT: [[UB_VAL:%.*]] = load i32, ptr [[OMP_UB:%.*]], align 4 +// CHECK-NEXT: br label [[COND_END]] + +// CHECK:cond.end: +// CHECK-NEXT: [[COND_PHI:%.*]] = phi i32 [ 99, [[COND_TRUE]] ], [ [[UB_VAL]], [[COND_FALSE]] ] +// CHECK-NEXT: store i32 [[COND_PHI]], ptr [[OMP_UB]], align 4 +// CHECK-NEXT: [[LB_VAL:%.*]] = load i32, ptr [[OMP_LB]], align 4 +// CHECK-NEXT: store i32 [[LB_VAL]], ptr [[OMP_IV]], align 4 +// CHECK-NEXT: br label [[OMP_FOR_COND:%.*]] + +// CHECK:omp.inner.for.cond: +// CHECK-NEXT: [[IV_VAL:%.*]] = load i32, ptr [[OMP_IV]], align 4 +// CHECK-NEXT: [[UB_VAL2:%.*]] = load i32, ptr [[OMP_UB]], align 4 +// CHECK-NEXT: [[CMP1:%.*]] = icmp sle i32 [[IV_VAL]], [[UB_VAL2]] +// CHECK-NEXT: br i1 [[CMP1]], label [[OMP_FOR_BODY:%.*]], label [[OMP_FOR_END:%.*]] + +// CHECK:omp.inner.for.body: +// CHECK-NEXT: [[IV_VAL2:%.*]] = load i32, ptr [[OMP_IV]], align 4 +// CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[IV_VAL2]], 1 +// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] +// CHECK-NEXT: store i32 [[ADD]], ptr [[I]], align 4 +// CHECK-NEXT: br label [[OMP_BODY_CONTINUE:%.*]] + +// CHECK:omp.body.continue: +// CHECK-NEXT: br label [[OMP_FOR_INC:%.*]] + +// CHECK:omp.inner.for.inc: +// CHECK-NEXT: [[IV_VAL3:%.*]] = load i32, ptr [[OMP_IV]], align 4 +// CHECK-NEXT: [[ADD2:%.*]] = add nsw i32 [[IV_VAL3]], 1 +// CHECK-NEXT: store i32 [[ADD2]], ptr [[OMP_IV]], align 4 +// CHECK-NEXT: br label [[OMP_FOR_COND]] + +// CHECK:omp.inner.for.end: +// CHECK-NEXT: br label [[OMP_LOOP_EXIT:%.*]] + +// CHECK:omp.loop.exit: +// CHECK-NEXT: call void @__kmpc_for_static_fini(ptr @2, i32 [[TID:%.*]]) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +void func3() { +#pragma omp metadirective when(user = {condition(0)} \ + : parallel for) \ + when(implementation = {extension(match_none)} \ + : parallel) default(parallel for) + + for (int i = 0; i < 100; i++) + ; + +} + +// CHECK-LABEL: define dso_local void @_Z5func3v() +// CHECK: entry +// CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @1, i32 0, ptr @_Z5func3v.omp_outlined) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + +// CHECK-LABEL: define internal void @_Z5func3v.omp_outlined +// CHECK-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], +// CHECK-SAME: ptr noalias noundef [[DOTBOUND_TID_:%.*]]) +// CHECK-NEXT: entry +// CHECK-NEXT: [[GLOB_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[BOUND_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[GLOB_TID__ADDR]], align 8 +// CHECK-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[BOUND_TID__ADDR]], align 8 +// CHECK-NEXT: store i32 0, ptr [[I]], align 4 +// CHECK-NEXT: br label %for.cond +// CHECK:for.cond: +// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I]], align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 100 +// CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] +// CHECK:for.body: +// CHECK-NEXT: br label [[FOR_INC:%.*]] +// CHECK:for.inc: +// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[I]], align 4 +// CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 +// CHECK-NEXT: store i32 [[INC]], ptr [[I]], align 4 +// CHECK-NEXT: br label [[FOR_COND:%.*]] +// CHECK:for.end: +// CHECK-NEXT: ret void +// CHECK-NEXT:} + +#endif diff --git a/clang/test/OpenMP/metadirective_messages.cpp b/clang/test/OpenMP/metadirective_messages.cpp index 7fce9fa446058..a248e9a4e82a9 100644 --- a/clang/test/OpenMP/metadirective_messages.cpp +++ b/clang/test/OpenMP/metadirective_messages.cpp @@ -2,21 +2,50 @@ // RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -verify -fopenmp-simd -x c++ -std=c++14 -fexceptions -fcxx-exceptions %s +// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -verify=expected,omp52 -fopenmp -fopenmp-version=52 -ferror-limit 100 -o - %s -Wuninitialized + void foo() { -#pragma omp metadirective // expected-error {{expected expression}} - ; -#pragma omp metadirective when() // expected-error {{expected valid context selector in when clause}} expected-error {{expected expression}} expected-warning {{expected identifier or string literal describing a context set; set skipped}} expected-note {{context set options are: 'construct' 'device' 'target_device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} - ; -#pragma omp metadirective when(device{}) // expected-warning {{expected '=' after the context set name "device"; '=' assumed}} expected-warning {{expected identifier or string literal describing a context selector; selector skipped}} expected-note {{context selector options are: 'kind' 'arch' 'isa'}} expected-note {{the ignored selector spans until here}} expected-error {{expected valid context selector in when clause}} expected-error {{expected expression}} - ; -#pragma omp metadirective when(device{arch(nvptx)}) // expected-error {{missing ':' in when clause}} expected-error {{expected expression}} expected-warning {{expected '=' after the context set name "device"; '=' assumed}} - ; -#pragma omp metadirective when(device{arch(nvptx)}: ) default() // expected-warning {{expected '=' after the context set name "device"; '=' assumed}} - ; -#pragma omp metadirective when(device = {arch(nvptx)} : ) default(xyz) // expected-error {{expected an OpenMP directive}} expected-error {{use of undeclared identifier 'xyz'}} - ; -#pragma omp metadirective when(device = {arch(nvptx)} : parallel default() // expected-error {{expected ',' or ')' in 'when' clause}} expected-error {{expected expression}} - ; -#pragma omp metadirective when(device = {isa("some-unsupported-feature")} : parallel) default(single) // expected-warning {{isa trait 'some-unsupported-feature' is not known to the current target; verify the spelling or consider restricting the context selector with the 'arch' selector further}} - ; -} + #if _OPENMP >= 202111 + #pragma omp metadirective // omp52-error {{expected expression}} + ; + #pragma omp metadirective when() // omp52-error {{expected valid context selector in when clause}} expected-error {{expected expression}} expected-warning {{expected identifier or string literal describing a context set; set skipped}} expected-note {{context set options are: 'construct' 'device' 'target_device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} + ; + #pragma omp metadirective when(device{}) // omp52-warning {{expected '=' after the context set name "device"; '=' assumed}} expected-warning {{expected identifier or string literal describing a context selector; selector skipped}} expected-note {{context selector options are: 'kind' 'arch' 'isa'}} expected-note {{the ignored selector spans until here}} expected-error {{expected valid context selector in when clause}} expected-error {{expected expression}} + ; + #pragma omp metadirective when(device{arch(nvptx)}) // omp52-error {{missing ':' in when clause}} expected-error {{expected expression}} expected-warning {{expected '=' after the context set name "device"; '=' assumed}} + ; + #pragma omp metadirective when(device{arch(nvptx)}: ) otherwise() // omp52-warning {{expected '=' after the context set name "device"; '=' assumed}} + ; + #pragma omp metadirective when(device = {arch(nvptx)} : ) otherwise(xyz) // omp52-error {{expected an OpenMP directive}} expected-error {{use of undeclared identifier 'xyz'}} + ; + #pragma omp metadirective when(device = {arch(nvptx)} : parallel otherwise() // omp52-error {{expected ',' or ')' in 'when' clause}} expected-error {{expected expression}} + ; + #pragma omp metadirective when(device = {isa("some-unsupported-feature")} : parallel) otherwise(single) // omp52-warning {{isa trait 'some-unsupported-feature' is not known to the current target; verify the spelling or consider restricting the context selector with the 'arch' selector further}} + ; + #pragma omp metadirective when(device = {arch(nvptx)} : parallel) default() // omp52-warning {{'default' clause for 'metadirective' is deprecated; use 'otherwise' instead}} + ; + #pragma omp metadirective when(device = {arch(nvptx)} : parallel) xyz() //omp52-error {{expected at least one clause on '#pragma omp metadirective' directive}} + ; + #else + #pragma omp metadirective // expected-error {{expected expression}} + ; + #pragma omp metadirective when() // expected-error {{expected valid context selector in when clause}} expected-error {{expected expression}} expected-warning {{expected identifier or string literal describing a context set; set skipped}} expected-note {{context set options are: 'construct' 'device' 'target_device' 'implementation' 'user'}} expected-note {{the ignored set spans until here}} + ; + #pragma omp metadirective when(device{}) // expected-warning {{expected '=' after the context set name "device"; '=' assumed}} expected-warning {{expected identifier or string literal describing a context selector; selector skipped}} expected-note {{context selector options are: 'kind' 'arch' 'isa'}} expected-note {{the ignored selector spans until here}} expected-error {{expected valid context selector in when clause}} expected-error {{expected expression}} + ; + #pragma omp metadirective when(device{arch(nvptx)}) // expected-error {{missing ':' in when clause}} expected-error {{expected expression}} expected-warning {{expected '=' after the context set name "device"; '=' assumed}} + ; + #pragma omp metadirective when(device{arch(nvptx)}: ) default() // expected-warning {{expected '=' after the context set name "device"; '=' assumed}} + ; + #pragma omp metadirective when(device = {arch(nvptx)} : ) default(xyz) // expected-error {{expected an OpenMP directive}} expected-error {{use of undeclared identifier 'xyz'}} + ; + #pragma omp metadirective when(device = {arch(nvptx)} : parallel default() // expected-error {{expected ',' or ')' in 'when' clause}} expected-error {{expected expression}} + ; + #pragma omp metadirective when(device = {isa("some-unsupported-feature")} : parallel) default(single) // expected-warning {{isa trait 'some-unsupported-feature' is not known to the current target; verify the spelling or consider restricting the context selector with the 'arch' selector further}} + ; + #pragma omp metadirective when(device = {isa("some-unsupported-feature")} : parallel) otherwise(single) // expected-warning {{isa trait 'some-unsupported-feature' is not known to the current target; verify the spelling or consider restricting the context selector with the 'arch' selector further}} //expected-error{{unexpected OpenMP clause 'otherwise' in directive '#pragma omp metadirective'}} + ; + #pragma omp metadirective when(device = {arch(nvptx)} : parallel) xyz() //expected-error {{expected at least one clause on '#pragma omp metadirective' directive}} + ; + #endif + } diff --git a/clang/test/OpenMP/metadirective_otherwise.cpp b/clang/test/OpenMP/metadirective_otherwise.cpp index 0533350c84eed..1616810ead639 100644 --- a/clang/test/OpenMP/metadirective_otherwise.cpp +++ b/clang/test/OpenMP/metadirective_otherwise.cpp @@ -1,105 +1,33 @@ -// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-linux -emit-llvm %s -o - | FileCheck %s -// expected-no-diagnostics - +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=52 -DOMP52 -triple x86_64-unknown-unknown -emit-llvm %s -o - | FileCheck %s +//expected-no-diagnostics #ifndef HEADER #define HEADER -void func1() { -#pragma omp metadirective when(user = {condition(0)} \ - : parallel for) otherwise() - for (int i = 0; i < 100; i++) - ; - -#pragma omp metadirective when(user = {condition(0)} \ - : parallel for) - for (int i = 0; i < 100; i++) - ; - -#pragma omp metadirective when(user = {condition(0)} \ - : parallel for) \ - when(implementation = {extension(match_none)} \ - : parallel) default(parallel for) - - for (int i = 0; i < 100; i++) - ; - - -} - -// CHECK-LABEL: define dso_local void @_Z5func1v() -// CHECK: entry -// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 -// CHECK-NEXT: [[I1:%.*]] = alloca i32, align 4 -// CHECK-NEXT: store i32 0, ptr [[I]], align 4 -// CHECK-NEXT: br label %[[FOR_COND:.*]] -// CHECK: [[FOR_COND]]: -// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I]], align 4 -// CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 100 -// CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END:.*]] -// CHECK: [[FOR_BODY]]: -// CHECK-NEXT: br label %[[FOR_INC:.*]] -// CHECK: [[FOR_INC]]: -// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[I]], align 4 -// CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 -// CHECK-NEXT: store i32 [[INC]], ptr [[I]], align 4 -// CHECK-NEXT: br label %[[FOR_COND]], !llvm.loop [[LOOP3:![0-9]+]] -// CHECK: [[FOR_END]]: -// CHECK-NEXT: store i32 0, ptr [[I1]], align 4 -// CHECK-NEXT: br label %[[FOR_COND2:.*]] -// CHECK: [[FOR_COND2]]: -// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[I1]], align 4 -// CHECK-NEXT: [[CMP3:%.*]] = icmp slt i32 [[TMP2]], 100 -// CHECK-NEXT: br i1 [[CMP3]], label %[[FOR_BODY4:.*]], label %[[FOR_END7:.*]] -// CHECK: [[FOR_BODY4]]: -// CHECK-NEXT: br label %[[FOR_INC5:.*]] -// CHECK: [[FOR_INC5]]: -// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[I1]], align 4 -// CHECK-NEXT: [[INC6:%.*]] = add nsw i32 [[TMP3]], 1 -// CHECK-NEXT: store i32 [[INC6]], ptr [[I1]], align 4 -// CHECK-NEXT: br label %[[FOR_COND2]], !llvm.loop [[LOOP5:![0-9]+]] -// CHECK: [[FOR_END7]]: -// CHECK: ret void - -void func2() { -#pragma omp metadirective when(user = {condition(1)} \ - : parallel for) otherwise() - for (int i = 0; i < 100; i++) - ; - -#pragma omp metadirective when(user = {condition(1)} \ - : parallel for) - for (int i = 0; i < 100; i++) - ; -} - -// CHECK-LABEL: define dso_local void @_Z5func2v() -// CHECK: entry -// CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2:[0-9]+]], i32 0, ptr @_Z5func2v.omp_outlined) -// CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 0, ptr @_Z5func2v.omp_outlined.1) -// CHECK-NEXT: ret void - - -void func3() { -#pragma omp metadirective when(user = {condition(0)} \ - : parallel for) \ - when(implementation = {extension(match_none)} \ - : parallel) default(parallel for) - - for (int i = 0; i < 100; i++) - ; - -} +#ifdef OMP52 +void func4(){ + #pragma omp metadirective when(user = {condition(0)} \ + : parallel for) otherwise(parallel) + for (int i = 0; i < 100; i++) + ; + + #pragma omp metadirective when(user = {condition(1)} \ + : parallel for) otherwise() + for (int i = 0; i < 100; i++) + ; + } +#endif -// CHECK-LABEL: define dso_local void @_Z5func3v() -// CHECK: entry -// CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @1, i32 0, ptr @_Z5func3v.omp_outlined) -// CHECK-NEXT: ret void -// CHECK-NEXT: } +// CHECK-LABEL: define dso_local void @_Z5func4v() +// CHECK: entry +// CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @1, i32 0, ptr @_Z5func4v.omp_outlined) +// CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @1, i32 0, ptr @_Z5func4v.omp_outlined.1) +// CHECK-NEXT: ret void +// CHECK-NEXT: } -// CHECK-LABEL: define internal void @_Z5func3v.omp_outlined +// CHECK-LABEL: define internal void @_Z5func4v.omp_outlined // CHECK-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], // CHECK-SAME: ptr noalias noundef [[DOTBOUND_TID_:%.*]]) -// CHECK-NEXT: entry +// CHECK: entry // CHECK-NEXT: [[GLOB_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[BOUND_TID__ADDR:%.*]] = alloca ptr, align 8 // CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 @@ -117,9 +45,66 @@ void func3() { // CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[I]], align 4 // CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 // CHECK-NEXT: store i32 [[INC]], ptr [[I]], align 4 -// CHECK-NEXT: br label [[FOR_COND:%.*]] +// CHECK-NEXT: br label [[FOR_COND:%.*]], !llvm.loop ![[LOOPID:[0-9]+]] // CHECK:for.end: // CHECK-NEXT: ret void // CHECK-NEXT:} +// CHECK-LABEL: define internal void @_Z5func4v.omp_outlined.1 +// CHECK-SAME: (ptr noalias noundef [[DOTGLOBAL_TID_:%.*]], +// CHECK-SAME: ptr noalias noundef [[DOTBOUND_TID_:%.*]]) +// CHECK-NEXT: entry +// CHECK-NEXT: [[GLOB_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: [[BOUND_TID__ADDR:%.*]] = alloca ptr, align 8 +// CHECK: [[OMP_IV:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[TMP:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[OMP_LB:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[OMP_UB:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[OMP_STRIDE:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[OMP_IS_LAST:%.*]] = alloca i32, align 4 +// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4 +// CHECK-NEXT: store ptr [[DOTGLOBAL_TID_]], ptr [[GLOB_TID__ADDR]], align 8 +// CHECK-NEXT: store ptr [[DOTBOUND_TID_]], ptr [[BOUND_TID__ADDR]], align 8 +// CHECK: store i32 0, ptr [[OMP_LB:%.*]], align 4 +// CHECK-NEXT: store i32 99, ptr [[OMP_UB:%.*]], align 4 +// CHECK-NEXT: store i32 1, ptr [[OMP_STRIDE:%.*]], align 4 +// CHECK-NEXT: store i32 0, ptr [[OMP_IS_LAST:%.*]], align 4 +// CHECK-NEXT: [[TID_PTR:%.*]] = load ptr, ptr [[GLOBAL_TID_ADDR:%.*]], align 8 +// CHECK-NEXT: [[TID:%.*]] = load i32, ptr [[TID_PTR]], align 4 +// CHECK-NEXT: call void @__kmpc_for_static_init_4(ptr @2, i32 [[TID]], i32 34, ptr [[OMP_IS_LAST]], ptr [[OMP_LB]], ptr [[OMP_UB]], ptr [[OMP_STRIDE]], i32 1, i32 1) +// CHECK: [[UB_VAL:%.*]] = load i32, ptr [[OMP_UB]], align 4 +// CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[UB_VAL]], 99 +// CHECK-NEXT: br i1 [[CMP]], label %cond.true, label %cond.false +// CHECK: cond.true: +// CHECK-NEXT: br label %cond.end +// CHECK: cond.false: +// CHECK-NEXT: [[UB_NEW:%.*]] = load i32, ptr [[OMP_UB]], align 4 +// CHECK-NEXT: br label %cond.end +// CHECK: cond.end: +// CHECK-NEXT: [[FINAL_UB:%.*]] = phi i32 [ 99, %cond.true ], [ [[UB_NEW]], %cond.false ] +// CHECK-NEXT: store i32 [[FINAL_UB]], ptr [[OMP_UB]], align 4 +// CHECK-NEXT: [[LB_VAL:%.*]] = load i32, ptr [[OMP_LB]], align 4 +// CHECK-NEXT: store i32 [[LB_VAL]], ptr [[OMP_IV]], align 4 +// CHECK-NEXT: br label %omp.inner.for.cond +// CHECK: omp.inner.for.cond: +// CHECK-NEXT: [[IV_VAL:%.*]] = load i32, ptr [[OMP_IV]], align 4 +// CHECK-NEXT: [[UB_FINAL:%.*]] = load i32, ptr [[OMP_UB]], align 4 +// CHECK-NEXT: [[CMP_LOOP:%.*]] = icmp sle i32 [[IV_VAL]], [[UB_FINAL]] +// CHECK-NEXT: br i1 [[CMP_LOOP]], label %omp.inner.for.body, label %omp.inner.for.end +// CHECK: omp.inner.for.body: +// CHECK-NEXT: [[IV_NEW:%.*]] = load i32, ptr [[OMP_IV]], align 4 +// CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[IV_NEW]], 1 +// CHECK-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]] +// CHECK-NEXT: store i32 [[ADD]], ptr [[I]], align 4 +// CHECK-NEXT: br label %omp.body.continue +// CHECK: omp.inner.for.inc: +// CHECK-NEXT: [[IV_CURR:%.*]] = load i32, ptr [[OMP_IV]], align 4 +// CHECK-NEXT: [[IV_NEXT:%.*]] = add nsw i32 [[IV_CURR]], 1 +// CHECK-NEXT: store i32 [[IV_NEXT]], ptr [[OMP_IV]], align 4 +// CHECK-NEXT: br label %omp.inner.for.cond +// CHECK: omp.loop.exit: +// CHECK-NEXT: call void @__kmpc_for_static_fini(ptr @2, i32 [[TID]]) +// CHECK-NEXT: ret void +// CHECK-NEXT: } + #endif _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits