@@ -121,6 +121,11 @@ class OpenACCClauseCIREmitter final
121
121
return constOp.getResult ();
122
122
}
123
123
124
+ mlir::Value createConstantInt (SourceLocation loc, unsigned width,
125
+ int64_t value) {
126
+ return createConstantInt (cgf.cgm .getLoc (loc), width, value);
127
+ }
128
+
124
129
mlir::acc::DeviceType decodeDeviceType (const IdentifierInfo *ii) {
125
130
// '*' case leaves no identifier-info, just a nullptr.
126
131
if (!ii)
@@ -184,37 +189,89 @@ class OpenACCClauseCIREmitter final
184
189
mlir::Location beginLoc;
185
190
mlir::Value varValue;
186
191
llvm::StringRef name;
192
+ llvm::SmallVector<mlir::Value> bounds;
187
193
};
188
194
195
+ mlir::Value createBound (mlir::Location boundLoc, mlir::Value lowerBound,
196
+ mlir::Value upperBound, mlir::Value extent) {
197
+ // Arrays always have a start-idx of 0.
198
+ mlir::Value startIdx = createConstantInt (boundLoc, 64 , 0 );
199
+ // Stride is always 1 in C/C++.
200
+ mlir::Value stride = createConstantInt (boundLoc, 64 , 1 );
201
+
202
+ auto bound = builder.create <mlir::acc::DataBoundsOp>(boundLoc, lowerBound,
203
+ upperBound);
204
+ bound.getStartIdxMutable ().assign (startIdx);
205
+ if (extent)
206
+ bound.getExtentMutable ().assign (extent);
207
+ bound.getStrideMutable ().assign (stride);
208
+
209
+ return bound;
210
+ }
211
+
189
212
// A helper function that gets the information from an operand to a data
190
213
// clause, so that it can be used to emit the data operations.
191
- inline DataOperandInfo getDataOperandInfo (OpenACCDirectiveKind dk,
192
- const Expr *e) {
214
+ DataOperandInfo getDataOperandInfo (OpenACCDirectiveKind dk, const Expr *e) {
193
215
// TODO: OpenACC: Cache was different enough as to need a separate
194
216
// `ActOnCacheVar`, so we are going to need to do some investigations here
195
217
// when it comes to implement this for cache.
196
218
if (dk == OpenACCDirectiveKind::Cache) {
197
219
cgf.cgm .errorNYI (e->getSourceRange (),
198
220
" OpenACC data operand for 'cache' directive" );
199
- return {cgf.cgm .getLoc (e->getBeginLoc ()), {}, {}};
221
+ return {cgf.cgm .getLoc (e->getBeginLoc ()), {}, {}, {} };
200
222
}
201
223
202
224
const Expr *curVarExpr = e->IgnoreParenImpCasts ();
203
225
204
226
mlir::Location exprLoc = cgf.cgm .getLoc (curVarExpr->getBeginLoc ());
227
+ llvm::SmallVector<mlir::Value> bounds;
228
+
229
+ // Assemble the list of bounds.
230
+ while (isa<ArraySectionExpr, ArraySubscriptExpr>(curVarExpr)) {
231
+ mlir::Location boundLoc = cgf.cgm .getLoc (curVarExpr->getBeginLoc ());
232
+ mlir::Value lowerBound;
233
+ mlir::Value upperBound;
234
+ mlir::Value extent;
235
+
236
+ if (const auto *section = dyn_cast<ArraySectionExpr>(curVarExpr)) {
237
+ if (const Expr *lb = section->getLowerBound ())
238
+ lowerBound = emitIntExpr (lb);
239
+ else
240
+ lowerBound = createConstantInt (boundLoc, 64 , 0 );
241
+
242
+ if (const Expr *len = section->getLength ()) {
243
+ extent = emitIntExpr (len);
244
+ } else {
245
+ QualType baseTy = ArraySectionExpr::getBaseOriginalType (
246
+ section->getBase ()->IgnoreParenImpCasts ());
247
+ // We know this is the case as implicit lengths are only allowed for
248
+ // array types with a constant size, or a dependent size. AND since
249
+ // we are codegen we know we're not dependent.
250
+ auto *arrayTy = cgf.getContext ().getAsConstantArrayType (baseTy);
251
+ // Rather than trying to calculate the extent based on the
252
+ // lower-bound, we can just emit this as an upper bound.
253
+ upperBound =
254
+ createConstantInt (boundLoc, 64 , arrayTy->getLimitedSize () - 1 );
255
+ }
205
256
206
- // TODO: OpenACC: Assemble the list of bounds.
207
- if (isa<ArraySectionExpr, ArraySubscriptExpr>(curVarExpr)) {
208
- cgf.cgm .errorNYI (curVarExpr->getSourceRange (),
209
- " OpenACC data clause array subscript/section" );
210
- return {exprLoc, {}, {}};
257
+ curVarExpr = section->getBase ()->IgnoreParenImpCasts ();
258
+ } else {
259
+ const auto *subscript = cast<ArraySubscriptExpr>(curVarExpr);
260
+
261
+ lowerBound = emitIntExpr (subscript->getIdx ());
262
+ // Length of an array index is always 1.
263
+ extent = createConstantInt (boundLoc, 64 , 1 );
264
+ curVarExpr = subscript->getBase ()->IgnoreParenImpCasts ();
265
+ }
266
+
267
+ bounds.push_back (createBound (boundLoc, lowerBound, upperBound, extent));
211
268
}
212
269
213
270
// TODO: OpenACC: if this is a member expr, emit the VarPtrPtr correctly.
214
271
if (isa<MemberExpr>(curVarExpr)) {
215
272
cgf.cgm .errorNYI (curVarExpr->getSourceRange (),
216
273
" OpenACC Data clause member expr" );
217
- return {exprLoc, {}, {}};
274
+ return {exprLoc, {}, {}, std::move (bounds) };
218
275
}
219
276
220
277
// Sema has made sure that only 4 types of things can get here, array
@@ -223,14 +280,14 @@ class OpenACCClauseCIREmitter final
223
280
// right.
224
281
const auto *dre = cast<DeclRefExpr>(curVarExpr);
225
282
const auto *vd = cast<VarDecl>(dre->getFoundDecl ()->getCanonicalDecl ());
226
- return {exprLoc, cgf.emitDeclRefLValue (dre).getPointer (), vd->getName ()};
283
+ return {exprLoc, cgf.emitDeclRefLValue (dre).getPointer (), vd->getName (),
284
+ std::move (bounds)};
227
285
}
228
286
229
287
template <typename BeforeOpTy, typename AfterOpTy>
230
288
void addDataOperand (const Expr *varOperand, mlir::acc::DataClause dataClause,
231
289
bool structured, bool implicit) {
232
290
DataOperandInfo opInfo = getDataOperandInfo (dirKind, varOperand);
233
- mlir::ValueRange bounds;
234
291
235
292
// TODO: OpenACC: we should comprehend the 'modifier-list' here for the data
236
293
// operand. At the moment, we don't have a uniform way to assign these
@@ -239,7 +296,7 @@ class OpenACCClauseCIREmitter final
239
296
240
297
auto beforeOp =
241
298
builder.create <BeforeOpTy>(opInfo.beginLoc , opInfo.varValue , structured,
242
- implicit, opInfo.name , bounds);
299
+ implicit, opInfo.name , opInfo. bounds );
243
300
operation.getDataClauseOperandsMutable ().append (beforeOp.getResult ());
244
301
245
302
AfterOpTy afterOp;
@@ -248,7 +305,7 @@ class OpenACCClauseCIREmitter final
248
305
builder.setInsertionPointAfter (operation);
249
306
afterOp = builder.create <AfterOpTy>(opInfo.beginLoc , beforeOp.getResult (),
250
307
opInfo.varValue , structured, implicit,
251
- opInfo.name , bounds);
308
+ opInfo.name , opInfo. bounds );
252
309
}
253
310
254
311
// Set the 'rest' of the info for both operations.
0 commit comments