Skip to content

Commit a549e73

Browse files
authored
[OpenACC][NFCI] Split recipe generation into its own class (#157160)
The recipe generation was dependent on the clause kind, which meant we had all of the recipe generation duplicated in each of clauses. This patch copy/pastes all of them into their own type to do recipe generation, which should reduce clang's size. Additionally, we've moved it off into its own file, which should make readability/organization improvements.
1 parent 7506900 commit a549e73

File tree

2 files changed

+347
-308
lines changed

2 files changed

+347
-308
lines changed

clang/lib/CIR/CodeGen/CIRGenOpenACCClause.cpp

Lines changed: 24 additions & 308 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
#include "CIRGenCXXABI.h"
1616
#include "CIRGenFunction.h"
17+
#include "CIRGenOpenACCRecipe.h"
1718

1819
#include "clang/AST/ExprCXX.h"
1920

@@ -356,299 +357,6 @@ class OpenACCClauseCIREmitter final
356357
}
357358
}
358359

359-
template <typename RecipeTy>
360-
std::string getRecipeName(SourceRange loc, QualType baseType,
361-
OpenACCReductionOperator reductionOp) {
362-
std::string recipeName;
363-
{
364-
llvm::raw_string_ostream stream(recipeName);
365-
366-
if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
367-
stream << "privatization_";
368-
} else if constexpr (std::is_same_v<RecipeTy,
369-
mlir::acc::FirstprivateRecipeOp>) {
370-
stream << "firstprivatization_";
371-
372-
} else if constexpr (std::is_same_v<RecipeTy,
373-
mlir::acc::ReductionRecipeOp>) {
374-
stream << "reduction_";
375-
// Values here are a little weird (for bitwise and/or is 'i' prefix, and
376-
// logical ops with 'l'), but are chosen to be the same as the MLIR
377-
// dialect names as well as to match the Flang versions of these.
378-
switch (reductionOp) {
379-
case OpenACCReductionOperator::Addition:
380-
stream << "add_";
381-
break;
382-
case OpenACCReductionOperator::Multiplication:
383-
stream << "mul_";
384-
break;
385-
case OpenACCReductionOperator::Max:
386-
stream << "max_";
387-
break;
388-
case OpenACCReductionOperator::Min:
389-
stream << "min_";
390-
break;
391-
case OpenACCReductionOperator::BitwiseAnd:
392-
stream << "iand_";
393-
break;
394-
case OpenACCReductionOperator::BitwiseOr:
395-
stream << "ior_";
396-
break;
397-
case OpenACCReductionOperator::BitwiseXOr:
398-
stream << "xor_";
399-
break;
400-
case OpenACCReductionOperator::And:
401-
stream << "land_";
402-
break;
403-
case OpenACCReductionOperator::Or:
404-
stream << "lor_";
405-
break;
406-
case OpenACCReductionOperator::Invalid:
407-
llvm_unreachable("invalid reduction operator");
408-
}
409-
} else {
410-
static_assert(!sizeof(RecipeTy), "Unknown Recipe op kind");
411-
}
412-
413-
MangleContext &mc = cgf.cgm.getCXXABI().getMangleContext();
414-
mc.mangleCanonicalTypeName(baseType, stream);
415-
}
416-
return recipeName;
417-
}
418-
419-
void createFirstprivateRecipeCopy(
420-
mlir::Location loc, mlir::Location locEnd, mlir::Value mainOp,
421-
CIRGenFunction::AutoVarEmission tempDeclEmission,
422-
mlir::acc::FirstprivateRecipeOp recipe, const VarDecl *varRecipe,
423-
const VarDecl *temporary) {
424-
mlir::Block *block = builder.createBlock(
425-
&recipe.getCopyRegion(), recipe.getCopyRegion().end(),
426-
{mainOp.getType(), mainOp.getType()}, {loc, loc});
427-
builder.setInsertionPointToEnd(&recipe.getCopyRegion().back());
428-
CIRGenFunction::LexicalScope ls(cgf, loc, block);
429-
430-
mlir::BlockArgument fromArg = block->getArgument(0);
431-
mlir::BlockArgument toArg = block->getArgument(1);
432-
433-
mlir::Type elementTy =
434-
mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
435-
436-
// Set the address of the emission to be the argument, so that we initialize
437-
// that instead of the variable in the other block.
438-
tempDeclEmission.setAllocatedAddress(
439-
Address{toArg, elementTy, cgf.getContext().getDeclAlign(varRecipe)});
440-
tempDeclEmission.EmittedAsOffload = true;
441-
442-
CIRGenFunction::DeclMapRevertingRAII declMapRAII{cgf, temporary};
443-
cgf.setAddrOfLocalVar(
444-
temporary,
445-
Address{fromArg, elementTy, cgf.getContext().getDeclAlign(varRecipe)});
446-
447-
cgf.emitAutoVarInit(tempDeclEmission);
448-
mlir::acc::YieldOp::create(builder, locEnd);
449-
}
450-
451-
// Create the 'init' section of the recipe, including the 'copy' section for
452-
// 'firstprivate'. Note that this function is not 'insertion point' clean, in
453-
// that it alters the insertion point to be inside of the 'destroy' section of
454-
// the recipe, but doesn't restore it aftewards.
455-
template <typename RecipeTy>
456-
void createRecipeInitCopy(mlir::Location loc, mlir::Location locEnd,
457-
SourceRange exprRange, mlir::Value mainOp,
458-
RecipeTy recipe, const VarDecl *varRecipe,
459-
const VarDecl *temporary) {
460-
assert(varRecipe && "Required recipe variable not set?");
461-
462-
CIRGenFunction::AutoVarEmission tempDeclEmission{
463-
CIRGenFunction::AutoVarEmission::invalid()};
464-
CIRGenFunction::DeclMapRevertingRAII declMapRAII{cgf, varRecipe};
465-
466-
// Do the 'init' section of the recipe IR, which does an alloca, then the
467-
// initialization (except for firstprivate).
468-
mlir::Block *block = builder.createBlock(&recipe.getInitRegion(),
469-
recipe.getInitRegion().end(),
470-
{mainOp.getType()}, {loc});
471-
builder.setInsertionPointToEnd(&recipe.getInitRegion().back());
472-
CIRGenFunction::LexicalScope ls(cgf, loc, block);
473-
474-
tempDeclEmission =
475-
cgf.emitAutoVarAlloca(*varRecipe, builder.saveInsertionPoint());
476-
477-
// 'firstprivate' doesn't do its initialization in the 'init' section,
478-
// instead does it in the 'copy' section. SO only do init here.
479-
// 'reduction' appears to use it too (rather than a 'copy' section), so
480-
// we probably have to do it here too, but we can do that when we get to
481-
// reduction implementation.
482-
if constexpr (std::is_same_v<RecipeTy, mlir::acc::PrivateRecipeOp>) {
483-
// We are OK with no init for builtins, arrays of builtins, or pointers,
484-
// else we should NYI so we know to go look for these.
485-
if (cgf.getContext().getLangOpts().CPlusPlus &&
486-
!varRecipe->getType()
487-
->getPointeeOrArrayElementType()
488-
->isBuiltinType() &&
489-
!varRecipe->getType()->isPointerType() && !varRecipe->getInit()) {
490-
// If we don't have any initialization recipe, we failed during Sema to
491-
// initialize this correctly. If we disable the
492-
// Sema::TentativeAnalysisScopes in SemaOpenACC::CreateInitRecipe, it'll
493-
// emit an error to tell us. However, emitting those errors during
494-
// production is a violation of the standard, so we cannot do them.
495-
cgf.cgm.errorNYI(exprRange, "private default-init recipe");
496-
}
497-
cgf.emitAutoVarInit(tempDeclEmission);
498-
} else if constexpr (std::is_same_v<RecipeTy,
499-
mlir::acc::ReductionRecipeOp>) {
500-
// Unlike Private, the recipe here is always required as it has to do
501-
// init, not just 'default' init.
502-
if (!varRecipe->getInit())
503-
cgf.cgm.errorNYI(exprRange, "reduction init recipe");
504-
cgf.emitAutoVarInit(tempDeclEmission);
505-
}
506-
507-
mlir::acc::YieldOp::create(builder, locEnd);
508-
509-
if constexpr (std::is_same_v<RecipeTy, mlir::acc::FirstprivateRecipeOp>) {
510-
if (!varRecipe->getInit()) {
511-
// If we don't have any initialization recipe, we failed during Sema to
512-
// initialize this correctly. If we disable the
513-
// Sema::TentativeAnalysisScopes in SemaOpenACC::CreateInitRecipe, it'll
514-
// emit an error to tell us. However, emitting those errors during
515-
// production is a violation of the standard, so we cannot do them.
516-
cgf.cgm.errorNYI(
517-
exprRange, "firstprivate copy-init recipe not properly generated");
518-
}
519-
520-
createFirstprivateRecipeCopy(loc, locEnd, mainOp, tempDeclEmission,
521-
recipe, varRecipe, temporary);
522-
}
523-
}
524-
525-
// This function generates the 'combiner' section for a reduction recipe. Note
526-
// that this function is not 'insertion point' clean, in that it alters the
527-
// insertion point to be inside of the 'combiner' section of the recipe, but
528-
// doesn't restore it aftewards.
529-
void createReductionRecipeCombiner(mlir::Location loc, mlir::Location locEnd,
530-
mlir::Value mainOp,
531-
mlir::acc::ReductionRecipeOp recipe) {
532-
mlir::Block *block = builder.createBlock(
533-
&recipe.getCombinerRegion(), recipe.getCombinerRegion().end(),
534-
{mainOp.getType(), mainOp.getType()}, {loc, loc});
535-
builder.setInsertionPointToEnd(&recipe.getCombinerRegion().back());
536-
CIRGenFunction::LexicalScope ls(cgf, loc, block);
537-
538-
mlir::BlockArgument lhsArg = block->getArgument(0);
539-
540-
mlir::acc::YieldOp::create(builder, locEnd, lhsArg);
541-
}
542-
543-
// This function generates the 'destroy' section for a recipe. Note
544-
// that this function is not 'insertion point' clean, in that it alters the
545-
// insertion point to be inside of the 'destroy' section of the recipe, but
546-
// doesn't restore it aftewards.
547-
void createRecipeDestroySection(mlir::Location loc, mlir::Location locEnd,
548-
mlir::Value mainOp, CharUnits alignment,
549-
QualType baseType,
550-
mlir::Region &destroyRegion) {
551-
mlir::Block *block =
552-
builder.createBlock(&destroyRegion, destroyRegion.end(),
553-
{mainOp.getType(), mainOp.getType()}, {loc, loc});
554-
builder.setInsertionPointToEnd(&destroyRegion.back());
555-
CIRGenFunction::LexicalScope ls(cgf, loc, block);
556-
557-
mlir::Type elementTy =
558-
mlir::cast<cir::PointerType>(mainOp.getType()).getPointee();
559-
// The destroy region has a signature of "original item, privatized item".
560-
// So the 2nd item is the one that needs destroying, the former is just for
561-
// reference and we don't really have a need for it at the moment.
562-
Address addr{block->getArgument(1), elementTy, alignment};
563-
cgf.emitDestroy(addr, baseType,
564-
cgf.getDestroyer(QualType::DK_cxx_destructor));
565-
566-
mlir::acc::YieldOp::create(builder, locEnd);
567-
}
568-
569-
mlir::acc::ReductionOperator convertReductionOp(OpenACCReductionOperator op) {
570-
switch (op) {
571-
case OpenACCReductionOperator::Addition:
572-
return mlir::acc::ReductionOperator::AccAdd;
573-
case OpenACCReductionOperator::Multiplication:
574-
return mlir::acc::ReductionOperator::AccMul;
575-
case OpenACCReductionOperator::Max:
576-
return mlir::acc::ReductionOperator::AccMax;
577-
case OpenACCReductionOperator::Min:
578-
return mlir::acc::ReductionOperator::AccMin;
579-
case OpenACCReductionOperator::BitwiseAnd:
580-
return mlir::acc::ReductionOperator::AccIand;
581-
case OpenACCReductionOperator::BitwiseOr:
582-
return mlir::acc::ReductionOperator::AccIor;
583-
case OpenACCReductionOperator::BitwiseXOr:
584-
return mlir::acc::ReductionOperator::AccXor;
585-
case OpenACCReductionOperator::And:
586-
return mlir::acc::ReductionOperator::AccLand;
587-
case OpenACCReductionOperator::Or:
588-
return mlir::acc::ReductionOperator::AccLor;
589-
case OpenACCReductionOperator::Invalid:
590-
llvm_unreachable("invalid reduction operator");
591-
}
592-
593-
llvm_unreachable("invalid reduction operator");
594-
}
595-
596-
template <typename RecipeTy>
597-
RecipeTy getOrCreateRecipe(ASTContext &astCtx, const Expr *varRef,
598-
const VarDecl *varRecipe, const VarDecl *temporary,
599-
OpenACCReductionOperator reductionOp,
600-
DeclContext *dc, QualType baseType,
601-
mlir::Value mainOp) {
602-
603-
if (baseType->isPointerType() ||
604-
(baseType->isArrayType() && !baseType->isConstantArrayType())) {
605-
// It is clear that the use of pointers/VLAs in a recipe are not properly
606-
// generated/don't do what they are supposed to do. In the case where we
607-
// have 'bounds', we can actually figure out what we want to
608-
// initialize/copy/destroy/compare/etc, but we haven't figured out how
609-
// that looks yet, both between the IR and generation code. For now, we
610-
// will do an NYI error no it.
611-
cgf.cgm.errorNYI(
612-
varRef->getSourceRange(),
613-
"OpenACC recipe generation for pointer/non-constant arrays");
614-
}
615-
616-
mlir::ModuleOp mod = builder.getBlock()
617-
->getParent()
618-
->template getParentOfType<mlir::ModuleOp>();
619-
620-
std::string recipeName = getRecipeName<RecipeTy>(varRef->getSourceRange(),
621-
baseType, reductionOp);
622-
if (auto recipe = mod.lookupSymbol<RecipeTy>(recipeName))
623-
return recipe;
624-
625-
mlir::Location loc = cgf.cgm.getLoc(varRef->getBeginLoc());
626-
mlir::Location locEnd = cgf.cgm.getLoc(varRef->getEndLoc());
627-
628-
mlir::OpBuilder modBuilder(mod.getBodyRegion());
629-
RecipeTy recipe;
630-
631-
if constexpr (std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
632-
recipe = RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType(),
633-
convertReductionOp(reductionOp));
634-
} else {
635-
recipe = RecipeTy::create(modBuilder, loc, recipeName, mainOp.getType());
636-
}
637-
638-
createRecipeInitCopy(loc, locEnd, varRef->getSourceRange(), mainOp, recipe,
639-
varRecipe, temporary);
640-
641-
if constexpr (std::is_same_v<RecipeTy, mlir::acc::ReductionRecipeOp>) {
642-
createReductionRecipeCombiner(loc, locEnd, mainOp, recipe);
643-
}
644-
645-
if (varRecipe && varRecipe->needsDestruction(cgf.getContext()))
646-
createRecipeDestroySection(loc, locEnd, mainOp,
647-
cgf.getContext().getDeclAlign(varRecipe),
648-
baseType, recipe.getDestroyRegion());
649-
return recipe;
650-
}
651-
652360
public:
653361
OpenACCClauseCIREmitter(OpTy &operation, CIRGen::CIRGenFunction &cgf,
654362
CIRGen::CIRGenBuilderTy &builder,
@@ -1287,11 +995,13 @@ class OpenACCClauseCIREmitter final
1287995
allocaDecl->setInit(varRecipe.InitExpr);
1288996
allocaDecl->setInitStyle(VarDecl::CallInit);
1289997

1290-
auto recipe = getOrCreateRecipe<mlir::acc::PrivateRecipeOp>(
1291-
cgf.getContext(), varExpr, allocaDecl, /*temporary=*/nullptr,
1292-
OpenACCReductionOperator::Invalid,
1293-
Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
1294-
privateOp.getResult());
998+
auto recipe =
999+
OpenACCRecipeBuilder<mlir::acc::PrivateRecipeOp>(cgf, builder)
1000+
.getOrCreateRecipe(cgf.getContext(), varExpr, allocaDecl,
1001+
/*temporary=*/nullptr,
1002+
OpenACCReductionOperator::Invalid,
1003+
Decl::castToDeclContext(cgf.curFuncDecl),
1004+
opInfo.baseType, privateOp.getResult());
12951005
// TODO: OpenACC: The dialect is going to change in the near future to
12961006
// have these be on a different operation, so when that changes, we
12971007
// probably need to change these here.
@@ -1329,11 +1039,15 @@ class OpenACCClauseCIREmitter final
13291039
allocaDecl->setInit(varRecipe.InitExpr);
13301040
allocaDecl->setInitStyle(VarDecl::CallInit);
13311041

1332-
auto recipe = getOrCreateRecipe<mlir::acc::FirstprivateRecipeOp>(
1333-
cgf.getContext(), varExpr, allocaDecl,
1334-
varRecipe.InitFromTemporary, OpenACCReductionOperator::Invalid,
1335-
Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
1336-
firstPrivateOp.getResult());
1042+
auto recipe =
1043+
OpenACCRecipeBuilder<mlir::acc::FirstprivateRecipeOp>(cgf,
1044+
builder)
1045+
.getOrCreateRecipe(cgf.getContext(), varExpr, allocaDecl,
1046+
varRecipe.InitFromTemporary,
1047+
OpenACCReductionOperator::Invalid,
1048+
Decl::castToDeclContext(cgf.curFuncDecl),
1049+
opInfo.baseType,
1050+
firstPrivateOp.getResult());
13371051

13381052
// TODO: OpenACC: The dialect is going to change in the near future to
13391053
// have these be on a different operation, so when that changes, we
@@ -1373,11 +1087,13 @@ class OpenACCClauseCIREmitter final
13731087
allocaDecl->setInit(varRecipe.InitExpr);
13741088
allocaDecl->setInitStyle(VarDecl::CallInit);
13751089

1376-
auto recipe = getOrCreateRecipe<mlir::acc::ReductionRecipeOp>(
1377-
cgf.getContext(), varExpr, allocaDecl,
1378-
/*temporary=*/nullptr, clause.getReductionOp(),
1379-
Decl::castToDeclContext(cgf.curFuncDecl), opInfo.baseType,
1380-
reductionOp.getResult());
1090+
auto recipe =
1091+
OpenACCRecipeBuilder<mlir::acc::ReductionRecipeOp>(cgf, builder)
1092+
.getOrCreateRecipe(cgf.getContext(), varExpr, allocaDecl,
1093+
/*temporary=*/nullptr,
1094+
clause.getReductionOp(),
1095+
Decl::castToDeclContext(cgf.curFuncDecl),
1096+
opInfo.baseType, reductionOp.getResult());
13811097

13821098
operation.addReduction(builder.getContext(), reductionOp, recipe);
13831099
}

0 commit comments

Comments
 (0)