[clang] 35e743d - default clause replaced by otherwise clause for metadirective in OpenMP 5.2 (#128640)
via cfe-commits
cfe-commits at lists.llvm.org
Thu May 1 22:00:00 PDT 2025
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.rav at 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
More information about the cfe-commits
mailing list