forked from OSchip/llvm-project
[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. llvm-svn: 368903
This commit is contained in:
parent
c264992853
commit
f8be476f0c
|
@ -448,7 +448,8 @@ class OMPLoopDirective : public OMPExecutableDirective {
|
|||
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 OMPExecutableDirective {
|
|||
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 OMPExecutableDirective {
|
|||
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 ||
|
||||
|
|
|
@ -72,6 +72,25 @@ void OMPLoopDirective::setFinals(ArrayRef<Expr *> A) {
|
|||
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 ASTContext &C, SourceLocation StartLoc,
|
|||
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 &C, SourceLocation StartLoc,
|
|||
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 ASTContext &C, SourceLocation StartLoc,
|
|||
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 *OMPParallelForDirective::Create(
|
|||
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 *OMPParallelForSimdDirective::Create(
|
|||
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 *OMPTargetParallelForDirective::Create(
|
|||
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 *OMPTaskLoopDirective::Create(
|
|||
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 *OMPTaskLoopSimdDirective::Create(
|
|||
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 *OMPDistributeDirective::Create(
|
|||
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 *OMPDistributeParallelForDirective::Create(
|
|||
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::Create(
|
|||
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 *OMPDistributeSimdDirective::Create(
|
|||
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 *OMPTargetParallelForSimdDirective::Create(
|
|||
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 ASTContext &C, SourceLocation StartLoc,
|
|||
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 *OMPTeamsDistributeDirective::Create(
|
|||
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 *OMPTeamsDistributeSimdDirective::Create(
|
|||
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 @@ OMPTeamsDistributeParallelForSimdDirective::Create(
|
|||
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::Create(
|
|||
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 *OMPTargetTeamsDistributeDirective::Create(
|
|||
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 @@ OMPTargetTeamsDistributeParallelForDirective::Create(
|
|||
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 @@ OMPTargetTeamsDistributeParallelForSimdDirective::Create(
|
|||
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::Create(
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -1324,6 +1324,16 @@ void CodeGenFunction::EmitOMPLoopBody(const OMPLoopDirective &D,
|
|||
// 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, const OMPLoopDirective &S,
|
|||
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(
|
||||
|
|
|
@ -4709,6 +4709,54 @@ StmtResult Sema::ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
|
|||
}
|
||||
|
||||
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::checkAndSetCond(Expr *S) {
|
|||
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 *Capture,
|
|||
|
||||
/// 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::buildNumIterations(
|
|||
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::buildPreCond(
|
|||
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::buildOrderedLoopData(
|
|||
|
||||
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();
|
||||
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 |= (ResultIterSpace.PreCond == nullptr ||
|
||||
ResultIterSpace.NumIterations == nullptr ||
|
||||
ResultIterSpace.CounterVar == nullptr ||
|
||||
ResultIterSpace.PrivateCounterVar == nullptr ||
|
||||
ResultIterSpace.CounterInit == nullptr ||
|
||||
ResultIterSpace.CounterStep == nullptr);
|
||||
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, SourceLocation Loc, ExprResult VarRef,
|
|||
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 DKind, Expr *CollapseLoopCountExpr,
|
|||
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 DKind, Expr *CollapseLoopCountExpr,
|
|||
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 DKind, Expr *CollapseLoopCountExpr,
|
|||
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 DKind, Expr *CollapseLoopCountExpr,
|
|||
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 DKind, Expr *CollapseLoopCountExpr,
|
|||
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 DKind, Expr *CollapseLoopCountExpr,
|
|||
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(OMPLinearClause &Clause, DeclRefExpr *IV,
|
|||
// 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(OMPLinearClause &Clause, DeclRefExpr *IV,
|
|||
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(),
|
||||
|
|
|
@ -2060,6 +2060,18 @@ void ASTStmtReader::VisitOMPLoopDirective(OMPLoopDirective *D) {
|
|||
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) {
|
||||
|
|
|
@ -1995,6 +1995,12 @@ void ASTStmtWriter::VisitOMPLoopDirective(OMPLoopDirective *D) {
|
|||
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) {
|
||||
|
|
|
@ -25,10 +25,176 @@
|
|||
|
||||
// CHECK-LABEL: loop_with_counter_collapse
|
||||
void loop_with_counter_collapse() {
|
||||
// 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
|
||||
// CHECK: call void @__kmpc_for_static_init_8(%struct.ident_t* @
|
||||
// CHECK: call void @__kmpc_for_static_fini(%struct.ident_t* @
|
||||
|
||||
// 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, It<char> end) {
|
|||
// 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(
|
||||
|
||||
|
||||
|
|
|
@ -651,10 +651,9 @@ public:
|
|||
;
|
||||
|
||||
#pragma omp parallel
|
||||
// expected-error@+6 2 {{expected loop invariant expression or '<invariant1> * ii + <invariant2>' kind of expression}}
|
||||
// expected-error@+5 {{expected loop invariant expression or '<invariant1> * TC::ii + <invariant2>' kind of expression}}
|
||||
// expected-error@+5 2 {{expected loop invariant expression or '<invariant1> * ii + <invariant2>' kind of expression}}
|
||||
// expected-error@+4 {{expected loop invariant expression or '<invariant1> * TC::ii + <invariant2>' kind of expression}}
|
||||
// expected-error@+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)
|
||||
|
|
|
@ -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')}}
|
||||
;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue