r368903 - [OPENMP]Support for non-rectangular loops.
Alexey Bataev via cfe-commits
cfe-commits at lists.llvm.org
Wed Aug 14 12:30:06 PDT 2019
Author: abataev
Date: Wed Aug 14 12:30:06 2019
New Revision: 368903
URL: http://llvm.org/viewvc/llvm-project?rev=368903&view=rev
Log:
[OPENMP]Support for non-rectangular loops.
Added basic support for non-rectangular loops. It requires an additional
analysis of min/max boundaries for non-rectangular loops. Since only
linear dependency is allowed, we can do this analysis.
Modified:
cfe/trunk/include/clang/AST/StmtOpenMP.h
cfe/trunk/lib/AST/StmtOpenMP.cpp
cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
cfe/trunk/lib/Sema/SemaOpenMP.cpp
cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
cfe/trunk/test/OpenMP/for_codegen.cpp
cfe/trunk/test/OpenMP/for_loop_messages.cpp
cfe/trunk/test/OpenMP/parallel_messages.cpp
Modified: cfe/trunk/include/clang/AST/StmtOpenMP.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/StmtOpenMP.h?rev=368903&r1=368902&r2=368903&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/StmtOpenMP.h (original)
+++ cfe/trunk/include/clang/AST/StmtOpenMP.h Wed Aug 14 12:30:06 2019
@@ -448,7 +448,8 @@ class OMPLoopDirective : public OMPExecu
PreInitsOffset = 8,
// The '...End' enumerators do not correspond to child expressions - they
// specify the offset to the end (and start of the following counters/
- // updates/finals arrays).
+ // updates/finals/dependent_counters/dependent_inits/finals_conditions
+ // arrays).
DefaultEnd = 9,
// The following 8 exprs are used by worksharing and distribute loops only.
IsLastIterVariableOffset = 9,
@@ -474,7 +475,8 @@ class OMPLoopDirective : public OMPExecu
CombinedNextUpperBoundOffset = 27,
CombinedDistConditionOffset = 28,
CombinedParForInDistConditionOffset = 29,
- // Offset to the end (and start of the following counters/updates/finals
+ // Offset to the end (and start of the following
+ // counters/updates/finals/dependent_counters/dependent_inits/finals_conditions
// arrays) for combined distribute loop directives.
CombinedDistributeEnd = 30,
};
@@ -517,6 +519,30 @@ class OMPLoopDirective : public OMPExecu
return MutableArrayRef<Expr *>(Storage, CollapsedNum);
}
+ /// Get the dependent counters storage.
+ MutableArrayRef<Expr *> getDependentCounters() {
+ Expr **Storage = reinterpret_cast<Expr **>(
+ &*std::next(child_begin(),
+ getArraysOffset(getDirectiveKind()) + 5 * CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
+ /// Get the dependent inits storage.
+ MutableArrayRef<Expr *> getDependentInits() {
+ Expr **Storage = reinterpret_cast<Expr **>(
+ &*std::next(child_begin(),
+ getArraysOffset(getDirectiveKind()) + 6 * CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
+ /// Get the finals conditions storage.
+ MutableArrayRef<Expr *> getFinalsConditions() {
+ Expr **Storage = reinterpret_cast<Expr **>(
+ &*std::next(child_begin(),
+ getArraysOffset(getDirectiveKind()) + 7 * CollapsedNum));
+ return MutableArrayRef<Expr *>(Storage, CollapsedNum);
+ }
+
protected:
/// Build instance of loop directive of class \a Kind.
///
@@ -551,9 +577,10 @@ protected:
/// Children number.
static unsigned numLoopChildren(unsigned CollapsedNum,
OpenMPDirectiveKind Kind) {
- return getArraysOffset(Kind) + 5 * CollapsedNum; // Counters,
- // PrivateCounters, Inits,
- // Updates and Finals
+ return getArraysOffset(Kind) +
+ 8 * CollapsedNum; // Counters, PrivateCounters, Inits,
+ // Updates, Finals, DependentCounters,
+ // DependentInits, FinalsConditions.
}
void setIterationVariable(Expr *IV) {
@@ -703,6 +730,9 @@ protected:
void setInits(ArrayRef<Expr *> A);
void setUpdates(ArrayRef<Expr *> A);
void setFinals(ArrayRef<Expr *> A);
+ void setDependentCounters(ArrayRef<Expr *> A);
+ void setDependentInits(ArrayRef<Expr *> A);
+ void setFinalsConditions(ArrayRef<Expr *> A);
public:
/// The expressions built to support OpenMP loops in combined/composite
@@ -798,6 +828,15 @@ public:
SmallVector<Expr *, 4> Updates;
/// Final loop counter values for GodeGen.
SmallVector<Expr *, 4> Finals;
+ /// List of counters required for the generation of the non-rectangular
+ /// loops.
+ SmallVector<Expr *, 4> DependentCounters;
+ /// List of initializers required for the generation of the non-rectangular
+ /// loops.
+ SmallVector<Expr *, 4> DependentInits;
+ /// List of final conditions required for the generation of the
+ /// non-rectangular loops.
+ SmallVector<Expr *, 4> FinalsConditions;
/// Init statement for all captured expressions.
Stmt *PreInits;
@@ -813,7 +852,9 @@ public:
}
/// Initialize all the fields to null.
- /// \param Size Number of elements in the counters/finals/updates arrays.
+ /// \param Size Number of elements in the
+ /// counters/finals/updates/dependent_counters/dependent_inits/finals_conditions
+ /// arrays.
void clear(unsigned Size) {
IterationVarRef = nullptr;
LastIteration = nullptr;
@@ -839,12 +880,18 @@ public:
Inits.resize(Size);
Updates.resize(Size);
Finals.resize(Size);
+ DependentCounters.resize(Size);
+ DependentInits.resize(Size);
+ FinalsConditions.resize(Size);
for (unsigned i = 0; i < Size; ++i) {
Counters[i] = nullptr;
PrivateCounters[i] = nullptr;
Inits[i] = nullptr;
Updates[i] = nullptr;
Finals[i] = nullptr;
+ DependentCounters[i] = nullptr;
+ DependentInits[i] = nullptr;
+ FinalsConditions[i] = nullptr;
}
PreInits = nullptr;
DistCombinedFields.LB = nullptr;
@@ -1078,6 +1125,24 @@ public:
return const_cast<OMPLoopDirective *>(this)->getFinals();
}
+ ArrayRef<Expr *> dependent_counters() { return getDependentCounters(); }
+
+ ArrayRef<Expr *> dependent_counters() const {
+ return const_cast<OMPLoopDirective *>(this)->getDependentCounters();
+ }
+
+ ArrayRef<Expr *> dependent_inits() { return getDependentInits(); }
+
+ ArrayRef<Expr *> dependent_inits() const {
+ return const_cast<OMPLoopDirective *>(this)->getDependentInits();
+ }
+
+ ArrayRef<Expr *> finals_conditions() { return getFinalsConditions(); }
+
+ ArrayRef<Expr *> finals_conditions() const {
+ return const_cast<OMPLoopDirective *>(this)->getFinalsConditions();
+ }
+
static bool classof(const Stmt *T) {
return T->getStmtClass() == OMPSimdDirectiveClass ||
T->getStmtClass() == OMPForDirectiveClass ||
Modified: cfe/trunk/lib/AST/StmtOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/StmtOpenMP.cpp?rev=368903&r1=368902&r2=368903&view=diff
==============================================================================
--- cfe/trunk/lib/AST/StmtOpenMP.cpp (original)
+++ cfe/trunk/lib/AST/StmtOpenMP.cpp Wed Aug 14 12:30:06 2019
@@ -72,6 +72,25 @@ void OMPLoopDirective::setFinals(ArrayRe
std::copy(A.begin(), A.end(), getFinals().begin());
}
+void OMPLoopDirective::setDependentCounters(ArrayRef<Expr *> A) {
+ assert(
+ A.size() == getCollapsedNumber() &&
+ "Number of dependent counters is not the same as the collapsed number");
+ llvm::copy(A, getDependentCounters().begin());
+}
+
+void OMPLoopDirective::setDependentInits(ArrayRef<Expr *> A) {
+ assert(A.size() == getCollapsedNumber() &&
+ "Number of dependent inits is not the same as the collapsed number");
+ llvm::copy(A, getDependentInits().begin());
+}
+
+void OMPLoopDirective::setFinalsConditions(ArrayRef<Expr *> A) {
+ assert(A.size() == getCollapsedNumber() &&
+ "Number of finals conditions is not the same as the collapsed number");
+ llvm::copy(A, getFinalsConditions().begin());
+}
+
OMPParallelDirective *OMPParallelDirective::Create(
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel) {
@@ -122,6 +141,9 @@ OMPSimdDirective::Create(const ASTContex
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
return Dir;
}
@@ -170,6 +192,9 @@ OMPForDirective::Create(const ASTContext
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
Dir->setHasCancel(HasCancel);
return Dir;
@@ -220,6 +245,9 @@ OMPForSimdDirective::Create(const ASTCon
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
return Dir;
}
@@ -383,6 +411,9 @@ OMPParallelForDirective *OMPParallelForD
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
Dir->setHasCancel(HasCancel);
return Dir;
@@ -432,6 +463,9 @@ OMPParallelForSimdDirective *OMPParallel
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
return Dir;
}
@@ -772,6 +806,9 @@ OMPTargetParallelForDirective *OMPTarget
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
Dir->setHasCancel(HasCancel);
return Dir;
@@ -914,6 +951,9 @@ OMPTaskLoopDirective *OMPTaskLoopDirecti
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
return Dir;
}
@@ -963,6 +1003,9 @@ OMPTaskLoopSimdDirective *OMPTaskLoopSim
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
return Dir;
}
@@ -1011,6 +1054,9 @@ OMPDistributeDirective *OMPDistributeDir
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
return Dir;
}
@@ -1089,6 +1135,9 @@ OMPDistributeParallelForDirective *OMPDi
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB);
Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB);
@@ -1157,6 +1206,9 @@ OMPDistributeParallelForSimdDirective::C
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB);
Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB);
@@ -1219,6 +1271,9 @@ OMPDistributeSimdDirective *OMPDistribut
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
return Dir;
}
@@ -1271,6 +1326,9 @@ OMPTargetParallelForSimdDirective *OMPTa
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
return Dir;
}
@@ -1315,6 +1373,9 @@ OMPTargetSimdDirective::Create(const AST
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
return Dir;
}
@@ -1363,6 +1424,9 @@ OMPTeamsDistributeDirective *OMPTeamsDis
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
return Dir;
}
@@ -1414,6 +1478,9 @@ OMPTeamsDistributeSimdDirective *OMPTeam
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
return Dir;
}
@@ -1471,6 +1538,9 @@ OMPTeamsDistributeParallelForSimdDirecti
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB);
Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB);
@@ -1540,6 +1610,9 @@ OMPTeamsDistributeParallelForDirective::
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB);
Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB);
@@ -1628,6 +1701,9 @@ OMPTargetTeamsDistributeDirective *OMPTa
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
return Dir;
}
@@ -1688,6 +1764,9 @@ OMPTargetTeamsDistributeParallelForDirec
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB);
Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB);
@@ -1761,6 +1840,9 @@ OMPTargetTeamsDistributeParallelForSimdD
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
Dir->setCombinedLowerBoundVariable(Exprs.DistCombinedFields.LB);
Dir->setCombinedUpperBoundVariable(Exprs.DistCombinedFields.UB);
@@ -1826,6 +1908,9 @@ OMPTargetTeamsDistributeSimdDirective::C
Dir->setInits(Exprs.Inits);
Dir->setUpdates(Exprs.Updates);
Dir->setFinals(Exprs.Finals);
+ Dir->setDependentCounters(Exprs.DependentCounters);
+ Dir->setDependentInits(Exprs.DependentInits);
+ Dir->setFinalsConditions(Exprs.FinalsConditions);
Dir->setPreInits(Exprs.PreInits);
return Dir;
}
Modified: cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp?rev=368903&r1=368902&r2=368903&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGStmtOpenMP.cpp Wed Aug 14 12:30:06 2019
@@ -1324,6 +1324,16 @@ void CodeGenFunction::EmitOMPLoopBody(co
// On a continue in the body, jump to the end.
JumpDest Continue = getJumpDestInCurrentScope("omp.body.continue");
BreakContinueStack.push_back(BreakContinue(LoopExit, Continue));
+ for (const Expr *E : D.finals_conditions()) {
+ if (!E)
+ continue;
+ // Check that loop counter in non-rectangular nest fits into the iteration
+ // space.
+ llvm::BasicBlock *NextBB = createBasicBlock("omp.body.next");
+ EmitBranchOnBoolExpr(E, NextBB, Continue.getBlock(),
+ getProfileCount(D.getBody()));
+ EmitBlock(NextBB);
+ }
// Emit loop body.
EmitStmt(D.getBody());
// The end (updates/cleanups).
@@ -1553,8 +1563,28 @@ static void emitPreCond(CodeGenFunction
CGF.EmitIgnoredExpr(I);
}
}
+ // Create temp loop control variables with their init values to support
+ // non-rectangular loops.
+ CodeGenFunction::OMPMapVars PreCondVars;
+ for (const Expr * E: S.dependent_counters()) {
+ if (!E)
+ continue;
+ assert(!E->getType().getNonReferenceType()->isRecordType() &&
+ "dependent counter must not be an iterator.");
+ const auto *VD = cast<VarDecl>(cast<DeclRefExpr>(E)->getDecl());
+ Address CounterAddr =
+ CGF.CreateMemTemp(VD->getType().getNonReferenceType());
+ (void)PreCondVars.setVarAddr(CGF, VD, CounterAddr);
+ }
+ (void)PreCondVars.apply(CGF);
+ for (const Expr *E : S.dependent_inits()) {
+ if (!E)
+ continue;
+ CGF.EmitIgnoredExpr(E);
+ }
// Check that loop is executed at least one time.
CGF.EmitBranchOnBoolExpr(Cond, TrueBlock, FalseBlock, TrueCount);
+ PreCondVars.restore(CGF);
}
void CodeGenFunction::EmitOMPLinearClause(
Modified: cfe/trunk/lib/Sema/SemaOpenMP.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOpenMP.cpp?rev=368903&r1=368902&r2=368903&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOpenMP.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOpenMP.cpp Wed Aug 14 12:30:06 2019
@@ -4709,6 +4709,54 @@ StmtResult Sema::ActOnOpenMPParallelDire
}
namespace {
+/// Iteration space of a single for loop.
+struct LoopIterationSpace final {
+ /// True if the condition operator is the strict compare operator (<, > or
+ /// !=).
+ bool IsStrictCompare = false;
+ /// Condition of the loop.
+ Expr *PreCond = nullptr;
+ /// This expression calculates the number of iterations in the loop.
+ /// It is always possible to calculate it before starting the loop.
+ Expr *NumIterations = nullptr;
+ /// The loop counter variable.
+ Expr *CounterVar = nullptr;
+ /// Private loop counter variable.
+ Expr *PrivateCounterVar = nullptr;
+ /// This is initializer for the initial value of #CounterVar.
+ Expr *CounterInit = nullptr;
+ /// This is step for the #CounterVar used to generate its update:
+ /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
+ Expr *CounterStep = nullptr;
+ /// Should step be subtracted?
+ bool Subtract = false;
+ /// Source range of the loop init.
+ SourceRange InitSrcRange;
+ /// Source range of the loop condition.
+ SourceRange CondSrcRange;
+ /// Source range of the loop increment.
+ SourceRange IncSrcRange;
+ /// Minimum value that can have the loop control variable. Used to support
+ /// non-rectangular loops. Applied only for LCV with the non-iterator types,
+ /// since only such variables can be used in non-loop invariant expressions.
+ Expr *MinValue = nullptr;
+ /// Maximum value that can have the loop control variable. Used to support
+ /// non-rectangular loops. Applied only for LCV with the non-iterator type,
+ /// since only such variables can be used in non-loop invariant expressions.
+ Expr *MaxValue = nullptr;
+ /// true, if the lower bound depends on the outer loop control var.
+ bool IsNonRectangularLB = false;
+ /// true, if the upper bound depends on the outer loop control var.
+ bool IsNonRectangularUB = false;
+ /// Index of the loop this loop depends on and forms non-rectangular loop
+ /// nest.
+ unsigned LoopDependentIdx = 0;
+ /// Final condition for the non-rectangular loop nest support. It is used to
+ /// check that the number of iterations for this particular counter must be
+ /// finished.
+ Expr *FinalCondition = nullptr;
+};
+
/// Helper class for checking canonical form of the OpenMP loops and
/// extracting iteration space of each loop in the loop nest, that will be used
/// for IR generation.
@@ -4758,6 +4806,9 @@ class OpenMPIterationSpaceChecker {
Optional<unsigned> CondDependOnLC;
/// Checks if the provide statement depends on the loop counter.
Optional<unsigned> doesDependOnLoopCounter(const Stmt *S, bool IsInitializer);
+ /// Original condition required for checking of the exit condition for
+ /// non-rectangular loop.
+ Expr *Condition = nullptr;
public:
OpenMPIterationSpaceChecker(Sema &SemaRef, DSAStackTy &Stack,
@@ -4789,7 +4840,7 @@ public:
bool isStrictTestOp() const { return TestIsStrictOp; }
/// Build the expression to calculate the number of iterations.
Expr *buildNumIterations(
- Scope *S, const bool LimitedType,
+ Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
/// Build the precondition expression for the loops.
Expr *
@@ -4813,8 +4864,21 @@ public:
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
SourceLocation Loc, Expr *Inc = nullptr,
OverloadedOperatorKind OOK = OO_Amp);
+ /// Builds the minimum value for the loop counter.
+ std::pair<Expr *, Expr *> buildMinMaxValues(
+ Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const;
+ /// Builds final condition for the non-rectangular loops.
+ Expr *buildFinalCondition(Scope *S) const;
/// Return true if any expression is dependent.
bool dependent() const;
+ /// Returns true if the initializer forms non-rectangular loop.
+ bool doesInitDependOnLC() const { return InitDependOnLC.hasValue(); }
+ /// Returns true if the condition forms non-rectangular loop.
+ bool doesCondDependOnLC() const { return CondDependOnLC.hasValue(); }
+ /// Returns index of the loop we depend on (starting from 1), or 0 otherwise.
+ unsigned getLoopDependentIdx() const {
+ return InitDependOnLC.getValueOr(CondDependOnLC.getValueOr(0));
+ }
private:
/// Check the right-hand side of an assignment in the increment
@@ -5013,9 +5077,9 @@ public:
return false;
}
bool VisitStmt(const Stmt *S) {
- bool Res = true;
+ bool Res = false;
for (const Stmt *Child : S->children())
- Res = Child && Visit(Child) && Res;
+ Res = (Child && Visit(Child)) || Res;
return Res;
}
explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
@@ -5165,6 +5229,7 @@ bool OpenMPIterationSpaceChecker::checkA
SemaRef.Diag(DefaultLoc, diag::err_omp_loop_not_canonical_cond) << LCDecl;
return true;
}
+ Condition = S;
S = getExprAsWritten(S);
SourceLocation CondLoc = S->getBeginLoc();
if (auto *BO = dyn_cast<BinaryOperator>(S)) {
@@ -5351,15 +5416,177 @@ tryBuildCapture(Sema &SemaRef, Expr *Cap
/// Build the expression to calculate the number of iterations.
Expr *OpenMPIterationSpaceChecker::buildNumIterations(
- Scope *S, const bool LimitedType,
+ Scope *S, ArrayRef<LoopIterationSpace> ResultIterSpaces, bool LimitedType,
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
ExprResult Diff;
QualType VarType = LCDecl->getType().getNonReferenceType();
if (VarType->isIntegerType() || VarType->isPointerType() ||
SemaRef.getLangOpts().CPlusPlus) {
+ Expr *LBVal = LB;
+ Expr *UBVal = UB;
+ // LB = TestIsLessOp.getValue() ? min(LB(MinVal), LB(MaxVal)) :
+ // max(LB(MinVal), LB(MaxVal))
+ if (InitDependOnLC) {
+ const LoopIterationSpace &IS =
+ ResultIterSpaces[ResultIterSpaces.size() - 1 -
+ InitDependOnLC.getValueOr(
+ CondDependOnLC.getValueOr(0))];
+ if (!IS.MinValue || !IS.MaxValue)
+ return nullptr;
+ // OuterVar = Min
+ ExprResult MinValue =
+ SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
+ if (!MinValue.isUsable())
+ return nullptr;
+
+ ExprResult LBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
+ IS.CounterVar, MinValue.get());
+ if (!LBMinVal.isUsable())
+ return nullptr;
+ // OuterVar = Min, LBVal
+ LBMinVal =
+ SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMinVal.get(), LBVal);
+ if (!LBMinVal.isUsable())
+ return nullptr;
+ // (OuterVar = Min, LBVal)
+ LBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMinVal.get());
+ if (!LBMinVal.isUsable())
+ return nullptr;
+
+ // OuterVar = Max
+ ExprResult MaxValue =
+ SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
+ if (!MaxValue.isUsable())
+ return nullptr;
+
+ ExprResult LBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
+ IS.CounterVar, MaxValue.get());
+ if (!LBMaxVal.isUsable())
+ return nullptr;
+ // OuterVar = Max, LBVal
+ LBMaxVal =
+ SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, LBMaxVal.get(), LBVal);
+ if (!LBMaxVal.isUsable())
+ return nullptr;
+ // (OuterVar = Max, LBVal)
+ LBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, LBMaxVal.get());
+ if (!LBMaxVal.isUsable())
+ return nullptr;
+
+ Expr *LBMin = tryBuildCapture(SemaRef, LBMinVal.get(), Captures).get();
+ Expr *LBMax = tryBuildCapture(SemaRef, LBMaxVal.get(), Captures).get();
+ if (!LBMin || !LBMax)
+ return nullptr;
+ // LB(MinVal) < LB(MaxVal)
+ ExprResult MinLessMaxRes =
+ SemaRef.BuildBinOp(S, DefaultLoc, BO_LT, LBMin, LBMax);
+ if (!MinLessMaxRes.isUsable())
+ return nullptr;
+ Expr *MinLessMax =
+ tryBuildCapture(SemaRef, MinLessMaxRes.get(), Captures).get();
+ if (!MinLessMax)
+ return nullptr;
+ if (TestIsLessOp.getValue()) {
+ // LB(MinVal) < LB(MaxVal) ? LB(MinVal) : LB(MaxVal) - min(LB(MinVal),
+ // LB(MaxVal))
+ ExprResult MinLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
+ MinLessMax, LBMin, LBMax);
+ if (!MinLB.isUsable())
+ return nullptr;
+ LBVal = MinLB.get();
+ } else {
+ // LB(MinVal) < LB(MaxVal) ? LB(MaxVal) : LB(MinVal) - max(LB(MinVal),
+ // LB(MaxVal))
+ ExprResult MaxLB = SemaRef.ActOnConditionalOp(DefaultLoc, DefaultLoc,
+ MinLessMax, LBMax, LBMin);
+ if (!MaxLB.isUsable())
+ return nullptr;
+ LBVal = MaxLB.get();
+ }
+ }
+ // UB = TestIsLessOp.getValue() ? max(UB(MinVal), UB(MaxVal)) :
+ // min(UB(MinVal), UB(MaxVal))
+ if (CondDependOnLC) {
+ const LoopIterationSpace &IS =
+ ResultIterSpaces[ResultIterSpaces.size() - 1 -
+ InitDependOnLC.getValueOr(
+ CondDependOnLC.getValueOr(0))];
+ if (!IS.MinValue || !IS.MaxValue)
+ return nullptr;
+ // OuterVar = Min
+ ExprResult MinValue =
+ SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MinValue);
+ if (!MinValue.isUsable())
+ return nullptr;
+
+ ExprResult UBMinVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
+ IS.CounterVar, MinValue.get());
+ if (!UBMinVal.isUsable())
+ return nullptr;
+ // OuterVar = Min, UBVal
+ UBMinVal =
+ SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMinVal.get(), UBVal);
+ if (!UBMinVal.isUsable())
+ return nullptr;
+ // (OuterVar = Min, UBVal)
+ UBMinVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMinVal.get());
+ if (!UBMinVal.isUsable())
+ return nullptr;
+
+ // OuterVar = Max
+ ExprResult MaxValue =
+ SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, IS.MaxValue);
+ if (!MaxValue.isUsable())
+ return nullptr;
+
+ ExprResult UBMaxVal = SemaRef.BuildBinOp(S, DefaultLoc, BO_Assign,
+ IS.CounterVar, MaxValue.get());
+ if (!UBMaxVal.isUsable())
+ return nullptr;
+ // OuterVar = Max, UBVal
+ UBMaxVal =
+ SemaRef.BuildBinOp(S, DefaultLoc, BO_Comma, UBMaxVal.get(), UBVal);
+ if (!UBMaxVal.isUsable())
+ return nullptr;
+ // (OuterVar = Max, UBVal)
+ UBMaxVal = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, UBMaxVal.get());
+ if (!UBMaxVal.isUsable())
+ return nullptr;
+
+ Expr *UBMin = tryBuildCapture(SemaRef, UBMinVal.get(), Captures).get();
+ Expr *UBMax = tryBuildCapture(SemaRef, UBMaxVal.get(), Captures).get();
+ if (!UBMin || !UBMax)
+ return nullptr;
+ // UB(MinVal) > UB(MaxVal)
+ ExprResult MinGreaterMaxRes =
+ SemaRef.BuildBinOp(S, DefaultLoc, BO_GT, UBMin, UBMax);
+ if (!MinGreaterMaxRes.isUsable())
+ return nullptr;
+ Expr *MinGreaterMax =
+ tryBuildCapture(SemaRef, MinGreaterMaxRes.get(), Captures).get();
+ if (!MinGreaterMax)
+ return nullptr;
+ if (TestIsLessOp.getValue()) {
+ // UB(MinVal) > UB(MaxVal) ? UB(MinVal) : UB(MaxVal) - max(UB(MinVal),
+ // UB(MaxVal))
+ ExprResult MaxUB = SemaRef.ActOnConditionalOp(
+ DefaultLoc, DefaultLoc, MinGreaterMax, UBMin, UBMax);
+ if (!MaxUB.isUsable())
+ return nullptr;
+ UBVal = MaxUB.get();
+ } else {
+ // UB(MinVal) > UB(MaxVal) ? UB(MaxVal) : UB(MinVal) - min(UB(MinVal),
+ // UB(MaxVal))
+ ExprResult MinUB = SemaRef.ActOnConditionalOp(
+ DefaultLoc, DefaultLoc, MinGreaterMax, UBMax, UBMin);
+ if (!MinUB.isUsable())
+ return nullptr;
+ UBVal = MinUB.get();
+ }
+ }
// Upper - Lower
- Expr *UBExpr = TestIsLessOp.getValue() ? UB : LB;
- Expr *LBExpr = TestIsLessOp.getValue() ? LB : UB;
+ Expr *UBExpr = TestIsLessOp.getValue() ? UBVal : LBVal;
+ Expr *LBExpr = TestIsLessOp.getValue() ? LBVal : UBVal;
Expr *Upper = tryBuildCapture(SemaRef, UBExpr, Captures).get();
Expr *Lower = tryBuildCapture(SemaRef, LBExpr, Captures).get();
if (!Upper || !Lower)
@@ -5446,6 +5673,127 @@ Expr *OpenMPIterationSpaceChecker::build
return Diff.get();
}
+std::pair<Expr *, Expr *> OpenMPIterationSpaceChecker::buildMinMaxValues(
+ Scope *S, llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
+ // Do not build for iterators, they cannot be used in non-rectangular loop
+ // nests.
+ if (LCDecl->getType()->isRecordType())
+ return std::make_pair(nullptr, nullptr);
+ // If we subtract, the min is in the condition, otherwise the min is in the
+ // init value.
+ Expr *MinExpr = nullptr;
+ Expr *MaxExpr = nullptr;
+ Expr *LBExpr = TestIsLessOp.getValue() ? LB : UB;
+ Expr *UBExpr = TestIsLessOp.getValue() ? UB : LB;
+ bool LBNonRect = TestIsLessOp.getValue() ? InitDependOnLC.hasValue()
+ : CondDependOnLC.hasValue();
+ bool UBNonRect = TestIsLessOp.getValue() ? CondDependOnLC.hasValue()
+ : InitDependOnLC.hasValue();
+ Expr *Lower =
+ LBNonRect ? LBExpr : tryBuildCapture(SemaRef, LBExpr, Captures).get();
+ Expr *Upper =
+ UBNonRect ? UBExpr : tryBuildCapture(SemaRef, UBExpr, Captures).get();
+ if (!Upper || !Lower)
+ return std::make_pair(nullptr, nullptr);
+
+ if (TestIsLessOp.getValue())
+ MinExpr = Lower;
+ else
+ MaxExpr = Upper;
+
+ // Build minimum/maximum value based on number of iterations.
+ ExprResult Diff;
+ QualType VarType = LCDecl->getType().getNonReferenceType();
+
+ Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Lower);
+ if (!Diff.isUsable())
+ return std::make_pair(nullptr, nullptr);
+
+ // Upper - Lower [- 1]
+ if (TestIsStrictOp)
+ Diff = SemaRef.BuildBinOp(
+ S, DefaultLoc, BO_Sub, Diff.get(),
+ SemaRef.ActOnIntegerConstant(SourceLocation(), 1).get());
+ if (!Diff.isUsable())
+ return std::make_pair(nullptr, nullptr);
+
+ // Upper - Lower [- 1] + Step
+ ExprResult NewStep = tryBuildCapture(SemaRef, Step, Captures);
+ if (!NewStep.isUsable())
+ return std::make_pair(nullptr, nullptr);
+
+ // Parentheses (for dumping/debugging purposes only).
+ Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
+ if (!Diff.isUsable())
+ return std::make_pair(nullptr, nullptr);
+
+ // (Upper - Lower [- 1]) / Step
+ Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Div, Diff.get(), NewStep.get());
+ if (!Diff.isUsable())
+ return std::make_pair(nullptr, nullptr);
+
+ // ((Upper - Lower [- 1]) / Step) * Step
+ // Parentheses (for dumping/debugging purposes only).
+ Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
+ if (!Diff.isUsable())
+ return std::make_pair(nullptr, nullptr);
+
+ Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Mul, Diff.get(), NewStep.get());
+ if (!Diff.isUsable())
+ return std::make_pair(nullptr, nullptr);
+
+ // Convert to the original type or ptrdiff_t, if original type is pointer.
+ if (!VarType->isAnyPointerType() &&
+ !SemaRef.Context.hasSameType(Diff.get()->getType(), VarType)) {
+ Diff = SemaRef.PerformImplicitConversion(
+ Diff.get(), VarType, Sema::AA_Converting, /*AllowExplicit=*/true);
+ } else if (VarType->isAnyPointerType() &&
+ !SemaRef.Context.hasSameType(
+ Diff.get()->getType(),
+ SemaRef.Context.getUnsignedPointerDiffType())) {
+ Diff = SemaRef.PerformImplicitConversion(
+ Diff.get(), SemaRef.Context.getUnsignedPointerDiffType(),
+ Sema::AA_Converting, /*AllowExplicit=*/true);
+ }
+ if (!Diff.isUsable())
+ return std::make_pair(nullptr, nullptr);
+
+ // Parentheses (for dumping/debugging purposes only).
+ Diff = SemaRef.ActOnParenExpr(DefaultLoc, DefaultLoc, Diff.get());
+ if (!Diff.isUsable())
+ return std::make_pair(nullptr, nullptr);
+
+ if (TestIsLessOp.getValue()) {
+ // MinExpr = Lower;
+ // MaxExpr = Lower + (((Upper - Lower [- 1]) / Step) * Step)
+ Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Add, Lower, Diff.get());
+ if (!Diff.isUsable())
+ return std::make_pair(nullptr, nullptr);
+ Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue*/ false);
+ if (!Diff.isUsable())
+ return std::make_pair(nullptr, nullptr);
+ MaxExpr = Diff.get();
+ } else {
+ // MaxExpr = Upper;
+ // MinExpr = Upper - (((Upper - Lower [- 1]) / Step) * Step)
+ Diff = SemaRef.BuildBinOp(S, DefaultLoc, BO_Sub, Upper, Diff.get());
+ if (!Diff.isUsable())
+ return std::make_pair(nullptr, nullptr);
+ Diff = SemaRef.ActOnFinishFullExpr(Diff.get(), /*DiscardedValue*/ false);
+ if (!Diff.isUsable())
+ return std::make_pair(nullptr, nullptr);
+ MinExpr = Diff.get();
+ }
+
+ return std::make_pair(MinExpr, MaxExpr);
+}
+
+Expr *OpenMPIterationSpaceChecker::buildFinalCondition(Scope *S) const {
+ if (InitDependOnLC || CondDependOnLC)
+ return Condition;
+ return nullptr;
+}
+
Expr *OpenMPIterationSpaceChecker::buildPreCond(
Scope *S, Expr *Cond,
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) const {
@@ -5453,8 +5801,10 @@ Expr *OpenMPIterationSpaceChecker::build
bool Suppress = SemaRef.getDiagnostics().getSuppressAllDiagnostics();
SemaRef.getDiagnostics().setSuppressAllDiagnostics(/*Val=*/true);
- ExprResult NewLB = tryBuildCapture(SemaRef, LB, Captures);
- ExprResult NewUB = tryBuildCapture(SemaRef, UB, Captures);
+ ExprResult NewLB =
+ InitDependOnLC ? LB : tryBuildCapture(SemaRef, LB, Captures);
+ ExprResult NewUB =
+ CondDependOnLC ? UB : tryBuildCapture(SemaRef, UB, Captures);
if (!NewLB.isUsable() || !NewUB.isUsable())
return nullptr;
@@ -5576,36 +5926,6 @@ Expr *OpenMPIterationSpaceChecker::build
return Diff.get();
}
-
-/// Iteration space of a single for loop.
-struct LoopIterationSpace final {
- /// True if the condition operator is the strict compare operator (<, > or
- /// !=).
- bool IsStrictCompare = false;
- /// Condition of the loop.
- Expr *PreCond = nullptr;
- /// This expression calculates the number of iterations in the loop.
- /// It is always possible to calculate it before starting the loop.
- Expr *NumIterations = nullptr;
- /// The loop counter variable.
- Expr *CounterVar = nullptr;
- /// Private loop counter variable.
- Expr *PrivateCounterVar = nullptr;
- /// This is initializer for the initial value of #CounterVar.
- Expr *CounterInit = nullptr;
- /// This is step for the #CounterVar used to generate its update:
- /// #CounterVar = #CounterInit + #CounterStep * CurrentIteration.
- Expr *CounterStep = nullptr;
- /// Should step be subtracted?
- bool Subtract = false;
- /// Source range of the loop init.
- SourceRange InitSrcRange;
- /// Source range of the loop condition.
- SourceRange CondSrcRange;
- /// Source range of the loop increment.
- SourceRange IncSrcRange;
-};
-
} // namespace
void Sema::ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init) {
@@ -5696,7 +6016,7 @@ static bool checkOpenMPIterationSpace(
unsigned TotalNestedLoopCount, Expr *CollapseLoopCountExpr,
Expr *OrderedLoopCountExpr,
Sema::VarsWithInheritedDSAType &VarsWithImplicitDSA,
- LoopIterationSpace &ResultIterSpace,
+ llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
// OpenMP [2.6, Canonical Loop Form]
// for (init-expr; test-expr; incr-expr) structured-block
@@ -5774,37 +6094,57 @@ static bool checkOpenMPIterationSpace(
return HasErrors;
// Build the loop's iteration space representation.
- ResultIterSpace.PreCond =
+ ResultIterSpaces[CurrentNestedLoopCount].PreCond =
ISC.buildPreCond(DSA.getCurScope(), For->getCond(), Captures);
- ResultIterSpace.NumIterations = ISC.buildNumIterations(
- DSA.getCurScope(),
- (isOpenMPWorksharingDirective(DKind) ||
- isOpenMPTaskLoopDirective(DKind) || isOpenMPDistributeDirective(DKind)),
- Captures);
- ResultIterSpace.CounterVar = ISC.buildCounterVar(Captures, DSA);
- ResultIterSpace.PrivateCounterVar = ISC.buildPrivateCounterVar();
- ResultIterSpace.CounterInit = ISC.buildCounterInit();
- ResultIterSpace.CounterStep = ISC.buildCounterStep();
- ResultIterSpace.InitSrcRange = ISC.getInitSrcRange();
- ResultIterSpace.CondSrcRange = ISC.getConditionSrcRange();
- ResultIterSpace.IncSrcRange = ISC.getIncrementSrcRange();
- ResultIterSpace.Subtract = ISC.shouldSubtractStep();
- ResultIterSpace.IsStrictCompare = ISC.isStrictTestOp();
-
- HasErrors |= (ResultIterSpace.PreCond == nullptr ||
- ResultIterSpace.NumIterations == nullptr ||
- ResultIterSpace.CounterVar == nullptr ||
- ResultIterSpace.PrivateCounterVar == nullptr ||
- ResultIterSpace.CounterInit == nullptr ||
- ResultIterSpace.CounterStep == nullptr);
+ ResultIterSpaces[CurrentNestedLoopCount].NumIterations =
+ ISC.buildNumIterations(DSA.getCurScope(), ResultIterSpaces,
+ (isOpenMPWorksharingDirective(DKind) ||
+ isOpenMPTaskLoopDirective(DKind) ||
+ isOpenMPDistributeDirective(DKind)),
+ Captures);
+ ResultIterSpaces[CurrentNestedLoopCount].CounterVar =
+ ISC.buildCounterVar(Captures, DSA);
+ ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar =
+ ISC.buildPrivateCounterVar();
+ ResultIterSpaces[CurrentNestedLoopCount].CounterInit = ISC.buildCounterInit();
+ ResultIterSpaces[CurrentNestedLoopCount].CounterStep = ISC.buildCounterStep();
+ ResultIterSpaces[CurrentNestedLoopCount].InitSrcRange = ISC.getInitSrcRange();
+ ResultIterSpaces[CurrentNestedLoopCount].CondSrcRange =
+ ISC.getConditionSrcRange();
+ ResultIterSpaces[CurrentNestedLoopCount].IncSrcRange =
+ ISC.getIncrementSrcRange();
+ ResultIterSpaces[CurrentNestedLoopCount].Subtract = ISC.shouldSubtractStep();
+ ResultIterSpaces[CurrentNestedLoopCount].IsStrictCompare =
+ ISC.isStrictTestOp();
+ std::tie(ResultIterSpaces[CurrentNestedLoopCount].MinValue,
+ ResultIterSpaces[CurrentNestedLoopCount].MaxValue) =
+ ISC.buildMinMaxValues(DSA.getCurScope(), Captures);
+ ResultIterSpaces[CurrentNestedLoopCount].FinalCondition =
+ ISC.buildFinalCondition(DSA.getCurScope());
+ ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularLB =
+ ISC.doesInitDependOnLC();
+ ResultIterSpaces[CurrentNestedLoopCount].IsNonRectangularUB =
+ ISC.doesCondDependOnLC();
+ ResultIterSpaces[CurrentNestedLoopCount].LoopDependentIdx =
+ ISC.getLoopDependentIdx();
+
+ HasErrors |=
+ (ResultIterSpaces[CurrentNestedLoopCount].PreCond == nullptr ||
+ ResultIterSpaces[CurrentNestedLoopCount].NumIterations == nullptr ||
+ ResultIterSpaces[CurrentNestedLoopCount].CounterVar == nullptr ||
+ ResultIterSpaces[CurrentNestedLoopCount].PrivateCounterVar == nullptr ||
+ ResultIterSpaces[CurrentNestedLoopCount].CounterInit == nullptr ||
+ ResultIterSpaces[CurrentNestedLoopCount].CounterStep == nullptr);
if (!HasErrors && DSA.isOrderedRegion()) {
if (DSA.getOrderedRegionParam().second->getNumForLoops()) {
if (CurrentNestedLoopCount <
DSA.getOrderedRegionParam().second->getLoopNumIterations().size()) {
DSA.getOrderedRegionParam().second->setLoopNumIterations(
- CurrentNestedLoopCount, ResultIterSpace.NumIterations);
+ CurrentNestedLoopCount,
+ ResultIterSpaces[CurrentNestedLoopCount].NumIterations);
DSA.getOrderedRegionParam().second->setLoopCounter(
- CurrentNestedLoopCount, ResultIterSpace.CounterVar);
+ CurrentNestedLoopCount,
+ ResultIterSpaces[CurrentNestedLoopCount].CounterVar);
}
}
for (auto &Pair : DSA.getDoacrossDependClauses()) {
@@ -5821,11 +6161,13 @@ static bool checkOpenMPIterationSpace(
Expr *CntValue;
if (Pair.first->getDependencyKind() == OMPC_DEPEND_source)
CntValue = ISC.buildOrderedLoopData(
- DSA.getCurScope(), ResultIterSpace.CounterVar, Captures,
+ DSA.getCurScope(),
+ ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
Pair.first->getDependencyLoc());
else
CntValue = ISC.buildOrderedLoopData(
- DSA.getCurScope(), ResultIterSpace.CounterVar, Captures,
+ DSA.getCurScope(),
+ ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
Pair.first->getDependencyLoc(),
Pair.second[CurrentNestedLoopCount].first,
Pair.second[CurrentNestedLoopCount].second);
@@ -5839,10 +6181,12 @@ static bool checkOpenMPIterationSpace(
/// Build 'VarRef = Start.
static ExprResult
buildCounterInit(Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
- ExprResult Start,
+ ExprResult Start, bool IsNonRectangularLB,
llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
// Build 'VarRef = Start.
- ExprResult NewStart = tryBuildCapture(SemaRef, Start.get(), Captures);
+ ExprResult NewStart = IsNonRectangularLB
+ ? Start.get()
+ : tryBuildCapture(SemaRef, Start.get(), Captures);
if (!NewStart.isUsable())
return ExprError();
if (!SemaRef.Context.hasSameType(NewStart.get()->getType(),
@@ -5863,6 +6207,7 @@ buildCounterInit(Sema &SemaRef, Scope *S
static ExprResult buildCounterUpdate(
Sema &SemaRef, Scope *S, SourceLocation Loc, ExprResult VarRef,
ExprResult Start, ExprResult Iter, ExprResult Step, bool Subtract,
+ bool IsNonRectangularLB,
llvm::MapVector<const Expr *, DeclRefExpr *> *Captures = nullptr) {
// Add parentheses (for debugging purposes only).
Iter = SemaRef.ActOnParenExpr(Loc, Loc, Iter.get());
@@ -5882,8 +6227,12 @@ static ExprResult buildCounterUpdate(
// Try to build 'VarRef = Start, VarRef (+|-)= Iter * Step' or
// 'VarRef = Start (+|-) Iter * Step'.
- ExprResult NewStart = Start;
- if (Captures)
+ if (!Start.isUsable())
+ return ExprError();
+ ExprResult NewStart = SemaRef.ActOnParenExpr(Loc, Loc, Start.get());
+ if (!NewStart.isUsable())
+ return ExprError();
+ if (Captures && !IsNonRectangularLB)
NewStart = tryBuildCapture(SemaRef, Start.get(), *Captures);
if (NewStart.isInvalid())
return ExprError();
@@ -6054,8 +6403,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
if (checkOpenMPIterationSpace(
DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr,
- OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt],
- Captures))
+ OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces, Captures))
return 0;
// Move on to the next nested for loop, or to the loop body.
// OpenMP [2.8.1, simd construct, Restrictions]
@@ -6068,8 +6416,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
if (checkOpenMPIterationSpace(
DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
std::max(OrderedLoopCount, NestedLoopCount), CollapseLoopCountExpr,
- OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces[Cnt],
- Captures))
+ OrderedLoopCountExpr, VarsWithImplicitDSA, IterSpaces, Captures))
return 0;
if (Cnt > 0 && IterSpaces[Cnt].CounterVar) {
// Handle initialization of captured loop iterator variables.
@@ -6530,6 +6877,9 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
Built.Inits.resize(NestedLoopCount);
Built.Updates.resize(NestedLoopCount);
Built.Finals.resize(NestedLoopCount);
+ Built.DependentCounters.resize(NestedLoopCount);
+ Built.DependentInits.resize(NestedLoopCount);
+ Built.FinalsConditions.resize(NestedLoopCount);
{
// We implement the following algorithm for obtaining the
// original loop iteration variable values based on the
@@ -6589,24 +6939,26 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
DeclRefExpr *CounterVar = buildDeclRefExpr(
SemaRef, VD, IS.CounterVar->getType(), IS.CounterVar->getExprLoc(),
/*RefersToCapture=*/true);
- ExprResult Init = buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
- IS.CounterInit, Captures);
+ ExprResult Init =
+ buildCounterInit(SemaRef, CurScope, UpdLoc, CounterVar,
+ IS.CounterInit, IS.IsNonRectangularLB, Captures);
if (!Init.isUsable()) {
HasErrors = true;
break;
}
ExprResult Update = buildCounterUpdate(
SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit, Iter,
- IS.CounterStep, IS.Subtract, &Captures);
+ IS.CounterStep, IS.Subtract, IS.IsNonRectangularLB, &Captures);
if (!Update.isUsable()) {
HasErrors = true;
break;
}
// Build final: IS.CounterVar = IS.Start + IS.NumIters * IS.Step
- ExprResult Final = buildCounterUpdate(
- SemaRef, CurScope, UpdLoc, CounterVar, IS.CounterInit,
- IS.NumIterations, IS.CounterStep, IS.Subtract, &Captures);
+ ExprResult Final =
+ buildCounterUpdate(SemaRef, CurScope, UpdLoc, CounterVar,
+ IS.CounterInit, IS.NumIterations, IS.CounterStep,
+ IS.Subtract, IS.IsNonRectangularLB, &Captures);
if (!Final.isUsable()) {
HasErrors = true;
break;
@@ -6622,6 +6974,16 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
Built.Inits[Cnt] = Init.get();
Built.Updates[Cnt] = Update.get();
Built.Finals[Cnt] = Final.get();
+ Built.DependentCounters[Cnt] = nullptr;
+ Built.DependentInits[Cnt] = nullptr;
+ Built.FinalsConditions[Cnt] = nullptr;
+ if (IS.IsNonRectangularLB) {
+ Built.DependentCounters[Cnt] =
+ Built.Counters[NestedLoopCount - 1 - IS.LoopDependentIdx];
+ Built.DependentInits[Cnt] =
+ Built.Inits[NestedLoopCount - 1 - IS.LoopDependentIdx];
+ Built.FinalsConditions[Cnt] = IS.FinalCondition;
+ }
}
}
@@ -6634,7 +6996,7 @@ checkOpenMPLoop(OpenMPDirectiveKind DKin
Built.NumIterations = NumIterations.get();
Built.CalcLastIteration = SemaRef
.ActOnFinishFullExpr(CalcLastIteration.get(),
- /*DiscardedValue*/ false)
+ /*DiscardedValue=*/false)
.get();
Built.PreCond = PreCond.get();
Built.PreInits = buildPreInits(C, Captures);
@@ -12778,9 +13140,9 @@ static bool FinishOpenMPLinearClause(OMP
// Build update: Var = InitExpr + IV * Step
ExprResult Update;
if (!Info.first)
- Update =
- buildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), *CurPrivate,
- InitExpr, IV, Step, /* Subtract */ false);
+ Update = buildCounterUpdate(
+ SemaRef, S, RefExpr->getExprLoc(), *CurPrivate, InitExpr, IV, Step,
+ /*Subtract=*/false, /*IsNonRectangularLB=*/false);
else
Update = *CurPrivate;
Update = SemaRef.ActOnFinishFullExpr(Update.get(), DE->getBeginLoc(),
@@ -12791,7 +13153,8 @@ static bool FinishOpenMPLinearClause(OMP
if (!Info.first)
Final =
buildCounterUpdate(SemaRef, S, RefExpr->getExprLoc(), CapturedRef,
- InitExpr, NumIterations, Step, /*Subtract=*/false);
+ InitExpr, NumIterations, Step, /*Subtract=*/false,
+ /*IsNonRectangularLB=*/false);
else
Final = *CurPrivate;
Final = SemaRef.ActOnFinishFullExpr(Final.get(), DE->getBeginLoc(),
Modified: cfe/trunk/lib/Serialization/ASTReaderStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderStmt.cpp?rev=368903&r1=368902&r2=368903&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderStmt.cpp Wed Aug 14 12:30:06 2019
@@ -2060,6 +2060,18 @@ void ASTStmtReader::VisitOMPLoopDirectiv
for (unsigned i = 0; i < CollapsedNum; ++i)
Sub.push_back(Record.readSubExpr());
D->setFinals(Sub);
+ Sub.clear();
+ for (unsigned i = 0; i < CollapsedNum; ++i)
+ Sub.push_back(Record.readSubExpr());
+ D->setDependentCounters(Sub);
+ Sub.clear();
+ for (unsigned i = 0; i < CollapsedNum; ++i)
+ Sub.push_back(Record.readSubExpr());
+ D->setDependentInits(Sub);
+ Sub.clear();
+ for (unsigned i = 0; i < CollapsedNum; ++i)
+ Sub.push_back(Record.readSubExpr());
+ D->setFinalsConditions(Sub);
}
void ASTStmtReader::VisitOMPParallelDirective(OMPParallelDirective *D) {
Modified: cfe/trunk/lib/Serialization/ASTWriterStmt.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterStmt.cpp?rev=368903&r1=368902&r2=368903&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterStmt.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterStmt.cpp Wed Aug 14 12:30:06 2019
@@ -1995,6 +1995,12 @@ void ASTStmtWriter::VisitOMPLoopDirectiv
for (auto I : D->finals()) {
Record.AddStmt(I);
}
+ for (Stmt *S : D->dependent_counters())
+ Record.AddStmt(S);
+ for (Stmt *S : D->dependent_inits())
+ Record.AddStmt(S);
+ for (Stmt *S : D->finals_conditions())
+ Record.AddStmt(S);
}
void ASTStmtWriter::VisitOMPParallelDirective(OMPParallelDirective *D) {
Modified: cfe/trunk/test/OpenMP/for_codegen.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_codegen.cpp?rev=368903&r1=368902&r2=368903&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_codegen.cpp (original)
+++ cfe/trunk/test/OpenMP/for_codegen.cpp Wed Aug 14 12:30:06 2019
@@ -25,10 +25,176 @@
// CHECK-LABEL: loop_with_counter_collapse
void loop_with_counter_collapse() {
- // LIFETIME: call void @llvm.lifetime.end
- // LIFETIME: call void @llvm.lifetime.end
- // CHECK: call void @__kmpc_for_static_init_8(%struct.ident_t* @
- // CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* @
+ // Captured initializations.
+ // CHECK: store i32 0, i32* [[I_TMP:%.+]],
+ // CHECK: [[VAL:%.+]] = load i32, i32* [[I_TMP]],
+ // CHECK: store i32 [[VAL]], i32* [[J_LB_MIN:%.+]],
+ // CHECK: store i32 3, i32* [[I_TMP]],
+ // CHECK: [[VAL:%.+]] = load i32, i32* [[I_TMP]],
+ // CHECK: store i32 [[VAL]], i32* [[J_LB_MAX:%.+]],
+ // CHECK: [[J_LB_MIN_VAL:%.+]] = load i32, i32* [[J_LB_MIN]],
+ // CHECK: [[J_LB_MAX_VAL:%.+]] = load i32, i32* [[J_LB_MAX]],
+ // CHECK: [[CMP:%.+]] = icmp slt i32 [[J_LB_MIN_VAL]], [[J_LB_MAX_VAL]]
+ // CHECK: [[BOOL:%.+]] = zext i1 [[CMP]] to i8
+ // CHECK: store i8 [[BOOL]], i8* [[J_LB_CMP:%.+]],
+ // CHECK: store i32 0, i32* [[I_TMP]],
+ // CHECK: [[VAL:%.+]] = load i32, i32* [[I_TMP]],
+ // CHECK: [[J_UB_MIN_VAL:%.+]] = add nsw i32 4, [[VAL]]
+ // CHECK: store i32 [[J_UB_MIN_VAL]], i32* [[J_UB_MIN:%.+]],
+ // CHECK: store i32 3, i32* [[I_TMP]],
+ // CHECK: [[VAL:%.+]] = load i32, i32* [[I_TMP]],
+ // CHECK: [[J_UB_MAX_VAL:%.+]] = add nsw i32 4, [[VAL]]
+ // CHECK: store i32 [[J_UB_MAX_VAL]], i32* [[J_UB_MAX:%.+]],
+ // CHECK: [[J_UB_MIN_VAL:%.+]] = load i32, i32* [[J_UB_MIN]],
+ // CHECK: [[J_UB_MAX_VAL:%.+]] = load i32, i32* [[J_UB_MAX]],
+ // CHECK: [[CMP:%.+]] = icmp sgt i32 [[J_UB_MIN_VAL]], [[J_UB_MAX_VAL]]
+ // CHECK: [[BOOL:%.+]] = zext i1 [[CMP]] to i8
+ // CHECK: store i8 [[BOOL]], i8* [[J_UB_CMP:%.+]],
+ // CHECK: [[J_UB_CMP_VAL:%.+]] = load i8, i8* [[J_UB_CMP]],
+ // CHECK: [[BOOL:%.+]] = trunc i8 [[J_UB_CMP_VAL]] to i1
+ // CHECK: br i1 [[BOOL]], label %[[TRUE:[^,]+]], label %[[FALSE:[^,]+]]
+ // CHECK: [[TRUE]]:
+ // CHECK: [[J_UB_MIN_VAL:%.+]] = load i32, i32* [[J_UB_MIN]],
+ // CHECK: br label %[[EXIT:[^,]+]]
+ // CHECK: [[FALSE]]:
+ // CHECK: [[J_UB_MAX_VAL:%.+]] = load i32, i32* [[J_UB_MAX]],
+ // CHECK: br label %[[EXIT]]
+ // CHECK: [[EXIT]]:
+ // CHECK: [[J_UB_VAL:%.+]] = phi i32 [ [[J_UB_MIN_VAL]], %[[TRUE]] ], [ [[J_UB_MAX_VAL]], %[[FALSE]] ]
+ // CHECK: store i32 [[J_UB_VAL]], i32* [[J_UB:%.+]],
+ // CHECK: [[J_LB_CMP_VAL:%.+]] = load i8, i8* [[J_LB_CMP]],
+ // CHECK: [[BOOL:%.+]] = trunc i8 [[J_LB_CMP_VAL]] to i1
+ // CHECK: br i1 [[BOOL]], label %[[TRUE:[^,]+]], label %[[FALSE:[^,]+]]
+ // CHECK: [[TRUE]]:
+ // CHECK: [[J_LB_MIN_VAL:%.+]] = load i32, i32* [[J_LB_MIN]],
+ // CHECK: br label %[[EXIT:[^,]+]]
+ // CHECK: [[FALSE]]:
+ // CHECK: [[J_LB_MAX_VAL:%.+]] = load i32, i32* [[J_LB_MAX]],
+ // CHECK: br label %[[EXIT]]
+ // CHECK: [[EXIT]]:
+ // CHECK: [[J_LB_VAL:%.+]] = phi i32 [ [[J_LB_MIN_VAL]], %[[TRUE]] ], [ [[J_LB_MAX_VAL]], %[[FALSE]] ]
+ // CHECK: store i32 [[J_LB_VAL]], i32* [[J_LB:%.+]],
+ // CHECK: [[J_UB_VAL:%.+]] = load i32, i32* [[J_UB]],
+ // CHECK: [[J_LB_VAL:%.+]] = load i32, i32* [[J_LB]],
+ // CHECK: [[SUB:%.+]] = sub nsw i32 [[J_UB_VAL]], [[J_LB_VAL]]
+ // CHECK: [[SUB_ST:%.+]] = sub nsw i32 [[SUB]], 1
+ // CHECK: [[ADD_ST:%.+]] = add nsw i32 [[SUB_ST]], 1
+ // CHECK: [[DIV_ST:%.+]] = sdiv i32 [[ADD_ST]], 1
+ // CHECK: [[CAST:%.+]] = sext i32 [[DIV_ST]] to i64
+ // CHECK: [[MUL:%.+]] = mul nsw i64 4, [[CAST]]
+ // CHECK: [[NUM_ITERS_VAL:%.+]] = sub nsw i64 [[MUL]], 1
+ // CHECK: store i64 [[NUM_ITERS_VAL]], i64* [[NUM_ITERS:%.+]],
+
+ // Initialization
+ // CHECK: store i32 0, i32* [[I:%.+]],
+ // CHECK: [[I_INIT:%.+]] = load i32, i32* [[I]],
+ // CHECK: store i32 [[I_INIT]], i32* [[J:%.+]],
+
+ // LIFETIME: call void @llvm.lifetime.end
+ // LIFETIME: call void @llvm.lifetime.end
+
+ // Precondition for j counter
+ // CHECK: store i32 0, i32* [[TMP_I:%.+]],
+ // CHECK: [[J_LB_VAL:%.+]] = load i32, i32* [[TMP_I]],
+ // CHECK: [[I_VAL:%.+]] = load i32, i32* [[TMP_I]],
+ // CHECK: [[J_UB_VAL:%.+]] = add nsw i32 4, [[I_VAL]]
+ // CHECK: [[CMP:%.+]] = icmp slt i32 [[J_LB_VAL]], [[J_UB_VAL]]
+ // CHECK: br i1 [[CMP]], label %[[THEN:[^,]+]], label %[[ELSE:[^,]+]]
+
+ // CHECK: [[THEN]]:
+ // CHECK: store i64 0, i64* [[LB:%.+]],
+ // CHECK: [[NUM_ITERS_VAL:%.+]] = load i64, i64* [[NUM_ITERS]],
+ // CHECK: store i64 [[NUM_ITERS_VAL]], i64* [[UB:%.+]],
+ // CHECK: store i64 1, i64* [[STRIDE:%.+]],
+ // CHECK: store i32 0, i32* [[IS_LAST:%.+]],
+ // CHECK: call void @__kmpc_for_static_init_8(%struct.ident_t* @{{.+}}, i32 %{{.+}}, i32 34, i32* [[IS_LAST]], i64* [[LB]], i64* [[UB]], i64* [[STRIDE]], i64 1, i64 1)
+ // CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
+ // CHECK: [[NUM_ITERS_VAL:%.+]] = load i64, i64* [[NUM_ITERS]],
+ // CHECK: [[CMP:%.+]] = icmp sgt i64 [[UB_VAL]], [[NUM_ITERS_VAL]]
+ // CHECK: br i1 [[CMP]], label %[[TRUE:[^,]+]], label %[[FALSE:[^,]+]]
+ // CHECK: [[TRUE]]:
+ // CHECK: [[NUM_ITERS_VAL:%.+]] = load i64, i64* [[NUM_ITERS]],
+ // CHECK: br label %[[DONE:[^,]+]]
+ // CHECK: [[FALSE]]:
+ // CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
+ // CHECK: br label %[[DONE]]
+ // CHECK: [[DONE]]:
+ // CHECK: [[TOP:%.+]] = phi i64 [ [[NUM_ITERS_VAL]], %[[TRUE]] ], [ [[UB_VAL]], %[[FALSE]] ]
+ // CHECK: store i64 [[TOP]], i64* [[UB]],
+ // CHECK: [[LB_VAL:%.+]] = load i64, i64* [[LB]],
+ // CHECK: store i64 [[LB_VAL]], i64* [[IV:%.+]],
+ // CHECK: br label %[[COND:[^,]+]]
+ // CHECK: [[COND]]:
+ // CHECK: [[IV_VAL:%.+]] = load i64, i64* [[IV]],
+ // CHECK: [[UB_VAL:%.+]] = load i64, i64* [[UB]],
+ // CHECK: [[CMP:%.+]] = icmp sle i64 [[IV_VAL]], [[UB_VAL]]
+ // CHECK: br i1 [[CMP]], label %[[BODY:[^,]+]], label %[[CLEANUP:[^,]+]]
+ // LIFETIME: [[CLEANUP]]:
+ // LIFETIME: br label %[[CLEANUP:[^,]+]]
+ // CHECK: [[BODY]]:
+ // CHECK: [[IV_VAL:%.+]] = load i64, i64* [[IV]],
+ // CHECK: [[J_UB_VAL:%.+]] = load i32, i32* [[J_UB]],
+ // CHECK: [[J_LB_VAL:%.+]] = load i32, i32* [[J_LB]],
+ // CHECK: [[SUB:%.+]] = sub nsw i32 [[J_UB_VAL]], [[J_LB_VAL]]
+ // CHECK: [[SUB_ST:%.+]] = sub nsw i32 [[SUB]], 1
+ // CHECK: [[ADD_ST:%.+]] = add nsw i32 [[SUB_ST]], 1
+ // CHECK: [[DIV_ST:%.+]] = sdiv i32 [[ADD_ST]], 1
+ // CHECK: [[MUL:%.+]] = mul nsw i32 1, [[DIV_ST]]
+ // CHECK: [[CAST:%.+]] = sext i32 [[MUL]] to i64
+ // CHECK: [[DIV:%.+]] = sdiv i64 [[IV_VAL]], [[CAST]]
+ // CHECK: [[MUL:%.+]] = mul nsw i64 [[DIV]], 1
+ // CHECK: [[ADD:%.+]] = add nsw i64 0, [[MUL]]
+ // CHECK: [[CAST:%.+]] = trunc i64 [[ADD]] to i32
+ // CHECK: store i32 [[CAST]], i32* [[I_PRIV:%.+]],
+ // CHECK: [[I_VAL:%.+]] = load i32, i32* [[I_PRIV]],
+ // CHECK: [[CONV:%.+]] = sext i32 [[I_VAL]] to i64
+ // CHECK: [[IV_VAL:%.+]] = load i64, i64* [[IV]],
+ // CHECK: [[IV_VAL1:%.+]] = load i64, i64* [[IV]],
+ // CHECK: [[J_UB_VAL:%.+]] = load i32, i32* [[J_UB]],
+ // CHECK: [[J_LB_VAL:%.+]] = load i32, i32* [[J_LB]],
+ // CHECK: [[SUB:%.+]] = sub nsw i32 [[J_UB_VAL]], [[J_LB_VAL]]
+ // CHECK: [[SUB_ST:%.+]] = sub nsw i32 [[SUB]], 1
+ // CHECK: [[ADD_ST:%.+]] = add nsw i32 [[SUB_ST]], 1
+ // CHECK: [[DIV_ST:%.+]] = sdiv i32 [[ADD_ST]], 1
+ // CHECK: [[MUL:%.+]] = mul nsw i32 1, [[DIV_ST]]
+ // CHECK: [[CAST:%.+]] = sext i32 [[MUL]] to i64
+ // CHECK: [[DIV:%.+]] = sdiv i64 [[IV_VAL1]], [[CAST]]
+ // CHECK: [[J_UB_VAL:%.+]] = load i32, i32* [[J_UB]],
+ // CHECK: [[J_LB_VAL:%.+]] = load i32, i32* [[J_LB]],
+ // CHECK: [[SUB:%.+]] = sub nsw i32 [[J_UB_VAL]], [[J_LB_VAL]]
+ // CHECK: [[SUB_ST:%.+]] = sub nsw i32 [[SUB]], 1
+ // CHECK: [[ADD_ST:%.+]] = add nsw i32 [[SUB_ST]], 1
+ // CHECK: [[DIV_ST:%.+]] = sdiv i32 [[ADD_ST]], 1
+ // CHECK: [[MUL:%.+]] = mul nsw i32 1, [[DIV_ST]]
+ // CHECK: [[CAST:%.+]] = sext i32 [[MUL]] to i64
+ // CHECK: [[MUL:%.+]] = mul nsw i64 [[DIV]], [[CAST]]
+ // CHECK: [[SUB:%.+]] = sub nsw i64 [[IV_VAL]], [[MUL]]
+ // CHECK: [[MUL:%.+]] = mul nsw i64 [[SUB:%.+]], 1
+ // CHECK: [[ADD:%.+]] = add nsw i64 [[CONV]], [[MUL]]
+ // CHECK: [[CAST:%.+]] = trunc i64 [[ADD]] to i32
+ // CHECK: store i32 [[CAST]], i32* [[J_PRIV:%.+]],
+
+ // Check that the loop variable is not out of its boundaries.
+ // CHECK: [[J_VAL:%.+]] = load i32, i32* [[J_PRIV]],
+ // CHECK: [[I_VAL:%.+]] = load i32, i32* [[I_PRIV]],
+ // CHECK: [[J_COND:%.+]] = add nsw i32 4, [[I_VAL]]
+ // CHECK: [[CMP:%.+]] = icmp slt i32 [[J_VAL]], [[J_COND]]
+ // CHECK: br i1 [[CMP]], label %[[NEXT:[^,]+]], label %[[BODY_CONT:[^,]+]]
+ // CHECK: [[NEXT]]:
+
+ // Main body is empty.
+ // CHECK: br label %[[BODY_CONT]]
+ // CHECK: [[BODY_CONT]]:
+ // CHECK: br label %[[INC:[^,]+]]
+ // CHECK: [[INC]]:
+ // CHECK: [[IV_VAL:%.+]] = load i64, i64* [[IV]],
+ // CHECK: [[ADD:%.+]] = add nsw i64 [[IV_VAL]], 1
+ // CHECK: store i64 [[ADD]], i64* [[IV]],
+ // CHECK: br label %[[COND]]
+ // CHECK: [[CLEANUP]]:
+ // CHECK: br label %[[EXIT:[^,]+]]
+ // CHECK: [[EXIT]]:
+ // CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* @{{.+}}, i32 %{{.+}})
// LIFETIME: call void @llvm.lifetime.end
// LIFETIME: call void @llvm.lifetime.end
// LIFETIME: call void @llvm.lifetime.end
@@ -40,7 +206,7 @@ void loop_with_counter_collapse() {
// LIFETIME: call void @llvm.lifetime.end
#pragma omp for collapse(2)
for (int i = 0; i < 4; i++) {
- for (int j = i; j < 4; j++) {
+ for (int j = i; j < 4 + i; j++) {
}
}
}
@@ -449,13 +615,14 @@ void for_with_references() {
// CHECK: [[I:%.+]] = alloca i8,
// CHECK: [[CNT:%.+]] = alloca i8*,
// CHECK: [[CNT_PRIV:%.+]] = alloca i8,
-// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void @__kmpc_for_static_init_8(
// CHECK-NOT: load i8, i8* [[CNT]],
// CHECK: call void @__kmpc_for_static_fini(
char i = 0;
char &cnt = i;
-#pragma omp for
+#pragma omp for collapse(2)
for (cnt = 0; cnt < 2; ++cnt)
+ for (int j = cnt; j < 4 + cnt; j++)
k = cnt;
}
@@ -528,13 +695,14 @@ void loop_with_It_plus(It<char> begin, I
// CHECK: call void @__kmpc_for_static_fini(
void loop_with_stmt_expr() {
-#pragma omp for
+#pragma omp for collapse(2)
for (int i = __extension__({float b = 0;b; }); i < __extension__({double c = 1;c; }); i += __extension__({char d = 1; d; }))
+ for (int j = i; j < 4 + i; j++)
;
}
// CHECK-LABEL: loop_with_stmt_expr
// CHECK: call i32 @__kmpc_global_thread_num(
-// CHECK: call void @__kmpc_for_static_init_4(
+// CHECK: call void @__kmpc_for_static_init_8(
// CHECK: call void @__kmpc_for_static_fini(
Modified: cfe/trunk/test/OpenMP/for_loop_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/for_loop_messages.cpp?rev=368903&r1=368902&r2=368903&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/for_loop_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/for_loop_messages.cpp Wed Aug 14 12:30:06 2019
@@ -651,10 +651,9 @@ public:
;
#pragma omp parallel
-// expected-error at +6 2 {{expected loop invariant expression or '<invariant1> * ii + <invariant2>' kind of expression}}
-// expected-error at +5 {{expected loop invariant expression or '<invariant1> * TC::ii + <invariant2>' kind of expression}}
// expected-error at +5 2 {{expected loop invariant expression or '<invariant1> * ii + <invariant2>' kind of expression}}
// expected-error at +4 {{expected loop invariant expression or '<invariant1> * TC::ii + <invariant2>' kind of expression}}
+// expected-error at +4 {{expected loop invariant expression or '<invariant1> * TC::ii + <invariant2>' kind of expression}}
#pragma omp for collapse(3)
for (ii = 10 + 25; ii < 1000; ii += 1)
for (iii = ii * 10 + 25; iii < ii / ii - 23; iii += 1)
Modified: cfe/trunk/test/OpenMP/parallel_messages.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/OpenMP/parallel_messages.cpp?rev=368903&r1=368902&r2=368903&view=diff
==============================================================================
--- cfe/trunk/test/OpenMP/parallel_messages.cpp (original)
+++ cfe/trunk/test/OpenMP/parallel_messages.cpp Wed Aug 14 12:30:06 2019
@@ -102,6 +102,6 @@ struct h {
h operator<(h, h);
void g::j() {
#pragma omp parallel for default(none) if(a::b)
- for (auto a = blocks.cbegin; a < blocks; ++a) // expected-error {{invalid operands to binary expression ('f' and 'int')}}
+ for (auto a = blocks.cbegin; a < blocks; ++a) // expected-error 2 {{invalid operands to binary expression ('f' and 'int')}}
;
}
More information about the cfe-commits
mailing list