@@ -32,46 +32,51 @@ constexpr bool isOneOfTypes =
32
32
template <typename ToTest, typename T>
33
33
constexpr bool isOneOfTypes<ToTest, T> = std::is_same_v<ToTest, T>;
34
34
35
+ template <typename OpTy>
35
36
class OpenACCClauseCIREmitter final
36
- : public OpenACCClauseVisitor<OpenACCClauseCIREmitter> {
37
- CIRGenModule &cgm;
37
+ : public OpenACCClauseVisitor<OpenACCClauseCIREmitter<OpTy>> {
38
+ OpTy &operation;
39
+ CIRGenFunction &cgf;
40
+ CIRGenBuilderTy &builder;
41
+
38
42
// This is necessary since a few of the clauses emit differently based on the
39
43
// directive kind they are attached to.
40
44
OpenACCDirectiveKind dirKind;
45
+ // TODO(cir): This source location should be able to go away once the NYI
46
+ // diagnostics are gone.
41
47
SourceLocation dirLoc;
42
48
43
- struct AttributeData {
44
- // Value of the 'default' attribute, added on 'data' and 'compute'/etc
45
- // constructs as a 'default-attr'.
46
- std::optional<ClauseDefaultValue> defaultVal = std::nullopt;
47
- // For directives that have their device type architectures listed in
48
- // attributes (init/shutdown/etc), the list of architectures to be emitted.
49
- llvm::SmallVector<mlir::acc::DeviceType> deviceTypeArchs{};
50
- } attrData;
51
-
52
49
void clauseNotImplemented (const OpenACCClause &c) {
53
- cgm.errorNYI (c.getSourceRange (), " OpenACC Clause" , c.getClauseKind ());
50
+ cgf. cgm .errorNYI (c.getSourceRange (), " OpenACC Clause" , c.getClauseKind ());
54
51
}
55
52
56
53
public:
57
- OpenACCClauseCIREmitter (CIRGenModule &cgm, OpenACCDirectiveKind dirKind,
58
- SourceLocation dirLoc)
59
- : cgm(cgm), dirKind(dirKind), dirLoc(dirLoc) {}
54
+ OpenACCClauseCIREmitter (OpTy &operation, CIRGenFunction &cgf,
55
+ CIRGenBuilderTy &builder,
56
+ OpenACCDirectiveKind dirKind, SourceLocation dirLoc)
57
+ : operation(operation), cgf(cgf), builder(builder), dirKind(dirKind),
58
+ dirLoc (dirLoc) {}
60
59
61
60
void VisitClause (const OpenACCClause &clause) {
62
61
clauseNotImplemented (clause);
63
62
}
64
63
65
64
void VisitDefaultClause (const OpenACCDefaultClause &clause) {
66
- switch (clause.getDefaultClauseKind ()) {
67
- case OpenACCDefaultClauseKind::None:
68
- attrData.defaultVal = ClauseDefaultValue::None;
69
- break ;
70
- case OpenACCDefaultClauseKind::Present:
71
- attrData.defaultVal = ClauseDefaultValue::Present;
72
- break ;
73
- case OpenACCDefaultClauseKind::Invalid:
74
- break ;
65
+ // This type-trait checks if 'op'(the first arg) is one of the mlir::acc
66
+ // operations listed in the rest of the arguments.
67
+ if constexpr (isOneOfTypes<OpTy, ParallelOp, SerialOp, KernelsOp, DataOp>) {
68
+ switch (clause.getDefaultClauseKind ()) {
69
+ case OpenACCDefaultClauseKind::None:
70
+ operation.setDefaultAttr (ClauseDefaultValue::None);
71
+ break ;
72
+ case OpenACCDefaultClauseKind::Present:
73
+ operation.setDefaultAttr (ClauseDefaultValue::Present);
74
+ break ;
75
+ case OpenACCDefaultClauseKind::Invalid:
76
+ break ;
77
+ }
78
+ } else {
79
+ return clauseNotImplemented (clause);
75
80
}
76
81
}
77
82
@@ -89,64 +94,70 @@ class OpenACCClauseCIREmitter final
89
94
}
90
95
91
96
void VisitDeviceTypeClause (const OpenACCDeviceTypeClause &clause) {
97
+ if constexpr (isOneOfTypes<OpTy, InitOp, ShutdownOp>) {
98
+ llvm::SmallVector<mlir::Attribute> deviceTypes;
99
+ std::optional<mlir::ArrayAttr> existingDeviceTypes =
100
+ operation.getDeviceTypes ();
101
+
102
+ // Ensure we keep the existing ones, and in the correct 'new' order.
103
+ if (existingDeviceTypes) {
104
+ for (const mlir::Attribute &Attr : *existingDeviceTypes)
105
+ deviceTypes.push_back (mlir::acc::DeviceTypeAttr::get (
106
+ builder.getContext (),
107
+ cast<mlir::acc::DeviceTypeAttr>(Attr).getValue ()));
108
+ }
92
109
93
- switch (dirKind) {
94
- case OpenACCDirectiveKind::Init:
95
- case OpenACCDirectiveKind::Set:
96
- case OpenACCDirectiveKind::Shutdown: {
97
- // Device type has a list that is either a 'star' (emitted as 'star'),
98
- // or an identifer list, all of which get added for attributes.
99
-
100
- for (const DeviceTypeArgument &arg : clause.getArchitectures ())
101
- attrData.deviceTypeArchs .push_back (decodeDeviceType (arg.first ));
102
- break ;
103
- }
104
- default :
110
+ for (const DeviceTypeArgument &arg : clause.getArchitectures ()) {
111
+ deviceTypes.push_back (mlir::acc::DeviceTypeAttr::get (
112
+ builder.getContext (), decodeDeviceType (arg.first )));
113
+ }
114
+ operation.removeDeviceTypesAttr ();
115
+ operation.setDeviceTypesAttr (
116
+ mlir::ArrayAttr::get (builder.getContext (), deviceTypes));
117
+ } else if constexpr (isOneOfTypes<OpTy, SetOp>) {
118
+ assert (!operation.getDeviceTypeAttr () && " already have device-type?" );
119
+ assert (clause.getArchitectures ().size () <= 1 );
120
+
121
+ if (!clause.getArchitectures ().empty ())
122
+ operation.setDeviceType (
123
+ decodeDeviceType (clause.getArchitectures ()[0 ].first ));
124
+ } else {
105
125
return clauseNotImplemented (clause);
106
126
}
107
127
}
108
128
109
- // Apply any of the clauses that resulted in an 'attribute'.
110
- template <typename Op>
111
- void applyAttributes (CIRGenBuilderTy &builder, Op &op) {
112
-
113
- if (attrData.defaultVal .has_value ()) {
114
- // FIXME: OpenACC: as we implement this for other directive kinds, we have
115
- // to expand this list.
116
- // This type-trait checks if 'op'(the first arg) is one of the mlir::acc
117
- // operations listed in the rest of the arguments.
118
- if constexpr (isOneOfTypes<Op, ParallelOp, SerialOp, KernelsOp, DataOp>)
119
- op.setDefaultAttr (*attrData.defaultVal );
120
- else
121
- cgm.errorNYI (dirLoc, " OpenACC 'default' clause lowering for " , dirKind);
122
- }
123
-
124
- if (!attrData.deviceTypeArchs .empty ()) {
125
- // FIXME: OpenACC: as we implement this for other directive kinds, we have
126
- // to expand this list, or more likely, have a 'noop' branch as most other
127
- // uses of this apply to the operands instead.
128
- // This type-trait checks if 'op'(the first arg) is one of the mlir::acc
129
- if constexpr (isOneOfTypes<Op, InitOp, ShutdownOp>) {
130
- llvm::SmallVector<mlir::Attribute> deviceTypes;
131
- for (mlir::acc::DeviceType DT : attrData.deviceTypeArchs )
132
- deviceTypes.push_back (
133
- mlir::acc::DeviceTypeAttr::get (builder.getContext (), DT));
134
-
135
- op.setDeviceTypesAttr (
136
- mlir::ArrayAttr::get (builder.getContext (), deviceTypes));
137
- } else if constexpr (isOneOfTypes<Op, SetOp>) {
138
- assert (attrData.deviceTypeArchs .size () <= 1 &&
139
- " Set can only have a single architecture" );
140
- if (!attrData.deviceTypeArchs .empty ())
141
- op.setDeviceType (attrData.deviceTypeArchs [0 ]);
129
+ void VisitSelfClause (const OpenACCSelfClause &clause) {
130
+ if constexpr (isOneOfTypes<OpTy, ParallelOp, SerialOp, KernelsOp>) {
131
+ if (clause.isEmptySelfClause ()) {
132
+ operation.setSelfAttr (true );
133
+ } else if (clause.isConditionExprClause ()) {
134
+ assert (clause.hasConditionExpr ());
135
+ mlir::Value condition =
136
+ cgf.evaluateExprAsBool (clause.getConditionExpr ());
137
+
138
+ mlir::Location exprLoc =
139
+ cgf.cgm .getLoc (clause.getConditionExpr ()->getBeginLoc ());
140
+ mlir::IntegerType targetType = mlir::IntegerType::get (
141
+ &cgf.getMLIRContext (), /* width=*/ 1 ,
142
+ mlir::IntegerType::SignednessSemantics::Signless);
143
+ auto conversionOp = builder.create <mlir::UnrealizedConversionCastOp>(
144
+ exprLoc, targetType, condition);
145
+ operation.getSelfCondMutable ().append (conversionOp.getResult (0 ));
142
146
} else {
143
- cgm.errorNYI (dirLoc, " OpenACC 'device_type' clause lowering for " ,
144
- dirKind);
147
+ llvm_unreachable (" var-list version of self shouldn't get here" );
145
148
}
149
+ } else {
150
+ return clauseNotImplemented (clause);
146
151
}
147
152
}
148
153
};
149
154
155
+ template <typename OpTy>
156
+ auto makeClauseEmitter (OpTy &op, CIRGenFunction &cgf, CIRGenBuilderTy &builder,
157
+ OpenACCDirectiveKind dirKind, SourceLocation dirLoc) {
158
+ return OpenACCClauseCIREmitter<OpTy>(op, cgf, builder, dirKind, dirLoc);
159
+ }
160
+
150
161
} // namespace
151
162
152
163
template <typename Op, typename TermOp>
@@ -158,24 +169,27 @@ mlir::LogicalResult CIRGenFunction::emitOpenACCOpAssociatedStmt(
158
169
159
170
llvm::SmallVector<mlir::Type> retTy;
160
171
llvm::SmallVector<mlir::Value> operands;
161
-
162
- // Clause-emitter must be here because it might modify operands.
163
- OpenACCClauseCIREmitter clauseEmitter (getCIRGenModule (), dirKind, dirLoc);
164
- clauseEmitter.VisitClauseList (clauses);
165
-
166
172
auto op = builder.create <Op>(start, retTy, operands);
167
173
168
- // Apply the attributes derived from the clauses.
169
- clauseEmitter.applyAttributes (builder, op);
174
+ {
175
+ mlir::OpBuilder::InsertionGuard guardCase (builder);
176
+ // Sets insertion point before the 'op', since every new expression needs to
177
+ // be before the operation.
178
+ builder.setInsertionPoint (op);
179
+ makeClauseEmitter (op, *this , builder, dirKind, dirLoc)
180
+ .VisitClauseList (clauses);
181
+ }
170
182
171
- mlir::Block &block = op.getRegion ().emplaceBlock ();
172
- mlir::OpBuilder::InsertionGuard guardCase (builder);
173
- builder.setInsertionPointToEnd (&block);
183
+ {
184
+ mlir::Block &block = op.getRegion ().emplaceBlock ();
185
+ mlir::OpBuilder::InsertionGuard guardCase (builder);
186
+ builder.setInsertionPointToEnd (&block);
174
187
175
- LexicalScope ls{*this , start, builder.getInsertionBlock ()};
176
- res = emitStmt (associatedStmt, /* useCurrentScope=*/ true );
188
+ LexicalScope ls{*this , start, builder.getInsertionBlock ()};
189
+ res = emitStmt (associatedStmt, /* useCurrentScope=*/ true );
177
190
178
- builder.create <TermOp>(end);
191
+ builder.create <TermOp>(end);
192
+ }
179
193
return res;
180
194
}
181
195
@@ -187,14 +201,16 @@ mlir::LogicalResult CIRGenFunction::emitOpenACCOp(
187
201
188
202
llvm::SmallVector<mlir::Type> retTy;
189
203
llvm::SmallVector<mlir::Value> operands;
190
-
191
- // Clause-emitter must be here because it might modify operands.
192
- OpenACCClauseCIREmitter clauseEmitter (getCIRGenModule (), dirKind, dirLoc);
193
- clauseEmitter.VisitClauseList (clauses);
194
-
195
204
auto op = builder.create <Op>(start, retTy, operands);
196
- // Apply the attributes derived from the clauses.
197
- clauseEmitter.applyAttributes (builder, op);
205
+
206
+ {
207
+ mlir::OpBuilder::InsertionGuard guardCase (builder);
208
+ // Sets insertion point before the 'op', since every new expression needs to
209
+ // be before the operation.
210
+ builder.setInsertionPoint (op);
211
+ makeClauseEmitter (op, *this , builder, dirKind, dirLoc)
212
+ .VisitClauseList (clauses);
213
+ }
198
214
return res;
199
215
}
200
216
@@ -254,46 +270,46 @@ mlir::LogicalResult CIRGenFunction::emitOpenACCShutdownConstruct(
254
270
255
271
mlir::LogicalResult
256
272
CIRGenFunction::emitOpenACCLoopConstruct (const OpenACCLoopConstruct &s) {
257
- getCIRGenModule () .errorNYI (s.getSourceRange (), " OpenACC Loop Construct" );
273
+ cgm .errorNYI (s.getSourceRange (), " OpenACC Loop Construct" );
258
274
return mlir::failure ();
259
275
}
260
276
mlir::LogicalResult CIRGenFunction::emitOpenACCCombinedConstruct (
261
277
const OpenACCCombinedConstruct &s) {
262
- getCIRGenModule () .errorNYI (s.getSourceRange (), " OpenACC Combined Construct" );
278
+ cgm .errorNYI (s.getSourceRange (), " OpenACC Combined Construct" );
263
279
return mlir::failure ();
264
280
}
265
281
mlir::LogicalResult CIRGenFunction::emitOpenACCEnterDataConstruct (
266
282
const OpenACCEnterDataConstruct &s) {
267
- getCIRGenModule () .errorNYI (s.getSourceRange (), " OpenACC EnterData Construct" );
283
+ cgm .errorNYI (s.getSourceRange (), " OpenACC EnterData Construct" );
268
284
return mlir::failure ();
269
285
}
270
286
mlir::LogicalResult CIRGenFunction::emitOpenACCExitDataConstruct (
271
287
const OpenACCExitDataConstruct &s) {
272
- getCIRGenModule () .errorNYI (s.getSourceRange (), " OpenACC ExitData Construct" );
288
+ cgm .errorNYI (s.getSourceRange (), " OpenACC ExitData Construct" );
273
289
return mlir::failure ();
274
290
}
275
291
mlir::LogicalResult CIRGenFunction::emitOpenACCHostDataConstruct (
276
292
const OpenACCHostDataConstruct &s) {
277
- getCIRGenModule () .errorNYI (s.getSourceRange (), " OpenACC HostData Construct" );
293
+ cgm .errorNYI (s.getSourceRange (), " OpenACC HostData Construct" );
278
294
return mlir::failure ();
279
295
}
280
296
mlir::LogicalResult
281
297
CIRGenFunction::emitOpenACCWaitConstruct (const OpenACCWaitConstruct &s) {
282
- getCIRGenModule () .errorNYI (s.getSourceRange (), " OpenACC Wait Construct" );
298
+ cgm .errorNYI (s.getSourceRange (), " OpenACC Wait Construct" );
283
299
return mlir::failure ();
284
300
}
285
301
mlir::LogicalResult
286
302
CIRGenFunction::emitOpenACCUpdateConstruct (const OpenACCUpdateConstruct &s) {
287
- getCIRGenModule () .errorNYI (s.getSourceRange (), " OpenACC Update Construct" );
303
+ cgm .errorNYI (s.getSourceRange (), " OpenACC Update Construct" );
288
304
return mlir::failure ();
289
305
}
290
306
mlir::LogicalResult
291
307
CIRGenFunction::emitOpenACCAtomicConstruct (const OpenACCAtomicConstruct &s) {
292
- getCIRGenModule () .errorNYI (s.getSourceRange (), " OpenACC Atomic Construct" );
308
+ cgm .errorNYI (s.getSourceRange (), " OpenACC Atomic Construct" );
293
309
return mlir::failure ();
294
310
}
295
311
mlir::LogicalResult
296
312
CIRGenFunction::emitOpenACCCacheConstruct (const OpenACCCacheConstruct &s) {
297
- getCIRGenModule () .errorNYI (s.getSourceRange (), " OpenACC Cache Construct" );
313
+ cgm .errorNYI (s.getSourceRange (), " OpenACC Cache Construct" );
298
314
return mlir::failure ();
299
315
}
0 commit comments