Skip to content

Commit fb91129

Browse files
committed
Add fuse directive patch
1 parent 5eb24fd commit fb91129

31 files changed

+3387
-2
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
@@ -3090,6 +3090,9 @@ DEF_TRAVERSE_STMT(OMPUnrollDirective,
30903090
DEF_TRAVERSE_STMT(OMPReverseDirective,
30913091
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
30923092

3093+
DEF_TRAVERSE_STMT(OMPFuseDirective,
3094+
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
3095+
30933096
DEF_TRAVERSE_STMT(OMPInterchangeDirective,
30943097
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
30953098

clang/include/clang/AST/StmtOpenMP.h

Lines changed: 98 additions & 1 deletion
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) {
@@ -5793,6 +5805,7 @@ class OMPReverseDirective final : public OMPLoopTransformationDirective {
57935805
llvm::omp::OMPD_reverse, StartLoc,
57945806
EndLoc, NumLoops) {
57955807
setNumGeneratedLoops(NumLoops);
5808+
setNumGeneratedLoopNests(1);
57965809
}
57975810

57985811
void setPreInits(Stmt *PreInits) {
@@ -5865,6 +5878,7 @@ class OMPInterchangeDirective final : public OMPLoopTransformationDirective {
58655878
llvm::omp::OMPD_interchange, StartLoc,
58665879
EndLoc, NumLoops) {
58675880
setNumGeneratedLoops(NumLoops);
5881+
setNumGeneratedLoopNests(1);
58685882
}
58695883

58705884
void setPreInits(Stmt *PreInits) {
@@ -5915,6 +5929,89 @@ class OMPInterchangeDirective final : public OMPLoopTransformationDirective {
59155929
}
59165930
};
59175931

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

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11612,6 +11612,14 @@ def note_omp_implicit_dsa : Note<
1161211612
"implicitly determined as %0">;
1161311613
def err_omp_loop_var_dsa : Error<
1161411614
"loop iteration variable in the associated loop of 'omp %1' directive may not be %0, predetermined as %2">;
11615+
def warn_omp_different_loop_ind_var_types : Warning <
11616+
"loop sequence following '#pragma omp %0' contains induction variables of differing types: %1 and %2">;
11617+
def err_omp_not_canonical_loop : Error <
11618+
"loop after '#pragma omp %0' is not in canonical form">;
11619+
def err_omp_not_a_loop_sequence : Error <
11620+
"statement after '#pragma omp %0' must be a loop sequence containing canonical loops or loop-generating constructs">;
11621+
def err_omp_empty_loop_sequence : Error <
11622+
"loop sequence after '#pragma omp %0' must contain at least 1 canonical loop or loop-generating construct">;
1161511623
def err_omp_not_for : Error<
1161611624
"%select{statement after '#pragma omp %1' must be a for loop|"
1161711625
"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
@@ -233,6 +233,7 @@ def OMPStripeDirective : StmtNode<OMPLoopTransformationDirective>;
233233
def OMPUnrollDirective : StmtNode<OMPLoopTransformationDirective>;
234234
def OMPReverseDirective : StmtNode<OMPLoopTransformationDirective>;
235235
def OMPInterchangeDirective : StmtNode<OMPLoopTransformationDirective>;
236+
def OMPFuseDirective : StmtNode<OMPLoopTransformationDirective>;
236237
def OMPForDirective : StmtNode<OMPLoopDirective>;
237238
def OMPForSimdDirective : StmtNode<OMPLoopDirective>;
238239
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
@@ -1481,6 +1488,26 @@ class SemaOpenMP : public SemaBase {
14811488
SmallVectorImpl<OMPLoopBasedDirective::HelperExprs> &LoopHelpers,
14821489
Stmt *&Body, SmallVectorImpl<SmallVector<Stmt *, 0>> &OriginalInits);
14831490

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

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

clang/lib/AST/StmtPrinter.cpp

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

793+
void StmtPrinter::VisitOMPFuseDirective(OMPFuseDirective *Node) {
794+
Indent() << "#pragma omp fuse";
795+
PrintOMPExecutableDirective(Node);
796+
}
797+
793798
void StmtPrinter::VisitOMPForDirective(OMPForDirective *Node) {
794799
Indent() << "#pragma omp for";
795800
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)