Skip to content

Commit dcdbd5b

Browse files
[OpenACC][NFCI] Implement 'recipe' generation for firstprivate copy (#153622)
The 'firstprivate' clause requires that we do a 'copy' operation, so this patch creates some AST nodes from which we can generate the copy operation, including a 'temporary' and array init. For the most part this is pretty similar to what 'private' does other than the fact that the source is copy (and not default init!), and that there is a temporary from which to copy. --------- Co-authored-by: Andy Kaylor <[email protected]>
1 parent 29976f2 commit dcdbd5b

File tree

1 file changed

+103
-14
lines changed

1 file changed

+103
-14
lines changed

clang/lib/Sema/SemaOpenACC.cpp

Lines changed: 103 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2604,31 +2604,120 @@ SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK, const Expr *VarExpr) {
26042604
QualType VarTy =
26052605
VarExpr->getType().getNonReferenceType().getUnqualifiedType();
26062606

2607+
IdentifierInfo *VarName = [&]() {
2608+
switch (CK) {
2609+
case OpenACCClauseKind::Private:
2610+
return &getASTContext().Idents.get("openacc.private.init");
2611+
case OpenACCClauseKind::FirstPrivate:
2612+
return &getASTContext().Idents.get("openacc.firstprivate.init");
2613+
case OpenACCClauseKind::Reduction:
2614+
return &getASTContext().Idents.get("openacc.reduction.init");
2615+
default:
2616+
llvm_unreachable("Unknown clause kind?");
2617+
}
2618+
}();
2619+
26072620
VarDecl *Recipe = VarDecl::Create(
26082621
getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2609-
VarExpr->getBeginLoc(),
2610-
&getASTContext().Idents.get("openacc.private.init"), VarTy,
2622+
VarExpr->getBeginLoc(), VarName, VarTy,
26112623
getASTContext().getTrivialTypeSourceInfo(VarTy), SC_Auto);
26122624

26132625
ExprResult Init;
26142626
VarDecl *Temporary = nullptr;
2615-
2616-
if (CK == OpenACCClauseKind::Private) {
2627+
{
26172628
// Trap errors so we don't get weird ones here. If we can't init, we'll just
26182629
// swallow the errors.
26192630
Sema::TentativeAnalysisScope Trap{SemaRef};
26202631
InitializedEntity Entity = InitializedEntity::InitializeVariable(Recipe);
2621-
InitializationKind Kind =
2622-
InitializationKind::CreateDefault(Recipe->getLocation());
26232632

2624-
InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, {});
2625-
Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, {});
2626-
} else if (CK == OpenACCClauseKind::FirstPrivate) {
2627-
// TODO: OpenACC: Implement this to do a 'copy' operation.
2628-
} else if (CK == OpenACCClauseKind::Reduction) {
2629-
// TODO: OpenACC: Implement this for whatever reduction needs.
2630-
} else {
2631-
llvm_unreachable("Unknown clause kind in CreateInitRecipe");
2633+
if (CK == OpenACCClauseKind::Private) {
2634+
InitializationKind Kind =
2635+
InitializationKind::CreateDefault(Recipe->getLocation());
2636+
2637+
InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, {});
2638+
Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, {});
2639+
2640+
} else if (CK == OpenACCClauseKind::FirstPrivate) {
2641+
// Create a VarDecl to be the 'copied-from' for the copy section of the
2642+
// recipe. This allows us to make the association so that we can use the
2643+
// standard 'generation' ability of the init.
2644+
Temporary = VarDecl::Create(
2645+
getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(),
2646+
VarExpr->getBeginLoc(), &getASTContext().Idents.get("openacc.temp"),
2647+
VarTy, getASTContext().getTrivialTypeSourceInfo(VarTy), SC_Auto);
2648+
auto *TemporaryDRE = DeclRefExpr::Create(
2649+
getASTContext(), NestedNameSpecifierLoc{}, SourceLocation{},
2650+
Temporary,
2651+
/*ReferstoEnclosingVariableOrCapture=*/false,
2652+
DeclarationNameInfo{DeclarationName{Temporary->getDeclName()},
2653+
VarExpr->getBeginLoc()},
2654+
VarTy, clang::VK_LValue, Temporary, nullptr, NOUR_None);
2655+
2656+
Expr *InitExpr = nullptr;
2657+
2658+
if (const auto *ArrTy = getASTContext().getAsConstantArrayType(VarTy)) {
2659+
// Arrays need to have each individual element initialized as there
2660+
// isn't a normal 'equals' feature in C/C++. This section sets these up
2661+
// as an init list after 'initializing' each individual element.
2662+
llvm::SmallVector<Expr *> Args;
2663+
2664+
// Decay to pointer for the array subscript expression.
2665+
auto *CastToPtr = ImplicitCastExpr::Create(
2666+
getASTContext(),
2667+
getASTContext().getPointerType(ArrTy->getElementType()),
2668+
CK_ArrayToPointerDecay, TemporaryDRE, /*BasePath=*/nullptr,
2669+
clang::VK_LValue, FPOptionsOverride{});
2670+
2671+
for (std::size_t I = 0; I < ArrTy->getLimitedSize(); ++I) {
2672+
// Each element needs to be some sort of copy initialization from an
2673+
// array-index of the original temporary (referenced via a
2674+
// DeclRefExpr).
2675+
2676+
auto *Idx = IntegerLiteral::Create(
2677+
getASTContext(), llvm::APInt(sizeof(std::size_t) * 8, I),
2678+
getASTContext().getSizeType(), VarExpr->getBeginLoc());
2679+
2680+
Expr *Subscript = new (getASTContext()) ArraySubscriptExpr(
2681+
CastToPtr, Idx, ArrTy->getElementType(), clang::VK_LValue,
2682+
OK_Ordinary, VarExpr->getBeginLoc());
2683+
2684+
// Generate a simple copy from the result of the subscript. This will
2685+
// do a bitwise copy or a copy-constructor, as necessary.
2686+
InitializedEntity CopyEntity =
2687+
InitializedEntity::InitializeElement(getASTContext(), I, Entity);
2688+
InitializationKind CopyKind =
2689+
InitializationKind::CreateCopy(VarExpr->getBeginLoc(), {});
2690+
InitializationSequence CopySeq(SemaRef.SemaRef, CopyEntity, CopyKind,
2691+
Subscript,
2692+
/*TopLevelOfInitList=*/true);
2693+
2694+
ExprResult ElemRes =
2695+
CopySeq.Perform(SemaRef.SemaRef, CopyEntity, CopyKind, Subscript);
2696+
Args.push_back(ElemRes.get());
2697+
}
2698+
2699+
InitExpr = new (getASTContext())
2700+
InitListExpr(getASTContext(), VarExpr->getBeginLoc(), Args,
2701+
VarExpr->getEndLoc());
2702+
InitExpr->setType(VarTy);
2703+
2704+
} else {
2705+
// If this isn't an array, we can just do normal copy init from a simple
2706+
// variable reference, so set that up.
2707+
InitExpr = TemporaryDRE;
2708+
}
2709+
2710+
InitializationKind Kind = InitializationKind::CreateForInit(
2711+
Recipe->getLocation(), /*DirectInit=*/true, InitExpr);
2712+
InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, InitExpr,
2713+
/*TopLevelOfInitList=*/false,
2714+
/*TreatUnavailableAsInvalid=*/false);
2715+
Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, InitExpr, &VarTy);
2716+
} else if (CK == OpenACCClauseKind::Reduction) {
2717+
// TODO: OpenACC: Implement this for whatever reduction needs.
2718+
} else {
2719+
llvm_unreachable("Unknown clause kind in CreateInitRecipe");
2720+
}
26322721
}
26332722

26342723
if (Init.get()) {

0 commit comments

Comments
 (0)