Skip to content

Commit 15d7a95

Browse files
authored
[CIR] Refactor recipe init generation, cleanup after init (llvm#153610)
In preperation of the firstprivate implementation, this separates out some functions to make it easier to read. Additionally, it cleans up the VarDecl->alloca relationship, which will prevent issues if we have to re-use the same vardecl for a future generated recipe (and causes concerns in firstprivate later).
1 parent 9828745 commit 15d7a95

File tree

2 files changed

+121
-64
lines changed

2 files changed

+121
-64
lines changed

clang/lib/CIR/CodeGen/CIRGenFunction.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,13 @@ class CIRGenFunction : public CIRGenTypeCache {
518518
symbolTable.insert(vd, addr.getPointer());
519519
}
520520

521+
/// Removes a declaration from the address-relationship. This is a function
522+
/// that shouldn't need to be used except in cases where we're adding/removing
523+
/// things that aren't part of the language-semantics AST.
524+
void removeAddrOfLocalVar(const clang::VarDecl *vd) {
525+
localDeclMap.erase(vd);
526+
}
527+
521528
bool shouldNullCheckClassCastValue(const CastExpr *ce);
522529

523530
RValue convertTempToRValue(Address addr, clang::QualType type,

clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp

Lines changed: 114 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -357,15 +357,11 @@ class OpenACCClauseCIREmitter final
357357
}
358358

359359
template <typename RecipeTy>
360-
RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef,
361-
const VarDecl *varRecipe, DeclContext *dc,
362-
QualType baseType, mlir::Value mainOp) {
363-
mlir::ModuleOp mod =
364-
builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
365-
360+
std::string getRecipeName(SourceRange loc, QualType baseType) {
366361
std::string recipeName;
367362
{
368363
llvm::raw_string_ostream stream(recipeName);
364+
369365
if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
370366
stream << "privatization_";
371367
} else if constexpr (std::is_same_v<RecipeTy,
@@ -375,84 +371,138 @@ class OpenACCClauseCIREmitter final
375371
} else if constexpr (std::is_same_v<RecipeTy,
376372
mlir::acc::ReductionRecipeOp>) {
377373
stream << "reduction_";
378-
// We don't have the reduction operation here well enough to know how to
379-
// spell this correctly (+ == 'add', etc), so when we implement
380-
// 'reduction' we have to do that here.
381-
cgf.cgm.errorNYI(varRef->getSourceRange(),
382-
"OpeNACC reduction recipe creation");
374+
// TODO: OpenACC: once we have this part implemented, we can remove the
375+
// SourceRange `loc` variable from this function. We don't have the
376+
// reduction operation here well enough to know how to spell this
377+
// correctly (+ == 'add', etc), so when we implement 'reduction' we have
378+
// to do that here.
379+
cgf.cgm.errorNYI(loc, "OpenACC reduction recipe name creation");
383380
} else {
384381
static_assert(!sizeof(RecipeTy), "Unknown Recipe op kind");
385382
}
386383

387384
MangleContext &mc = cgf.cgm.getCXXABI().getMangleContext();
388385
mc.mangleCanonicalTypeName(baseType, stream);
389386
}
387+
return recipeName;
388+
}
390389

391-
if (auto recipe = mod.lookupSymbol<RecipeTy>(recipeName))
392-
return recipe;
393-
394-
mlir::Location loc = cgf.cgm.getLoc(varRef->getBeginLoc());
395-
mlir::Location locEnd = cgf.cgm.getLoc(varRef->getEndLoc());
390+
// Create the 'init' section of the recipe, including the 'copy' section for
391+
// 'firstprivate'.
392+
template <typename RecipeTy>
393+
void createRecipeInitCopy(mlir::Location loc, mlir::Location locEnd,
394+
SourceRange exprRange, mlir::Value mainOp,
395+
RecipeTy recipe, const VarDecl *varRecipe,
396+
const VarDecl *temporary) {
397+
assert(varRecipe && "Required recipe variable not set?");
398+
if constexpr (std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
399+
// We haven't implemented the 'init' recipe for Reduction yet, so NYI
400+
// it.
401+
cgf.cgm.errorNYI(exprRange, "OpenACC Reduction recipe init");
402+
}
396403

397-
mlir::OpBuilder modBuilder(mod.getBodyRegion());
398-
auto recipe =
399-
RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
404+
if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
405+
// We haven't implemented the 'init'/copy recipe for firstprivate yet, so
406+
// NYI it.
407+
cgf.cgm.errorNYI(exprRange, "OpenACC firstprivate recipe init");
408+
}
400409

401410
CIRGenFunction::AutoVarEmission tempDeclEmission{
402411
CIRGenFunction::AutoVarEmission::invalid()};
403412

404-
// Init section.
405-
{
406-
llvm::SmallVector<mlir::Type> argsTys{mainOp.getType()};
407-
llvm::SmallVector<mlir::Location> argsLocs{loc};
408-
builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(),
409-
argsTys, argsLocs);
410-
builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
411-
412-
if constexpr (!std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
413-
// We have only implemented 'init' for private, so make this NYI until
414-
// we have explicitly implemented everything.
415-
cgf.cgm.errorNYI(varRef->getSourceRange(),
416-
"OpenACC non-private recipe init");
413+
// Do the 'init' section of the recipe IR, which does an alloca, then the
414+
// initialization (except for firstprivate).
415+
builder.createBlock(&recipe.getInitRegion(), recipe.getInitRegion().end(),
416+
{mainOp.getType()}, {loc});
417+
builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
418+
tempDeclEmission =
419+
cgf.emitAutoVarAlloca(*varRecipe, builder.saveInsertionPoint());
420+
// 'firstprivate' doesn't do its initialization in the 'init' section,
421+
// instead does it in the 'copy' section. SO only do init here.
422+
// 'reduction' appears to use it too (rather than a 'copy' section), so
423+
// we probably have to do it here too, but we can do that when we get to
424+
// reduction implementation.
425+
if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
426+
// We are OK with no init for builtins, arrays of builtins, or pointers,
427+
// else we should NYI so we know to go look for these.
428+
if (!varRecipe->getType()
429+
->getPointeeOrArrayElementType()
430+
->isBuiltinType() &&
431+
!varRecipe->getType()->isPointerType() && !varRecipe->getInit()) {
432+
// If we don't have any initialization recipe, we failed during Sema to
433+
// initialize this correctly. If we disable the
434+
// Sema::TentativeAnalysisScopes in SemaOpenACC::CreateInitRecipe, it'll
435+
// emit an error to tell us. However, emitting those errors during
436+
// production is a violation of the standard, so we cannot do them.
437+
cgf.cgm.errorNYI(exprRange, "private default-init recipe");
417438
}
439+
cgf.emitAutoVarInit(tempDeclEmission);
440+
}
418441

419-
if (varRecipe) {
420-
tempDeclEmission =
421-
cgf.emitAutoVarAlloca(*varRecipe, builder.saveInsertionPoint());
422-
cgf.emitAutoVarInit(tempDeclEmission);
442+
mlir::acc::YieldOp::create(builder, locEnd);
443+
444+
if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
445+
if (!varRecipe->getInit()) {
446+
// If we don't have any initialization recipe, we failed during Sema to
447+
// initialize this correctly. If we disable the
448+
// Sema::TentativeAnalysisScopes in SemaOpenACC::CreateInitRecipe, it'll
449+
// emit an error to tell us. However, emitting those errors during
450+
// production is a violation of the standard, so we cannot do them.
451+
cgf.cgm.errorNYI(
452+
exprRange, "firstprivate copy-init recipe not properly generated");
423453
}
424454

425-
mlir::acc::YieldOp::create(builder, locEnd);
455+
cgf.cgm.errorNYI(exprRange, "firstprivate copy section generation");
426456
}
427457

428-
// Copy section.
429-
if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp> ||
430-
std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
431-
// TODO: OpenACC: 'private' doesn't emit this, but for the other two we
432-
// have to figure out what 'copy' means here.
433-
cgf.cgm.errorNYI(varRef->getSourceRange(),
434-
"OpenACC record type privatization copy section");
435-
}
458+
// Make sure we cleanup after ourselves here.
459+
cgf.removeAddrOfLocalVar(varRecipe);
460+
}
436461

437-
// Destroy section (doesn't currently exist).
438-
if (varRecipe && varRecipe->needsDestruction(cgf.getContext())) {
439-
llvm::SmallVector<mlir::Type> argsTys{mainOp.getType()};
440-
llvm::SmallVector<mlir::Location> argsLocs{loc};
441-
mlir::Block *block = builder.createBlock(&recipe.getDestroyRegion(),
442-
recipe.getDestroyRegion().end(),
443-
argsTys, argsLocs);
444-
builder.setInsertionPointToEnd(&recipe.getDestroyRegion().back());
445-
446-
mlir::Type elementTy =
447-
mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
448-
Address addr{block->getArgument(0), elementTy,
449-
cgf.getContext().getDeclAlign(varRecipe)};
450-
cgf.emitDestroy(addr, baseType,
451-
cgf.getDestroyer(QualType::DK_cxx_destructor));
452-
453-
mlir::acc::YieldOp::create(builder, locEnd);
454-
}
462+
void createRecipeDestroySection(mlir::Location loc, mlir::Location locEnd,
463+
mlir::Value mainOp, CharUnits alignment,
464+
QualType baseType,
465+
mlir::Region &destroyRegion) {
466+
mlir::Block *block = builder.createBlock(
467+
&destroyRegion, destroyRegion.end(), {mainOp.getType()}, {loc});
468+
builder.setInsertionPointToEnd(&destroyRegion.back());
469+
470+
mlir::Type elementTy =
471+
mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
472+
Address addr{block->getArgument(0), elementTy, alignment};
473+
cgf.emitDestroy(addr, baseType,
474+
cgf.getDestroyer(QualType::DK_cxx_destructor));
475+
476+
mlir::acc::YieldOp::create(builder, locEnd);
477+
}
478+
479+
template <typename RecipeTy>
480+
RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef,
481+
const VarDecl *varRecipe, const VarDecl *temporary,
482+
DeclContext *dc, QualType baseType,
483+
mlir::Value mainOp) {
484+
mlir::ModuleOp mod =
485+
builder.getBlock()->getParent()->getParentOfType<mlir::ModuleOp>();
486+
487+
std::string recipeName =
488+
getRecipeName<RecipeTy>(varRef->getSourceRange(), baseType);
489+
if (auto recipe = mod.lookupSymbol<RecipeTy>(recipeName))
490+
return recipe;
491+
492+
mlir::Location loc = cgf.cgm.getLoc(varRef->getBeginLoc());
493+
mlir::Location locEnd = cgf.cgm.getLoc(varRef->getEndLoc());
494+
495+
mlir::OpBuilder modBuilder(mod.getBodyRegion());
496+
auto recipe =
497+
RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
498+
499+
createRecipeInitCopy(loc, locEnd, varRef->getSourceRange(), mainOp, recipe,
500+
varRecipe, temporary);
455501

502+
if (varRecipe && varRecipe->needsDestruction(cgf.getContext()))
503+
createRecipeDestroySection(loc, locEnd, mainOp,
504+
cgf.getContext().getDeclAlign(varRecipe),
505+
baseType, recipe.getDestroyRegion());
456506
return recipe;
457507
}
458508

@@ -1088,7 +1138,7 @@ class OpenACCClauseCIREmitter final
10881138
{
10891139
mlir::OpBuilder::InsertionGuard guardCase(builder);
10901140
auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>(
1091-
cgf.getContext(), varExpr, varRecipe,
1141+
cgf.getContext(), varExpr, varRecipe, /*temporary=*/nullptr,
10921142
Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
10931143
privateOp.getResult());
10941144
// TODO: OpenACC: The dialect is going to change in the near future to

0 commit comments

Comments
 (0)