Index: include/clang/AST/StmtOpenMP.h =================================================================== --- include/clang/AST/StmtOpenMP.h +++ include/clang/AST/StmtOpenMP.h @@ -318,8 +318,9 @@ /// \brief Offsets to the stored exprs. /// This enumeration contains offsets to all the pointers to children /// expressions stored in OMPLoopDirective. - /// The first 9 children are nesessary for all the loop directives, and - /// the next 10 are specific to the worksharing ones. + /// The first 9 children are necessary for all the loop directives, + /// the next 8 are specific to the worksharing ones, and the next 11 are + /// used for combined constructs containing two pragmas associated to loops. /// After the fixed children, three arrays of length CollapsedNum are /// allocated: loop counters, their updates and final values. /// PrevLowerBound and PrevUpperBound are used to communicate blocking @@ -344,7 +345,7 @@ // specify the offset to the end (and start of the following counters/ // updates/finals arrays). DefaultEnd = 9, - // The following 12 exprs are used by worksharing and distribute loops only. + // The following 8 exprs are used by worksharing and distribute loops only. IsLastIterVariableOffset = 9, LowerBoundVariableOffset = 10, UpperBoundVariableOffset = 11, @@ -353,13 +354,22 @@ NextLowerBoundOffset = 14, NextUpperBoundOffset = 15, NumIterationsOffset = 16, + // Offset to the end for worksharing loop directives. + WorksharingEnd = 17, PrevLowerBoundVariableOffset = 17, PrevUpperBoundVariableOffset = 18, DistIncOffset = 19, PrevEnsureUpperBoundOffset = 20, + CombinedLowerBoundVariableOffset = 21, + CombinedUpperBoundVariableOffset = 22, + CombinedEnsureUpperBoundOffset = 23, + CombinedInitOffset = 24, + CombinedConditionOffset = 25, + CombinedNextLowerBoundOffset = 26, + CombinedNextUpperBoundOffset = 27, // Offset to the end (and start of the following counters/updates/finals - // arrays) for worksharing loop directives. - WorksharingEnd = 21, + // arrays) for combined distribute loop directives. + CombinedDistributeEnd = 28, }; /// \brief Get the counters storage. @@ -423,11 +433,12 @@ /// \brief Offset to the start of children expression arrays. static unsigned getArraysOffset(OpenMPDirectiveKind Kind) { - return (isOpenMPWorksharingDirective(Kind) || - isOpenMPTaskLoopDirective(Kind) || - isOpenMPDistributeDirective(Kind)) - ? WorksharingEnd - : DefaultEnd; + if (isOpenMPLoopBoundSharingDirective(Kind)) + return CombinedDistributeEnd; + if (isOpenMPWorksharingDirective(Kind) || isOpenMPTaskLoopDirective(Kind) || + isOpenMPDistributeDirective(Kind)) + return WorksharingEnd; + return DefaultEnd; } /// \brief Children number. @@ -515,33 +526,60 @@ *std::next(child_begin(), NumIterationsOffset) = NI; } void setPrevLowerBoundVariable(Expr *PrevLB) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); *std::next(child_begin(), PrevLowerBoundVariableOffset) = PrevLB; } void setPrevUpperBoundVariable(Expr *PrevUB) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); *std::next(child_begin(), PrevUpperBoundVariableOffset) = PrevUB; } void setDistInc(Expr *DistInc) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); *std::next(child_begin(), DistIncOffset) = DistInc; } void setPrevEnsureUpperBound(Expr *PrevEUB) { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); *std::next(child_begin(), PrevEnsureUpperBoundOffset) = PrevEUB; } + void setCombinedLowerBoundVariable(Expr *CombLB) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedLowerBoundVariableOffset) = CombLB; + } + void setCombinedUpperBoundVariable(Expr *CombUB) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedUpperBoundVariableOffset) = CombUB; + } + void setCombinedEnsureUpperBound(Expr *CombEUB) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedEnsureUpperBoundOffset) = CombEUB; + } + void setCombinedInit(Expr *CombInit) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedInitOffset) = CombInit; + } + void setCombinedCond(Expr *CombCond) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedConditionOffset) = CombCond; + } + void setCombinedNextLowerBound(Expr *CombNLB) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedNextLowerBoundOffset) = CombNLB; + } + void setCombinedNextUpperBound(Expr *CombNUB) { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + *std::next(child_begin(), CombinedNextUpperBoundOffset) = CombNUB; + } void setCounters(ArrayRef A); void setPrivateCounters(ArrayRef A); void setInits(ArrayRef A); @@ -549,6 +587,33 @@ void setFinals(ArrayRef A); public: + /// The expressions built to support OpenMP loops in combined/composite + /// pragmas (e.g. pragma omp distribute parallel for) + struct DistCombinedHelperExprs { + /// DistributeLowerBound - used when composing 'omp distribute' with + /// 'omp for' in a same construct. + Expr *LB; + /// DistributeUpperBound - used when composing 'omp distribute' with + /// 'omp for' in a same construct. + Expr *UB; + /// DistributeEnsureUpperBound - used when composing 'omp distribute' + /// with 'omp for' in a same construct, EUB depends on DistUB + Expr *EUB; + /// Distribute loop iteration variable init used when composing 'omp + /// distribute' + /// with 'omp for' in a same construct + Expr *Init; + /// Distribute Loop condition used when composing 'omp distribute' + /// with 'omp for' in a same construct + Expr *Cond; + /// Update of LowerBound for statically sheduled omp loops for + /// outer loop in combined constructs (e.g. 'distribute parallel for') + Expr *NLB; + /// Update of UpperBound for statically sheduled omp loops for + /// outer loop in combined constructs (e.g. 'distribute parallel for') + Expr *NUB; + }; + /// \brief The expressions built for the OpenMP loop CodeGen for the /// whole collapsed loop nest. struct HelperExprs { @@ -611,6 +676,9 @@ /// Init statement for all captured expressions. Stmt *PreInits; + /// Expressions used when combining OpenMP loop pragmas + DistCombinedHelperExprs DistCombinedFields; + /// \brief Check if all the expressions are built (does not check the /// worksharing ones). bool builtAll() { @@ -654,6 +722,13 @@ Finals[i] = nullptr; } PreInits = nullptr; + DistCombinedFields.LB = nullptr; + DistCombinedFields.UB = nullptr; + DistCombinedFields.EUB = nullptr; + DistCombinedFields.Init = nullptr; + DistCombinedFields.Cond = nullptr; + DistCombinedFields.NLB = nullptr; + DistCombinedFields.NUB = nullptr; } }; @@ -757,37 +832,71 @@ *std::next(child_begin(), NumIterationsOffset))); } Expr *getPrevLowerBoundVariable() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); return const_cast(reinterpret_cast( *std::next(child_begin(), PrevLowerBoundVariableOffset))); } Expr *getPrevUpperBoundVariable() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); return const_cast(reinterpret_cast( *std::next(child_begin(), PrevUpperBoundVariableOffset))); } Expr *getDistInc() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); return const_cast(reinterpret_cast( *std::next(child_begin(), DistIncOffset))); } Expr *getPrevEnsureUpperBound() const { - assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind()) || - isOpenMPDistributeDirective(getDirectiveKind())) && - "expected worksharing loop directive"); + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); return const_cast(reinterpret_cast( *std::next(child_begin(), PrevEnsureUpperBoundOffset))); } + Expr *getCombinedLowerBoundVariable() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast(reinterpret_cast( + *std::next(child_begin(), CombinedLowerBoundVariableOffset))); + } + Expr *getCombinedUpperBoundVariable() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast(reinterpret_cast( + *std::next(child_begin(), CombinedUpperBoundVariableOffset))); + } + Expr *getCombinedEnsureUpperBound() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast(reinterpret_cast( + *std::next(child_begin(), CombinedEnsureUpperBoundOffset))); + } + Expr *getCombinedInit() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast(reinterpret_cast( + *std::next(child_begin(), CombinedInitOffset))); + } + Expr *getCombinedCond() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast(reinterpret_cast( + *std::next(child_begin(), CombinedConditionOffset))); + } + Expr *getCombinedNextLowerBound() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast(reinterpret_cast( + *std::next(child_begin(), CombinedNextLowerBoundOffset))); + } + Expr *getCombinedNextUpperBound() const { + assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) && + "expected loop bound sharing directive"); + return const_cast(reinterpret_cast( + *std::next(child_begin(), CombinedNextUpperBoundOffset))); + } const Stmt *getBody() const { // This relies on the loop form is already checked by Sema. Stmt *Body = getAssociatedStmt()->IgnoreContainers(true); Index: lib/AST/StmtOpenMP.cpp =================================================================== --- lib/AST/StmtOpenMP.cpp +++ lib/AST/StmtOpenMP.cpp @@ -147,10 +147,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -201,10 +197,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -368,10 +360,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -421,10 +409,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -759,10 +743,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -904,10 +884,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -957,10 +933,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -1009,10 +981,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -1095,6 +1063,13 @@ Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); return Dir; } @@ -1153,6 +1128,13 @@ Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); return Dir; } @@ -1200,10 +1182,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -1256,10 +1234,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -1352,10 +1326,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -1407,10 +1377,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -1474,6 +1440,13 @@ Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); return Dir; } @@ -1534,6 +1507,13 @@ Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); return Dir; } @@ -1606,10 +1586,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); @@ -1676,6 +1652,13 @@ Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); return Dir; } @@ -1739,6 +1722,13 @@ Dir->setUpdates(Exprs.Updates); Dir->setFinals(Exprs.Finals); Dir->setPreInits(Exprs.PreInits); + Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB); + Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB); + Dir->setCombinedEnsureUpperBound(Exprs.DistCombinedFields.EUB); + Dir->setCombinedInit(Exprs.DistCombinedFields.Init); + Dir->setCombinedCond(Exprs.DistCombinedFields.Cond); + Dir->setCombinedNextLowerBound(Exprs.DistCombinedFields.NLB); + Dir->setCombinedNextUpperBound(Exprs.DistCombinedFields.NUB); return Dir; } @@ -1789,10 +1779,6 @@ Dir->setNextLowerBound(Exprs.NLB); Dir->setNextUpperBound(Exprs.NUB); Dir->setNumIterations(Exprs.NumIterations); - Dir->setPrevLowerBoundVariable(Exprs.PrevLB); - Dir->setPrevUpperBoundVariable(Exprs.PrevUB); - Dir->setDistInc(Exprs.DistInc); - Dir->setPrevEnsureUpperBound(Exprs.PrevEUB); Dir->setCounters(Exprs.Counters); Dir->setPrivateCounters(Exprs.PrivateCounters); Dir->setInits(Exprs.Inits); Index: lib/Basic/OpenMPKinds.cpp =================================================================== --- lib/Basic/OpenMPKinds.cpp +++ lib/Basic/OpenMPKinds.cpp @@ -854,14 +854,10 @@ bool clang::isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind) { return Kind == OMPD_distribute_parallel_for || Kind == OMPD_distribute_parallel_for_simd || - Kind == OMPD_distribute_simd || Kind == OMPD_teams_distribute || - Kind == OMPD_teams_distribute_simd || Kind == OMPD_teams_distribute_parallel_for_simd || Kind == OMPD_teams_distribute_parallel_for || - Kind == OMPD_target_teams_distribute || Kind == OMPD_target_teams_distribute_parallel_for || - Kind == OMPD_target_teams_distribute_parallel_for_simd || - Kind == OMPD_target_teams_distribute_simd; + Kind == OMPD_target_teams_distribute_parallel_for_simd; } void clang::getOpenMPCaptureRegions( Index: lib/Sema/SemaOpenMP.cpp =================================================================== --- lib/Sema/SemaOpenMP.cpp +++ lib/Sema/SemaOpenMP.cpp @@ -4068,7 +4068,7 @@ SourceLocation InitLoc = IterSpaces[0].InitSrcRange.getBegin(); // Build variables passed into runtime, necessary for worksharing directives. - ExprResult LB, UB, IL, ST, EUB, PrevLB, PrevUB; + ExprResult LB, UB, IL, ST, EUB, CombLB, CombUB, PrevLB, PrevUB, CombEUB; if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind)) { // Lower bound variable, initialized with zero. @@ -4116,8 +4116,32 @@ // enclosing region. E.g. in 'distribute parallel for' the bounds obtained // by scheduling 'distribute' have to be passed to the schedule of 'for'. if (isOpenMPLoopBoundSharingDirective(DKind)) { - auto *CD = cast(AStmt)->getCapturedDecl(); + // Lower bound variable, initialized with zero. + VarDecl *CombLBDecl = + buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.lb"); + CombLB = buildDeclRefExpr(SemaRef, CombLBDecl, VType, InitLoc); + SemaRef.AddInitializerToDecl( + CombLBDecl, SemaRef.ActOnIntegerConstant(InitLoc, 0).get(), + /*DirectInit*/ false); + + // Upper bound variable, initialized with last iteration number. + VarDecl *CombUBDecl = + buildVarDecl(SemaRef, InitLoc, VType, ".omp.comb.ub"); + CombUB = buildDeclRefExpr(SemaRef, CombUBDecl, VType, InitLoc); + SemaRef.AddInitializerToDecl(CombUBDecl, LastIteration.get(), + /*DirectInit*/ false); + + ExprResult CombIsUBGreater = SemaRef.BuildBinOp( + CurScope, InitLoc, BO_GT, CombUB.get(), LastIteration.get()); + ExprResult CombCondOp = + SemaRef.ActOnConditionalOp(InitLoc, InitLoc, CombIsUBGreater.get(), + LastIteration.get(), CombUB.get()); + CombEUB = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, CombUB.get(), + CombCondOp.get()); + CombEUB = SemaRef.ActOnFinishFullExpr(CombEUB.get()); + + auto *CD = cast(AStmt)->getCapturedDecl(); // We expect to have at least 2 more parameters than the 'parallel' // directive does - the lower and upper bounds of the previous schedule. assert(CD->getNumParams() >= 4 && @@ -4139,7 +4163,7 @@ // Build the iteration variable and its initialization before loop. ExprResult IV; - ExprResult Init; + ExprResult Init, CombInit; { VarDecl *IVDecl = buildVarDecl(SemaRef, InitLoc, RealVType, ".omp.iv"); IV = buildDeclRefExpr(SemaRef, IVDecl, RealVType, InitLoc); @@ -4150,6 +4174,18 @@ : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); Init = SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), RHS); Init = SemaRef.ActOnFinishFullExpr(Init.get()); + + if (isOpenMPLoopBoundSharingDirective(DKind)) { + Expr *CombRHS = + (isOpenMPWorksharingDirective(DKind) || + isOpenMPTaskLoopDirective(DKind) || + isOpenMPDistributeDirective(DKind)) + ? CombLB.get() + : SemaRef.ActOnIntegerConstant(SourceLocation(), 0).get(); + CombInit = + SemaRef.BuildBinOp(CurScope, InitLoc, BO_Assign, IV.get(), CombRHS); + CombInit = SemaRef.ActOnFinishFullExpr(CombInit.get()); + } } // Loop condition (IV < NumIterations) or (IV <= UB) for worksharing loops. @@ -4160,7 +4196,11 @@ ? SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), UB.get()) : SemaRef.BuildBinOp(CurScope, CondLoc, BO_LT, IV.get(), NumIterations.get()); - + ExprResult CombCond; + if (isOpenMPLoopBoundSharingDirective(DKind)) { + CombCond = + SemaRef.BuildBinOp(CurScope, CondLoc, BO_LE, IV.get(), CombUB.get()); + } // Loop increment (IV = IV + 1) SourceLocation IncLoc; ExprResult Inc = @@ -4175,7 +4215,9 @@ // Increments for worksharing loops (LB = LB + ST; UB = UB + ST). // Used for directives with static scheduling. - ExprResult NextLB, NextUB; + // In combined construct, add combined version that use CombLB and CombUB + // base variables for the update + ExprResult NextLB, NextUB, CombNextLB, CombNextUB; if (isOpenMPWorksharingDirective(DKind) || isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind)) { // LB + ST @@ -4198,9 +4240,32 @@ NextUB = SemaRef.ActOnFinishFullExpr(NextUB.get()); if (!NextUB.isUsable()) return 0; - } - - // Create: increment expression for distribute loop when combined in a same + if (isOpenMPLoopBoundSharingDirective(DKind)) { + CombNextLB = + SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombLB.get(), ST.get()); + if (!NextLB.isUsable()) + return 0; + // LB = LB + ST + CombNextLB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombLB.get(), + CombNextLB.get()); + CombNextLB = SemaRef.ActOnFinishFullExpr(CombNextLB.get()); + if (!CombNextLB.isUsable()) + return 0; + // UB + ST + CombNextUB = + SemaRef.BuildBinOp(CurScope, IncLoc, BO_Add, CombUB.get(), ST.get()); + if (!CombNextUB.isUsable()) + return 0; + // UB = UB + ST + CombNextUB = SemaRef.BuildBinOp(CurScope, IncLoc, BO_Assign, CombUB.get(), + CombNextUB.get()); + CombNextUB = SemaRef.ActOnFinishFullExpr(CombNextUB.get()); + if (!CombNextUB.isUsable()) + return 0; + } + } + + // Create increment expression for distribute loop when combined in a same // directive with for as IV = IV + ST; ensure upper bound expression based // on PrevUB instead of NumIterations - used to implement 'for' when found // in combination with 'distribute', like in 'distribute parallel for' @@ -4346,6 +4411,13 @@ Built.PrevUB = PrevUB.get(); Built.DistInc = DistInc.get(); Built.PrevEUB = PrevEUB.get(); + Built.DistCombinedFields.LB = CombLB.get(); + Built.DistCombinedFields.UB = CombUB.get(); + Built.DistCombinedFields.EUB = CombEUB.get(); + Built.DistCombinedFields.Init = CombInit.get(); + Built.DistCombinedFields.Cond = CombCond.get(); + Built.DistCombinedFields.NLB = CombNextLB.get(); + Built.DistCombinedFields.NUB = CombNextUB.get(); Expr *CounterVal = SemaRef.DefaultLvalueConversion(IV.get()).get(); // Fill data for doacross depend clauses. Index: lib/Serialization/ASTReaderStmt.cpp =================================================================== --- lib/Serialization/ASTReaderStmt.cpp +++ lib/Serialization/ASTReaderStmt.cpp @@ -2578,6 +2578,13 @@ D->setPrevUpperBoundVariable(Record.readSubExpr()); D->setDistInc(Record.readSubExpr()); D->setPrevEnsureUpperBound(Record.readSubExpr()); + D->setCombinedLowerBoundVariable(Record.readSubExpr()); + D->setCombinedUpperBoundVariable(Record.readSubExpr()); + D->setCombinedEnsureUpperBound(Record.readSubExpr()); + D->setCombinedInit(Record.readSubExpr()); + D->setCombinedCond(Record.readSubExpr()); + D->setCombinedNextLowerBound(Record.readSubExpr()); + D->setCombinedNextUpperBound(Record.readSubExpr()); } SmallVector Sub; unsigned CollapsedNum = D->getCollapsedNumber(); Index: lib/Serialization/ASTWriterStmt.cpp =================================================================== --- lib/Serialization/ASTWriterStmt.cpp +++ lib/Serialization/ASTWriterStmt.cpp @@ -2248,6 +2248,13 @@ Record.AddStmt(D->getPrevUpperBoundVariable()); Record.AddStmt(D->getDistInc()); Record.AddStmt(D->getPrevEnsureUpperBound()); + Record.AddStmt(D->getCombinedLowerBoundVariable()); + Record.AddStmt(D->getCombinedUpperBoundVariable()); + Record.AddStmt(D->getCombinedEnsureUpperBound()); + Record.AddStmt(D->getCombinedInit()); + Record.AddStmt(D->getCombinedCond()); + Record.AddStmt(D->getCombinedNextLowerBound()); + Record.AddStmt(D->getCombinedNextUpperBound()); } for (auto I : D->counters()) { Record.AddStmt(I); Index: test/OpenMP/distribute_parallel_for_ast_print.cpp =================================================================== --- test/OpenMP/distribute_parallel_for_ast_print.cpp +++ test/OpenMP/distribute_parallel_for_ast_print.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -verify -std=c++11 -fopenmp -fopenmp-version=45 -ast-print %s | FileCheck %s // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -x c++ -std=c++11 -emit-pch -o %t %s // RUN: %clang_cc1 -fopenmp -fopenmp-version=45 -std=c++11 -include-pch %t -fsyntax-only -verify %s -ast-print | FileCheck %s // expected-no-diagnostics @@ -109,6 +109,41 @@ return T(); } +void foo(int argc, char **argv) { + int b, c, d, e, f, h; + static int a; +// CHECK: static int a; + static float g; +#pragma omp threadprivate(g) + [&]() { +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for schedule(guided, argc) default(none) copyin(g) dist_schedule(static, a) private(a) + // CHECK: #pragma omp distribute parallel for schedule(guided, argc) default(none) copyin(g) dist_schedule(static, a) private(a) + for (int i = 0; i < 2; ++i) +// CHECK: for (int i = 0; i < 2; ++i) + [&]() { + a = 2; + // CHECK: a = 2; + }(); + + }(); + [&]() { +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for private(argc, b), firstprivate(argv, c), lastprivate(d, f) collapse(2) schedule(auto) if (argc) num_threads(a) default(shared) shared(e) reduction(+ : h) dist_schedule(static, b) + for (int i = 0; i < 10; ++i) + for (int j = 0; j < 10; ++j) + [&]() { + a++; + }(); + // CHECK: #pragma omp distribute parallel for private(argc,b) firstprivate(argv,c) lastprivate(d,f) collapse(2) schedule(auto) if(argc) num_threads(a) default(shared) shared(e) reduction(+: h) dist_schedule(static, b) + // CHECK-NEXT: for (int i = 0; i < 10; ++i) + // CHECK-NEXT: for (int j = 0; j < 10; ++j) + // CHECK: a++; + }(); +} + int main(int argc, char **argv) { int b = argc, c, d, e, f, h; static int a; Index: test/OpenMP/distribute_parallel_for_messages.cpp =================================================================== --- /dev/null +++ test/OpenMP/distribute_parallel_for_messages.cpp @@ -0,0 +1,118 @@ +// RUN: %clang_cc1 -verify -fopenmp -ferror-limit 100 -std=c++11 -o - %s + +void foo() { +} + +#pragma omp distribute parallel for // expected-error {{unexpected OpenMP directive '#pragma omp distribute parallel for'}} + +int main(int argc, char **argv) { +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for { // expected-warning {{extra tokens at the end of '#pragma omp distribute parallel for' are ignored}} + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for ( // expected-warning {{extra tokens at the end of '#pragma omp distribute parallel for' are ignored}} + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for[ // expected-warning {{extra tokens at the end of '#pragma omp distribute parallel for' are ignored}} + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for] // expected-warning {{extra tokens at the end of '#pragma omp distribute parallel for' are ignored}} + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for) // expected-warning {{extra tokens at the end of '#pragma omp distribute parallel for' are ignored}} + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for } // expected-warning {{extra tokens at the end of '#pragma omp distribute parallel for' are ignored}} + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for unknown() // expected-warning {{extra tokens at the end of '#pragma omp distribute parallel for' are ignored}} + for (int i = 0; i < argc; ++i) + foo(); +L1: + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for + for (int i = 0; i < argc; ++i) + foo(); +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for + for (int i = 0; i < argc; ++i) { + goto L1; // expected-error {{use of undeclared label 'L1'}} + argc++; + } + + for (int i = 0; i < 10; ++i) { + switch (argc) { + case (0): +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for + for (int i = 0; i < argc; ++i) { + foo(); + break; // expected-error {{'break' statement cannot be used in OpenMP for loop}} + continue; + } + default: + break; + } + } +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for default(none) + for (int i = 0; i < 10; ++i) + ++argc; // expected-error {{variable 'argc' must have explicitly specified data sharing attributes}} + + goto L2; // expected-error {{use of undeclared label 'L2'}} +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for + for (int i = 0; i < argc; ++i) + L2: + foo(); +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for + for (int i = 0; i < argc; ++i) { + return 1; // expected-error {{cannot return from OpenMP region}} + } + + [[]] // expected-error {{an attribute list cannot appear here}} +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for + for (int n = 0; n < 100; ++n) { + } + + return 0; +} + +void test_ordered() { +#pragma omp target +#pragma omp teams +#pragma omp distribute parallel for collapse(2) collapse(3) // expected-error {{directive '#pragma omp distribute parallel for' cannot contain more than one 'collapse' clause}} + for (int i = 0; i < 16; ++i) + for (int j = 0; j < 16; ++j) + ; +} +