Skip to content

Commit 23d4756

Browse files
authored
[OpenACC][CIR] Add lowering for 'copy' array indexes (#140971)
The array indexes(and sections) are represented by the acc.bounds operation, which this ensures we fill in properly. The lowerbound is required, so we always get that. The upperbound or extent is required. We typically do extent, since that is the 'length' as specified by ACC, but in cases where we have implicit length, we use the extent instead. It isn't clear when 'stride' should be anything besides 1, though by my reading, since we have full-types in the emitted code, we should never have it be anything but 1. This patch enables these for copy on compute and combined constructs, and makes sure to test everything I could think of for combinations/permutations.
1 parent 34813d9 commit 23d4756

File tree

3 files changed

+996
-13
lines changed

3 files changed

+996
-13
lines changed

clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,11 @@ class OpenACCClauseCIREmitter final
121121
return constOp.getResult();
122122
}
123123

124+
mlir::Value createConstantInt(SourceLocation loc, unsigned width,
125+
int64_t value) {
126+
return createConstantInt(cgf.cgm.getLoc(loc), width, value);
127+
}
128+
124129
mlir::acc::DeviceType decodeDeviceType(const IdentifierInfo *ii) {
125130
// '*' case leaves no identifier-info, just a nullptr.
126131
if (!ii)
@@ -184,37 +189,89 @@ class OpenACCClauseCIREmitter final
184189
mlir::Location beginLoc;
185190
mlir::Value varValue;
186191
llvm::StringRef name;
192+
llvm::SmallVector<mlir::Value> bounds;
187193
};
188194

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+
189212
// A helper function that gets the information from an operand to a data
190213
// 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) {
193215
// TODO: OpenACC: Cache was different enough as to need a separate
194216
// `ActOnCacheVar`, so we are going to need to do some investigations here
195217
// when it comes to implement this for cache.
196218
if (dk == OpenACCDirectiveKind::Cache) {
197219
cgf.cgm.errorNYI(e->getSourceRange(),
198220
"OpenACC data operand for 'cache' directive");
199-
return {cgf.cgm.getLoc(e->getBeginLoc()), {}, {}};
221+
return {cgf.cgm.getLoc(e->getBeginLoc()), {}, {}, {}};
200222
}
201223

202224
const Expr *curVarExpr = e->IgnoreParenImpCasts();
203225

204226
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+
}
205256

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));
211268
}
212269

213270
// TODO: OpenACC: if this is a member expr, emit the VarPtrPtr correctly.
214271
if (isa<MemberExpr>(curVarExpr)) {
215272
cgf.cgm.errorNYI(curVarExpr->getSourceRange(),
216273
"OpenACC Data clause member expr");
217-
return {exprLoc, {}, {}};
274+
return {exprLoc, {}, {}, std::move(bounds)};
218275
}
219276

220277
// Sema has made sure that only 4 types of things can get here, array
@@ -223,14 +280,14 @@ class OpenACCClauseCIREmitter final
223280
// right.
224281
const auto *dre = cast<DeclRefExpr>(curVarExpr);
225282
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)};
227285
}
228286

229287
template <typename BeforeOpTy, typename AfterOpTy>
230288
void addDataOperand(const Expr *varOperand, mlir::acc::DataClause dataClause,
231289
bool structured, bool implicit) {
232290
DataOperandInfo opInfo = getDataOperandInfo(dirKind, varOperand);
233-
mlir::ValueRange bounds;
234291

235292
// TODO: OpenACC: we should comprehend the 'modifier-list' here for the data
236293
// operand. At the moment, we don't have a uniform way to assign these
@@ -239,7 +296,7 @@ class OpenACCClauseCIREmitter final
239296

240297
auto beforeOp =
241298
builder.create<BeforeOpTy>(opInfo.beginLoc, opInfo.varValue, structured,
242-
implicit, opInfo.name, bounds);
299+
implicit, opInfo.name, opInfo.bounds);
243300
operation.getDataClauseOperandsMutable().append(beforeOp.getResult());
244301

245302
AfterOpTy afterOp;
@@ -248,7 +305,7 @@ class OpenACCClauseCIREmitter final
248305
builder.setInsertionPointAfter(operation);
249306
afterOp = builder.create<AfterOpTy>(opInfo.beginLoc, beforeOp.getResult(),
250307
opInfo.varValue, structured, implicit,
251-
opInfo.name, bounds);
308+
opInfo.name, opInfo.bounds);
252309
}
253310

254311
// Set the 'rest' of the info for both operations.

0 commit comments

Comments
 (0)