summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Bataev <a.bataev@hotmail.com>2019-10-07 18:54:57 +0000
committerAlexey Bataev <a.bataev@hotmail.com>2019-10-07 18:54:57 +0000
commitf8c3d1a886ce2dffb92f17863b576a5f4b08f6f9 (patch)
tree9e5605124f5478bad11d647e19fb0f68f679ac14
parentb886fe4cb63a677a7ac7a75ee5d2282247b99301 (diff)
downloadclang-f8c3d1a886ce2dffb92f17863b576a5f4b08f6f9.tar.gz
[OPENMP50]Treat range-based for as canonical loop.
According to OpenMP 5.0, range-based for is also considered as a canonical form of loops. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@373939 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/StmtOpenMP.h17
-rw-r--r--include/clang/Sema/Sema.h4
-rw-r--r--lib/CodeGen/CGStmtOpenMP.cpp33
-rw-r--r--lib/Parse/ParseDecl.cpp2
-rw-r--r--lib/Sema/SemaOpenMP.cpp49
-rw-r--r--lib/Sema/SemaStmt.cpp5
-rw-r--r--test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/distribute_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/for_ast_print.cpp26
-rw-r--r--test/OpenMP/for_loop_messages.cpp2
-rw-r--r--test/OpenMP/for_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_codegen.cpp159
-rw-r--r--test/OpenMP/parallel_for_loop_messages.cpp2
-rw-r--r--test/OpenMP/parallel_for_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_loop_messages.cpp2
-rw-r--r--test/OpenMP/target_parallel_for_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/target_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_loop_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp2
-rw-r--r--test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_loop_messages.cpp2
-rw-r--r--test/OpenMP/taskloop_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_loop_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp2
-rw-r--r--test/OpenMP/teams_distribute_simd_loop_messages.cpp2
27 files changed, 291 insertions, 42 deletions
diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h
index c9efe32387..ef69158d61 100644
--- a/include/clang/AST/StmtOpenMP.h
+++ b/include/clang/AST/StmtOpenMP.h
@@ -17,6 +17,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/OpenMPClause.h"
#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
#include "clang/Basic/OpenMPKinds.h"
#include "clang/Basic/SourceLocation.h"
@@ -1087,10 +1088,22 @@ public:
// This relies on the loop form is already checked by Sema.
const Stmt *Body =
getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
- Body = cast<ForStmt>(Body)->getBody();
+ if (auto *For = dyn_cast<ForStmt>(Body)) {
+ Body = For->getBody();
+ } else {
+ assert(isa<CXXForRangeStmt>(Body) &&
+ "Expected caonical for loop or range-based for loop.");
+ Body = cast<CXXForRangeStmt>(Body)->getBody();
+ }
for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) {
Body = Body->IgnoreContainers();
- Body = cast<ForStmt>(Body)->getBody();
+ if (auto *For = dyn_cast<ForStmt>(Body)) {
+ Body = For->getBody();
+ } else {
+ assert(isa<CXXForRangeStmt>(Body) &&
+ "Expected caonical for loop or range-based for loop.");
+ Body = cast<CXXForRangeStmt>(Body)->getBody();
+ }
}
return Body;
}
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 402ee4f858..a77cbc09e4 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -9154,6 +9154,10 @@ public:
/// construct.
void startOpenMPLoop();
+ /// If the current region is a range loop-based region, mark the start of the
+ /// loop construct.
+ void startOpenMPCXXRangeFor();
+
/// Check if the specified variable is used in 'private' clause.
/// \param Level Relative level of nested OpenMP construct for that the check
/// is performed.
diff --git a/lib/CodeGen/CGStmtOpenMP.cpp b/lib/CodeGen/CGStmtOpenMP.cpp
index 1ab6a8d963..c70244d779 100644
--- a/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/lib/CodeGen/CGStmtOpenMP.cpp
@@ -142,6 +142,24 @@ class OMPLoopScope : public CodeGenFunction::RunCleanupsScope {
}
}
(void)PreCondVars.apply(CGF);
+ // Emit init, __range and __end variables for C++ range loops.
+ const Stmt *Body =
+ S.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
+ for (unsigned Cnt = 0; Cnt < S.getCollapsedNumber(); ++Cnt) {
+ Body = Body->IgnoreContainers();
+ if (auto *For = dyn_cast<ForStmt>(Body)) {
+ Body = For->getBody();
+ } else {
+ assert(isa<CXXForRangeStmt>(Body) &&
+ "Expected caonical for loop or range-based for loop.");
+ auto *CXXFor = cast<CXXForRangeStmt>(Body);
+ if (const Stmt *Init = CXXFor->getInit())
+ CGF.EmitStmt(Init);
+ CGF.EmitStmt(CXXFor->getRangeStmt());
+ CGF.EmitStmt(CXXFor->getEndStmt());
+ Body = CXXFor->getBody();
+ }
+ }
if (const auto *PreInits = cast_or_null<DeclStmt>(S.getPreInits())) {
for (const auto *I : PreInits->decls())
CGF.EmitVarDecl(cast<VarDecl>(*I));
@@ -1350,6 +1368,21 @@ void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
getProfileCount(D.getBody()));
EmitBlock(NextBB);
}
+ // Emit loop variables for C++ range loops.
+ const Stmt *Body =
+ D.getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers();
+ for (unsigned Cnt = 0; Cnt < D.getCollapsedNumber(); ++Cnt) {
+ Body = Body->IgnoreContainers();
+ if (auto *For = dyn_cast<ForStmt>(Body)) {
+ Body = For->getBody();
+ } else {
+ assert(isa<CXXForRangeStmt>(Body) &&
+ "Expected caonical for loop or range-based for loop.");
+ auto *CXXFor = cast<CXXForRangeStmt>(Body);
+ EmitStmt(CXXFor->getLoopVarStmt());
+ Body = CXXFor->getBody();
+ }
+ }
// Emit loop body.
EmitStmt(D.getBody());
// The end (updates/cleanups).
diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp
index 942c520a0b..1ef8b984e4 100644
--- a/lib/Parse/ParseDecl.cpp
+++ b/lib/Parse/ParseDecl.cpp
@@ -2100,6 +2100,8 @@ Parser::DeclGroupPtrTy Parser::ParseDeclGroup(ParsingDeclSpec &DS,
bool IsForRangeLoop = false;
if (TryConsumeToken(tok::colon, FRI->ColonLoc)) {
IsForRangeLoop = true;
+ if (getLangOpts().OpenMP)
+ Actions.startOpenMPCXXRangeFor();
if (Tok.is(tok::l_brace))
FRI->RangeExpr = ParseBraceInitializer();
else
diff --git a/lib/Sema/SemaOpenMP.cpp b/lib/Sema/SemaOpenMP.cpp
index 7ec5ba335f..b0fd6aa5fd 100644
--- a/lib/Sema/SemaOpenMP.cpp
+++ b/lib/Sema/SemaOpenMP.cpp
@@ -2008,6 +2008,14 @@ void Sema::startOpenMPLoop() {
DSAStack->loopInit();
}
+void Sema::startOpenMPCXXRangeFor() {
+ assert(LangOpts.OpenMP && "OpenMP must be enabled.");
+ if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
+ DSAStack->resetPossibleLoopCounter();
+ DSAStack->loopStart();
+ }
+}
+
bool Sema::isOpenMPPrivateDecl(const ValueDecl *D, unsigned Level) const {
assert(LangOpts.OpenMP && "OpenMP is not allowed");
if (isOpenMPLoopDirective(DSAStack->getCurrentDirective())) {
@@ -6490,10 +6498,13 @@ static bool checkOpenMPIterationSpace(
Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
- // OpenMP [2.6, Canonical Loop Form]
+ // OpenMP [2.9.1, Canonical Loop Form]
// for (init-expr; test-expr; incr-expr) structured-block
+ // for (range-decl: range-expr) structured-block
auto *For = dyn_cast_or_null<ForStmt>(S);
- if (!For) {
+ auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
+ // Ranged for is supported only in OpenMP 5.0.
+ if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
<< (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != nullptr)
<< getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
@@ -6515,12 +6526,14 @@ static bool checkOpenMPIterationSpace(
}
return true;
}
- assert(For->getBody());
+ assert(((For && For->getBody()) || (CXXFor && CXXFor->getBody())) &&
+ "No loop body.");
- OpenMPIterationSpaceChecker ISC(SemaRef, DSA, For->getForLoc());
+ OpenMPIterationSpaceChecker ISC(SemaRef, DSA,
+ For ? For->getForLoc() : CXXFor->getForLoc());
// Check init.
- Stmt *Init = For->getInit();
+ Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
if (ISC.checkAndSetInit(Init))
return true;
@@ -6556,18 +6569,18 @@ static bool checkOpenMPIterationSpace(
assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars");
// Check test-expr.
- HasErrors |= ISC.checkAndSetCond(For->getCond());
+ HasErrors |= ISC.checkAndSetCond(For ? For->getCond() : CXXFor->getCond());
// Check incr-expr.
- HasErrors |= ISC.checkAndSetInc(For->getInc());
+ HasErrors |= ISC.checkAndSetInc(For ? For->getInc() : CXXFor->getInc());
}
if (ISC.dependent() || SemaRef.CurContext->isDependentContext() || HasErrors)
return HasErrors;
// Build the loop's iteration space representation.
- ResultIterSpaces[CurrentNestedLoopCount].PreCond =
- ISC.buildPreCond(DSA.getCurScope(), For->getCond(), Captures);
+ ResultIterSpaces[CurrentNestedLoopCount].PreCond = ISC.buildPreCond(
+ DSA.getCurScope(), For ? For->getCond() : CXXFor->getCond(), Captures);
ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
(isOpenMPWorksharingDirective(DKind) ||
@@ -6881,7 +6894,14 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// All loops associated with the construct must be perfectly nested; that
// is, there must be no intervening code nor any OpenMP directive between
// any two loops.
- CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers();
+ if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
+ CurStmt = For->getBody();
+ } else {
+ assert(isa<CXXForRangeStmt>(CurStmt) &&
+ "Expected canonical for or range-based for loops.");
+ CurStmt = cast<CXXForRangeStmt>(CurStmt)->getBody();
+ }
+ CurStmt = CurStmt->IgnoreContainers();
}
for (unsigned Cnt = NestedLoopCount; Cnt < OrderedLoopCount; ++Cnt) {
if (checkOpenMPIterationSpace(
@@ -6901,7 +6921,14 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
// All loops associated with the construct must be perfectly nested; that
// is, there must be no intervening code nor any OpenMP directive between
// any two loops.
- CurStmt = cast<ForStmt>(CurStmt)->getBody()->IgnoreContainers();
+ if (auto *For = dyn_cast<ForStmt>(CurStmt)) {
+ CurStmt = For->getBody();
+ } else {
+ assert(isa<CXXForRangeStmt>(CurStmt) &&
+ "Expected canonical for or range-based for loops.");
+ CurStmt = cast<CXXForRangeStmt>(CurStmt)->getBody();
+ }
+ CurStmt = CurStmt->IgnoreContainers();
}
Built.clear(/* size */ NestedLoopCount);
diff --git a/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index cff20aab03..6c680f29da 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -2674,6 +2674,11 @@ StmtResult Sema::BuildCXXForRangeStmt(SourceLocation ForLoc,
if (Kind == BFRK_Check)
return StmtResult();
+ // In OpenMP loop region loop control variable must be private. Perform
+ // analysis of first part (if any).
+ if (getLangOpts().OpenMP >= 50 && BeginDeclStmt.isUsable())
+ ActOnOpenMPLoopInitialization(ForLoc, BeginDeclStmt.get());
+
return new (Context) CXXForRangeStmt(
InitStmt, RangeDS, cast_or_null<DeclStmt>(BeginDeclStmt.get()),
cast_or_null<DeclStmt>(EndDeclStmt.get()), NotEqExpr.get(),
diff --git a/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp b/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp
index 64c1b9130b..8fd035262e 100644
--- a/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp
@@ -379,7 +379,7 @@ int test_iteration_spaces() {
#pragma omp target
#pragma omp teams
-// expected-error@+2 {{statement after '#pragma omp distribute parallel for simd' must be a for loop}}
+// omp4-error@+2 {{statement after '#pragma omp distribute parallel for simd' must be a for loop}}
#pragma omp distribute parallel for simd
for (auto &item : a) {
item = item + 1;
diff --git a/test/OpenMP/distribute_simd_loop_messages.cpp b/test/OpenMP/distribute_simd_loop_messages.cpp
index d4869f1c79..423e5f1b11 100644
--- a/test/OpenMP/distribute_simd_loop_messages.cpp
+++ b/test/OpenMP/distribute_simd_loop_messages.cpp
@@ -376,7 +376,7 @@ int test_iteration_spaces() {
#pragma omp target
#pragma omp teams
- // expected-error@+2 {{statement after '#pragma omp distribute simd' must be a for loop}}
+ // omp4-error@+2 {{statement after '#pragma omp distribute simd' must be a for loop}}
#pragma omp distribute simd
for (auto &item : a) {
item = item + 1;
diff --git a/test/OpenMP/for_ast_print.cpp b/test/OpenMP/for_ast_print.cpp
index cdbe9aaffd..edb4b9a7ac 100644
--- a/test/OpenMP/for_ast_print.cpp
+++ b/test/OpenMP/for_ast_print.cpp
@@ -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
@@ -103,6 +103,7 @@ public:
template <class T, int N>
T tmain(T argc) {
T b = argc, c, d, e, f, g;
+ T arr[N];
static T a;
// CHECK: static T a;
#pragma omp for schedule(dynamic) linear(a) allocate(a)
@@ -113,6 +114,7 @@ T tmain(T argc) {
// CHECK-NEXT: a = 2;
#pragma omp parallel
#pragma omp for allocate(argc) private(argc, b), firstprivate(c, d), lastprivate(d, f) collapse(N) schedule(static, N) ordered(N) nowait
+ for (auto &x : arr)
for (int i = 0; i < 2; ++i)
for (int j = 0; j < 2; ++j)
for (int j = 0; j < 2; ++j)
@@ -126,6 +128,7 @@ T tmain(T argc) {
foo();
// CHECK-NEXT: #pragma omp parallel
// CHECK-NEXT: #pragma omp for allocate(argc) private(argc,b) firstprivate(c,d) lastprivate(d,f) collapse(N) schedule(static, N) ordered(N) nowait
+ // CHECK-NEXT: for (auto &x : arr)
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: for (int j = 0; j < 2; ++j)
// CHECK-NEXT: for (int j = 0; j < 2; ++j)
@@ -143,6 +146,7 @@ T tmain(T argc) {
int main(int argc, char **argv) {
// CHECK: int main(int argc, char **argv) {
int b = argc, c, d, e, f, g;
+ float arr[20];
static int a;
// CHECK: static int a;
#pragma omp for schedule(guided, argc) reduction(+:argv[0][:1])
@@ -152,15 +156,17 @@ int main(int argc, char **argv) {
// CHECK-NEXT: for (int i = 0; i < 2; ++i)
// CHECK-NEXT: a = 2;
#pragma omp parallel
-#pragma omp for private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) schedule(auto) ordered nowait linear(g:-1)
+#pragma omp for private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(3) schedule(auto) ordered nowait linear(g:-1)
for (int i = 0; i < 10; ++i)
for (int j = 0; j < 10; ++j)
- foo();
+ for (auto x : arr)
+ foo(), (void)x;
// CHECK-NEXT: #pragma omp parallel
- // CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) schedule(auto) ordered nowait linear(g: -1)
+ // CHECK-NEXT: #pragma omp for private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(3) schedule(auto) ordered nowait linear(g: -1)
// CHECK-NEXT: for (int i = 0; i < 10; ++i)
// CHECK-NEXT: for (int j = 0; j < 10; ++j)
- // CHECK-NEXT: foo();
+ // CHECK-NEXT: for (auto x : arr)
+ // CHECK-NEXT: foo() , (void)x;
char buf[9] = "01234567";
char *p, *q;
#pragma omp parallel
diff --git a/test/OpenMP/for_loop_messages.cpp b/test/OpenMP/for_loop_messages.cpp
index 36727070ed..73c69ede6d 100644
--- a/test/OpenMP/for_loop_messages.cpp
+++ b/test/OpenMP/for_loop_messages.cpp
@@ -370,7 +370,7 @@ int test_iteration_spaces() {
}
#pragma omp parallel
-// expected-error@+2 {{statement after '#pragma omp for' must be a for loop}}
+// omp4-error@+2 {{statement after '#pragma omp for' must be a for loop}}
#pragma omp for
for (auto &item : a) {
item = item + 1;
diff --git a/test/OpenMP/for_simd_loop_messages.cpp b/test/OpenMP/for_simd_loop_messages.cpp
index 4b62bcad03..99f30a64eb 100644
--- a/test/OpenMP/for_simd_loop_messages.cpp
+++ b/test/OpenMP/for_simd_loop_messages.cpp
@@ -333,7 +333,7 @@ int test_iteration_spaces() {
}
#pragma omp parallel
-// expected-error@+2 {{statement after '#pragma omp for simd' must be a for loop}}
+// omp4-error@+2 {{statement after '#pragma omp for simd' must be a for loop}}
#pragma omp for simd
for (auto &item : a) {
item = item + 1;
diff --git a/test/OpenMP/parallel_for_codegen.cpp b/test/OpenMP/parallel_for_codegen.cpp
index 9e3390214d..ffa715548a 100644
--- a/test/OpenMP/parallel_for_codegen.cpp
+++ b/test/OpenMP/parallel_for_codegen.cpp
@@ -469,6 +469,165 @@ int decrement_nowait () {
return 0;
// OMP5: ret i32 0
}
+
+// OMP5-LABEL: range_for_single
+void range_for_single() {
+ int arr[10] = {0};
+// OMP5: call void (%struct.ident_t*, i32, void (i32*, i32*, ...)*, ...) @__kmpc_fork_call(%struct.ident_t* {{.+}}, i32 1, void (i32*, i32*, ...)* bitcast (void (i32*, i32*, [10 x i32]*)* [[OUTLINED:@.+]] to void (i32*, i32*, ...)*), [10 x i32]* %{{.+}})
+#pragma omp parallel for
+ for (auto &a : arr)
+ (void)a;
+}
+
+// OMP5: define internal void @.omp_outlined.(i32* {{.+}}, i32* {{.+}}, [10 x i32]* dereferenceable(40) %arr)
+// OMP5: [[ARR_ADDR:%.+]] = alloca [10 x i32]*,
+// OMP5: [[IV:%.+]] = alloca i64,
+// OMP5: [[RANGE_ADDR:%.+]] = alloca [10 x i32]*,
+// OMP5: [[END_ADDR:%.+]] = alloca i32*,
+// OMP5: alloca i32*,
+// OMP5: alloca i32*,
+// OMP5: alloca i64,
+// OMP5: [[BEGIN_INIT:%.+]] = alloca i32*,
+// OMP5: [[LB:%.+]] = alloca i64,
+// OMP5: [[UB:%.+]] = alloca i64,
+// OMP5: [[STRIDE:%.+]] = alloca i64,
+// OMP5: [[IS_LAST:%.+]] = alloca i32,
+// OMP5: [[BEGIN:%.+]] = alloca i32*,
+// OMP5: [[A_PTR:%.+]] = alloca i32*,
+// OMP5: [[GTID:%.+]] = call i32 @__kmpc_global_thread_num(
+
+// __range = arr;
+// OMP5: [[ARR:%.+]] = load [10 x i32]*, [10 x i32]** [[ARR_ADDR]],
+// OMP5: store [10 x i32]* [[ARR]], [10 x i32]** [[RANGE_ADDR]],
+
+// __end = end(_range);
+// OMP5: [[RANGE:%.+]] = load [10 x i32]*, [10 x i32]** [[RANGE_ADDR]],
+// OMP5: [[RANGE_0:%.+]] = getelementptr inbounds [10 x i32], [10 x i32]* [[RANGE]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// OMP5: [[RANGE_10:%.+]] = getelementptr inbounds i32, i32* [[RANGE_0]], i{{[0-9]+}} 10
+// OMP5: store i32* [[RANGE_10]], i32** [[END_ADDR]],
+
+// OMP5: [[RANGE:%.+]] = load [10 x i32]*, [10 x i32]** [[RANGE_ADDR]],
+// OMP5: [[RANGE_0:%.+]] = getelementptr inbounds [10 x i32], [10 x i32]* [[RANGE]], i{{[0-9]+}} 0, i{{[0-9]+}} 0
+// OMP5: store i32* [[RANGE_0]], i32** [[CAP1:%.+]],
+// OMP5: [[END:%.+]] = load i32*, i32** [[END_ADDR]],
+// OMP5: store i32* [[END]], i32** [[CAP2:%.+]],
+
+// calculate number of elements.
+// OMP5: [[CAP2_VAL:%.+]] = load i32*, i32** [[CAP2]],
+// OMP5: [[CAP1_VAL:%.+]] = load i32*, i32** [[CAP1]],
+// OMP5: [[CAP2_I64:%.+]] = ptrtoint i32* [[CAP2_VAL]] to i64
+// OMP5: [[CAP1_I64:%.+]] = ptrtoint i32* [[CAP1_VAL]] to i64
+// OMP5: [[DIFF:%.+]] = sub i64 [[CAP2_I64]], [[CAP1_I64]]
+// OMP5: [[NUM:%.+]] = sdiv exact i64 [[DIFF]], 4
+// OMP5: [[NUM1:%.+]] = sub nsw i64 [[NUM]], 1
+// OMP5: [[NUM2:%.+]] = add nsw i64 [[NUM1]], 1
+// OMP5: [[NUM3:%.+]] = sdiv i64 [[NUM2]], 1
+// OMP5: [[NUM4:%.+]] = sub nsw i64 [[NUM3]], 1
+// OMP5: store i64 [[NUM4]], i64* [[CAP3:%.+]],
+// OMP5: [[RANGE_0:%.+]] = load i32*, i32** [[CAP1]],
+
+// __begin = begin(range);
+// OMP5: store i32* [[RANGE_0]], i32** [[BEGIN_INIT]],
+// OMP5: [[CAP1_VAL:%.+]] = load i32*, i32** [[CAP1]],
+// OMP5: [[CAP2_VAL:%.+]] = load i32*, i32** [[CAP2]],
+// OMP5: [[CMP:%.+]] = icmp ult i32* [[CAP1_VAL]], [[CAP2_VAL]]
+
+// __begin >= __end ? goto then : goto exit;
+// OMP5: br i1 [[CMP]], label %[[THEN:.+]], label %[[EXIT:.+]]
+
+// OMP5: [[THEN]]:
+
+// lb = 0;
+// OMP5: store i64 0, i64* [[LB]],
+
+// ub = number of elements
+// OMP5: [[NUM:%.+]] = load i64, i64* [[CAP3]],
+// OMP5: store i64 [[NUM]], i64* [[UB]],
+
+// stride = 1;
+// OMP5: store i64 1, i64* [[STRIDE]],
+
+// is_last = 0;
+// OMP5: store i32 0, i32* [[IS_LAST]],
+
+// loop.
+// OMP5: call void @__kmpc_for_static_init_8(%struct.ident_t* {{.+}}, i32 [[GTID]], i32 34, i32* [[IS_LAST]], i64* [[LB]], i64* [[UB]], i64* [[STRIDE]], i64 1, i64 1)
+
+// ub = (ub > number_of_elems ? number_of_elems : ub);
+// OMP5: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
+// OMP5: [[NUM_VAL:%.+]] = load i64, i64* [[CAP3]],
+// OMP5: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], [[NUM_VAL]]
+// OMP5: br i1 [[CMP]], label %[[TRUE:.+]], label %[[FALSE:.+]]
+
+// OMP5: [[TRUE]]:
+// OMP5: [[NUM_VAL:%.+]] = load i64, i64* [[CAP3]],
+// OMP5: br label %[[END:.+]]
+
+// OMP5: [[FALSE]]:
+// OMP5: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
+// OMP5: br label %[[END:.+]]
+
+// OMP5: [[END]]:
+// OMP5: [[MIN:%.+]] = phi i64 [ [[NUM_VAL]], %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
+// OMP%: store i64 [[MIN]], i64* [[UB]],
+
+// iv = lb;
+// OMP5: [[LB_VAL:%.+]] = load i64, i64* [[LB]],
+// OMP5: store i64 [[LB_VAL]], i64* [[IV]],
+
+// goto loop;
+// loop:
+// OMP5: br label %[[LOOP:.+]]
+
+// OMP5: [[LOOP]]:
+
+// iv <= ub ? goto body : goto end;
+// OMP5: [[IV_VAL:%.+]] = load i64, i64* [[IV]],
+// OMP5: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
+// OMP5: [[CMP:%.+]] = icmp sle i64 [[IV_VAL]], [[UB_VAL]]
+// OMP5: br i1 [[CMP]], label %[[BODY:.+]], label %[[END:.+]]
+
+// body:
+// __begin = begin(arr) + iv * 1;
+// OMP5: [[BODY]]:
+// OMP5: [[CAP1_VAL:%.+]] = load i32*, i32** [[CAP1]],
+// OMP5: [[IV_VAL:%.+]] = load i64, i64* [[IV]],
+// OMP5: [[MUL:%.+]] = mul nsw i64 [[IV_VAL]], 1
+// OMP5: [[ADDR:%.+]] = getelementptr inbounds i32, i32* [[CAP1_VAL]], i64 [[MUL]]
+// OMP5: store i32* [[ADDR]], i32** [[BEGIN]],
+
+// a = *__begin;
+// OMP5: [[BEGIN_VAL:%.+]] = load i32*, i32** [[BEGIN]],
+// OMP5: store i32* [[BEGIN_VAL]], i32** [[A_PTR]],
+
+// (void)a;
+// OMP5: load i32*, i32** [[A_PTR]],
+
+// iv += 1;
+// OMP5: [[IV_VAL:%.+]] = load i64, i64* [[IV]],
+// OMP5: [[IV_VAL_ADD_1:%.+]] = add nsw i64 [[IV_VAL]], 1
+// OMP5: store i64 [[IV_VAL_ADD_1]], i64* [[IV]],
+
+// goto loop;
+// OMP5: br label %[[LOOP]]
+
+// end:
+// OMP5: [[END]]:
+// OMP5: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 [[GTID]])
+// exit:
+// OMP5: [[EXIT]]:
+// OMP5: ret void
+
+// OMP5-LABEL: range_for_collapsed
+void range_for_collapsed() {
+ int arr[10] = {0};
+// OMP5: call void @__kmpc_for_static_init_8(%struct.ident_t* {{.+}}, i32 [[GTID%.+]], i32 34, i32* %{{.+}}, i64* %{{.+}}, i64* %{{.+}}, i64* %{{.+}}, i64 1, i64 1)
+#pragma omp parallel for collapse(2)
+ for (auto &a : arr)
+ for (auto b : arr)
+ a = b;
+// OMP5: call void @__kmpc_for_static_fini(%struct.ident_t* {{.+}}, i32 [[GTID]])
+}
#endif // OMP5
#endif // HEADER
diff --git a/test/OpenMP/parallel_for_loop_messages.cpp b/test/OpenMP/parallel_for_loop_messages.cpp
index c234b52899..beaf56e7bc 100644
--- a/test/OpenMP/parallel_for_loop_messages.cpp
+++ b/test/OpenMP/parallel_for_loop_messages.cpp
@@ -281,7 +281,7 @@ int test_iteration_spaces() {
c[globalii] += a[globalii] + ii;
}
-// expected-error@+2 {{statement after '#pragma omp parallel for' must be a for loop}}
+// omp4-error@+2 {{statement after '#pragma omp parallel for' must be a for loop}}
#pragma omp parallel for
for (auto &item : a) {
item = item + 1;
diff --git a/test/OpenMP/parallel_for_simd_loop_messages.cpp b/test/OpenMP/parallel_for_simd_loop_messages.cpp
index 006e3e79a4..5a0202c4e5 100644
--- a/test/OpenMP/parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/parallel_for_simd_loop_messages.cpp
@@ -283,7 +283,7 @@ int test_iteration_spaces() {
c[globalii] += a[globalii] + ii;
}
-// expected-error@+2 {{statement after '#pragma omp parallel for simd' must be a for loop}}
+// omp4-error@+2 {{statement after '#pragma omp parallel for simd' must be a for loop}}
#pragma omp parallel for simd
for (auto &item : a) {
item = item + 1;
diff --git a/test/OpenMP/simd_loop_messages.cpp b/test/OpenMP/simd_loop_messages.cpp
index 701c52f1b9..5a98be5376 100644
--- a/test/OpenMP/simd_loop_messages.cpp
+++ b/test/OpenMP/simd_loop_messages.cpp
@@ -300,7 +300,7 @@ int test_iteration_spaces() {
c[globalii] += a[globalii] + ii;
}
- // expected-error@+2 {{statement after '#pragma omp simd' must be a for loop}}
+ // omp4-error@+2 {{statement after '#pragma omp simd' must be a for loop}}
#pragma omp simd
for (auto &item : a) {
item = item + 1;
diff --git a/test/OpenMP/target_parallel_for_loop_messages.cpp b/test/OpenMP/target_parallel_for_loop_messages.cpp
index 1aa32d543e..ec82d1c15e 100644
--- a/test/OpenMP/target_parallel_for_loop_messages.cpp
+++ b/test/OpenMP/target_parallel_for_loop_messages.cpp
@@ -281,7 +281,7 @@ int test_iteration_spaces() {
c[globalii] += a[globalii] + ii;
}
-// expected-error@+2 {{statement after '#pragma omp target parallel for' must be a for loop}}
+// omp4-error@+2 {{statement after '#pragma omp target parallel for' must be a for loop}}
#pragma omp target parallel for
for (auto &item : a) {
item = item + 1;
diff --git a/test/OpenMP/target_parallel_for_simd_loop_messages.cpp b/test/OpenMP/target_parallel_for_simd_loop_messages.cpp
index a17b13fe04..3ec5f5d381 100644
--- a/test/OpenMP/target_parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/target_parallel_for_simd_loop_messages.cpp
@@ -283,7 +283,7 @@ int test_iteration_spaces() {
c[globalii] += a[globalii] + ii;
}
-// expected-error@+2 {{statement after '#pragma omp target parallel for simd' must be a for loop}}
+// omp4-error@+2 {{statement after '#pragma omp target parallel for simd' must be a for loop}}
#pragma omp target parallel for simd
for (auto &item : a) {
item = item + 1;
diff --git a/test/OpenMP/target_simd_loop_messages.cpp b/test/OpenMP/target_simd_loop_messages.cpp
index 48fd7719ea..1e894efff8 100644
--- a/test/OpenMP/target_simd_loop_messages.cpp
+++ b/test/OpenMP/target_simd_loop_messages.cpp
@@ -283,7 +283,7 @@ int test_iteration_spaces() {
c[globalii] += a[globalii] + ii;
}
-// expected-error@+2 {{statement after '#pragma omp target simd' must be a for loop}}
+// omp4-error@+2 {{statement after '#pragma omp target simd' must be a for loop}}
#pragma omp target simd
for (auto &item : a) {
item = item + 1;
diff --git a/test/OpenMP/target_teams_distribute_loop_messages.cpp b/test/OpenMP/target_teams_distribute_loop_messages.cpp
index 53fb9cac57..4f8ca8d94b 100644
--- a/test/OpenMP/target_teams_distribute_loop_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_loop_messages.cpp
@@ -269,7 +269,7 @@ int test_iteration_spaces() {
}
#pragma omp target teams distribute
-// expected-error@+1 {{statement after '#pragma omp target teams distribute' must be a for loop}}
+// omp4-error@+1 {{statement after '#pragma omp target teams distribute' must be a for loop}}
for (auto &item : a) {
item = item + 1;
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp
index f95211b905..9530acd293 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp
@@ -267,7 +267,7 @@ int test_iteration_spaces() {
}
#pragma omp target teams distribute parallel for
-// expected-error@+1 {{statement after '#pragma omp target teams distribute parallel for' must be a for loop}}
+// omp4-error@+1 {{statement after '#pragma omp target teams distribute parallel for' must be a for loop}}
for (auto &item : a) {
item = item + 1;
}
diff --git a/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp b/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp
index 3ab59b3065..8435ef625c 100644
--- a/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp
@@ -269,7 +269,7 @@ int test_iteration_spaces() {
c[globalii] += a[globalii] + ii;
}
-// expected-error@+2 {{statement after '#pragma omp target teams distribute parallel for simd' must be a for loop}}
+// omp4-error@+2 {{statement after '#pragma omp target teams distribute parallel for simd' must be a for loop}}
#pragma omp target teams distribute parallel for simd
for (auto &item : a) {
item = item + 1;
diff --git a/test/OpenMP/taskloop_loop_messages.cpp b/test/OpenMP/taskloop_loop_messages.cpp
index 9a8b4aaea0..1783a5265d 100644
--- a/test/OpenMP/taskloop_loop_messages.cpp
+++ b/test/OpenMP/taskloop_loop_messages.cpp
@@ -350,7 +350,7 @@ int test_iteration_spaces() {
}
#pragma omp parallel
-// expected-error@+2 {{statement after '#pragma omp taskloop' must be a for loop}}
+// omp4-error@+2 {{statement after '#pragma omp taskloop' must be a for loop}}
#pragma omp taskloop
for (auto &item : a) {
item = item + 1;
diff --git a/test/OpenMP/taskloop_simd_loop_messages.cpp b/test/OpenMP/taskloop_simd_loop_messages.cpp
index 72c9ec4844..9a345d6a63 100644
--- a/test/OpenMP/taskloop_simd_loop_messages.cpp
+++ b/test/OpenMP/taskloop_simd_loop_messages.cpp
@@ -352,7 +352,7 @@ int test_iteration_spaces() {
}
#pragma omp parallel
-// expected-error@+2 {{statement after '#pragma omp taskloop simd' must be a for loop}}
+// omp4-error@+2 {{statement after '#pragma omp taskloop simd' must be a for loop}}
#pragma omp taskloop simd
for (auto &item : a) {
item = item + 1;
diff --git a/test/OpenMP/teams_distribute_loop_messages.cpp b/test/OpenMP/teams_distribute_loop_messages.cpp
index 44cf917097..617d0353b9 100644
--- a/test/OpenMP/teams_distribute_loop_messages.cpp
+++ b/test/OpenMP/teams_distribute_loop_messages.cpp
@@ -317,7 +317,7 @@ int test_iteration_spaces() {
#pragma omp target
#pragma omp teams distribute
-// expected-error@+1 {{statement after '#pragma omp teams distribute' must be a for loop}}
+// omp4-error@+1 {{statement after '#pragma omp teams distribute' must be a for loop}}
for (auto &item : a) {
item = item + 1;
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp
index d9b01c972f..f5948027e5 100644
--- a/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp
@@ -315,7 +315,7 @@ int test_iteration_spaces() {
#pragma omp target
#pragma omp teams distribute parallel for
-// expected-error@+1 {{statement after '#pragma omp teams distribute parallel for' must be a for loop}}
+// omp4-error@+1 {{statement after '#pragma omp teams distribute parallel for' must be a for loop}}
for (auto &item : a) {
item = item + 1;
}
diff --git a/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp b/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp
index ba201e49ef..4359aea70f 100644
--- a/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp
+++ b/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp
@@ -317,7 +317,7 @@ int test_iteration_spaces() {
#pragma omp target
#pragma omp teams distribute parallel for simd
-// expected-error@+1 {{statement after '#pragma omp teams distribute parallel for simd' must be a for loop}}
+// omp4-error@+1 {{statement after '#pragma omp teams distribute parallel for simd' must be a for loop}}
for (auto &item : a) {
item = item + 1;
}
diff --git a/test/OpenMP/teams_distribute_simd_loop_messages.cpp b/test/OpenMP/teams_distribute_simd_loop_messages.cpp
index 6cb51839c2..b3020d1a61 100644
--- a/test/OpenMP/teams_distribute_simd_loop_messages.cpp
+++ b/test/OpenMP/teams_distribute_simd_loop_messages.cpp
@@ -317,7 +317,7 @@ int test_iteration_spaces() {
#pragma omp target
#pragma omp teams distribute simd
-// expected-error@+1 {{statement after '#pragma omp teams distribute simd' must be a for loop}}
+// omp4-error@+1 {{statement after '#pragma omp teams distribute simd' must be a for loop}}
for (auto &item : a) {
item = item + 1;
}