Skip to content

[OpenACC][CIR] Add lowering for 'copy' array indexes #140971

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 70 additions & 13 deletions clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ class OpenACCClauseCIREmitter final
return constOp.getResult();
}

mlir::Value createConstantInt(SourceLocation loc, unsigned width,
int64_t value) {
return createConstantInt(cgf.cgm.getLoc(loc), width, value);
}

mlir::acc::DeviceType decodeDeviceType(const IdentifierInfo *ii) {
// '*' case leaves no identifier-info, just a nullptr.
if (!ii)
Expand Down Expand Up @@ -184,37 +189,89 @@ class OpenACCClauseCIREmitter final
mlir::Location beginLoc;
mlir::Value varValue;
llvm::StringRef name;
llvm::SmallVector<mlir::Value> bounds;
};

mlir::Value createBound(mlir::Location boundLoc, mlir::Value lowerBound,
mlir::Value upperBound, mlir::Value extent) {
// Arrays always have a start-idx of 0.
mlir::Value startIdx = createConstantInt(boundLoc, 64, 0);
// Stride is always 1 in C/C++.
mlir::Value stride = createConstantInt(boundLoc, 64, 1);

auto bound = builder.create<mlir::acc::DataBoundsOp>(boundLoc, lowerBound,
upperBound);
bound.getStartIdxMutable().assign(startIdx);
if (extent)
bound.getExtentMutable().assign(extent);
bound.getStrideMutable().assign(stride);

return bound;
}

// A helper function that gets the information from an operand to a data
// clause, so that it can be used to emit the data operations.
inline DataOperandInfo getDataOperandInfo(OpenACCDirectiveKind dk,
const Expr *e) {
DataOperandInfo getDataOperandInfo(OpenACCDirectiveKind dk, const Expr *e) {
// TODO: OpenACC: Cache was different enough as to need a separate
// `ActOnCacheVar`, so we are going to need to do some investigations here
// when it comes to implement this for cache.
if (dk == OpenACCDirectiveKind::Cache) {
cgf.cgm.errorNYI(e->getSourceRange(),
"OpenACC data operand for 'cache' directive");
return {cgf.cgm.getLoc(e->getBeginLoc()), {}, {}};
return {cgf.cgm.getLoc(e->getBeginLoc()), {}, {}, {}};
}

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

mlir::Location exprLoc = cgf.cgm.getLoc(curVarExpr->getBeginLoc());
llvm::SmallVector<mlir::Value> bounds;

// Assemble the list of bounds.
while (isa<ArraySectionExpr, ArraySubscriptExpr>(curVarExpr)) {
mlir::Location boundLoc = cgf.cgm.getLoc(curVarExpr->getBeginLoc());
mlir::Value lowerBound;
mlir::Value upperBound;
mlir::Value extent;

if (const auto *section = dyn_cast<ArraySectionExpr>(curVarExpr)) {
if (const Expr *lb = section->getLowerBound())
lowerBound = emitIntExpr(lb);
else
lowerBound = createConstantInt(boundLoc, 64, 0);

if (const Expr *len = section->getLength()) {
extent = emitIntExpr(len);
} else {
QualType baseTy = ArraySectionExpr::getBaseOriginalType(
section->getBase()->IgnoreParenImpCasts());
// We know this is the case as implicit lengths are only allowed for
// array types with a constant size, or a dependent size. AND since
// we are codegen we know we're not dependent.
auto *arrayTy = cgf.getContext().getAsConstantArrayType(baseTy);
// Rather than trying to calculate the extent based on the
// lower-bound, we can just emit this as an upper bound.
upperBound =
createConstantInt(boundLoc, 64, arrayTy->getLimitedSize() - 1);
}

// TODO: OpenACC: Assemble the list of bounds.
if (isa<ArraySectionExpr, ArraySubscriptExpr>(curVarExpr)) {
cgf.cgm.errorNYI(curVarExpr->getSourceRange(),
"OpenACC data clause array subscript/section");
return {exprLoc, {}, {}};
curVarExpr = section->getBase()->IgnoreParenImpCasts();
} else {
const auto *subscript = cast<ArraySubscriptExpr>(curVarExpr);

lowerBound = emitIntExpr(subscript->getIdx());
// Length of an array index is always 1.
extent = createConstantInt(boundLoc, 64, 1);
curVarExpr = subscript->getBase()->IgnoreParenImpCasts();
}

bounds.push_back(createBound(boundLoc, lowerBound, upperBound, extent));
}

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

// Sema has made sure that only 4 types of things can get here, array
Expand All @@ -223,14 +280,14 @@ class OpenACCClauseCIREmitter final
// right.
const auto *dre = cast<DeclRefExpr>(curVarExpr);
const auto *vd = cast<VarDecl>(dre->getFoundDecl()->getCanonicalDecl());
return {exprLoc, cgf.emitDeclRefLValue(dre).getPointer(), vd->getName()};
return {exprLoc, cgf.emitDeclRefLValue(dre).getPointer(), vd->getName(),
std::move(bounds)};
}

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

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

auto beforeOp =
builder.create<BeforeOpTy>(opInfo.beginLoc, opInfo.varValue, structured,
implicit, opInfo.name, bounds);
implicit, opInfo.name, opInfo.bounds);
operation.getDataClauseOperandsMutable().append(beforeOp.getResult());

AfterOpTy afterOp;
Expand All @@ -248,7 +305,7 @@ class OpenACCClauseCIREmitter final
builder.setInsertionPointAfter(operation);
afterOp = builder.create<AfterOpTy>(opInfo.beginLoc, beforeOp.getResult(),
opInfo.varValue, structured, implicit,
opInfo.name, bounds);
opInfo.name, opInfo.bounds);
}

// Set the 'rest' of the info for both operations.
Expand Down
Loading