Revert "[Clang][OpenMP] Implement Loop splitting #pragma omp split directive " (#190335)
Reverts llvm/llvm-project#183261 15 new lit tests failing in openmp
This commit is contained in:
parent
15ed4f6c49
commit
00aede8f19
@ -1453,9 +1453,6 @@ class CursorKind(BaseEnumeration):
|
||||
# OpenMP fuse directive.
|
||||
OMP_FUSE_DIRECTIVE = 311
|
||||
|
||||
# OpenMP split directive.
|
||||
OMP_SPLIT_DIRECTIVE = 312
|
||||
|
||||
# OpenACC Compute Construct.
|
||||
OPEN_ACC_COMPUTE_DIRECTIVE = 320
|
||||
|
||||
|
||||
@ -2166,10 +2166,6 @@ enum CXCursorKind {
|
||||
*/
|
||||
CXCursor_OMPFuseDirective = 311,
|
||||
|
||||
/** OpenMP split directive.
|
||||
*/
|
||||
CXCursor_OMPSplitDirective = 312,
|
||||
|
||||
/** OpenACC Compute Construct.
|
||||
*/
|
||||
CXCursor_OpenACCComputeConstruct = 320,
|
||||
|
||||
@ -39,7 +39,6 @@
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include "llvm/Support/TrailingObjects.h"
|
||||
#include <cassert>
|
||||
#include <climits>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <utility>
|
||||
@ -1024,106 +1023,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents the 'counts' clause in the '#pragma omp split' directive.
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp split counts(3, omp_fill, 2)
|
||||
/// for (int i = 0; i < n; ++i) { ... }
|
||||
/// \endcode
|
||||
class OMPCountsClause final
|
||||
: public OMPClause,
|
||||
private llvm::TrailingObjects<OMPCountsClause, Expr *> {
|
||||
friend class OMPClauseReader;
|
||||
friend class llvm::TrailingObjects<OMPCountsClause, Expr *>;
|
||||
|
||||
/// Location of '('.
|
||||
SourceLocation LParenLoc;
|
||||
|
||||
/// Number of count expressions in the clause.
|
||||
unsigned NumCounts = 0;
|
||||
|
||||
/// 0-based index of the omp_fill list item.
|
||||
std::optional<unsigned> OmpFillIndex;
|
||||
|
||||
/// Source location of the omp_fill keyword.
|
||||
SourceLocation OmpFillLoc;
|
||||
|
||||
/// Build an empty clause.
|
||||
explicit OMPCountsClause(int NumCounts)
|
||||
: OMPClause(llvm::omp::OMPC_counts, SourceLocation(), SourceLocation()),
|
||||
NumCounts(NumCounts) {}
|
||||
|
||||
/// Sets the location of '('.
|
||||
void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; }
|
||||
void setOmpFillIndex(std::optional<unsigned> Idx) { OmpFillIndex = Idx; }
|
||||
void setOmpFillLoc(SourceLocation Loc) { OmpFillLoc = Loc; }
|
||||
|
||||
/// Sets the count expressions.
|
||||
void setCountsRefs(ArrayRef<Expr *> VL) {
|
||||
assert(VL.size() == NumCounts);
|
||||
llvm::copy(VL, getCountsRefs().begin());
|
||||
}
|
||||
|
||||
public:
|
||||
/// Build a 'counts' AST node.
|
||||
///
|
||||
/// \param C Context of the AST.
|
||||
/// \param StartLoc Location of the 'counts' identifier.
|
||||
/// \param LParenLoc Location of '('.
|
||||
/// \param EndLoc Location of ')'.
|
||||
/// \param Counts Content of the clause.
|
||||
static OMPCountsClause *Create(const ASTContext &C, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, ArrayRef<Expr *> Counts,
|
||||
std::optional<unsigned> FillIdx,
|
||||
SourceLocation FillLoc);
|
||||
|
||||
/// Build an empty 'counts' AST node for deserialization.
|
||||
///
|
||||
/// \param C Context of the AST.
|
||||
/// \param NumCounts Number of items in the clause.
|
||||
static OMPCountsClause *CreateEmpty(const ASTContext &C, unsigned NumCounts);
|
||||
|
||||
/// Returns the location of '('.
|
||||
SourceLocation getLParenLoc() const { return LParenLoc; }
|
||||
|
||||
/// Returns the number of list items.
|
||||
unsigned getNumCounts() const { return NumCounts; }
|
||||
|
||||
std::optional<unsigned> getOmpFillIndex() const { return OmpFillIndex; }
|
||||
SourceLocation getOmpFillLoc() const { return OmpFillLoc; }
|
||||
bool hasOmpFill() const { return OmpFillIndex.has_value(); }
|
||||
|
||||
/// Returns the count expressions.
|
||||
MutableArrayRef<Expr *> getCountsRefs() {
|
||||
return getTrailingObjects(NumCounts);
|
||||
}
|
||||
ArrayRef<Expr *> getCountsRefs() const {
|
||||
return getTrailingObjects(NumCounts);
|
||||
}
|
||||
|
||||
child_range children() {
|
||||
MutableArrayRef<Expr *> Counts = getCountsRefs();
|
||||
return child_range(reinterpret_cast<Stmt **>(Counts.begin()),
|
||||
reinterpret_cast<Stmt **>(Counts.end()));
|
||||
}
|
||||
const_child_range children() const {
|
||||
ArrayRef<Expr *> Counts = getCountsRefs();
|
||||
return const_child_range(reinterpret_cast<Stmt *const *>(Counts.begin()),
|
||||
reinterpret_cast<Stmt *const *>(Counts.end()));
|
||||
}
|
||||
child_range used_children() {
|
||||
return child_range(child_iterator(), child_iterator());
|
||||
}
|
||||
const_child_range used_children() const {
|
||||
return const_child_range(const_child_iterator(), const_child_iterator());
|
||||
}
|
||||
|
||||
static bool classof(const OMPClause *T) {
|
||||
return T->getClauseKind() == llvm::omp::OMPC_counts;
|
||||
}
|
||||
};
|
||||
|
||||
/// This class represents the 'permutation' clause in the
|
||||
/// '#pragma omp interchange' directive.
|
||||
///
|
||||
|
||||
@ -3202,9 +3202,6 @@ DEF_TRAVERSE_STMT(OMPFuseDirective,
|
||||
DEF_TRAVERSE_STMT(OMPInterchangeDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPSplitDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
DEF_TRAVERSE_STMT(OMPForDirective,
|
||||
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
|
||||
|
||||
@ -3506,13 +3503,6 @@ bool RecursiveASTVisitor<Derived>::VisitOMPSizesClause(OMPSizesClause *C) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPCountsClause(OMPCountsClause *C) {
|
||||
for (Expr *E : C->getCountsRefs())
|
||||
TRY_TO(TraverseStmt(E));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool RecursiveASTVisitor<Derived>::VisitOMPPermutationClause(
|
||||
OMPPermutationClause *C) {
|
||||
|
||||
@ -6065,84 +6065,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// Represents the '#pragma omp split' loop transformation directive.
|
||||
///
|
||||
/// \code{.c}
|
||||
/// #pragma omp split counts(3, omp_fill, 2)
|
||||
/// for (int i = 0; i < n; ++i)
|
||||
/// ...
|
||||
/// \endcode
|
||||
///
|
||||
/// This directive transforms a single loop into multiple loops based on
|
||||
/// index ranges. The transformation splits the iteration space of the loop
|
||||
/// into multiple contiguous ranges. The \c counts clause is required and
|
||||
/// exactly one list item must be \c omp_fill.
|
||||
class OMPSplitDirective final
|
||||
: public OMPCanonicalLoopNestTransformationDirective {
|
||||
friend class ASTStmtReader;
|
||||
friend class OMPExecutableDirective;
|
||||
|
||||
/// Offsets of child members.
|
||||
enum {
|
||||
PreInitsOffset = 0,
|
||||
TransformedStmtOffset,
|
||||
};
|
||||
|
||||
explicit OMPSplitDirective(SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
unsigned NumLoops)
|
||||
: OMPCanonicalLoopNestTransformationDirective(
|
||||
OMPSplitDirectiveClass, llvm::omp::OMPD_split, StartLoc, EndLoc,
|
||||
NumLoops) {}
|
||||
|
||||
void setPreInits(Stmt *PreInits) {
|
||||
Data->getChildren()[PreInitsOffset] = PreInits;
|
||||
}
|
||||
|
||||
void setTransformedStmt(Stmt *S) {
|
||||
Data->getChildren()[TransformedStmtOffset] = S;
|
||||
}
|
||||
|
||||
public:
|
||||
/// Create a new AST node representation for '#pragma omp split'.
|
||||
///
|
||||
/// \param C Context of the AST.
|
||||
/// \param StartLoc Location of the introducer (e.g. the 'omp' token).
|
||||
/// \param EndLoc Location of the directive's end (e.g. the tok::eod).
|
||||
/// \param Clauses The directive's clauses (e.g. the required \c counts
|
||||
/// clause).
|
||||
/// \param NumLoops Number of affected loops (should be 1 for split).
|
||||
/// \param AssociatedStmt The outermost associated loop.
|
||||
/// \param TransformedStmt The loop nest after splitting, or nullptr in
|
||||
/// dependent contexts.
|
||||
/// \param PreInits Helper preinits statements for the loop nest.
|
||||
static OMPSplitDirective *Create(const ASTContext &C, SourceLocation StartLoc,
|
||||
SourceLocation EndLoc,
|
||||
ArrayRef<OMPClause *> Clauses,
|
||||
unsigned NumLoops, Stmt *AssociatedStmt,
|
||||
Stmt *TransformedStmt, Stmt *PreInits);
|
||||
|
||||
/// Build an empty '#pragma omp split' AST node for deserialization.
|
||||
///
|
||||
/// \param C Context of the AST.
|
||||
/// \param NumClauses Number of clauses to allocate.
|
||||
/// \param NumLoops Number of associated loops to allocate.
|
||||
static OMPSplitDirective *CreateEmpty(const ASTContext &C,
|
||||
unsigned NumClauses, unsigned NumLoops);
|
||||
|
||||
/// Gets/sets the associated loops after the transformation, i.e. after
|
||||
/// de-sugaring.
|
||||
Stmt *getTransformedStmt() const {
|
||||
return Data->getChildren()[TransformedStmtOffset];
|
||||
}
|
||||
|
||||
/// Return preinits statement.
|
||||
Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
|
||||
|
||||
static bool classof(const Stmt *T) {
|
||||
return T->getStmtClass() == OMPSplitDirectiveClass;
|
||||
}
|
||||
};
|
||||
|
||||
/// This represents '#pragma omp scan' directive.
|
||||
///
|
||||
/// \code
|
||||
|
||||
@ -8781,26 +8781,6 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt,
|
||||
OMPTargetUpdateDirective>
|
||||
ompTargetUpdateDirective;
|
||||
|
||||
/// Matches any ``#pragma omp split`` executable directive.
|
||||
///
|
||||
/// Given
|
||||
///
|
||||
/// \code
|
||||
/// #pragma omp split counts(2, omp_fill)
|
||||
/// for (int i = 0; i < n; ++i) {}
|
||||
/// \endcode
|
||||
///
|
||||
/// ``ompSplitDirective()`` matches the split directive.
|
||||
extern const internal::VariadicDynCastAllOfMatcher<Stmt, OMPSplitDirective>
|
||||
ompSplitDirective;
|
||||
|
||||
/// Matches OpenMP ``counts`` clause used by ``#pragma omp split``.
|
||||
///
|
||||
/// Given ``#pragma omp split counts(1, 2, omp_fill)``, ``ompCountsClause()``
|
||||
/// matches the ``counts`` clause node.
|
||||
extern const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPCountsClause>
|
||||
ompCountsClause;
|
||||
|
||||
/// Matches OpenMP ``default`` clause.
|
||||
///
|
||||
/// Given
|
||||
|
||||
@ -11174,8 +11174,6 @@ def err_omp_bind_required_on_loop : Error<
|
||||
"construct">;
|
||||
def err_omp_loop_reduction_clause : Error<
|
||||
"'reduction' clause not allowed with '#pragma omp loop bind(teams)'">;
|
||||
def err_omp_split_counts_not_one_omp_fill : Error<
|
||||
"exactly one 'omp_fill' must appear in the 'counts' clause">;
|
||||
def warn_break_binds_to_switch : Warning<
|
||||
"'break' is bound to loop, GCC binds it to switch">,
|
||||
InGroup<GccCompat>;
|
||||
|
||||
@ -244,7 +244,6 @@ def OMPTileDirective : StmtNode<OMPCanonicalLoopNestTransformationDirective>;
|
||||
def OMPStripeDirective : StmtNode<OMPCanonicalLoopNestTransformationDirective>;
|
||||
def OMPUnrollDirective : StmtNode<OMPCanonicalLoopNestTransformationDirective>;
|
||||
def OMPReverseDirective : StmtNode<OMPCanonicalLoopNestTransformationDirective>;
|
||||
def OMPSplitDirective : StmtNode<OMPCanonicalLoopNestTransformationDirective>;
|
||||
def OMPInterchangeDirective
|
||||
: StmtNode<OMPCanonicalLoopNestTransformationDirective>;
|
||||
def OMPCanonicalLoopSequenceTransformationDirective
|
||||
|
||||
@ -6812,9 +6812,6 @@ private:
|
||||
/// Parses the 'sizes' clause of a '#pragma omp tile' directive.
|
||||
OMPClause *ParseOpenMPSizesClause();
|
||||
|
||||
/// Parses the 'counts' clause of a '#pragma omp split' directive.
|
||||
OMPClause *ParseOpenMPCountsClause();
|
||||
|
||||
/// Parses the 'permutation' clause of a '#pragma omp interchange' directive.
|
||||
OMPClause *ParseOpenMPPermutationClause();
|
||||
|
||||
|
||||
@ -42,7 +42,6 @@ class FunctionScopeInfo;
|
||||
|
||||
class DeclContext;
|
||||
class DeclGroupRef;
|
||||
class EnumConstantDecl;
|
||||
class ParsedAttr;
|
||||
class Scope;
|
||||
|
||||
@ -458,11 +457,6 @@ public:
|
||||
/// Called on well-formed '#pragma omp reverse'.
|
||||
StmtResult ActOnOpenMPReverseDirective(Stmt *AStmt, SourceLocation StartLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// Called on well-formed '#pragma omp split' after parsing of its
|
||||
/// associated statement.
|
||||
StmtResult ActOnOpenMPSplitDirective(ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AStmt, SourceLocation StartLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// Called on well-formed '#pragma omp interchange' after parsing of its
|
||||
/// clauses and the associated statement.
|
||||
StmtResult ActOnOpenMPInterchangeDirective(ArrayRef<OMPClause *> Clauses,
|
||||
@ -917,12 +911,6 @@ public:
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc);
|
||||
/// Called on well-formed 'counts' clause after parsing its arguments.
|
||||
OMPClause *
|
||||
ActOnOpenMPCountsClause(ArrayRef<Expr *> CountExprs, SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc, SourceLocation EndLoc,
|
||||
std::optional<unsigned> FillIdx,
|
||||
SourceLocation FillLoc, unsigned FillCount);
|
||||
/// Called on well-form 'permutation' clause after parsing its arguments.
|
||||
OMPClause *ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs,
|
||||
SourceLocation StartLoc,
|
||||
|
||||
@ -1965,7 +1965,6 @@ enum StmtCode {
|
||||
STMP_OMP_STRIPE_DIRECTIVE,
|
||||
STMT_OMP_UNROLL_DIRECTIVE,
|
||||
STMT_OMP_REVERSE_DIRECTIVE,
|
||||
STMT_OMP_SPLIT_DIRECTIVE,
|
||||
STMT_OMP_INTERCHANGE_DIRECTIVE,
|
||||
STMT_OMP_FUSE_DIRECTIVE,
|
||||
STMT_OMP_FOR_DIRECTIVE,
|
||||
|
||||
@ -15,12 +15,10 @@
|
||||
#include "clang/AST/Attr.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclOpenMP.h"
|
||||
#include "clang/AST/Expr.h"
|
||||
#include "clang/AST/ExprOpenMP.h"
|
||||
#include "clang/Basic/LLVM.h"
|
||||
#include "clang/Basic/OpenMPKinds.h"
|
||||
#include "clang/Basic/TargetInfo.h"
|
||||
#include "llvm/ADT/Sequence.h"
|
||||
#include "llvm/ADT/SmallPtrSet.h"
|
||||
#include "llvm/Support/ErrorHandling.h"
|
||||
#include <algorithm>
|
||||
@ -988,26 +986,6 @@ OMPSizesClause *OMPSizesClause::CreateEmpty(const ASTContext &C,
|
||||
return new (Mem) OMPSizesClause(NumSizes);
|
||||
}
|
||||
|
||||
OMPCountsClause *OMPCountsClause::Create(
|
||||
const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc, ArrayRef<Expr *> Counts,
|
||||
std::optional<unsigned> FillIdx, SourceLocation FillLoc) {
|
||||
OMPCountsClause *Clause = CreateEmpty(C, Counts.size());
|
||||
Clause->setLocStart(StartLoc);
|
||||
Clause->setLParenLoc(LParenLoc);
|
||||
Clause->setLocEnd(EndLoc);
|
||||
Clause->setCountsRefs(Counts);
|
||||
Clause->setOmpFillIndex(FillIdx);
|
||||
Clause->setOmpFillLoc(FillLoc);
|
||||
return Clause;
|
||||
}
|
||||
|
||||
OMPCountsClause *OMPCountsClause::CreateEmpty(const ASTContext &C,
|
||||
unsigned NumCounts) {
|
||||
void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(NumCounts));
|
||||
return new (Mem) OMPCountsClause(NumCounts);
|
||||
}
|
||||
|
||||
OMPPermutationClause *OMPPermutationClause::Create(const ASTContext &C,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
@ -2006,19 +1984,6 @@ void OMPClausePrinter::VisitOMPSizesClause(OMPSizesClause *Node) {
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPCountsClause(OMPCountsClause *Node) {
|
||||
OS << "counts(";
|
||||
std::optional<unsigned> FillIdx = Node->getOmpFillIndex();
|
||||
ArrayRef<Expr *> Refs = Node->getCountsRefs();
|
||||
llvm::interleaveComma(llvm::seq<unsigned>(Refs.size()), OS, [&](unsigned I) {
|
||||
if (FillIdx && I == *FillIdx)
|
||||
OS << "omp_fill";
|
||||
else
|
||||
Refs[I]->printPretty(OS, nullptr, Policy, 0);
|
||||
});
|
||||
OS << ")";
|
||||
}
|
||||
|
||||
void OMPClausePrinter::VisitOMPPermutationClause(OMPPermutationClause *Node) {
|
||||
OS << "permutation(";
|
||||
llvm::interleaveComma(Node->getArgsRefs(), OS, [&](const Expr *E) {
|
||||
|
||||
@ -552,27 +552,6 @@ OMPInterchangeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
|
||||
SourceLocation(), SourceLocation(), NumLoops);
|
||||
}
|
||||
|
||||
OMPSplitDirective *
|
||||
OMPSplitDirective::Create(const ASTContext &C, SourceLocation StartLoc,
|
||||
SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses,
|
||||
unsigned NumLoops, Stmt *AssociatedStmt,
|
||||
Stmt *TransformedStmt, Stmt *PreInits) {
|
||||
OMPSplitDirective *Dir = createDirective<OMPSplitDirective>(
|
||||
C, Clauses, AssociatedStmt, TransformedStmtOffset + 1, StartLoc, EndLoc,
|
||||
NumLoops);
|
||||
Dir->setTransformedStmt(TransformedStmt);
|
||||
Dir->setPreInits(PreInits);
|
||||
return Dir;
|
||||
}
|
||||
|
||||
OMPSplitDirective *OMPSplitDirective::CreateEmpty(const ASTContext &C,
|
||||
unsigned NumClauses,
|
||||
unsigned NumLoops) {
|
||||
return createEmptyDirective<OMPSplitDirective>(
|
||||
C, NumClauses, /*HasAssociatedStmt=*/true, TransformedStmtOffset + 1,
|
||||
SourceLocation(), SourceLocation(), NumLoops);
|
||||
}
|
||||
|
||||
OMPFuseDirective *OMPFuseDirective::Create(
|
||||
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
|
||||
ArrayRef<OMPClause *> Clauses, unsigned NumGeneratedTopLevelLoops,
|
||||
|
||||
@ -800,11 +800,6 @@ void StmtPrinter::VisitOMPInterchangeDirective(OMPInterchangeDirective *Node) {
|
||||
PrintOMPExecutableDirective(Node);
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitOMPSplitDirective(OMPSplitDirective *Node) {
|
||||
Indent() << "#pragma omp split";
|
||||
PrintOMPExecutableDirective(Node);
|
||||
}
|
||||
|
||||
void StmtPrinter::VisitOMPFuseDirective(OMPFuseDirective *Node) {
|
||||
Indent() << "#pragma omp fuse";
|
||||
PrintOMPExecutableDirective(Node);
|
||||
|
||||
@ -498,12 +498,6 @@ void OMPClauseProfiler::VisitOMPSizesClause(const OMPSizesClause *C) {
|
||||
Profiler->VisitExpr(E);
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPCountsClause(const OMPCountsClause *C) {
|
||||
for (auto *E : C->getCountsRefs())
|
||||
if (E)
|
||||
Profiler->VisitExpr(E);
|
||||
}
|
||||
|
||||
void OMPClauseProfiler::VisitOMPPermutationClause(
|
||||
const OMPPermutationClause *C) {
|
||||
for (Expr *E : C->getArgsRefs())
|
||||
@ -1057,10 +1051,6 @@ void StmtProfiler::VisitOMPInterchangeDirective(
|
||||
VisitOMPCanonicalLoopNestTransformationDirective(S);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitOMPSplitDirective(const OMPSplitDirective *S) {
|
||||
VisitOMPCanonicalLoopNestTransformationDirective(S);
|
||||
}
|
||||
|
||||
void StmtProfiler::VisitOMPCanonicalLoopSequenceTransformationDirective(
|
||||
const OMPCanonicalLoopSequenceTransformationDirective *S) {
|
||||
VisitOMPExecutableDirective(S);
|
||||
|
||||
@ -1139,10 +1139,6 @@ const internal::VariadicDynCastAllOfMatcher<Stmt, OMPExecutableDirective>
|
||||
ompExecutableDirective;
|
||||
const internal::VariadicDynCastAllOfMatcher<Stmt, OMPTargetUpdateDirective>
|
||||
ompTargetUpdateDirective;
|
||||
const internal::VariadicDynCastAllOfMatcher<Stmt, OMPSplitDirective>
|
||||
ompSplitDirective;
|
||||
const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPCountsClause>
|
||||
ompCountsClause;
|
||||
const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPDefaultClause>
|
||||
ompDefaultClause;
|
||||
const internal::VariadicDynCastAllOfMatcher<OMPClause, OMPFromClause>
|
||||
|
||||
@ -529,12 +529,10 @@ RegistryMaps::RegistryMaps() {
|
||||
REGISTER_MATCHER(objcTryStmt);
|
||||
REGISTER_MATCHER(ofClass);
|
||||
REGISTER_MATCHER(ofKind);
|
||||
REGISTER_MATCHER(ompCountsClause);
|
||||
REGISTER_MATCHER(ompDefaultClause);
|
||||
REGISTER_MATCHER(ompFromClause);
|
||||
REGISTER_MATCHER(ompToClause);
|
||||
REGISTER_MATCHER(ompExecutableDirective);
|
||||
REGISTER_MATCHER(ompSplitDirective);
|
||||
REGISTER_MATCHER(ompTargetUpdateDirective);
|
||||
REGISTER_MATCHER(on);
|
||||
REGISTER_MATCHER(onImplicitObjectArgument);
|
||||
|
||||
@ -256,7 +256,6 @@ unsigned clang::getOpenMPSimpleClauseType(OpenMPClauseKind Kind, StringRef Str,
|
||||
case OMPC_safelen:
|
||||
case OMPC_simdlen:
|
||||
case OMPC_sizes:
|
||||
case OMPC_counts:
|
||||
case OMPC_permutation:
|
||||
case OMPC_allocator:
|
||||
case OMPC_collapse:
|
||||
@ -636,7 +635,6 @@ const char *clang::getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind,
|
||||
case OMPC_safelen:
|
||||
case OMPC_simdlen:
|
||||
case OMPC_sizes:
|
||||
case OMPC_counts:
|
||||
case OMPC_permutation:
|
||||
case OMPC_allocator:
|
||||
case OMPC_collapse:
|
||||
@ -817,8 +815,7 @@ bool clang::isOpenMPLoopBoundSharingDirective(OpenMPDirectiveKind Kind) {
|
||||
bool clang::isOpenMPCanonicalLoopNestTransformationDirective(
|
||||
OpenMPDirectiveKind DKind) {
|
||||
return DKind == OMPD_tile || DKind == OMPD_unroll || DKind == OMPD_reverse ||
|
||||
DKind == OMPD_split || DKind == OMPD_interchange ||
|
||||
DKind == OMPD_stripe;
|
||||
DKind == OMPD_interchange || DKind == OMPD_stripe;
|
||||
}
|
||||
|
||||
bool clang::isOpenMPCanonicalLoopSequenceTransformationDirective(
|
||||
|
||||
@ -230,9 +230,6 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
|
||||
case Stmt::OMPReverseDirectiveClass:
|
||||
EmitOMPReverseDirective(cast<OMPReverseDirective>(*S));
|
||||
break;
|
||||
case Stmt::OMPSplitDirectiveClass:
|
||||
EmitOMPSplitDirective(cast<OMPSplitDirective>(*S));
|
||||
break;
|
||||
case Stmt::OMPInterchangeDirectiveClass:
|
||||
EmitOMPInterchangeDirective(cast<OMPInterchangeDirective>(*S));
|
||||
break;
|
||||
|
||||
@ -197,8 +197,6 @@ class OMPLoopScope : public CodeGenFunction::RunCleanupsScope {
|
||||
PreInits = Unroll->getPreInits();
|
||||
} else if (const auto *Reverse = dyn_cast<OMPReverseDirective>(&S)) {
|
||||
PreInits = Reverse->getPreInits();
|
||||
} else if (const auto *Split = dyn_cast<OMPSplitDirective>(&S)) {
|
||||
PreInits = Split->getPreInits();
|
||||
} else if (const auto *Interchange =
|
||||
dyn_cast<OMPInterchangeDirective>(&S)) {
|
||||
PreInits = Interchange->getPreInits();
|
||||
@ -3205,12 +3203,6 @@ void CodeGenFunction::EmitOMPReverseDirective(const OMPReverseDirective &S) {
|
||||
EmitStmt(S.getTransformedStmt());
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitOMPSplitDirective(const OMPSplitDirective &S) {
|
||||
// Emit the de-sugared statement (the split loops).
|
||||
OMPTransformDirectiveScopeRAII SplitScope(*this, &S);
|
||||
EmitStmt(S.getTransformedStmt());
|
||||
}
|
||||
|
||||
void CodeGenFunction::EmitOMPInterchangeDirective(
|
||||
const OMPInterchangeDirective &S) {
|
||||
// Emit the de-sugared statement.
|
||||
|
||||
@ -3930,7 +3930,6 @@ public:
|
||||
void EmitOMPStripeDirective(const OMPStripeDirective &S);
|
||||
void EmitOMPUnrollDirective(const OMPUnrollDirective &S);
|
||||
void EmitOMPReverseDirective(const OMPReverseDirective &S);
|
||||
void EmitOMPSplitDirective(const OMPSplitDirective &S);
|
||||
void EmitOMPInterchangeDirective(const OMPInterchangeDirective &S);
|
||||
void EmitOMPFuseDirective(const OMPFuseDirective &S);
|
||||
void EmitOMPForDirective(const OMPForDirective &S);
|
||||
|
||||
@ -28,7 +28,6 @@
|
||||
#include "llvm/Frontend/OpenMP/DirectiveNameParser.h"
|
||||
#include "llvm/Frontend/OpenMP/OMPAssume.h"
|
||||
#include "llvm/Frontend/OpenMP/OMPContext.h"
|
||||
#include <climits>
|
||||
#include <optional>
|
||||
|
||||
using namespace clang;
|
||||
@ -2425,10 +2424,6 @@ StmtResult Parser::ParseOpenMPExecutableDirective(
|
||||
Diag(Loc, diag::err_omp_required_clause)
|
||||
<< getOpenMPDirectiveName(DKind, OMPVersion) << "sizes";
|
||||
}
|
||||
if (DKind == OMPD_split && !SeenClauses[unsigned(OMPC_counts)]) {
|
||||
Diag(Loc, diag::err_omp_required_clause)
|
||||
<< getOpenMPDirectiveName(DKind, OMPVersion) << "counts";
|
||||
}
|
||||
|
||||
StmtResult AssociatedStmt;
|
||||
if (HasAssociatedStatement) {
|
||||
@ -2991,51 +2986,6 @@ OMPClause *Parser::ParseOpenMPSizesClause() {
|
||||
OpenLoc, CloseLoc);
|
||||
}
|
||||
|
||||
OMPClause *Parser::ParseOpenMPCountsClause() {
|
||||
SourceLocation ClauseNameLoc, OpenLoc, CloseLoc;
|
||||
SmallVector<Expr *, 4> ValExprs;
|
||||
std::optional<unsigned> FillIdx;
|
||||
unsigned FillCount = 0;
|
||||
SourceLocation FillLoc;
|
||||
|
||||
assert(getOpenMPClauseName(OMPC_counts) == PP.getSpelling(Tok) &&
|
||||
"Expected parsing to start at clause name");
|
||||
ClauseNameLoc = ConsumeToken();
|
||||
|
||||
BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
|
||||
if (T.consumeOpen()) {
|
||||
Diag(Tok, diag::err_expected) << tok::l_paren;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
do {
|
||||
if (Tok.is(tok::identifier) &&
|
||||
Tok.getIdentifierInfo()->getName() == "omp_fill") {
|
||||
if (FillCount == 0)
|
||||
FillIdx = ValExprs.size();
|
||||
++FillCount;
|
||||
FillLoc = Tok.getLocation();
|
||||
ConsumeToken();
|
||||
ValExprs.push_back(nullptr);
|
||||
} else {
|
||||
ExprResult Val = ParseConstantExpression();
|
||||
if (!Val.isUsable()) {
|
||||
T.skipToEnd();
|
||||
return nullptr;
|
||||
}
|
||||
ValExprs.push_back(Val.get());
|
||||
}
|
||||
} while (TryConsumeToken(tok::comma));
|
||||
|
||||
if (T.consumeClose())
|
||||
return nullptr;
|
||||
OpenLoc = T.getOpenLocation();
|
||||
CloseLoc = T.getCloseLocation();
|
||||
|
||||
return Actions.OpenMP().ActOnOpenMPCountsClause(
|
||||
ValExprs, ClauseNameLoc, OpenLoc, CloseLoc, FillIdx, FillLoc, FillCount);
|
||||
}
|
||||
|
||||
OMPClause *Parser::ParseOpenMPLoopRangeClause() {
|
||||
SourceLocation ClauseNameLoc = ConsumeToken();
|
||||
SourceLocation FirstLoc, CountLoc;
|
||||
@ -3482,15 +3432,6 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
|
||||
}
|
||||
Clause = ParseOpenMPPermutationClause();
|
||||
break;
|
||||
case OMPC_counts:
|
||||
if (!FirstClause) {
|
||||
Diag(Tok, diag::err_omp_more_one_clause)
|
||||
<< getOpenMPDirectiveName(DKind, OMPVersion)
|
||||
<< getOpenMPClauseName(CKind) << 0;
|
||||
ErrorFound = true;
|
||||
}
|
||||
Clause = ParseOpenMPCountsClause();
|
||||
break;
|
||||
case OMPC_uses_allocators:
|
||||
Clause = ParseOpenMPUsesAllocatorClause(DKind);
|
||||
break;
|
||||
|
||||
@ -1508,7 +1508,6 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
|
||||
case Stmt::OMPUnrollDirectiveClass:
|
||||
case Stmt::OMPReverseDirectiveClass:
|
||||
case Stmt::OMPInterchangeDirectiveClass:
|
||||
case Stmt::OMPSplitDirectiveClass:
|
||||
case Stmt::OMPFuseDirectiveClass:
|
||||
case Stmt::OMPSingleDirectiveClass:
|
||||
case Stmt::OMPTargetDataDirectiveClass:
|
||||
|
||||
@ -4627,7 +4627,6 @@ void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,
|
||||
case OMPD_stripe:
|
||||
case OMPD_unroll:
|
||||
case OMPD_reverse:
|
||||
case OMPD_split:
|
||||
case OMPD_interchange:
|
||||
case OMPD_fuse:
|
||||
case OMPD_assume:
|
||||
@ -6467,10 +6466,6 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
|
||||
"reverse directive does not support any clauses");
|
||||
Res = ActOnOpenMPReverseDirective(AStmt, StartLoc, EndLoc);
|
||||
break;
|
||||
case OMPD_split:
|
||||
Res =
|
||||
ActOnOpenMPSplitDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc);
|
||||
break;
|
||||
case OMPD_interchange:
|
||||
Res = ActOnOpenMPInterchangeDirective(ClausesWithImplicit, AStmt, StartLoc,
|
||||
EndLoc);
|
||||
@ -15916,235 +15911,6 @@ StmtResult SemaOpenMP::ActOnOpenMPReverseDirective(Stmt *AStmt,
|
||||
buildPreInits(Context, PreInits));
|
||||
}
|
||||
|
||||
/// Build the AST for \#pragma omp split counts(c1, c2, ...).
|
||||
///
|
||||
/// Splits the single associated loop into N consecutive loops, where N is the
|
||||
/// number of count expressions.
|
||||
StmtResult SemaOpenMP::ActOnOpenMPSplitDirective(ArrayRef<OMPClause *> Clauses,
|
||||
Stmt *AStmt,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation EndLoc) {
|
||||
ASTContext &Context = getASTContext();
|
||||
Scope *CurScope = SemaRef.getCurScope();
|
||||
|
||||
// Empty statement should only be possible if there already was an error.
|
||||
if (!AStmt)
|
||||
return StmtError();
|
||||
|
||||
const auto *CountsClause =
|
||||
OMPExecutableDirective::getSingleClause<OMPCountsClause>(Clauses);
|
||||
if (!CountsClause)
|
||||
return StmtError();
|
||||
|
||||
// Split applies to a single loop; check it is transformable and get helpers.
|
||||
constexpr unsigned NumLoops = 1;
|
||||
Stmt *Body = nullptr;
|
||||
SmallVector<OMPLoopBasedDirective::HelperExprs, NumLoops> LoopHelpers(
|
||||
NumLoops);
|
||||
SmallVector<SmallVector<Stmt *>, NumLoops + 1> OriginalInits;
|
||||
if (!checkTransformableLoopNest(OMPD_split, AStmt, NumLoops, LoopHelpers,
|
||||
Body, OriginalInits))
|
||||
return StmtError();
|
||||
|
||||
// Delay applying the transformation to when template is completely
|
||||
// instantiated.
|
||||
if (SemaRef.CurContext->isDependentContext())
|
||||
return OMPSplitDirective::Create(Context, StartLoc, EndLoc, Clauses,
|
||||
NumLoops, AStmt, nullptr, nullptr);
|
||||
|
||||
assert(LoopHelpers.size() == NumLoops &&
|
||||
"Expecting a single-dimensional loop iteration space");
|
||||
assert(OriginalInits.size() == NumLoops &&
|
||||
"Expecting a single-dimensional loop iteration space");
|
||||
OMPLoopBasedDirective::HelperExprs &LoopHelper = LoopHelpers.front();
|
||||
|
||||
// Find the loop statement.
|
||||
Stmt *LoopStmt = nullptr;
|
||||
collectLoopStmts(AStmt, {LoopStmt});
|
||||
|
||||
// Determine the PreInit declarations.
|
||||
SmallVector<Stmt *> PreInits;
|
||||
addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
|
||||
|
||||
// Type and name of the original loop variable; we create one IV per segment
|
||||
// and assign it to the original var so the body sees the same name.
|
||||
auto *IterationVarRef = cast<DeclRefExpr>(LoopHelper.IterationVarRef);
|
||||
QualType IVTy = IterationVarRef->getType();
|
||||
uint64_t IVWidth = Context.getTypeSize(IVTy);
|
||||
auto *OrigVar = cast<DeclRefExpr>(LoopHelper.Counters.front());
|
||||
|
||||
// Iteration variable SourceLocations.
|
||||
SourceLocation OrigVarLoc = OrigVar->getExprLoc();
|
||||
SourceLocation OrigVarLocBegin = OrigVar->getBeginLoc();
|
||||
SourceLocation OrigVarLocEnd = OrigVar->getEndLoc();
|
||||
// Internal variable names.
|
||||
std::string OrigVarName = OrigVar->getNameInfo().getAsString();
|
||||
|
||||
if (!CountsClause->hasOmpFill())
|
||||
return StmtError();
|
||||
unsigned FillIdx = *CountsClause->getOmpFillIndex();
|
||||
|
||||
unsigned NumItems = CountsClause->getNumCounts();
|
||||
SmallVector<uint64_t, 4> CountValues(NumItems, 0);
|
||||
ArrayRef<Expr *> Refs = CountsClause->getCountsRefs();
|
||||
for (unsigned I = 0; I < NumItems; ++I) {
|
||||
if (I == FillIdx)
|
||||
continue;
|
||||
Expr *CountExpr = Refs[I];
|
||||
if (!CountExpr)
|
||||
return OMPSplitDirective::Create(Context, StartLoc, EndLoc, Clauses,
|
||||
NumLoops, AStmt, nullptr, nullptr);
|
||||
std::optional<llvm::APSInt> OptVal =
|
||||
CountExpr->getIntegerConstantExpr(Context);
|
||||
if (!OptVal || OptVal->isNegative())
|
||||
return OMPSplitDirective::Create(Context, StartLoc, EndLoc, Clauses,
|
||||
NumLoops, AStmt, nullptr, nullptr);
|
||||
CountValues[I] = OptVal->getZExtValue();
|
||||
}
|
||||
|
||||
Expr *NumIterExpr = LoopHelper.NumIterations;
|
||||
|
||||
uint64_t RightSum = 0;
|
||||
for (unsigned I = FillIdx + 1; I < NumItems; ++I)
|
||||
RightSum += CountValues[I];
|
||||
|
||||
auto MakeIntLit = [&](uint64_t Val) {
|
||||
return IntegerLiteral::Create(Context, llvm::APInt(IVWidth, Val), IVTy,
|
||||
OrigVarLoc);
|
||||
};
|
||||
|
||||
size_t NumSegments = NumItems;
|
||||
SmallVector<Stmt *, 4> SplitLoops;
|
||||
|
||||
auto *IterVarDecl = cast<VarDecl>(IterationVarRef->getDecl());
|
||||
SplitLoops.push_back(new (Context) DeclStmt(DeclGroupRef(IterVarDecl),
|
||||
IterationVarRef->getBeginLoc(),
|
||||
IterationVarRef->getEndLoc()));
|
||||
|
||||
uint64_t LeftAccum = 0;
|
||||
uint64_t RightRemaining = RightSum;
|
||||
|
||||
for (size_t Seg = 0; Seg < NumSegments; ++Seg) {
|
||||
Expr *StartExpr = nullptr;
|
||||
Expr *EndExpr = nullptr;
|
||||
|
||||
if (Seg < FillIdx) {
|
||||
StartExpr = MakeIntLit(LeftAccum);
|
||||
LeftAccum += CountValues[Seg];
|
||||
EndExpr = MakeIntLit(LeftAccum);
|
||||
} else if (Seg == FillIdx) {
|
||||
StartExpr = MakeIntLit(LeftAccum);
|
||||
if (RightRemaining == 0) {
|
||||
EndExpr = NumIterExpr;
|
||||
} else {
|
||||
ExprResult Sub =
|
||||
SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
|
||||
MakeIntLit(RightRemaining));
|
||||
if (!Sub.isUsable())
|
||||
return StmtError();
|
||||
EndExpr = Sub.get();
|
||||
}
|
||||
} else {
|
||||
if (RightRemaining == RightSum) {
|
||||
if (RightSum == 0)
|
||||
StartExpr = NumIterExpr;
|
||||
else {
|
||||
ExprResult Sub =
|
||||
SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
|
||||
MakeIntLit(RightRemaining));
|
||||
if (!Sub.isUsable())
|
||||
return StmtError();
|
||||
StartExpr = Sub.get();
|
||||
}
|
||||
} else {
|
||||
ExprResult Sub =
|
||||
SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
|
||||
MakeIntLit(RightRemaining));
|
||||
if (!Sub.isUsable())
|
||||
return StmtError();
|
||||
StartExpr = Sub.get();
|
||||
}
|
||||
RightRemaining -= CountValues[Seg];
|
||||
if (RightRemaining == 0)
|
||||
EndExpr = NumIterExpr;
|
||||
else {
|
||||
ExprResult Sub =
|
||||
SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Sub, NumIterExpr,
|
||||
MakeIntLit(RightRemaining));
|
||||
if (!Sub.isUsable())
|
||||
return StmtError();
|
||||
EndExpr = Sub.get();
|
||||
}
|
||||
}
|
||||
|
||||
SmallString<64> IVName(".split.iv.");
|
||||
IVName += (Twine(Seg) + "." + OrigVarName).str();
|
||||
VarDecl *IVDecl = buildVarDecl(SemaRef, {}, IVTy, IVName, nullptr, OrigVar);
|
||||
auto MakeIVRef = [&SemaRef = this->SemaRef, IVDecl, IVTy, OrigVarLoc]() {
|
||||
return buildDeclRefExpr(SemaRef, IVDecl, IVTy, OrigVarLoc);
|
||||
};
|
||||
|
||||
SemaRef.AddInitializerToDecl(IVDecl, StartExpr, /*DirectInit=*/false);
|
||||
StmtResult InitStmt = new (Context)
|
||||
DeclStmt(DeclGroupRef(IVDecl), OrigVarLocBegin, OrigVarLocEnd);
|
||||
if (!InitStmt.isUsable())
|
||||
return StmtError();
|
||||
|
||||
ExprResult CondExpr = SemaRef.BuildBinOp(
|
||||
CurScope, LoopHelper.Cond->getExprLoc(), BO_LT, MakeIVRef(), EndExpr);
|
||||
if (!CondExpr.isUsable())
|
||||
return StmtError();
|
||||
|
||||
ExprResult IncrExpr = SemaRef.BuildUnaryOp(
|
||||
CurScope, LoopHelper.Inc->getExprLoc(), UO_PreInc, MakeIVRef());
|
||||
if (!IncrExpr.isUsable())
|
||||
return StmtError();
|
||||
|
||||
ExprResult IVAssign = SemaRef.BuildBinOp(CurScope, OrigVarLoc, BO_Assign,
|
||||
IterationVarRef, MakeIVRef());
|
||||
if (!IVAssign.isUsable())
|
||||
return StmtError();
|
||||
|
||||
SmallVector<Stmt *, 4> BodyStmts;
|
||||
BodyStmts.push_back(IVAssign.get());
|
||||
BodyStmts.append(LoopHelper.Updates.begin(), LoopHelper.Updates.end());
|
||||
if (auto *CXXRangeFor = dyn_cast<CXXForRangeStmt>(LoopStmt)) {
|
||||
if (Seg == 0) {
|
||||
BodyStmts.push_back(CXXRangeFor->getLoopVarStmt());
|
||||
} else {
|
||||
VarDecl *LoopVar = CXXRangeFor->getLoopVariable();
|
||||
DeclRefExpr *LVRef = buildDeclRefExpr(
|
||||
SemaRef, LoopVar, LoopVar->getType().getNonReferenceType(),
|
||||
OrigVarLoc);
|
||||
ExprResult LVAssign = SemaRef.BuildBinOp(
|
||||
CurScope, OrigVarLoc, BO_Assign, LVRef, LoopVar->getInit());
|
||||
if (!LVAssign.isUsable())
|
||||
return StmtError();
|
||||
BodyStmts.push_back(LVAssign.get());
|
||||
}
|
||||
}
|
||||
BodyStmts.push_back(Body);
|
||||
|
||||
auto *LoopBody =
|
||||
CompoundStmt::Create(Context, BodyStmts, FPOptionsOverride(),
|
||||
Body->getBeginLoc(), Body->getEndLoc());
|
||||
|
||||
auto *For = new (Context)
|
||||
ForStmt(Context, InitStmt.get(), CondExpr.get(), nullptr,
|
||||
IncrExpr.get(), LoopBody, LoopHelper.Init->getBeginLoc(),
|
||||
LoopHelper.Init->getBeginLoc(), LoopHelper.Inc->getEndLoc());
|
||||
SplitLoops.push_back(For);
|
||||
}
|
||||
|
||||
auto *SplitStmt = CompoundStmt::Create(
|
||||
Context, SplitLoops, FPOptionsOverride(),
|
||||
SplitLoops.front()->getBeginLoc(), SplitLoops.back()->getEndLoc());
|
||||
|
||||
return OMPSplitDirective::Create(Context, StartLoc, EndLoc, Clauses, NumLoops,
|
||||
AStmt, SplitStmt,
|
||||
buildPreInits(Context, PreInits));
|
||||
}
|
||||
|
||||
StmtResult SemaOpenMP::ActOnOpenMPInterchangeDirective(
|
||||
ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
|
||||
SourceLocation EndLoc) {
|
||||
@ -18093,42 +17859,6 @@ OMPClause *SemaOpenMP::ActOnOpenMPSizesClause(ArrayRef<Expr *> SizeExprs,
|
||||
SanitizedSizeExprs);
|
||||
}
|
||||
|
||||
OMPClause *SemaOpenMP::ActOnOpenMPCountsClause(ArrayRef<Expr *> CountExprs,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc,
|
||||
std::optional<unsigned> FillIdx,
|
||||
SourceLocation FillLoc,
|
||||
unsigned FillCount) {
|
||||
SmallVector<Expr *> SanitizedCountExprs(CountExprs);
|
||||
|
||||
for (unsigned I = 0; I < SanitizedCountExprs.size(); ++I) {
|
||||
Expr *&CountExpr = SanitizedCountExprs[I];
|
||||
if (FillIdx && I == *FillIdx)
|
||||
continue;
|
||||
if (!CountExpr)
|
||||
continue;
|
||||
|
||||
bool IsValid = isNonNegativeIntegerValue(CountExpr, SemaRef, OMPC_counts,
|
||||
/*StrictlyPositive=*/false);
|
||||
|
||||
QualType CountTy = CountExpr->getType();
|
||||
if (!CountTy->isIntegerType())
|
||||
IsValid = false;
|
||||
|
||||
if (!CountExpr->isInstantiationDependent() && !IsValid)
|
||||
CountExpr = nullptr;
|
||||
}
|
||||
|
||||
if (FillCount != 1) {
|
||||
Diag(FillCount == 0 ? StartLoc : FillLoc,
|
||||
diag::err_omp_split_counts_not_one_omp_fill);
|
||||
}
|
||||
|
||||
return OMPCountsClause::Create(getASTContext(), StartLoc, LParenLoc, EndLoc,
|
||||
SanitizedCountExprs, FillIdx, FillLoc);
|
||||
}
|
||||
|
||||
OMPClause *SemaOpenMP::ActOnOpenMPPermutationClause(ArrayRef<Expr *> PermExprs,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
|
||||
@ -1769,17 +1769,6 @@ public:
|
||||
EndLoc);
|
||||
}
|
||||
|
||||
OMPClause *RebuildOMPCountsClause(ArrayRef<Expr *> Counts,
|
||||
SourceLocation StartLoc,
|
||||
SourceLocation LParenLoc,
|
||||
SourceLocation EndLoc,
|
||||
std::optional<unsigned> FillIdx,
|
||||
SourceLocation FillLoc) {
|
||||
unsigned FillCount = FillIdx ? 1 : 0;
|
||||
return getSema().OpenMP().ActOnOpenMPCountsClause(
|
||||
Counts, StartLoc, LParenLoc, EndLoc, FillIdx, FillLoc, FillCount);
|
||||
}
|
||||
|
||||
/// Build a new OpenMP 'permutation' clause.
|
||||
OMPClause *RebuildOMPPermutationClause(ArrayRef<Expr *> PermExprs,
|
||||
SourceLocation StartLoc,
|
||||
@ -9770,17 +9759,6 @@ StmtResult TreeTransform<Derived>::TransformOMPInterchangeDirective(
|
||||
return Res;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
StmtResult
|
||||
TreeTransform<Derived>::TransformOMPSplitDirective(OMPSplitDirective *D) {
|
||||
DeclarationNameInfo DirName;
|
||||
getDerived().getSema().OpenMP().StartOpenMPDSABlock(
|
||||
D->getDirectiveKind(), DirName, nullptr, D->getBeginLoc());
|
||||
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
|
||||
getDerived().getSema().OpenMP().EndOpenMPDSABlock(Res.get());
|
||||
return Res;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
StmtResult
|
||||
TreeTransform<Derived>::TransformOMPFuseDirective(OMPFuseDirective *D) {
|
||||
@ -10637,28 +10615,6 @@ OMPClause *TreeTransform<Derived>::TransformOMPSizesClause(OMPSizesClause *C) {
|
||||
C->getLParenLoc(), C->getEndLoc());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPCountsClause(OMPCountsClause *C) {
|
||||
SmallVector<Expr *, 4> TransformedCounts;
|
||||
TransformedCounts.reserve(C->getNumCounts());
|
||||
for (Expr *E : C->getCountsRefs()) {
|
||||
if (!E) {
|
||||
TransformedCounts.push_back(nullptr);
|
||||
continue;
|
||||
}
|
||||
|
||||
ExprResult T = getDerived().TransformExpr(E);
|
||||
if (T.isInvalid())
|
||||
return nullptr;
|
||||
TransformedCounts.push_back(T.get());
|
||||
}
|
||||
|
||||
return RebuildOMPCountsClause(TransformedCounts, C->getBeginLoc(),
|
||||
C->getLParenLoc(), C->getEndLoc(),
|
||||
C->getOmpFillIndex(), C->getOmpFillLoc());
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
OMPClause *
|
||||
TreeTransform<Derived>::TransformOMPPermutationClause(OMPPermutationClause *C) {
|
||||
|
||||
@ -11437,11 +11437,6 @@ OMPClause *OMPClauseReader::readClause() {
|
||||
C = OMPSizesClause::CreateEmpty(Context, NumSizes);
|
||||
break;
|
||||
}
|
||||
case llvm::omp::OMPC_counts: {
|
||||
unsigned NumCounts = Record.readInt();
|
||||
C = OMPCountsClause::CreateEmpty(Context, NumCounts);
|
||||
break;
|
||||
}
|
||||
case llvm::omp::OMPC_permutation: {
|
||||
unsigned NumLoops = Record.readInt();
|
||||
C = OMPPermutationClause::CreateEmpty(Context, NumLoops);
|
||||
@ -11855,16 +11850,6 @@ void OMPClauseReader::VisitOMPSizesClause(OMPSizesClause *C) {
|
||||
C->setLParenLoc(Record.readSourceLocation());
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPCountsClause(OMPCountsClause *C) {
|
||||
bool HasFill = Record.readBool();
|
||||
if (HasFill)
|
||||
C->setOmpFillIndex(Record.readInt());
|
||||
C->setOmpFillLoc(Record.readSourceLocation());
|
||||
for (Expr *&E : C->getCountsRefs())
|
||||
E = Record.readSubExpr();
|
||||
C->setLParenLoc(Record.readSourceLocation());
|
||||
}
|
||||
|
||||
void OMPClauseReader::VisitOMPPermutationClause(OMPPermutationClause *C) {
|
||||
for (Expr *&E : C->getArgsRefs())
|
||||
E = Record.readSubExpr();
|
||||
|
||||
@ -2529,10 +2529,6 @@ void ASTStmtReader::VisitOMPInterchangeDirective(OMPInterchangeDirective *D) {
|
||||
VisitOMPCanonicalLoopNestTransformationDirective(D);
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitOMPSplitDirective(OMPSplitDirective *D) {
|
||||
VisitOMPCanonicalLoopNestTransformationDirective(D);
|
||||
}
|
||||
|
||||
void ASTStmtReader::VisitOMPFuseDirective(OMPFuseDirective *D) {
|
||||
VisitOMPCanonicalLoopSequenceTransformationDirective(D);
|
||||
}
|
||||
@ -3691,13 +3687,6 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
|
||||
break;
|
||||
}
|
||||
|
||||
case STMT_OMP_SPLIT_DIRECTIVE: {
|
||||
unsigned NumLoops = Record[ASTStmtReader::NumStmtFields];
|
||||
unsigned NumClauses = Record[ASTStmtReader::NumStmtFields + 1];
|
||||
S = OMPSplitDirective::CreateEmpty(Context, NumClauses, NumLoops);
|
||||
break;
|
||||
}
|
||||
|
||||
case STMT_OMP_FUSE_DIRECTIVE: {
|
||||
unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
|
||||
S = OMPFuseDirective::CreateEmpty(Context, NumClauses);
|
||||
|
||||
@ -8070,17 +8070,6 @@ void OMPClauseWriter::VisitOMPSizesClause(OMPSizesClause *C) {
|
||||
Record.AddSourceLocation(C->getLParenLoc());
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPCountsClause(OMPCountsClause *C) {
|
||||
Record.push_back(C->getNumCounts());
|
||||
Record.push_back(C->hasOmpFill());
|
||||
if (C->hasOmpFill())
|
||||
Record.push_back(*C->getOmpFillIndex());
|
||||
Record.AddSourceLocation(C->getOmpFillLoc());
|
||||
for (Expr *Count : C->getCountsRefs())
|
||||
Record.AddStmt(Count);
|
||||
Record.AddSourceLocation(C->getLParenLoc());
|
||||
}
|
||||
|
||||
void OMPClauseWriter::VisitOMPPermutationClause(OMPPermutationClause *C) {
|
||||
Record.push_back(C->getNumLoops());
|
||||
for (Expr *Size : C->getArgsRefs())
|
||||
|
||||
@ -2546,11 +2546,6 @@ void ASTStmtWriter::VisitOMPInterchangeDirective(OMPInterchangeDirective *D) {
|
||||
Code = serialization::STMT_OMP_INTERCHANGE_DIRECTIVE;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitOMPSplitDirective(OMPSplitDirective *D) {
|
||||
VisitOMPCanonicalLoopNestTransformationDirective(D);
|
||||
Code = serialization::STMT_OMP_SPLIT_DIRECTIVE;
|
||||
}
|
||||
|
||||
void ASTStmtWriter::VisitOMPCanonicalLoopSequenceTransformationDirective(
|
||||
OMPCanonicalLoopSequenceTransformationDirective *D) {
|
||||
VisitStmt(D);
|
||||
|
||||
@ -1812,7 +1812,6 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
|
||||
case Stmt::OMPStripeDirectiveClass:
|
||||
case Stmt::OMPTileDirectiveClass:
|
||||
case Stmt::OMPInterchangeDirectiveClass:
|
||||
case Stmt::OMPSplitDirectiveClass:
|
||||
case Stmt::OMPFuseDirectiveClass:
|
||||
case Stmt::OMPInteropDirectiveClass:
|
||||
case Stmt::OMPDispatchDirectiveClass:
|
||||
|
||||
@ -1,19 +0,0 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -fopenmp-version=60 -ast-dump %s | FileCheck %s
|
||||
//
|
||||
// OMPSplitDirective / OMPCountsClause;
|
||||
|
||||
void body(int);
|
||||
|
||||
void test(void) {
|
||||
#pragma omp split counts(3, omp_fill)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
body(i);
|
||||
}
|
||||
|
||||
// CHECK: OMPSplitDirective
|
||||
// CHECK: OMPCountsClause
|
||||
// CHECK: IntegerLiteral{{.*}}3
|
||||
// CHECK: <<<NULL>>>
|
||||
// CHECK: ForStmt
|
||||
// CHECK: <<<NULL>>>
|
||||
// CHECK: CallExpr
|
||||
@ -1,11 +0,0 @@
|
||||
// RUN: c-index-test -test-load-source local %s -fopenmp=libomp -fopenmp-version=60 | FileCheck %s
|
||||
|
||||
void test(void) {
|
||||
#pragma omp split counts(3, omp_fill)
|
||||
for (int i = 0; i < 20; i += 1)
|
||||
;
|
||||
}
|
||||
|
||||
// CHECK: openmp-split.c:4:1: OMPSplitDirective= Extent=[4:1 - 4:38]
|
||||
// CHECK: openmp-split.c:4:26: IntegerLiteral= Extent=[4:26 - 4:27]
|
||||
// CHECK: openmp-split.c:5:3: ForStmt= Extent=[5:3 - 6:6]
|
||||
@ -1,10 +0,0 @@
|
||||
// Static analyzer invocation on split loop (no crash).
|
||||
// RUN: %clang -target x86_64-unknown-linux-gnu --analyze -fopenmp -fopenmp-version=60 %s -o %t.plist
|
||||
|
||||
void g(int);
|
||||
|
||||
void f(int n) {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int i = 0; i < n; ++i)
|
||||
g(i);
|
||||
}
|
||||
@ -1,71 +0,0 @@
|
||||
// AST dump + ast-print round-trip for omp_fill at every position in counts().
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -fsyntax-only -verify %s
|
||||
// expected-no-diagnostics
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -ast-dump %s | FileCheck %s --check-prefix=DUMP
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -ast-print %s | FileCheck %s --check-prefix=PRINT
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
extern "C" void body(...);
|
||||
|
||||
// --- omp_fill at last position: counts(2, omp_fill) ---
|
||||
// PRINT-LABEL: void fill_last(
|
||||
// DUMP-LABEL: FunctionDecl {{.*}} fill_last
|
||||
void fill_last(int n) {
|
||||
// PRINT: #pragma omp split counts(2, omp_fill)
|
||||
// DUMP: OMPSplitDirective
|
||||
// DUMP: OMPCountsClause
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
// PRINT: for (int i = 0; i < n; ++i)
|
||||
// DUMP: ForStmt
|
||||
for (int i = 0; i < n; ++i)
|
||||
body(i);
|
||||
}
|
||||
|
||||
// --- omp_fill at first position: counts(omp_fill, 3) ---
|
||||
// PRINT-LABEL: void fill_first(
|
||||
// DUMP-LABEL: FunctionDecl {{.*}} fill_first
|
||||
void fill_first(int n) {
|
||||
// PRINT: #pragma omp split counts(omp_fill, 3)
|
||||
// DUMP: OMPSplitDirective
|
||||
// DUMP: OMPCountsClause
|
||||
#pragma omp split counts(omp_fill, 3)
|
||||
// PRINT: for (int i = 0; i < n; ++i)
|
||||
// DUMP: ForStmt
|
||||
for (int i = 0; i < n; ++i)
|
||||
body(i);
|
||||
}
|
||||
|
||||
// --- omp_fill at middle position: counts(1, omp_fill, 1) ---
|
||||
// PRINT-LABEL: void fill_mid(
|
||||
// DUMP-LABEL: FunctionDecl {{.*}} fill_mid
|
||||
void fill_mid(int n) {
|
||||
// PRINT: #pragma omp split counts(1, omp_fill, 1)
|
||||
// DUMP: OMPSplitDirective
|
||||
// DUMP: OMPCountsClause
|
||||
#pragma omp split counts(1, omp_fill, 1)
|
||||
// PRINT: for (int i = 0; i < n; ++i)
|
||||
// DUMP: ForStmt
|
||||
for (int i = 0; i < n; ++i)
|
||||
body(i);
|
||||
}
|
||||
|
||||
// --- omp_fill as sole item: counts(omp_fill) ---
|
||||
// PRINT-LABEL: void fill_only(
|
||||
// DUMP-LABEL: FunctionDecl {{.*}} fill_only
|
||||
void fill_only(int n) {
|
||||
// PRINT: #pragma omp split counts(omp_fill)
|
||||
// DUMP: OMPSplitDirective
|
||||
// DUMP: OMPCountsClause
|
||||
#pragma omp split counts(omp_fill)
|
||||
// PRINT: for (int i = 0; i < n; ++i)
|
||||
// DUMP: ForStmt
|
||||
for (int i = 0; i < n; ++i)
|
||||
body(i);
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,17 +0,0 @@
|
||||
// Split nested inside `omp parallel for` outer loop.
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
extern "C" void body(int, int);
|
||||
|
||||
// CHECK: define {{.*}} @composition(
|
||||
// CHECK: .split.iv
|
||||
// CHECK: call void @body
|
||||
extern "C" void composition(void) {
|
||||
#pragma omp parallel for
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int j = 0; j < 10; ++j)
|
||||
body(i, j);
|
||||
}
|
||||
}
|
||||
@ -1,13 +0,0 @@
|
||||
// Associated statement may be a compound `{ for (...) {} }` (split still finds the loop).
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -x c++ -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @f(
|
||||
// CHECK: .split.iv
|
||||
extern "C" void f(void) {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
{
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
/* C++ `constexpr` locals as `counts` operands (distinct from NTTP in split_template_nttp.cpp). */
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -x c++ -std=c++17 -fopenmp -fopenmp-version=60 -fsyntax-only -verify %s
|
||||
// expected-no-diagnostics
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -x c++ -std=c++17 -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
extern "C" void body(int);
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @from_constexpr
|
||||
// CHECK: .split.iv.0
|
||||
// CHECK: icmp slt i32 {{.*}}, 4
|
||||
// CHECK: .split.iv.1
|
||||
// CHECK: icmp slt i32 {{.*}}, 10
|
||||
extern "C" void from_constexpr(void) {
|
||||
static constexpr int C0 = 4;
|
||||
#pragma omp split counts(C0, omp_fill)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
body(i);
|
||||
}
|
||||
@ -1,56 +0,0 @@
|
||||
/* `counts` operands as ICEs: macros, enumerators, sizeof (not only raw literals). */
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -fsyntax-only -verify %s
|
||||
// expected-no-diagnostics
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
#define M1 2
|
||||
|
||||
extern void body(int);
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @from_macros
|
||||
// CHECK: .split.iv.0
|
||||
// CHECK: icmp slt i32 {{.*}}, 2
|
||||
// CHECK: .split.iv.1
|
||||
// CHECK: icmp slt i32 {{.*}}, 10
|
||||
void from_macros(void) {
|
||||
#pragma omp split counts(M1, omp_fill)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
body(i);
|
||||
}
|
||||
|
||||
enum { EFirst = 3 };
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @from_enum
|
||||
// CHECK: .split.iv.0
|
||||
// CHECK: icmp slt i32 {{.*}}, 3
|
||||
// CHECK: .split.iv.1
|
||||
// CHECK: icmp slt i32 {{.*}}, 10
|
||||
void from_enum(void) {
|
||||
#pragma omp split counts(EFirst, omp_fill)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
body(i);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @from_sizeof
|
||||
// CHECK: .split.iv.0
|
||||
// CHECK: icmp slt i32 {{.*}}, 1
|
||||
// CHECK: .split.iv.1
|
||||
// CHECK: icmp slt i32 {{.*}}, 10
|
||||
void from_sizeof(void) {
|
||||
#pragma omp split counts(sizeof(char), omp_fill)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
body(i);
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @from_macro_expr
|
||||
// CHECK: .split.iv.0
|
||||
// CHECK: icmp slt i32 {{.*}}, 4
|
||||
// CHECK: .split.iv.1
|
||||
// CHECK: icmp slt i32 {{.*}}, 10
|
||||
#define BASE 1
|
||||
void from_macro_expr(void) {
|
||||
#pragma omp split counts(BASE + 3, omp_fill)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
body(i);
|
||||
}
|
||||
@ -1,123 +0,0 @@
|
||||
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --include-generated-funcs --version 5
|
||||
/*
|
||||
* Verify #pragma omp split counts(c1, c2, ...) at syntax and IR levels.
|
||||
* counts(3, omp_fill, 2) with n=10 splits into: [0..3), [3..8), [8..10).
|
||||
* Sum 0+1+...+9 = 45.
|
||||
* For end-to-end runtime tests see openmp/runtime/test/transform/split/.
|
||||
*/
|
||||
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -fsyntax-only -verify %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fopenmp -fopenmp-version=60 -emit-llvm %s -o - | FileCheck %s --check-prefix=IR
|
||||
|
||||
int main(void) {
|
||||
const int n = 10;
|
||||
int sum = 0;
|
||||
|
||||
#pragma omp split counts(3, omp_fill, 2)
|
||||
for (int i = 0; i < n; ++i) {
|
||||
sum += i;
|
||||
}
|
||||
|
||||
return (sum == 45) ? 0 : 1;
|
||||
}
|
||||
// IR-LABEL: define dso_local i32 @main(
|
||||
// IR-SAME: ) #[[ATTR0:[0-9]+]] {
|
||||
// IR-NEXT: [[ENTRY:.*:]]
|
||||
// IR-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
|
||||
// IR-NEXT: [[N:%.*]] = alloca i32, align 4
|
||||
// IR-NEXT: [[SUM:%.*]] = alloca i32, align 4
|
||||
// IR-NEXT: [[I:%.*]] = alloca i32, align 4
|
||||
// IR-NEXT: [[DOTOMP_IV:%.*]] = alloca i32, align 4
|
||||
// IR-NEXT: [[DOTSPLIT_IV_0_I:%.*]] = alloca i32, align 4
|
||||
// IR-NEXT: [[DOTSPLIT_IV_1_I:%.*]] = alloca i32, align 4
|
||||
// IR-NEXT: [[DOTSPLIT_IV_2_I:%.*]] = alloca i32, align 4
|
||||
// IR-NEXT: store i32 0, ptr [[RETVAL]], align 4
|
||||
// IR-NEXT: store i32 10, ptr [[N]], align 4
|
||||
// IR-NEXT: store i32 0, ptr [[SUM]], align 4
|
||||
// IR-NEXT: store i32 0, ptr [[I]], align 4
|
||||
// IR-NEXT: store i32 0, ptr [[DOTSPLIT_IV_0_I]], align 4
|
||||
// IR-NEXT: br label %[[FOR_COND:.*]]
|
||||
// IR: [[FOR_COND]]:
|
||||
// IR-NEXT: [[TMP0:%.*]] = load i32, ptr [[DOTSPLIT_IV_0_I]], align 4
|
||||
// IR-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 3
|
||||
// IR-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END:.*]]
|
||||
// IR: [[FOR_BODY]]:
|
||||
// IR-NEXT: [[TMP1:%.*]] = load i32, ptr [[DOTSPLIT_IV_0_I]], align 4
|
||||
// IR-NEXT: store i32 [[TMP1]], ptr [[DOTOMP_IV]], align 4
|
||||
// IR-NEXT: [[TMP2:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4
|
||||
// IR-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], 1
|
||||
// IR-NEXT: [[ADD:%.*]] = add nsw i32 0, [[MUL]]
|
||||
// IR-NEXT: store i32 [[ADD]], ptr [[I]], align 4
|
||||
// IR-NEXT: [[TMP3:%.*]] = load i32, ptr [[I]], align 4
|
||||
// IR-NEXT: [[TMP4:%.*]] = load i32, ptr [[SUM]], align 4
|
||||
// IR-NEXT: [[ADD1:%.*]] = add nsw i32 [[TMP4]], [[TMP3]]
|
||||
// IR-NEXT: store i32 [[ADD1]], ptr [[SUM]], align 4
|
||||
// IR-NEXT: br label %[[FOR_INC:.*]]
|
||||
// IR: [[FOR_INC]]:
|
||||
// IR-NEXT: [[TMP5:%.*]] = load i32, ptr [[DOTSPLIT_IV_0_I]], align 4
|
||||
// IR-NEXT: [[INC:%.*]] = add nsw i32 [[TMP5]], 1
|
||||
// IR-NEXT: store i32 [[INC]], ptr [[DOTSPLIT_IV_0_I]], align 4
|
||||
// IR-NEXT: br label %[[FOR_COND]], !llvm.loop [[LOOP2:![0-9]+]]
|
||||
// IR: [[FOR_END]]:
|
||||
// IR-NEXT: store i32 3, ptr [[DOTSPLIT_IV_1_I]], align 4
|
||||
// IR-NEXT: br label %[[FOR_COND2:.*]]
|
||||
// IR: [[FOR_COND2]]:
|
||||
// IR-NEXT: [[TMP6:%.*]] = load i32, ptr [[DOTSPLIT_IV_1_I]], align 4
|
||||
// IR-NEXT: [[CMP3:%.*]] = icmp slt i32 [[TMP6]], 8
|
||||
// IR-NEXT: br i1 [[CMP3]], label %[[FOR_BODY4:.*]], label %[[FOR_END10:.*]]
|
||||
// IR: [[FOR_BODY4]]:
|
||||
// IR-NEXT: [[TMP7:%.*]] = load i32, ptr [[DOTSPLIT_IV_1_I]], align 4
|
||||
// IR-NEXT: store i32 [[TMP7]], ptr [[DOTOMP_IV]], align 4
|
||||
// IR-NEXT: [[TMP8:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4
|
||||
// IR-NEXT: [[MUL5:%.*]] = mul nsw i32 [[TMP8]], 1
|
||||
// IR-NEXT: [[ADD6:%.*]] = add nsw i32 0, [[MUL5]]
|
||||
// IR-NEXT: store i32 [[ADD6]], ptr [[I]], align 4
|
||||
// IR-NEXT: [[TMP9:%.*]] = load i32, ptr [[I]], align 4
|
||||
// IR-NEXT: [[TMP10:%.*]] = load i32, ptr [[SUM]], align 4
|
||||
// IR-NEXT: [[ADD7:%.*]] = add nsw i32 [[TMP10]], [[TMP9]]
|
||||
// IR-NEXT: store i32 [[ADD7]], ptr [[SUM]], align 4
|
||||
// IR-NEXT: br label %[[FOR_INC8:.*]]
|
||||
// IR: [[FOR_INC8]]:
|
||||
// IR-NEXT: [[TMP11:%.*]] = load i32, ptr [[DOTSPLIT_IV_1_I]], align 4
|
||||
// IR-NEXT: [[INC9:%.*]] = add nsw i32 [[TMP11]], 1
|
||||
// IR-NEXT: store i32 [[INC9]], ptr [[DOTSPLIT_IV_1_I]], align 4
|
||||
// IR-NEXT: br label %[[FOR_COND2]], !llvm.loop [[LOOP4:![0-9]+]]
|
||||
// IR: [[FOR_END10]]:
|
||||
// IR-NEXT: store i32 8, ptr [[DOTSPLIT_IV_2_I]], align 4
|
||||
// IR-NEXT: br label %[[FOR_COND11:.*]]
|
||||
// IR: [[FOR_COND11]]:
|
||||
// IR-NEXT: [[TMP12:%.*]] = load i32, ptr [[DOTSPLIT_IV_2_I]], align 4
|
||||
// IR-NEXT: [[CMP12:%.*]] = icmp slt i32 [[TMP12]], 10
|
||||
// IR-NEXT: br i1 [[CMP12]], label %[[FOR_BODY13:.*]], label %[[FOR_END19:.*]]
|
||||
// IR: [[FOR_BODY13]]:
|
||||
// IR-NEXT: [[TMP13:%.*]] = load i32, ptr [[DOTSPLIT_IV_2_I]], align 4
|
||||
// IR-NEXT: store i32 [[TMP13]], ptr [[DOTOMP_IV]], align 4
|
||||
// IR-NEXT: [[TMP14:%.*]] = load i32, ptr [[DOTOMP_IV]], align 4
|
||||
// IR-NEXT: [[MUL14:%.*]] = mul nsw i32 [[TMP14]], 1
|
||||
// IR-NEXT: [[ADD15:%.*]] = add nsw i32 0, [[MUL14]]
|
||||
// IR-NEXT: store i32 [[ADD15]], ptr [[I]], align 4
|
||||
// IR-NEXT: [[TMP15:%.*]] = load i32, ptr [[I]], align 4
|
||||
// IR-NEXT: [[TMP16:%.*]] = load i32, ptr [[SUM]], align 4
|
||||
// IR-NEXT: [[ADD16:%.*]] = add nsw i32 [[TMP16]], [[TMP15]]
|
||||
// IR-NEXT: store i32 [[ADD16]], ptr [[SUM]], align 4
|
||||
// IR-NEXT: br label %[[FOR_INC17:.*]]
|
||||
// IR: [[FOR_INC17]]:
|
||||
// IR-NEXT: [[TMP17:%.*]] = load i32, ptr [[DOTSPLIT_IV_2_I]], align 4
|
||||
// IR-NEXT: [[INC18:%.*]] = add nsw i32 [[TMP17]], 1
|
||||
// IR-NEXT: store i32 [[INC18]], ptr [[DOTSPLIT_IV_2_I]], align 4
|
||||
// IR-NEXT: br label %[[FOR_COND11]], !llvm.loop [[LOOP5:![0-9]+]]
|
||||
// IR: [[FOR_END19]]:
|
||||
// IR-NEXT: [[TMP18:%.*]] = load i32, ptr [[SUM]], align 4
|
||||
// IR-NEXT: [[CMP20:%.*]] = icmp eq i32 [[TMP18]], 45
|
||||
// IR-NEXT: [[TMP19:%.*]] = zext i1 [[CMP20]] to i64
|
||||
// IR-NEXT: [[COND:%.*]] = select i1 [[CMP20]], i32 0, i32 1
|
||||
// IR-NEXT: ret i32 [[COND]]
|
||||
//
|
||||
//.
|
||||
// IR: [[LOOP2]] = distinct !{[[LOOP2]], [[META3:![0-9]+]]}
|
||||
// IR: [[META3]] = !{!"llvm.loop.mustprogress"}
|
||||
// IR: [[LOOP4]] = distinct !{[[LOOP4]], [[META3]]}
|
||||
// IR: [[LOOP5]] = distinct !{[[LOOP5]], [[META3]]}
|
||||
//.
|
||||
@ -1,61 +0,0 @@
|
||||
/*
|
||||
* Error and delayed-transformation cases for #pragma omp split counts(...).
|
||||
*/
|
||||
// 1) Required clause missing: err_omp_required_clause
|
||||
// RUN: not %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -fsyntax-only -DTEST_REQUIRED_CLAUSE %s 2>&1 | FileCheck %s --check-prefix=REQ
|
||||
// 2) counts(negative): non-negative diagnostic
|
||||
// RUN: not %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -fsyntax-only -DTEST_NEGATIVE %s 2>&1 | FileCheck %s --check-prefix=NEG
|
||||
// 3) counts(non-integer): integral type diagnostic
|
||||
// RUN: not %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -fsyntax-only -DTEST_FLOAT %s 2>&1 | FileCheck %s --check-prefix=FLOAT
|
||||
// 6) Loop not transformable (while): must be a for loop
|
||||
// RUN: not %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -fsyntax-only -DTEST_WHILE %s 2>&1 | FileCheck %s --check-prefix=WHILE
|
||||
// Two invalid counts — two diagnostics on the clause
|
||||
// RUN: not %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -fsyntax-only -DTEST_DOUBLE_NEGATIVE %s 2>&1 | FileCheck %s --check-prefix=DBLNEG
|
||||
|
||||
#ifdef TEST_REQUIRED_CLAUSE
|
||||
void test_required_clause_missing(void) {
|
||||
#pragma omp split
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
}
|
||||
}
|
||||
// REQ: error: {{.*}}requires the 'counts' clause
|
||||
#endif
|
||||
|
||||
#ifdef TEST_NEGATIVE
|
||||
void test_negative_count(void) {
|
||||
#pragma omp split counts(-1, omp_fill)
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
}
|
||||
}
|
||||
// NEG: error: {{.*}}counts{{.*}}non-negative integer
|
||||
#endif
|
||||
|
||||
#ifdef TEST_FLOAT
|
||||
void test_float_count(void) {
|
||||
#pragma omp split counts(2.5, omp_fill)
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
}
|
||||
}
|
||||
// FLOAT: error: {{.*}}integral or unscoped enumeration type
|
||||
#endif
|
||||
|
||||
#ifdef TEST_WHILE
|
||||
void test_while_not_for(void) {
|
||||
int i = 0;
|
||||
#pragma omp split counts(5, omp_fill)
|
||||
while (i < 10) {
|
||||
++i;
|
||||
}
|
||||
}
|
||||
// WHILE: error: {{.*}}must be a for loop
|
||||
#endif
|
||||
|
||||
#ifdef TEST_DOUBLE_NEGATIVE
|
||||
void test_two_negative_counts(void) {
|
||||
#pragma omp split counts(-1, -1, omp_fill)
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
}
|
||||
}
|
||||
// DBLNEG: error: {{.*}}counts{{.*}}non-negative integer
|
||||
// DBLNEG: error: {{.*}}counts{{.*}}non-negative integer
|
||||
#endif
|
||||
@ -1,14 +0,0 @@
|
||||
// `distribute` outer loop with inner `split` (combined-construct interop beyond host `teams` case).
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -x c++ -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @f(
|
||||
// CHECK: .split.iv
|
||||
extern "C" void f(void) {
|
||||
#pragma omp distribute
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int j = 0; j < 10; ++j) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
// Driver forwards `-fopenmp-version=60` with split source (`###` only — no link).
|
||||
// REQUIRES: x86-registered-target
|
||||
//
|
||||
// RUN: %clang -### --target=x86_64-unknown-linux-gnu -fopenmp -fopenmp-version=60 -c %s -o %t.o 2>&1 | FileCheck %s --check-prefix=INVOC
|
||||
|
||||
void f(int n) {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int i = 0; i < n; ++i) {
|
||||
}
|
||||
}
|
||||
|
||||
// INVOC: -fopenmp-version=60
|
||||
@ -1,24 +0,0 @@
|
||||
/* Non-int IV types with split. */
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s --check-prefix=U32
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s --check-prefix=I64
|
||||
|
||||
extern void body(unsigned int);
|
||||
extern void body64(long);
|
||||
|
||||
// U32-LABEL: define {{.*}} @unsigned_iv
|
||||
// U32: .split.iv
|
||||
// U32-DAG: icmp ult i32
|
||||
void unsigned_iv(void) {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (unsigned i = 0; i < 10U; ++i)
|
||||
body(i);
|
||||
}
|
||||
|
||||
// I64-LABEL: define {{.*}} @long_iv
|
||||
// I64: .split.iv
|
||||
// I64-DAG: icmp slt i64
|
||||
void long_iv(void) {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (long i = 0; i < 10L; ++i)
|
||||
body64(i);
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
// Outer-declared iteration variable + split.
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
extern "C" void body(int);
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @outer_iv(
|
||||
// CHECK: .split.iv
|
||||
extern "C" void outer_iv(int n) {
|
||||
int i;
|
||||
#pragma omp split counts(3, omp_fill)
|
||||
for (i = 0; i < n; ++i)
|
||||
body(i);
|
||||
}
|
||||
@ -1,20 +0,0 @@
|
||||
// Split on loop in constructor using member-related bound.
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
extern "C" void body(int);
|
||||
|
||||
struct S {
|
||||
int n;
|
||||
S() : n(10) {
|
||||
#pragma omp split counts(3, omp_fill)
|
||||
for (int i = 0; i < n; ++i)
|
||||
body(i);
|
||||
}
|
||||
};
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @_ZN1SC1Ev
|
||||
// CHECK: .split.iv
|
||||
void use_s() {
|
||||
S s;
|
||||
}
|
||||
@ -1,99 +0,0 @@
|
||||
// OpenMP split / counts: parse and semantic diagnostics.
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -std=c++17 -fopenmp -fopenmp-version=60 -fsyntax-only -verify %s
|
||||
|
||||
void body(int);
|
||||
|
||||
void parse_and_clause_errors() {
|
||||
|
||||
// Malformed `counts` — missing '('
|
||||
// expected-error@+1 {{expected '('}}
|
||||
#pragma omp split counts
|
||||
;
|
||||
|
||||
// Empty `counts` list
|
||||
// expected-error@+1 {{expected expression}}
|
||||
#pragma omp split counts()
|
||||
;
|
||||
|
||||
// Truncated list / missing ')'
|
||||
// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
|
||||
#pragma omp split counts(3
|
||||
for (int i = 0; i < 7; ++i)
|
||||
;
|
||||
|
||||
// Trailing comma only
|
||||
// expected-error@+1 {{expected expression}}
|
||||
#pragma omp split counts(3,)
|
||||
;
|
||||
|
||||
// Expression after comma missing
|
||||
// expected-error@+2 {{expected expression}}
|
||||
// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
|
||||
#pragma omp split counts(3,
|
||||
;
|
||||
|
||||
// Incomplete arithmetic in count (like `tile_messages` sizes(5+))
|
||||
// expected-error@+2 {{expected expression}}
|
||||
// expected-error@+1 {{expected ')'}} expected-note@+1 {{to match this '('}}
|
||||
#pragma omp split counts(5+
|
||||
;
|
||||
|
||||
// `for` keyword not a constant-expression operand
|
||||
// expected-error@+1 {{expected expression}}
|
||||
#pragma omp split counts(for)
|
||||
;
|
||||
|
||||
// Duplicate `counts` clauses
|
||||
// expected-error@+1 {{directive '#pragma omp split' cannot contain more than one 'counts' clause}}
|
||||
#pragma omp split counts(2, omp_fill) counts(3, omp_fill)
|
||||
for (int i = 0; i < 7; ++i)
|
||||
;
|
||||
|
||||
// Disallowed extra clause
|
||||
// expected-error@+1 {{unexpected OpenMP clause 'collapse' in directive '#pragma omp split'}}
|
||||
#pragma omp split counts(2, omp_fill) collapse(2)
|
||||
for (int i = 0; i < 7; ++i)
|
||||
;
|
||||
|
||||
// Non-relational loop condition (canonical loop check)
|
||||
#pragma omp split counts(omp_fill)
|
||||
// expected-error@+1 {{condition of OpenMP for loop must be a relational comparison ('<', '<=', '>', '>=', or '!=') of loop variable 'i'}}
|
||||
for (int i = 0; i / 3 < 7; ++i)
|
||||
;
|
||||
|
||||
// More than one `omp_fill`
|
||||
// expected-error@+1 {{exactly one 'omp_fill' must appear in the 'counts' clause}}
|
||||
#pragma omp split counts(omp_fill, omp_fill)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
body(i);
|
||||
|
||||
// No `omp_fill` at all — also triggers "exactly one" diagnostic.
|
||||
// expected-error@+1 {{exactly one 'omp_fill' must appear in the 'counts' clause}}
|
||||
#pragma omp split counts(2, 3)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
body(i);
|
||||
|
||||
// Positive: `omp_fill` may appear at any position in `counts` (not required to be last).
|
||||
#pragma omp split counts(omp_fill, 2)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
body(i);
|
||||
}
|
||||
|
||||
void associated_statement_diagnostics() {
|
||||
{
|
||||
// expected-error@+2 {{expected statement}}
|
||||
#pragma omp split counts(omp_fill)
|
||||
}
|
||||
|
||||
// Not a `for` loop (contrast `split_diag_errors.c` / `while`)
|
||||
// expected-error@+2 {{statement after '#pragma omp split' must be a for loop}}
|
||||
#pragma omp split counts(omp_fill)
|
||||
int b = 0;
|
||||
|
||||
// expected-warning@+2 {{extra tokens at the end of '#pragma omp split' are ignored}}
|
||||
// expected-error@+1 {{directive '#pragma omp split' requires the 'counts' clause}}
|
||||
#pragma omp split foo
|
||||
for (int i = 0; i < 7; ++i)
|
||||
;
|
||||
}
|
||||
@ -1,12 +0,0 @@
|
||||
// Split attaches to the outer canonical `for`; inner loop stays unsplit.
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
// Exactly one split IV — the outer loop; inner `for` uses plain `i`/`j` control flow.
|
||||
// CHECK-COUNT-1: .split.iv
|
||||
void f(void) {
|
||||
#pragma omp split counts(omp_fill)
|
||||
for (int i = 0; i < 4; ++i)
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
}
|
||||
}
|
||||
@ -1,27 +0,0 @@
|
||||
// Split inside `#pragma omp target` — host and device IR show `.split.iv`.
|
||||
//
|
||||
// RUN: %clang_cc1 -DCK_SPLIT -verify -fopenmp -fopenmp-version=60 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -o - 2>&1 | FileCheck -check-prefix=HOST %s
|
||||
// RUN: %clang_cc1 -DCK_SPLIT -verify -fopenmp -fopenmp-version=60 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm-bc %s -o %t-split-host.bc
|
||||
// RUN: %clang_cc1 -DCK_SPLIT -verify -fopenmp -fopenmp-version=60 -x c++ -triple powerpc64le-unknown-unknown -fopenmp-targets=nvptx64-nvidia-cuda -emit-llvm %s -fopenmp-is-target-device -fopenmp-host-ir-file-path %t-split-host.bc -o - 2>&1 | FileCheck -check-prefix=DEVICE %s
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifdef CK_SPLIT
|
||||
extern "C" void body(int);
|
||||
|
||||
void host_split_in_target(int n) {
|
||||
#pragma omp target map(to : n)
|
||||
{
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int i = 0; i < n; ++i)
|
||||
body(i);
|
||||
}
|
||||
}
|
||||
|
||||
// HOST: define {{.*}}void {{.*}}host_split_in_target
|
||||
// HOST: .split.iv
|
||||
// HOST: __tgt_target_kernel
|
||||
|
||||
// DEVICE: define {{.*}}void @__omp_offloading_
|
||||
// DEVICE: .split.iv
|
||||
#endif
|
||||
@ -1,34 +0,0 @@
|
||||
/* Split + counts with omp_fill: syntax, AST dump, ast-print, IR. */
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -fsyntax-only -verify %s
|
||||
// expected-no-diagnostics
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -ast-dump %s | FileCheck %s --check-prefix=DUMP
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -ast-print %s | FileCheck %s --check-prefix=PRINT
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s --check-prefix=LLVM
|
||||
|
||||
void body(int);
|
||||
|
||||
// PRINT-LABEL: void foo(
|
||||
// DUMP-LABEL: FunctionDecl {{.*}} foo
|
||||
void foo(int n) {
|
||||
// PRINT: #pragma omp split counts(3, omp_fill)
|
||||
// DUMP: OMPSplitDirective
|
||||
// DUMP-NEXT: |-OMPCountsClause
|
||||
// DUMP-NEXT: | |-IntegerLiteral {{.*}} 'int' 3
|
||||
// DUMP-NEXT: | `-{{.*}}
|
||||
// DUMP-NEXT: {{.*}}`-ForStmt
|
||||
#pragma omp split counts(3, omp_fill)
|
||||
// PRINT: for (int i = 0; i < n; ++i)
|
||||
for (int i = 0; i < n; ++i)
|
||||
body(i);
|
||||
}
|
||||
|
||||
// LLVM-LABEL: define {{.*}}void @foo(
|
||||
// LLVM: .split.iv.0.i
|
||||
// LLVM: icmp slt i32 {{.*}}, 3
|
||||
// LLVM: call void @body(
|
||||
// LLVM: store i32 3, ptr %.split.iv.1.i
|
||||
// LLVM: icmp slt i32 {{.*}}, %{{.*}}
|
||||
// LLVM: call void @body(
|
||||
@ -1,22 +0,0 @@
|
||||
// `#pragma omp split` / `counts` require OpenMP 6.x in this implementation.
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -std=c++17 -fopenmp -fopenmp-version=60 -fsyntax-only -DONLY_OK -verify %s
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -std=c++17 -fopenmp -fopenmp-version=52 -fsyntax-only -DONLY_BAD52 -verify=expected52 %s
|
||||
|
||||
#if defined(ONLY_OK)
|
||||
void ok60(void) {
|
||||
#pragma omp split counts(omp_fill)
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
}
|
||||
}
|
||||
// expected-no-diagnostics
|
||||
#endif
|
||||
|
||||
#if defined(ONLY_BAD52)
|
||||
// expected52-error@+2 {{unexpected OpenMP clause 'counts' in directive '#pragma omp split'}}
|
||||
void bad52(void) {
|
||||
#pragma omp split counts(omp_fill)
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@ -1,30 +0,0 @@
|
||||
// Optimized split IR at -O1; split + `-fopenmp-simd` syntax-only; -g debug-info smoke.
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -O1 -emit-llvm -DTEST_BODY %s -o - | FileCheck %s --check-prefix=O1
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp-simd -fopenmp-version=60 -fsyntax-only -verify -DTEST_SIMD %s
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -O0 -emit-llvm -debug-info-kind=limited -DTEST_BODY %s -o - | FileCheck %s --check-prefix=DBG
|
||||
|
||||
extern "C" void body(int);
|
||||
|
||||
#if defined(TEST_SIMD)
|
||||
// expected-no-diagnostics
|
||||
void simd_ok(int n) {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int i = 0; i < n; ++i)
|
||||
body(i);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(TEST_BODY)
|
||||
// O1-LABEL: define {{.*}} @_Z4testi
|
||||
// O1: .split.iv
|
||||
// DBG-LABEL: define {{.*}} @_Z4testi
|
||||
// DBG: .split.iv
|
||||
// DBG: !dbg
|
||||
void test(int n) {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int i = 0; i < n; ++i)
|
||||
body(i);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
// Valid nesting — `split` inside `omp parallel` (contrast `teams` rejection in split_teams_nesting.cpp).
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -x c++ -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @f(
|
||||
// CHECK: __kmpc_fork_call
|
||||
// CHECK: .split.iv
|
||||
extern "C" void f(void) {
|
||||
#pragma omp parallel
|
||||
{
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
// PCH round-trip for AST dump/print and host IR (split + counts).
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -fsyntax-only -verify %s
|
||||
// expected-no-diagnostics
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -ast-dump %s | FileCheck %s --check-prefix=DUMP
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -ast-print %s | FileCheck %s --check-prefix=PRINT
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK1
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -include-pch %t -ast-dump-all %s | FileCheck %s --check-prefix=DUMP
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -include-pch %t -ast-print %s | FileCheck %s --check-prefix=PRINT
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -O0 -include-pch %t -emit-llvm %s -o - | FileCheck %s --check-prefix=CHECK2
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
extern "C" void body(int);
|
||||
|
||||
// PRINT-LABEL: void foo(
|
||||
// DUMP-LABEL: FunctionDecl {{.*}} foo
|
||||
void foo(int n) {
|
||||
// PRINT: #pragma omp split counts(3, omp_fill)
|
||||
// DUMP: OMPSplitDirective
|
||||
// DUMP-NEXT: OMPCountsClause
|
||||
// DUMP: IntegerLiteral {{.*}} 3
|
||||
#pragma omp split counts(3, omp_fill)
|
||||
// DUMP: ForStmt
|
||||
for (int i = 0; i < n; ++i)
|
||||
body(i);
|
||||
}
|
||||
|
||||
// CHECK1-LABEL: define {{.*}} @_Z3foo
|
||||
// CHECK1: .split.iv
|
||||
// CHECK1: icmp
|
||||
// CHECK1: call void @body
|
||||
|
||||
// CHECK2-LABEL: define {{.*}} @_Z3foo
|
||||
// CHECK2: .split.iv
|
||||
// CHECK2: icmp
|
||||
// CHECK2: call void @body
|
||||
|
||||
#endif /* HEADER */
|
||||
@ -1,25 +0,0 @@
|
||||
// C++ range-for + split: verify syntax, IR, and PreInits (range evaluated once).
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -x c++ -std=c++17 -fopenmp -fopenmp-version=60 -fsyntax-only -verify %s
|
||||
// expected-no-diagnostics
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -x c++ -std=c++17 -fopenmp -fopenmp-version=60 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
extern "C" void body(int);
|
||||
|
||||
// CHECK-LABEL: define dso_local void @_Z10range_fillv
|
||||
// CHECK: __range
|
||||
// CHECK: __begin
|
||||
// CHECK: __end
|
||||
// CHECK: .split.iv.0
|
||||
// CHECK: icmp slt i64 {{.*}}, 2
|
||||
// CHECK: call void @body
|
||||
// CHECK: .split.iv.1
|
||||
// CHECK: icmp slt
|
||||
// CHECK: call void @body
|
||||
void range_fill() {
|
||||
int a[] = {10, 20, 30, 40};
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int x : a)
|
||||
body(x);
|
||||
}
|
||||
@ -1,24 +0,0 @@
|
||||
// C++20 module interface with `#pragma omp split` — emit BMI + import; AST retains directive.
|
||||
//
|
||||
// RUN: rm -rf %t && split-file %s %t && cd %t
|
||||
// RUN: %clang_cc1 -std=c++20 -fopenmp -fopenmp-version=60 -triple x86_64-unknown-linux-gnu %t/SplitMod.cppm -emit-module-interface -o %t/SplitMod.pcm
|
||||
// RUN: %clang_cc1 -std=c++20 -fopenmp -fopenmp-version=60 -triple x86_64-unknown-linux-gnu %t/UseSplitMod.cpp -fmodule-file=SplitMod=%t/SplitMod.pcm -ast-dump-all | FileCheck %t/SplitMod.cppm
|
||||
|
||||
// expected-no-diagnostics
|
||||
|
||||
//--- SplitMod.cppm
|
||||
module;
|
||||
export module SplitMod;
|
||||
|
||||
export void splitfoo(int n) {
|
||||
// CHECK: OMPSplitDirective
|
||||
// CHECK: OMPCountsClause
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int i = 0; i < n; ++i) {
|
||||
}
|
||||
}
|
||||
|
||||
//--- UseSplitMod.cpp
|
||||
import SplitMod;
|
||||
|
||||
void g(void) { splitfoo(10); }
|
||||
@ -1,13 +0,0 @@
|
||||
// Split is not valid nested inside `teams` (host diagnostic).
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -x c++ -fopenmp -fopenmp-version=60 -fsyntax-only -verify %s
|
||||
|
||||
void g(void) {
|
||||
#pragma omp teams
|
||||
{
|
||||
// expected-error@+1 {{region cannot be closely nested inside 'teams' region}}
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
// Non-type template parameter as counts operand — IR after instantiation.
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -x c++ -std=c++17 -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @_Z1fILi5EEvv
|
||||
// CHECK: .split.iv
|
||||
// CHECK: icmp slt i32{{.*}} 5
|
||||
template <int N>
|
||||
void f() {
|
||||
#pragma omp split counts(N, omp_fill)
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
}
|
||||
}
|
||||
|
||||
template void f<5>();
|
||||
@ -1,30 +0,0 @@
|
||||
// Dependent template defers transformation; explicit instantiation emits IR.
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -x c++ -std=c++17 -fopenmp -fopenmp-version=60 -ast-dump -DTEST_DEP %s | FileCheck %s --check-prefix=DEP
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -x c++ -std=c++17 -fopenmp -fopenmp-version=60 -O0 -emit-llvm -DTEST_INST %s -o - | FileCheck %s --check-prefix=LLVM
|
||||
|
||||
extern "C" void body(int);
|
||||
|
||||
#if defined(TEST_DEP)
|
||||
template <typename T>
|
||||
void dep_split(T n) {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (T i = 0; i < n; ++i)
|
||||
body((int)i);
|
||||
}
|
||||
// DEP-LABEL: dep_split
|
||||
// DEP: OMPSplitDirective
|
||||
// DEP: ForStmt
|
||||
#endif
|
||||
|
||||
#if defined(TEST_INST)
|
||||
template <typename T>
|
||||
void dep_split(T n) {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (T i = 0; i < n; ++i)
|
||||
body((int)i);
|
||||
}
|
||||
template void dep_split<int>(int);
|
||||
// LLVM: .split.iv
|
||||
// LLVM: call void @body
|
||||
#endif
|
||||
@ -1,14 +0,0 @@
|
||||
// Volatile trip count — IR shows `load volatile` of bound + split IVs (omp_fill segment).
|
||||
//
|
||||
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fopenmp -fopenmp-version=60 -O0 -emit-llvm %s -o - | FileCheck %s
|
||||
|
||||
volatile int n;
|
||||
|
||||
// CHECK-LABEL: define {{.*}} @f
|
||||
// CHECK: load volatile i32, ptr @n
|
||||
// CHECK: .split.iv
|
||||
void f(void) {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int i = 0; i < n; ++i) {
|
||||
}
|
||||
}
|
||||
@ -2362,11 +2362,6 @@ void OMPClauseEnqueue::VisitOMPSizesClause(const OMPSizesClause *C) {
|
||||
Visitor->AddStmt(E);
|
||||
}
|
||||
|
||||
void OMPClauseEnqueue::VisitOMPCountsClause(const OMPCountsClause *C) {
|
||||
for (auto E : C->getCountsRefs())
|
||||
Visitor->AddStmt(E);
|
||||
}
|
||||
|
||||
void OMPClauseEnqueue::VisitOMPPermutationClause(
|
||||
const OMPPermutationClause *C) {
|
||||
for (auto E : C->getArgsRefs())
|
||||
@ -6331,8 +6326,6 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
|
||||
return cxstring::createRef("OMPInterchangeDirective");
|
||||
case CXCursor_OMPFuseDirective:
|
||||
return cxstring::createRef("OMPFuseDirective");
|
||||
case CXCursor_OMPSplitDirective:
|
||||
return cxstring::createRef("OMPSplitDirective");
|
||||
case CXCursor_OMPForDirective:
|
||||
return cxstring::createRef("OMPForDirective");
|
||||
case CXCursor_OMPForSimdDirective:
|
||||
|
||||
@ -697,9 +697,6 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
|
||||
case Stmt::OMPReverseDirectiveClass:
|
||||
K = CXCursor_OMPReverseDirective;
|
||||
break;
|
||||
case Stmt::OMPSplitDirectiveClass:
|
||||
K = CXCursor_OMPSplitDirective;
|
||||
break;
|
||||
case Stmt::OMPInterchangeDirectiveClass:
|
||||
K = CXCursor_OMPInterchangeDirective;
|
||||
break;
|
||||
|
||||
@ -7,9 +7,7 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "ASTMatchersTest.h"
|
||||
#include "clang/AST/OpenMPClause.h"
|
||||
#include "clang/AST/PrettyPrinter.h"
|
||||
#include "clang/AST/StmtOpenMP.h"
|
||||
#include "clang/ASTMatchers/ASTMatchFinder.h"
|
||||
#include "clang/ASTMatchers/ASTMatchers.h"
|
||||
#include "clang/Tooling/Tooling.h"
|
||||
@ -3105,66 +3103,6 @@ TEST(ASTMatchersTestOpenMP, OMPTargetUpdateDirective_CountExpression) {
|
||||
}
|
||||
}
|
||||
|
||||
// OpenMP 6 split directive / counts clause
|
||||
TEST(ASTMatchersTestOpenMP, OMPSplitDirective) {
|
||||
auto Matcher = stmt(ompSplitDirective(hasStructuredBlock(forStmt())));
|
||||
|
||||
StringRef SplitOk = R"(
|
||||
void f() {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int i = 0; i < 10; ++i) {}
|
||||
}
|
||||
)";
|
||||
EXPECT_TRUE(matchesWithOpenMP60(SplitOk, Matcher));
|
||||
|
||||
StringRef ParallelOnly = R"(
|
||||
void f() {
|
||||
#pragma omp parallel
|
||||
;
|
||||
}
|
||||
)";
|
||||
EXPECT_TRUE(notMatchesWithOpenMP60(ParallelOnly, Matcher));
|
||||
}
|
||||
|
||||
TEST(ASTMatchersTestOpenMP, OMPSplitDirective_HasCountsClause) {
|
||||
auto Matcher = stmt(ompSplitDirective(hasAnyClause(ompCountsClause())));
|
||||
|
||||
StringRef Source0 = R"(
|
||||
void f() {
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int i = 0; i < 10; ++i) {}
|
||||
}
|
||||
)";
|
||||
EXPECT_TRUE(matchesWithOpenMP60(Source0, Matcher));
|
||||
}
|
||||
|
||||
TEST(ASTMatchersTestOpenMP, OMPCountsClause_OmpFillOperand) {
|
||||
StringRef Source0 = R"(
|
||||
void f() {
|
||||
#pragma omp split counts(1, omp_fill)
|
||||
for (int i = 0; i < 10; ++i) {}
|
||||
}
|
||||
)";
|
||||
auto AST = tooling::buildASTFromCodeWithArgs(
|
||||
Source0, {"-std=gnu++11", "-target", "i386-unknown-unknown",
|
||||
"-fopenmp=libomp", "-fopenmp-version=60"});
|
||||
ASSERT_TRUE(AST);
|
||||
auto Results = match(ompSplitDirective().bind("split"), AST->getASTContext());
|
||||
ASSERT_EQ(Results.size(), 1u);
|
||||
const auto *Dir = Results[0].getNodeAs<OMPSplitDirective>("split");
|
||||
ASSERT_TRUE(Dir);
|
||||
const OMPCountsClause *Counts = nullptr;
|
||||
for (OMPClause *C : Dir->clauses()) {
|
||||
if ((Counts = dyn_cast<OMPCountsClause>(C)))
|
||||
break;
|
||||
}
|
||||
ASSERT_TRUE(Counts);
|
||||
ASSERT_EQ(Counts->getNumCounts(), 2u);
|
||||
EXPECT_TRUE(Counts->hasOmpFill());
|
||||
EXPECT_EQ(*Counts->getOmpFillIndex(), 1u);
|
||||
EXPECT_FALSE(Counts->getCountsRefs()[1]);
|
||||
}
|
||||
|
||||
TEST(ASTMatchersTest, Finder_DynamicOnlyAcceptsSomeMatchers) {
|
||||
MatchFinder Finder;
|
||||
EXPECT_TRUE(Finder.addDynamicMatcher(decl(), nullptr));
|
||||
|
||||
@ -289,20 +289,6 @@ testing::AssertionResult notMatchesWithOpenMP51(const Twine &Code,
|
||||
{"-fopenmp=libomp", "-fopenmp-version=51"});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
testing::AssertionResult matchesWithOpenMP60(const Twine &Code,
|
||||
const T &AMatcher) {
|
||||
return matchesConditionally(Code, AMatcher, true,
|
||||
{"-fopenmp=libomp", "-fopenmp-version=60"});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
testing::AssertionResult notMatchesWithOpenMP60(const Twine &Code,
|
||||
const T &AMatcher) {
|
||||
return matchesConditionally(Code, AMatcher, false,
|
||||
{"-fopenmp=libomp", "-fopenmp-version=60"});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
testing::AssertionResult matchesWithFixedpoint(const std::string &Code,
|
||||
const T &AMatcher) {
|
||||
|
||||
@ -142,7 +142,6 @@ def OMPC_CopyPrivate : Clause<[Spelling<"copyprivate">]> {
|
||||
let flangClass = "OmpObjectList";
|
||||
}
|
||||
def OMPC_Counts : Clause<[Spelling<"counts">]> {
|
||||
let clangClass = "OMPCountsClause";
|
||||
}
|
||||
def OMPC_Default : Clause<[Spelling<"default">]> {
|
||||
let clangClass = "OMPDefaultClause";
|
||||
@ -1204,6 +1203,16 @@ def OMP_EndSingle : Directive<[Spelling<"end single">]> {
|
||||
let category = OMP_Single.category;
|
||||
let languages = [L_Fortran];
|
||||
}
|
||||
def OMP_Split : Directive<[Spelling<"split">]> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<OMPC_Apply, 60>,
|
||||
];
|
||||
let allowedOnceClauses = [
|
||||
VersionedClause<OMPC_Counts, 60>,
|
||||
];
|
||||
let association = AS_LoopNest;
|
||||
let category = CA_Executable;
|
||||
}
|
||||
def OMP_Target : Directive<[Spelling<"target">]> {
|
||||
let allowedClauses = [
|
||||
VersionedClause<OMPC_Allocate>,
|
||||
@ -1426,16 +1435,6 @@ def OMP_Stripe : Directive<[Spelling<"stripe">]> {
|
||||
let association = AS_LoopNest;
|
||||
let category = CA_Executable;
|
||||
}
|
||||
def OMP_Split : Directive<[Spelling<"split">]> {
|
||||
let allowedOnceClauses = [
|
||||
VersionedClause<OMPC_Counts, 60>,
|
||||
];
|
||||
let requiredClauses = [
|
||||
VersionedClause<OMPC_Counts, 60>,
|
||||
];
|
||||
let association = AS_LoopNest;
|
||||
let category = CA_Executable;
|
||||
}
|
||||
def OMP_Unknown : Directive<[Spelling<"unknown">]> {
|
||||
let isDefault = true;
|
||||
let association = AS_None;
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("do\n");
|
||||
#pragma omp split counts(omp_fill, 2)
|
||||
for (int i = 0; i < 7; ++i)
|
||||
printf("i=%d\n", i);
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK-NEXT: i=0
|
||||
// CHECK-NEXT: i=1
|
||||
// CHECK-NEXT: i=2
|
||||
// CHECK-NEXT: i=3
|
||||
// CHECK-NEXT: i=4
|
||||
// CHECK-NEXT: i=5
|
||||
// CHECK-NEXT: i=6
|
||||
// CHECK-NEXT: done
|
||||
@ -1,24 +0,0 @@
|
||||
// RUN: %libomp-cxx-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
|
||||
int main() {
|
||||
std::vector<int> v = {10, 20, 30, 40, 50, 60};
|
||||
printf("do\n");
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int x : v)
|
||||
printf("x=%d\n", x);
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK-NEXT: x=10
|
||||
// CHECK-NEXT: x=20
|
||||
// CHECK-NEXT: x=30
|
||||
// CHECK-NEXT: x=40
|
||||
// CHECK-NEXT: x=50
|
||||
// CHECK-NEXT: x=60
|
||||
// CHECK-NEXT: done
|
||||
@ -1,26 +0,0 @@
|
||||
// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("do\n");
|
||||
#pragma omp split counts(3, omp_fill, 2)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
printf("i=%d\n", i);
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK-NEXT: i=0
|
||||
// CHECK-NEXT: i=1
|
||||
// CHECK-NEXT: i=2
|
||||
// CHECK-NEXT: i=3
|
||||
// CHECK-NEXT: i=4
|
||||
// CHECK-NEXT: i=5
|
||||
// CHECK-NEXT: i=6
|
||||
// CHECK-NEXT: i=7
|
||||
// CHECK-NEXT: i=8
|
||||
// CHECK-NEXT: i=9
|
||||
// CHECK-NEXT: done
|
||||
@ -1,27 +0,0 @@
|
||||
// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
int n = 8;
|
||||
printf("do\n");
|
||||
#pragma omp split counts(1, omp_fill, 1)
|
||||
for (int i = -1; i <= n; ++i)
|
||||
printf("i=%d\n", i);
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK-NEXT: i=-1
|
||||
// CHECK-NEXT: i=0
|
||||
// CHECK-NEXT: i=1
|
||||
// CHECK-NEXT: i=2
|
||||
// CHECK-NEXT: i=3
|
||||
// CHECK-NEXT: i=4
|
||||
// CHECK-NEXT: i=5
|
||||
// CHECK-NEXT: i=6
|
||||
// CHECK-NEXT: i=7
|
||||
// CHECK-NEXT: i=8
|
||||
// CHECK-NEXT: done
|
||||
@ -1,139 +0,0 @@
|
||||
// RUN: %libomp-cxx20-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
struct Reporter {
|
||||
const char *name;
|
||||
|
||||
Reporter(const char *name) : name(name) { print("ctor"); }
|
||||
|
||||
Reporter() : name("<anon>") { print("ctor"); }
|
||||
|
||||
Reporter(const Reporter &that) : name(that.name) { print("copy ctor"); }
|
||||
|
||||
Reporter(Reporter &&that) : name(that.name) { print("move ctor"); }
|
||||
|
||||
~Reporter() { print("dtor"); }
|
||||
|
||||
const Reporter &operator=(const Reporter &that) {
|
||||
print("copy assign");
|
||||
this->name = that.name;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Reporter &operator=(Reporter &&that) {
|
||||
print("move assign");
|
||||
this->name = that.name;
|
||||
return *this;
|
||||
}
|
||||
|
||||
struct Iterator {
|
||||
const Reporter *owner;
|
||||
int pos;
|
||||
|
||||
Iterator(const Reporter *owner, int pos) : owner(owner), pos(pos) {}
|
||||
|
||||
Iterator(const Iterator &that) : owner(that.owner), pos(that.pos) {
|
||||
owner->print("iterator copy ctor");
|
||||
}
|
||||
|
||||
Iterator(Iterator &&that) : owner(that.owner), pos(that.pos) {
|
||||
owner->print("iterator move ctor");
|
||||
}
|
||||
|
||||
~Iterator() { owner->print("iterator dtor"); }
|
||||
|
||||
const Iterator &operator=(const Iterator &that) {
|
||||
owner->print("iterator copy assign");
|
||||
this->owner = that.owner;
|
||||
this->pos = that.pos;
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Iterator &operator=(Iterator &&that) {
|
||||
owner->print("iterator move assign");
|
||||
this->owner = that.owner;
|
||||
this->pos = that.pos;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Iterator &that) const {
|
||||
owner->print("iterator %d == %d", this->pos, that.pos);
|
||||
return this->pos == that.pos;
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator &that) const {
|
||||
owner->print("iterator %d != %d", this->pos, that.pos);
|
||||
return this->pos != that.pos;
|
||||
}
|
||||
|
||||
Iterator &operator++() {
|
||||
owner->print("iterator prefix ++");
|
||||
pos += 1;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Iterator operator++(int) {
|
||||
owner->print("iterator postfix ++");
|
||||
auto result = *this;
|
||||
pos += 1;
|
||||
return result;
|
||||
}
|
||||
|
||||
int operator*() const {
|
||||
owner->print("iterator deref: %d", pos);
|
||||
return pos;
|
||||
}
|
||||
|
||||
size_t operator-(const Iterator &that) const {
|
||||
int result = this->pos - that.pos;
|
||||
owner->print("iterator distance: %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
Iterator operator+(int steps) const {
|
||||
owner->print("iterator advance: %d += %d", this->pos, steps);
|
||||
return Iterator(owner, pos + steps);
|
||||
}
|
||||
};
|
||||
|
||||
Iterator begin() const {
|
||||
print("begin()");
|
||||
return Iterator(this, 0);
|
||||
}
|
||||
|
||||
Iterator end() const {
|
||||
print("end()");
|
||||
return Iterator(this, 4);
|
||||
}
|
||||
|
||||
void print(const char *msg, ...) const {
|
||||
va_list args;
|
||||
va_start(args, msg);
|
||||
printf("[%s] ", name);
|
||||
vprintf(msg, args);
|
||||
printf("\n");
|
||||
va_end(args);
|
||||
}
|
||||
};
|
||||
|
||||
int main() {
|
||||
printf("do\n");
|
||||
Reporter range("range");
|
||||
#pragma omp split counts(1, omp_fill, 1)
|
||||
for (auto it = range.begin(); it != range.end(); ++it)
|
||||
printf("v=%d\n", *it);
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK: [range] ctor
|
||||
// CHECK: v=0
|
||||
// CHECK: v=1
|
||||
// CHECK: v=2
|
||||
// CHECK: v=3
|
||||
// CHECK: done
|
||||
// CHECK: [range] dtor
|
||||
@ -1,22 +0,0 @@
|
||||
// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
int n = 4;
|
||||
printf("do\n");
|
||||
#pragma omp split counts(2, omp_fill)
|
||||
for (int i = 0; i <= n; ++i)
|
||||
printf("i=%d\n", i);
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK-NEXT: i=0
|
||||
// CHECK-NEXT: i=1
|
||||
// CHECK-NEXT: i=2
|
||||
// CHECK-NEXT: i=3
|
||||
// CHECK-NEXT: i=4
|
||||
// CHECK-NEXT: done
|
||||
@ -1,22 +0,0 @@
|
||||
// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("do\n");
|
||||
#pragma omp split counts(1, omp_fill, 1)
|
||||
for (int i = 5; i >= 0; --i)
|
||||
printf("i=%d\n", i);
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK-NEXT: i=5
|
||||
// CHECK-NEXT: i=4
|
||||
// CHECK-NEXT: i=3
|
||||
// CHECK-NEXT: i=2
|
||||
// CHECK-NEXT: i=1
|
||||
// CHECK-NEXT: i=0
|
||||
// CHECK-NEXT: done
|
||||
@ -1,27 +0,0 @@
|
||||
// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
int v = 3;
|
||||
printf("do\n");
|
||||
#pragma omp split counts(v, omp_fill)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
printf("i=%d\n", i);
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK-NEXT: i=0
|
||||
// CHECK-NEXT: i=1
|
||||
// CHECK-NEXT: i=2
|
||||
// CHECK-NEXT: i=3
|
||||
// CHECK-NEXT: i=4
|
||||
// CHECK-NEXT: i=5
|
||||
// CHECK-NEXT: i=6
|
||||
// CHECK-NEXT: i=7
|
||||
// CHECK-NEXT: i=8
|
||||
// CHECK-NEXT: i=9
|
||||
// CHECK-NEXT: done
|
||||
@ -1,22 +0,0 @@
|
||||
// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
int n = 19;
|
||||
int c = 3;
|
||||
printf("do\n");
|
||||
#pragma omp split counts(1, omp_fill, 1)
|
||||
for (int i = 7; i < n; i += c)
|
||||
printf("i=%d\n", i);
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK-NEXT: i=7
|
||||
// CHECK-NEXT: i=10
|
||||
// CHECK-NEXT: i=13
|
||||
// CHECK-NEXT: i=16
|
||||
// CHECK-NEXT: done
|
||||
@ -1,27 +0,0 @@
|
||||
// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("do\n");
|
||||
#pragma omp parallel num_threads(1)
|
||||
{
|
||||
#pragma omp split counts(2, omp_fill, 2)
|
||||
for (int i = 0; i < 8; ++i)
|
||||
printf("i=%d\n", i);
|
||||
}
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK-NEXT: i=0
|
||||
// CHECK-NEXT: i=1
|
||||
// CHECK-NEXT: i=2
|
||||
// CHECK-NEXT: i=3
|
||||
// CHECK-NEXT: i=4
|
||||
// CHECK-NEXT: i=5
|
||||
// CHECK-NEXT: i=6
|
||||
// CHECK-NEXT: i=7
|
||||
// CHECK-NEXT: done
|
||||
@ -1,23 +0,0 @@
|
||||
// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
int n = 6;
|
||||
printf("do\n");
|
||||
#pragma omp split counts(omp_fill)
|
||||
for (int i = 0; i < n; ++i)
|
||||
printf("i=%d\n", i);
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK-NEXT: i=0
|
||||
// CHECK-NEXT: i=1
|
||||
// CHECK-NEXT: i=2
|
||||
// CHECK-NEXT: i=3
|
||||
// CHECK-NEXT: i=4
|
||||
// CHECK-NEXT: i=5
|
||||
// CHECK-NEXT: done
|
||||
@ -1,26 +0,0 @@
|
||||
// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("do\n");
|
||||
#pragma omp split counts(2, 2, omp_fill)
|
||||
for (int i = 0; i < 10; ++i)
|
||||
printf("i=%d\n", i);
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK-NEXT: i=0
|
||||
// CHECK-NEXT: i=1
|
||||
// CHECK-NEXT: i=2
|
||||
// CHECK-NEXT: i=3
|
||||
// CHECK-NEXT: i=4
|
||||
// CHECK-NEXT: i=5
|
||||
// CHECK-NEXT: i=6
|
||||
// CHECK-NEXT: i=7
|
||||
// CHECK-NEXT: i=8
|
||||
// CHECK-NEXT: i=9
|
||||
// CHECK-NEXT: done
|
||||
@ -1,32 +0,0 @@
|
||||
// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
// Tiny trip counts: trip=1 with counts(1, omp_fill) and trip=0.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
int n;
|
||||
|
||||
n = 1;
|
||||
printf("trip1\n");
|
||||
#pragma omp split counts(1, omp_fill)
|
||||
for (int i = 0; i < n; ++i)
|
||||
printf("i=%d\n", i);
|
||||
printf("end1\n");
|
||||
|
||||
n = 0;
|
||||
printf("trip0\n");
|
||||
#pragma omp split counts(omp_fill)
|
||||
for (int i = 0; i < n; ++i)
|
||||
printf("i=%d\n", i);
|
||||
printf("end0\n");
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: trip1
|
||||
// CHECK-NEXT: i=0
|
||||
// CHECK-NEXT: end1
|
||||
// CHECK-NEXT: trip0
|
||||
// CHECK-NEXT: end0
|
||||
@ -1,24 +0,0 @@
|
||||
// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("do\n");
|
||||
#pragma omp split counts(3, omp_fill)
|
||||
for (unsigned i = 0; i < 8; ++i)
|
||||
printf("i=%u\n", i);
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK-NEXT: i=0
|
||||
// CHECK-NEXT: i=1
|
||||
// CHECK-NEXT: i=2
|
||||
// CHECK-NEXT: i=3
|
||||
// CHECK-NEXT: i=4
|
||||
// CHECK-NEXT: i=5
|
||||
// CHECK-NEXT: i=6
|
||||
// CHECK-NEXT: i=7
|
||||
// CHECK-NEXT: done
|
||||
@ -1,21 +0,0 @@
|
||||
// RUN: %libomp-compile-and-run | FileCheck %s --match-full-lines
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("do\n");
|
||||
#pragma omp split counts(0, omp_fill)
|
||||
for (int i = 0; i < 5; ++i)
|
||||
printf("i=%d\n", i);
|
||||
printf("done\n");
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
// CHECK: do
|
||||
// CHECK-NEXT: i=0
|
||||
// CHECK-NEXT: i=1
|
||||
// CHECK-NEXT: i=2
|
||||
// CHECK-NEXT: i=3
|
||||
// CHECK-NEXT: i=4
|
||||
// CHECK-NEXT: done
|
||||
Loading…
x
Reference in New Issue
Block a user