diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h index c9efe3238715..ef69158d61f9 100644 --- a/clang/include/clang/AST/StmtOpenMP.h +++ b/clang/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(Body)->getBody(); + if (auto *For = dyn_cast(Body)) { + Body = For->getBody(); + } else { + assert(isa(Body) && + "Expected caonical for loop or range-based for loop."); + Body = cast(Body)->getBody(); + } for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) { Body = Body->IgnoreContainers(); - Body = cast(Body)->getBody(); + if (auto *For = dyn_cast(Body)) { + Body = For->getBody(); + } else { + assert(isa(Body) && + "Expected caonical for loop or range-based for loop."); + Body = cast(Body)->getBody(); + } } return Body; } diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 402ee4f858af..a77cbc09e400 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 1ab6a8d963be..c70244d77940 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/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(Body)) { + Body = For->getBody(); + } else { + assert(isa(Body) && + "Expected caonical for loop or range-based for loop."); + auto *CXXFor = cast(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(S.getPreInits())) { for (const auto *I : PreInits->decls()) CGF.EmitVarDecl(cast(*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(Body)) { + Body = For->getBody(); + } else { + assert(isa(Body) && + "Expected caonical for loop or range-based for loop."); + auto *CXXFor = cast(Body); + EmitStmt(CXXFor->getLoopVarStmt()); + Body = CXXFor->getBody(); + } + } // Emit loop body. EmitStmt(D.getBody()); // The end (updates/cleanups). diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 942c520a0b50..1ef8b984e4db 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/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/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 7ec5ba335fd7..b0fd6aa5fd5f 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/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 ResultIterSpaces, llvm::MapVector &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(S); - if (!For) { + auto *CXXFor = dyn_cast_or_null(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(CurStmt)->getBody()->IgnoreContainers(); + if (auto *For = dyn_cast(CurStmt)) { + CurStmt = For->getBody(); + } else { + assert(isa(CurStmt) && + "Expected canonical for or range-based for loops."); + CurStmt = cast(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(CurStmt)->getBody()->IgnoreContainers(); + if (auto *For = dyn_cast(CurStmt)) { + CurStmt = For->getBody(); + } else { + assert(isa(CurStmt) && + "Expected canonical for or range-based for loops."); + CurStmt = cast(CurStmt)->getBody(); + } + CurStmt = CurStmt->IgnoreContainers(); } Built.clear(/* size */ NestedLoopCount); diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index cff20aab0308..6c680f29da4f 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/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(BeginDeclStmt.get()), cast_or_null(EndDeclStmt.get()), NotEqExpr.get(), diff --git a/clang/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp b/clang/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp index 64c1b9130bcf..8fd035262ecf 100644 --- a/clang/test/OpenMP/distribute_parallel_for_simd_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/distribute_simd_loop_messages.cpp b/clang/test/OpenMP/distribute_simd_loop_messages.cpp index d4869f1c79af..423e5f1b1166 100644 --- a/clang/test/OpenMP/distribute_simd_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/for_ast_print.cpp b/clang/test/OpenMP/for_ast_print.cpp index cdbe9aaffdd5..edb4b9a7ac0e 100644 --- a/clang/test/OpenMP/for_ast_print.cpp +++ b/clang/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 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/clang/test/OpenMP/for_loop_messages.cpp b/clang/test/OpenMP/for_loop_messages.cpp index 36727070eded..73c69ede6d12 100644 --- a/clang/test/OpenMP/for_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/for_simd_loop_messages.cpp b/clang/test/OpenMP/for_simd_loop_messages.cpp index 4b62bcad03e8..99f30a64eb5e 100644 --- a/clang/test/OpenMP/for_simd_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/parallel_for_codegen.cpp b/clang/test/OpenMP/parallel_for_codegen.cpp index 9e3390214d78..ffa715548a85 100644 --- a/clang/test/OpenMP/parallel_for_codegen.cpp +++ b/clang/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/clang/test/OpenMP/parallel_for_loop_messages.cpp b/clang/test/OpenMP/parallel_for_loop_messages.cpp index c234b52899f0..beaf56e7bcb6 100644 --- a/clang/test/OpenMP/parallel_for_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/parallel_for_simd_loop_messages.cpp b/clang/test/OpenMP/parallel_for_simd_loop_messages.cpp index 006e3e79a445..5a0202c4e576 100644 --- a/clang/test/OpenMP/parallel_for_simd_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/simd_loop_messages.cpp b/clang/test/OpenMP/simd_loop_messages.cpp index 701c52f1b9bb..5a98be537615 100644 --- a/clang/test/OpenMP/simd_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/target_parallel_for_loop_messages.cpp b/clang/test/OpenMP/target_parallel_for_loop_messages.cpp index 1aa32d543ec9..ec82d1c15e74 100644 --- a/clang/test/OpenMP/target_parallel_for_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/target_parallel_for_simd_loop_messages.cpp b/clang/test/OpenMP/target_parallel_for_simd_loop_messages.cpp index a17b13fe0446..3ec5f5d3817d 100644 --- a/clang/test/OpenMP/target_parallel_for_simd_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/target_simd_loop_messages.cpp b/clang/test/OpenMP/target_simd_loop_messages.cpp index 48fd7719eab8..1e894efff8b2 100644 --- a/clang/test/OpenMP/target_simd_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/target_teams_distribute_loop_messages.cpp b/clang/test/OpenMP/target_teams_distribute_loop_messages.cpp index 53fb9cac5728..4f8ca8d94b3b 100644 --- a/clang/test/OpenMP/target_teams_distribute_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp index f95211b905a7..9530acd2935f 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp index 3ab59b30654c..8435ef625c74 100644 --- a/clang/test/OpenMP/target_teams_distribute_parallel_for_simd_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/taskloop_loop_messages.cpp b/clang/test/OpenMP/taskloop_loop_messages.cpp index 9a8b4aaea041..1783a5265d9f 100644 --- a/clang/test/OpenMP/taskloop_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/taskloop_simd_loop_messages.cpp b/clang/test/OpenMP/taskloop_simd_loop_messages.cpp index 72c9ec484498..9a345d6a6300 100644 --- a/clang/test/OpenMP/taskloop_simd_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/teams_distribute_loop_messages.cpp b/clang/test/OpenMP/teams_distribute_loop_messages.cpp index 44cf9170977f..617d0353b948 100644 --- a/clang/test/OpenMP/teams_distribute_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp index d9b01c972f29..f5948027e56c 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp b/clang/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp index ba201e49ef7e..4359aea70fa7 100644 --- a/clang/test/OpenMP/teams_distribute_parallel_for_simd_loop_messages.cpp +++ b/clang/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/clang/test/OpenMP/teams_distribute_simd_loop_messages.cpp b/clang/test/OpenMP/teams_distribute_simd_loop_messages.cpp index 6cb51839c2d9..b3020d1a610f 100644 --- a/clang/test/OpenMP/teams_distribute_simd_loop_messages.cpp +++ b/clang/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; }