12
12
13
13
#include < type_traits>
14
14
15
+ #include " CIRGenFunction.h"
16
+
15
17
#include " mlir/Dialect/Arith/IR/Arith.h"
16
18
#include " mlir/Dialect/OpenACC/OpenACC.h"
17
19
#include " llvm/ADT/TypeSwitch.h"
18
- namespace clang {
20
+
21
+ using namespace clang ;
22
+ using namespace clang ::CIRGen;
23
+
24
+ namespace {
19
25
// Simple type-trait to see if the first template arg is one of the list, so we
20
26
// can tell whether to `if-constexpr` a bunch of stuff.
21
27
template <typename ToTest, typename T, typename ... Tys>
@@ -32,77 +38,10 @@ template <typename CompOpTy> struct CombinedConstructClauseInfo {
32
38
ComputeOpTy computeOp;
33
39
mlir::acc::LoopOp loopOp;
34
40
};
35
-
36
41
template <typename ToTest> constexpr bool isCombinedType = false ;
37
42
template <typename T>
38
43
constexpr bool isCombinedType<CombinedConstructClauseInfo<T>> = true ;
39
44
40
- namespace {
41
- struct DataOperandInfo {
42
- mlir::Location beginLoc;
43
- mlir::Value varValue;
44
- llvm::StringRef name;
45
- };
46
-
47
- inline mlir::Value emitOpenACCIntExpr (CIRGen::CIRGenFunction &cgf,
48
- CIRGen::CIRGenBuilderTy &builder,
49
- const Expr *intExpr) {
50
- mlir::Value expr = cgf.emitScalarExpr (intExpr);
51
- mlir::Location exprLoc = cgf.cgm .getLoc (intExpr->getBeginLoc ());
52
-
53
- mlir::IntegerType targetType = mlir::IntegerType::get (
54
- &cgf.getMLIRContext (), cgf.getContext ().getIntWidth (intExpr->getType ()),
55
- intExpr->getType ()->isSignedIntegerOrEnumerationType ()
56
- ? mlir::IntegerType::SignednessSemantics::Signed
57
- : mlir::IntegerType::SignednessSemantics::Unsigned);
58
-
59
- auto conversionOp = builder.create <mlir::UnrealizedConversionCastOp>(
60
- exprLoc, targetType, expr);
61
- return conversionOp.getResult (0 );
62
- }
63
-
64
- // A helper function that gets the information from an operand to a data
65
- // clause, so that it can be used to emit the data operations.
66
- inline DataOperandInfo getDataOperandInfo (CIRGen::CIRGenFunction &cgf,
67
- CIRGen::CIRGenBuilderTy &builder,
68
- OpenACCDirectiveKind dk,
69
- const Expr *e) {
70
- // TODO: OpenACC: Cache was different enough as to need a separate
71
- // `ActOnCacheVar`, so we are going to need to do some investigations here
72
- // when it comes to implement this for cache.
73
- if (dk == OpenACCDirectiveKind::Cache) {
74
- cgf.cgm .errorNYI (e->getSourceRange (),
75
- " OpenACC data operand for 'cache' directive" );
76
- return {cgf.cgm .getLoc (e->getBeginLoc ()), {}, {}};
77
- }
78
-
79
- const Expr *curVarExpr = e->IgnoreParenImpCasts ();
80
-
81
- mlir::Location exprLoc = cgf.cgm .getLoc (curVarExpr->getBeginLoc ());
82
-
83
- // TODO: OpenACC: Assemble the list of bounds.
84
- if (isa<ArraySectionExpr, ArraySubscriptExpr>(curVarExpr)) {
85
- cgf.cgm .errorNYI (curVarExpr->getSourceRange (),
86
- " OpenACC data clause array subscript/section" );
87
- return {exprLoc, {}, {}};
88
- }
89
-
90
- // TODO: OpenACC: if this is a member expr, emit the VarPtrPtr correctly.
91
- if (isa<MemberExpr>(curVarExpr)) {
92
- cgf.cgm .errorNYI (curVarExpr->getSourceRange (),
93
- " OpenACC Data clause member expr" );
94
- return {exprLoc, {}, {}};
95
- }
96
-
97
- // Sema has made sure that only 4 types of things can get here, array
98
- // subscript, array section, member expr, or DRE to a var decl (or the former
99
- // 3 wrapping a var-decl), so we should be able to assume this is right.
100
- const auto *dre = cast<DeclRefExpr>(curVarExpr);
101
- const auto *vd = cast<VarDecl>(dre->getFoundDecl ()->getCanonicalDecl ());
102
- return {exprLoc, cgf.emitDeclRefLValue (dre).getPointer (), vd->getName ()};
103
- }
104
- } // namespace
105
-
106
45
template <typename OpTy>
107
46
class OpenACCClauseCIREmitter final
108
47
: public OpenACCClauseVisitor<OpenACCClauseCIREmitter<OpTy>> {
@@ -127,6 +66,10 @@ class OpenACCClauseCIREmitter final
127
66
// Keep track of the data operands so that we can update their async clauses.
128
67
llvm::SmallVector<mlir::Operation *> dataOperands;
129
68
69
+ void clauseNotImplemented (const OpenACCClause &c) {
70
+ cgf.cgm .errorNYI (c.getSourceRange (), " OpenACC Clause" , c.getClauseKind ());
71
+ }
72
+
130
73
void setLastDeviceTypeClause (const OpenACCDeviceTypeClause &clause) {
131
74
lastDeviceTypeValues.clear ();
132
75
@@ -137,12 +80,19 @@ class OpenACCClauseCIREmitter final
137
80
});
138
81
}
139
82
140
- void clauseNotImplemented (const OpenACCClause &c ) {
141
- cgf. cgm . errorNYI (c. getSourceRange (), " OpenACC Clause " , c. getClauseKind () );
142
- }
83
+ mlir::Value emitIntExpr (const Expr *intExpr ) {
84
+ mlir::Value expr = cgf. emitScalarExpr (intExpr );
85
+ mlir::Location exprLoc = cgf. cgm . getLoc (intExpr-> getBeginLoc ());
143
86
144
- mlir::Value emitOpenACCIntExpr (const Expr *intExpr) {
145
- return clang::emitOpenACCIntExpr (cgf, builder, intExpr);
87
+ mlir::IntegerType targetType = mlir::IntegerType::get (
88
+ &cgf.getMLIRContext (), cgf.getContext ().getIntWidth (intExpr->getType ()),
89
+ intExpr->getType ()->isSignedIntegerOrEnumerationType ()
90
+ ? mlir::IntegerType::SignednessSemantics::Signed
91
+ : mlir::IntegerType::SignednessSemantics::Unsigned);
92
+
93
+ auto conversionOp = builder.create <mlir::UnrealizedConversionCastOp>(
94
+ exprLoc, targetType, expr);
95
+ return conversionOp.getResult (0 );
146
96
}
147
97
148
98
// 'condition' as an OpenACC grammar production is used for 'if' and (some
@@ -218,11 +168,56 @@ class OpenACCClauseCIREmitter final
218
168
computeEmitter.Visit (&c);
219
169
}
220
170
171
+ struct DataOperandInfo {
172
+ mlir::Location beginLoc;
173
+ mlir::Value varValue;
174
+ llvm::StringRef name;
175
+ };
176
+
177
+ // A helper function that gets the information from an operand to a data
178
+ // clause, so that it can be used to emit the data operations.
179
+ inline DataOperandInfo getDataOperandInfo (OpenACCDirectiveKind dk,
180
+ const Expr *e) {
181
+ // TODO: OpenACC: Cache was different enough as to need a separate
182
+ // `ActOnCacheVar`, so we are going to need to do some investigations here
183
+ // when it comes to implement this for cache.
184
+ if (dk == OpenACCDirectiveKind::Cache) {
185
+ cgf.cgm .errorNYI (e->getSourceRange (),
186
+ " OpenACC data operand for 'cache' directive" );
187
+ return {cgf.cgm .getLoc (e->getBeginLoc ()), {}, {}};
188
+ }
189
+
190
+ const Expr *curVarExpr = e->IgnoreParenImpCasts ();
191
+
192
+ mlir::Location exprLoc = cgf.cgm .getLoc (curVarExpr->getBeginLoc ());
193
+
194
+ // TODO: OpenACC: Assemble the list of bounds.
195
+ if (isa<ArraySectionExpr, ArraySubscriptExpr>(curVarExpr)) {
196
+ cgf.cgm .errorNYI (curVarExpr->getSourceRange (),
197
+ " OpenACC data clause array subscript/section" );
198
+ return {exprLoc, {}, {}};
199
+ }
200
+
201
+ // TODO: OpenACC: if this is a member expr, emit the VarPtrPtr correctly.
202
+ if (isa<MemberExpr>(curVarExpr)) {
203
+ cgf.cgm .errorNYI (curVarExpr->getSourceRange (),
204
+ " OpenACC Data clause member expr" );
205
+ return {exprLoc, {}, {}};
206
+ }
207
+
208
+ // Sema has made sure that only 4 types of things can get here, array
209
+ // subscript, array section, member expr, or DRE to a var decl (or the
210
+ // former 3 wrapping a var-decl), so we should be able to assume this is
211
+ // right.
212
+ const auto *dre = cast<DeclRefExpr>(curVarExpr);
213
+ const auto *vd = cast<VarDecl>(dre->getFoundDecl ()->getCanonicalDecl ());
214
+ return {exprLoc, cgf.emitDeclRefLValue (dre).getPointer (), vd->getName ()};
215
+ }
216
+
221
217
template <typename BeforeOpTy, typename AfterOpTy>
222
218
void addDataOperand (const Expr *varOperand, mlir::acc::DataClause dataClause,
223
219
bool structured, bool implicit) {
224
- DataOperandInfo opInfo =
225
- getDataOperandInfo (cgf, builder, dirKind, varOperand);
220
+ DataOperandInfo opInfo = getDataOperandInfo (dirKind, varOperand);
226
221
mlir::ValueRange bounds;
227
222
228
223
// TODO: OpenACC: we should comprehend the 'modifier-list' here for the data
@@ -394,7 +389,7 @@ class OpenACCClauseCIREmitter final
394
389
if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp,
395
390
mlir::acc::KernelsOp>) {
396
391
operation.addNumWorkersOperand (builder.getContext (),
397
- emitOpenACCIntExpr (clause.getIntExpr ()),
392
+ emitIntExpr (clause.getIntExpr ()),
398
393
lastDeviceTypeValues);
399
394
} else if constexpr (isCombinedType<OpTy>) {
400
395
applyToComputeOp (clause);
@@ -407,7 +402,7 @@ class OpenACCClauseCIREmitter final
407
402
if constexpr (isOneOfTypes<OpTy, mlir::acc::ParallelOp,
408
403
mlir::acc::KernelsOp>) {
409
404
operation.addVectorLengthOperand (builder.getContext (),
410
- emitOpenACCIntExpr (clause.getIntExpr ()),
405
+ emitIntExpr (clause.getIntExpr ()),
411
406
lastDeviceTypeValues);
412
407
} else if constexpr (isCombinedType<OpTy>) {
413
408
applyToComputeOp (clause);
@@ -432,7 +427,7 @@ class OpenACCClauseCIREmitter final
432
427
mlir::OpBuilder::InsertionGuard guardCase (builder);
433
428
if (!dataOperands.empty ())
434
429
builder.setInsertionPoint (dataOperands.front ());
435
- intExpr = emitOpenACCIntExpr (clause.getIntExpr ());
430
+ intExpr = emitIntExpr (clause.getIntExpr ());
436
431
}
437
432
operation.addAsyncOperand (builder.getContext (), intExpr,
438
433
lastDeviceTypeValues);
@@ -444,7 +439,7 @@ class OpenACCClauseCIREmitter final
444
439
operation.setAsync (true );
445
440
else
446
441
operation.getAsyncOperandMutable ().append (
447
- emitOpenACCIntExpr (clause.getIntExpr ()));
442
+ emitIntExpr (clause.getIntExpr ()));
448
443
} else if constexpr (isCombinedType<OpTy>) {
449
444
applyToComputeOp (clause);
450
445
} else {
@@ -499,8 +494,7 @@ class OpenACCClauseCIREmitter final
499
494
void VisitDeviceNumClause (const OpenACCDeviceNumClause &clause) {
500
495
if constexpr (isOneOfTypes<OpTy, mlir::acc::InitOp, mlir::acc::ShutdownOp,
501
496
mlir::acc::SetOp>) {
502
- operation.getDeviceNumMutable ().append (
503
- emitOpenACCIntExpr (clause.getIntExpr ()));
497
+ operation.getDeviceNumMutable ().append (emitIntExpr (clause.getIntExpr ()));
504
498
} else {
505
499
llvm_unreachable (
506
500
" init, shutdown, set, are only valid device_num constructs" );
@@ -512,7 +506,7 @@ class OpenACCClauseCIREmitter final
512
506
mlir::acc::KernelsOp>) {
513
507
llvm::SmallVector<mlir::Value> values;
514
508
for (const Expr *E : clause.getIntExprs ())
515
- values.push_back (emitOpenACCIntExpr (E));
509
+ values.push_back (emitIntExpr (E));
516
510
517
511
operation.addNumGangsOperands (builder.getContext (), values,
518
512
lastDeviceTypeValues);
@@ -531,9 +525,9 @@ class OpenACCClauseCIREmitter final
531
525
} else {
532
526
llvm::SmallVector<mlir::Value> values;
533
527
if (clause.hasDevNumExpr ())
534
- values.push_back (emitOpenACCIntExpr (clause.getDevNumExpr ()));
528
+ values.push_back (emitIntExpr (clause.getDevNumExpr ()));
535
529
for (const Expr *E : clause.getQueueIdExprs ())
536
- values.push_back (emitOpenACCIntExpr (E));
530
+ values.push_back (emitIntExpr (E));
537
531
operation.addWaitOperands (builder.getContext (), clause.hasDevNumExpr (),
538
532
values, lastDeviceTypeValues);
539
533
}
@@ -549,7 +543,7 @@ class OpenACCClauseCIREmitter final
549
543
void VisitDefaultAsyncClause (const OpenACCDefaultAsyncClause &clause) {
550
544
if constexpr (isOneOfTypes<OpTy, mlir::acc::SetOp>) {
551
545
operation.getDefaultAsyncMutable ().append (
552
- emitOpenACCIntExpr (clause.getIntExpr ()));
546
+ emitIntExpr (clause.getIntExpr ()));
553
547
} else {
554
548
llvm_unreachable (" set, is only valid device_num constructs" );
555
549
}
@@ -639,7 +633,7 @@ class OpenACCClauseCIREmitter final
639
633
if constexpr (isOneOfTypes<OpTy, mlir::acc::LoopOp>) {
640
634
if (clause.hasIntExpr ())
641
635
operation.addWorkerNumOperand (builder.getContext (),
642
- emitOpenACCIntExpr (clause.getIntExpr ()),
636
+ emitIntExpr (clause.getIntExpr ()),
643
637
lastDeviceTypeValues);
644
638
else
645
639
operation.addEmptyWorker (builder.getContext (), lastDeviceTypeValues);
@@ -657,7 +651,7 @@ class OpenACCClauseCIREmitter final
657
651
if constexpr (isOneOfTypes<OpTy, mlir::acc::LoopOp>) {
658
652
if (clause.hasIntExpr ())
659
653
operation.addVectorOperand (builder.getContext (),
660
- emitOpenACCIntExpr (clause.getIntExpr ()),
654
+ emitIntExpr (clause.getIntExpr ()),
661
655
lastDeviceTypeValues);
662
656
else
663
657
operation.addEmptyVector (builder.getContext (), lastDeviceTypeValues);
@@ -693,7 +687,7 @@ class OpenACCClauseCIREmitter final
693
687
} else if (isa<OpenACCAsteriskSizeExpr>(expr)) {
694
688
values.push_back (createConstantInt (exprLoc, 64 , -1 ));
695
689
} else {
696
- values.push_back (emitOpenACCIntExpr (expr));
690
+ values.push_back (emitIntExpr (expr));
697
691
}
698
692
}
699
693
@@ -728,5 +722,54 @@ auto makeClauseEmitter(OpTy &op, CIRGen::CIRGenFunction &cgf,
728
722
OpenACCDirectiveKind dirKind, SourceLocation dirLoc) {
729
723
return OpenACCClauseCIREmitter<OpTy>(op, cgf, builder, dirKind, dirLoc);
730
724
}
725
+ } // namespace
726
+
727
+ template <typename Op>
728
+ void CIRGenFunction::emitOpenACCClauses (
729
+ Op &op, OpenACCDirectiveKind dirKind, SourceLocation dirLoc,
730
+ ArrayRef<const OpenACCClause *> clauses) {
731
+ mlir::OpBuilder::InsertionGuard guardCase (builder);
732
+
733
+ // Sets insertion point before the 'op', since every new expression needs to
734
+ // be before the operation.
735
+ builder.setInsertionPoint (op);
736
+ makeClauseEmitter (op, *this , builder, dirKind, dirLoc).emitClauses (clauses);
737
+ }
738
+
739
+ #define EXPL_SPEC (N ) \
740
+ template void CIRGenFunction::emitOpenACCClauses<N>( \
741
+ N &, OpenACCDirectiveKind, SourceLocation, \
742
+ ArrayRef<const OpenACCClause *>);
743
+ EXPL_SPEC (mlir::acc::ParallelOp)
744
+ EXPL_SPEC(mlir::acc::SerialOp)
745
+ EXPL_SPEC(mlir::acc::KernelsOp)
746
+ EXPL_SPEC(mlir::acc::LoopOp)
747
+ EXPL_SPEC(mlir::acc::DataOp)
748
+ EXPL_SPEC(mlir::acc::InitOp)
749
+ EXPL_SPEC(mlir::acc::ShutdownOp)
750
+ EXPL_SPEC(mlir::acc::SetOp)
751
+ EXPL_SPEC(mlir::acc::WaitOp)
752
+ #undef EXPL_SPEC
753
+
754
+ template <typename ComputeOp, typename LoopOp>
755
+ void CIRGenFunction::emitOpenACCClauses (
756
+ ComputeOp &op, LoopOp &loopOp, OpenACCDirectiveKind dirKind,
757
+ SourceLocation dirLoc, ArrayRef<const OpenACCClause *> clauses) {
758
+ static_assert (std::is_same_v<mlir::acc::LoopOp, LoopOp>);
759
+
760
+ CombinedConstructClauseInfo<ComputeOp> inf{op, loopOp};
761
+ // We cannot set the insertion point here and do so in the emitter, but make
762
+ // sure we reset it with the 'guard' anyway.
763
+ mlir::OpBuilder::InsertionGuard guardCase (builder);
764
+ makeClauseEmitter (inf, *this , builder, dirKind, dirLoc).emitClauses (clauses);
765
+ }
766
+
767
+ #define EXPL_SPEC (N ) \
768
+ template void CIRGenFunction::emitOpenACCClauses<N, mlir::acc::LoopOp>( \
769
+ N &, mlir::acc::LoopOp &, OpenACCDirectiveKind, SourceLocation, \
770
+ ArrayRef<const OpenACCClause *>);
731
771
732
- } // namespace clang
772
+ EXPL_SPEC (mlir::acc::ParallelOp)
773
+ EXPL_SPEC(mlir::acc::SerialOp)
774
+ EXPL_SPEC(mlir::acc::KernelsOp)
775
+ #undef EXPL_SPEC
0 commit comments