Skip to content

Commit 204d902

Browse files
committed
Add fuse directive patch
1 parent 6fd3c20 commit 204d902

31 files changed

+3391
-4
lines changed

clang/include/clang-c/Index.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2162,6 +2162,10 @@ enum CXCursorKind {
21622162
*/
21632163
CXCursor_OMPStripeDirective = 310,
21642164

2165+
/** OpenMP fuse directive
2166+
*/
2167+
CXCursor_OMPFuseDirective = 318,
2168+
21652169
/** OpenACC Compute Construct.
21662170
*/
21672171
CXCursor_OpenACCComputeConstruct = 320,

clang/include/clang/AST/RecursiveASTVisitor.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3080,6 +3080,9 @@ DEF_TRAVERSE_STMT(OMPUnrollDirective,
30803080
DEF_TRAVERSE_STMT(OMPReverseDirective,
30813081
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
30823082

3083+
DEF_TRAVERSE_STMT(OMPFuseDirective,
3084+
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
3085+
30833086
DEF_TRAVERSE_STMT(OMPInterchangeDirective,
30843087
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
30853088

clang/include/clang/AST/StmtOpenMP.h

Lines changed: 102 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -962,6 +962,9 @@ class OMPLoopTransformationDirective : public OMPLoopBasedDirective {
962962

963963
/// Number of loops generated by this loop transformation.
964964
unsigned NumGeneratedLoops = 0;
965+
/// Number of top level canonical loop nests generated by this loop
966+
/// transformation
967+
unsigned NumGeneratedLoopNests = 0;
965968

966969
protected:
967970
explicit OMPLoopTransformationDirective(StmtClass SC,
@@ -973,6 +976,9 @@ class OMPLoopTransformationDirective : public OMPLoopBasedDirective {
973976

974977
/// Set the number of loops generated by this loop transformation.
975978
void setNumGeneratedLoops(unsigned Num) { NumGeneratedLoops = Num; }
979+
/// Set the number of top level canonical loop nests generated by this loop
980+
/// transformation
981+
void setNumGeneratedLoopNests(unsigned Num) { NumGeneratedLoopNests = Num; }
976982

977983
public:
978984
/// Return the number of associated (consumed) loops.
@@ -981,6 +987,10 @@ class OMPLoopTransformationDirective : public OMPLoopBasedDirective {
981987
/// Return the number of loops generated by this loop transformation.
982988
unsigned getNumGeneratedLoops() const { return NumGeneratedLoops; }
983989

990+
/// Return the number of top level canonical loop nests generated by this loop
991+
/// transformation
992+
unsigned getNumGeneratedLoopNests() const { return NumGeneratedLoopNests; }
993+
984994
/// Get the de-sugared statements after the loop transformation.
985995
///
986996
/// Might be nullptr if either the directive generates no loops and is handled
@@ -995,7 +1005,8 @@ class OMPLoopTransformationDirective : public OMPLoopBasedDirective {
9951005
Stmt::StmtClass C = T->getStmtClass();
9961006
return C == OMPTileDirectiveClass || C == OMPUnrollDirectiveClass ||
9971007
C == OMPReverseDirectiveClass || C == OMPInterchangeDirectiveClass ||
998-
C == OMPStripeDirectiveClass;
1008+
C == OMPStripeDirectiveClass ||
1009+
C == OMPFuseDirectiveClass;
9991010
}
10001011
};
10011012

@@ -5562,6 +5573,7 @@ class OMPTileDirective final : public OMPLoopTransformationDirective {
55625573
llvm::omp::OMPD_tile, StartLoc, EndLoc,
55635574
NumLoops) {
55645575
setNumGeneratedLoops(2 * NumLoops);
5576+
setNumGeneratedLoopNests(1);
55655577
}
55665578

55675579
void setPreInits(Stmt *PreInits) {
@@ -5790,7 +5802,11 @@ class OMPReverseDirective final : public OMPLoopTransformationDirective {
57905802
explicit OMPReverseDirective(SourceLocation StartLoc, SourceLocation EndLoc)
57915803
: OMPLoopTransformationDirective(OMPReverseDirectiveClass,
57925804
llvm::omp::OMPD_reverse, StartLoc,
5793-
EndLoc, 1) {}
5805+
EndLoc, 1) {
5806+
5807+
setNumGeneratedLoopNests(1);
5808+
setNumGeneratedLoops(1);
5809+
}
57945810

57955811
void setPreInits(Stmt *PreInits) {
57965812
Data->getChildren()[PreInitsOffset] = PreInits;
@@ -5857,7 +5873,8 @@ class OMPInterchangeDirective final : public OMPLoopTransformationDirective {
58575873
: OMPLoopTransformationDirective(OMPInterchangeDirectiveClass,
58585874
llvm::omp::OMPD_interchange, StartLoc,
58595875
EndLoc, NumLoops) {
5860-
setNumGeneratedLoops(3 * NumLoops);
5876+
setNumGeneratedLoops(NumLoops);
5877+
setNumGeneratedLoopNests(1);
58615878
}
58625879

58635880
void setPreInits(Stmt *PreInits) {
@@ -5908,6 +5925,88 @@ class OMPInterchangeDirective final : public OMPLoopTransformationDirective {
59085925
}
59095926
};
59105927

5928+
/// Represents the '#pragma omp fuse' loop transformation directive
5929+
///
5930+
/// \code{c}
5931+
/// #pragma omp fuse
5932+
/// {
5933+
/// for(int i = 0; i < m1; ++i) {...}
5934+
/// for(int j = 0; j < m2; ++j) {...}
5935+
/// ...
5936+
/// }
5937+
/// \endcode
5938+
5939+
class OMPFuseDirective final : public OMPLoopTransformationDirective {
5940+
friend class ASTStmtReader;
5941+
friend class OMPExecutableDirective;
5942+
5943+
// Offsets of child members.
5944+
enum {
5945+
PreInitsOffset = 0,
5946+
TransformedStmtOffset,
5947+
};
5948+
5949+
explicit OMPFuseDirective(SourceLocation StartLoc, SourceLocation EndLoc,
5950+
unsigned NumLoops)
5951+
: OMPLoopTransformationDirective(OMPFuseDirectiveClass,
5952+
llvm::omp::OMPD_fuse, StartLoc, EndLoc,
5953+
NumLoops) {
5954+
setNumGeneratedLoops(1);
5955+
// TODO: After implementing the looprange clause, change this logic
5956+
setNumGeneratedLoopNests(1);
5957+
}
5958+
5959+
void setPreInits(Stmt *PreInits) {
5960+
Data->getChildren()[PreInitsOffset] = PreInits;
5961+
}
5962+
5963+
void setTransformedStmt(Stmt *S) {
5964+
Data->getChildren()[TransformedStmtOffset] = S;
5965+
}
5966+
5967+
public:
5968+
/// Create a new AST node representation for #pragma omp fuse'
5969+
///
5970+
/// \param C Context of the AST
5971+
/// \param StartLoc Location of the introducer (e.g the 'omp' token)
5972+
/// \param EndLoc Location of the directive's end (e.g the tok::eod)
5973+
/// \param Clauses The directive's clauses
5974+
/// \param NumLoops Number of total affected loops
5975+
/// \param NumLoopNests Number of affected top level canonical loops
5976+
/// (number of items in the 'looprange' clause if present)
5977+
/// \param AssociatedStmt The outermost associated loop
5978+
/// \param TransformedStmt The loop nest after fusion, or nullptr in
5979+
/// dependent
5980+
/// \param PreInits Helper preinits statements for the loop nest
5981+
static OMPFuseDirective *Create(const ASTContext &C, SourceLocation StartLoc,
5982+
SourceLocation EndLoc,
5983+
ArrayRef<OMPClause *> Clauses,
5984+
unsigned NumLoops, unsigned NumLoopNests,
5985+
Stmt *AssociatedStmt, Stmt *TransformedStmt,
5986+
Stmt *PreInits);
5987+
5988+
/// Build an empty '#pragma omp fuse' AST node for deserialization
5989+
///
5990+
/// \param C Context of the AST
5991+
/// \param NumClauses Number of clauses to allocate
5992+
/// \param NumLoops Number of associated loops to allocate
5993+
static OMPFuseDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
5994+
unsigned NumLoops);
5995+
5996+
/// Gets the associated loops after the transformation. This is the de-sugared
5997+
/// replacement or nulltpr in dependent contexts.
5998+
Stmt *getTransformedStmt() const {
5999+
return Data->getChildren()[TransformedStmtOffset];
6000+
}
6001+
6002+
/// Return preinits statement.
6003+
Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
6004+
6005+
static bool classof(const Stmt *T) {
6006+
return T->getStmtClass() == OMPFuseDirectiveClass;
6007+
}
6008+
};
6009+
59116010
/// This represents '#pragma omp scan' directive.
59126011
///
59136012
/// \code

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11558,6 +11558,14 @@ def note_omp_implicit_dsa : Note<
1155811558
"implicitly determined as %0">;
1155911559
def err_omp_loop_var_dsa : Error<
1156011560
"loop iteration variable in the associated loop of 'omp %1' directive may not be %0, predetermined as %2">;
11561+
def warn_omp_different_loop_ind_var_types : Warning <
11562+
"loop sequence following '#pragma omp %0' contains induction variables of differing types: %1 and %2">;
11563+
def err_omp_not_canonical_loop : Error <
11564+
"loop after '#pragma omp %0' is not in canonical form">;
11565+
def err_omp_not_a_loop_sequence : Error <
11566+
"statement after '#pragma omp %0' must be a loop sequence containing canonical loops or loop-generating constructs">;
11567+
def err_omp_empty_loop_sequence : Error <
11568+
"loop sequence after '#pragma omp %0' must contain at least 1 canonical loop or loop-generating construct">;
1156111569
def err_omp_not_for : Error<
1156211570
"%select{statement after '#pragma omp %1' must be a for loop|"
1156311571
"expected %2 for loops after '#pragma omp %1'%select{|, but found only %4}3}0">;

clang/include/clang/Basic/StmtNodes.td

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,7 @@ def OMPStripeDirective : StmtNode<OMPLoopTransformationDirective>;
234234
def OMPUnrollDirective : StmtNode<OMPLoopTransformationDirective>;
235235
def OMPReverseDirective : StmtNode<OMPLoopTransformationDirective>;
236236
def OMPInterchangeDirective : StmtNode<OMPLoopTransformationDirective>;
237+
def OMPFuseDirective : StmtNode<OMPLoopTransformationDirective>;
237238
def OMPForDirective : StmtNode<OMPLoopDirective>;
238239
def OMPForSimdDirective : StmtNode<OMPLoopDirective>;
239240
def OMPSectionsDirective : StmtNode<OMPExecutableDirective>;

clang/include/clang/Sema/SemaOpenMP.h

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,13 @@ class SemaOpenMP : public SemaBase {
457457
Stmt *AStmt,
458458
SourceLocation StartLoc,
459459
SourceLocation EndLoc);
460+
461+
/// Called on well-formed '#pragma omp fuse' after parsing of its
462+
/// clauses and the associated statement.
463+
StmtResult ActOnOpenMPFuseDirective(ArrayRef<OMPClause *> Clauses,
464+
Stmt *AStmt, SourceLocation StartLoc,
465+
SourceLocation EndLoc);
466+
460467
/// Called on well-formed '\#pragma omp for' after parsing
461468
/// of the associated statement.
462469
StmtResult
@@ -1480,6 +1487,26 @@ class SemaOpenMP : public SemaBase {
14801487
SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14811488
Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits);
14821489

1490+
/// Analyzes and checks a loop sequence for use by a loop transformation
1491+
///
1492+
/// \param Kind The loop transformation directive kind.
1493+
/// \param NumLoops [out] Number of total canonical loops
1494+
/// \param LoopSeqSize [out] Number of top level canonical loops
1495+
/// \param LoopHelpers [out] The multiple loop analyses results.
1496+
/// \param LoopStmts [out] The multiple Stmt of each For loop.
1497+
/// \param OriginalInits [out] The multiple collection of statements and
1498+
/// declarations that must have been executed/declared
1499+
/// before entering the loop.
1500+
/// \param Context
1501+
/// \return Whether there was an absence of errors or not
1502+
bool checkTransformableLoopSequence(
1503+
OpenMPDirectiveKind Kind, Stmt *AStmt, unsigned &LoopSeqSize,
1504+
unsigned &NumLoops,
1505+
SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
1506+
SmallVectorImpl<Stmt *> &ForStmts,
1507+
SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits,
1508+
ASTContext &Context);
1509+
14831510
/// Helper to keep information about the current `omp begin/end declare
14841511
/// variant` nesting.
14851512
struct OMPDeclareVariantScope {

clang/include/clang/Serialization/ASTBitCodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1948,6 +1948,7 @@ enum StmtCode {
19481948
STMT_OMP_UNROLL_DIRECTIVE,
19491949
STMT_OMP_REVERSE_DIRECTIVE,
19501950
STMT_OMP_INTERCHANGE_DIRECTIVE,
1951+
STMT_OMP_FUSE_DIRECTIVE,
19511952
STMT_OMP_FOR_DIRECTIVE,
19521953
STMT_OMP_FOR_SIMD_DIRECTIVE,
19531954
STMT_OMP_SECTIONS_DIRECTIVE,

clang/lib/AST/StmtOpenMP.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,8 @@ OMPUnrollDirective::Create(const ASTContext &C, SourceLocation StartLoc,
456456
auto *Dir = createDirective<OMPUnrollDirective>(
457457
C, Clauses, AssociatedStmt, TransformedStmtOffset + 1, StartLoc, EndLoc);
458458
Dir->setNumGeneratedLoops(NumGeneratedLoops);
459+
// The number of generated loops and loop nests during unroll matches
460+
Dir->setNumGeneratedLoopNests(NumGeneratedLoops);
459461
Dir->setTransformedStmt(TransformedStmt);
460462
Dir->setPreInits(PreInits);
461463
return Dir;
@@ -505,6 +507,29 @@ OMPInterchangeDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses,
505507
SourceLocation(), SourceLocation(), NumLoops);
506508
}
507509

510+
OMPFuseDirective *OMPFuseDirective::Create(
511+
const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
512+
ArrayRef<OMPClause *> Clauses, unsigned NumLoops, unsigned NumLoopNests,
513+
Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits) {
514+
515+
OMPFuseDirective *Dir = createDirective<OMPFuseDirective>(
516+
C, Clauses, AssociatedStmt, TransformedStmtOffset + 1, StartLoc, EndLoc,
517+
NumLoops);
518+
Dir->setTransformedStmt(TransformedStmt);
519+
Dir->setPreInits(PreInits);
520+
Dir->setNumGeneratedLoopNests(NumLoopNests);
521+
Dir->setNumGeneratedLoops(NumLoops);
522+
return Dir;
523+
}
524+
525+
OMPFuseDirective *OMPFuseDirective::CreateEmpty(const ASTContext &C,
526+
unsigned NumClauses,
527+
unsigned NumLoops) {
528+
return createEmptyDirective<OMPFuseDirective>(
529+
C, NumClauses, /*HasAssociatedStmt=*/true, TransformedStmtOffset + 1,
530+
SourceLocation(), SourceLocation(), NumLoops);
531+
}
532+
508533
OMPForSimdDirective *
509534
OMPForSimdDirective::Create(const ASTContext &C, SourceLocation StartLoc,
510535
SourceLocation EndLoc, unsigned CollapsedNum,

clang/lib/AST/StmtPrinter.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -791,6 +791,11 @@ void StmtPrinter::VisitOMPInterchangeDirective(OMPInterchangeDirective *Node) {
791791
PrintOMPExecutableDirective(Node);
792792
}
793793

794+
void StmtPrinter::VisitOMPFuseDirective(OMPFuseDirective *Node) {
795+
Indent() << "#pragma omp fuse";
796+
PrintOMPExecutableDirective(Node);
797+
}
798+
794799
void StmtPrinter::VisitOMPForDirective(OMPForDirective *Node) {
795800
Indent() << "#pragma omp for";
796801
PrintOMPExecutableDirective(Node);

clang/lib/AST/StmtProfile.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1026,6 +1026,10 @@ void StmtProfiler::VisitOMPInterchangeDirective(
10261026
VisitOMPLoopTransformationDirective(S);
10271027
}
10281028

1029+
void StmtProfiler::VisitOMPFuseDirective(const OMPFuseDirective *S) {
1030+
VisitOMPLoopTransformationDirective(S);
1031+
}
1032+
10291033
void StmtProfiler::VisitOMPForDirective(const OMPForDirective *S) {
10301034
VisitOMPLoopDirective(S);
10311035
}

0 commit comments

Comments
 (0)