Skip to content
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
98 changes: 83 additions & 15 deletions clang/lib/Sema/SemaOpenACC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2589,6 +2589,63 @@ SemaOpenACC::ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) {
return BuildOpenACCAsteriskSizeExpr(AsteriskLoc);
}

/// Loops through a type and generates an appropriate InitListExpr to generate
/// type initialization.
static Expr *GenerateReductionInitRecipeExpr(ASTContext &Context,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this could have an enum argument indicating the required initializer kind (zero, one, least, largest, all 1's, etc.).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I was thinking a few things, either that, or a function object/function pointer that knows how to do the lowering. I was intending to do that as a part of my patch though.

SourceRange ExprRange,
QualType Ty) {
Ty = Ty.getCanonicalType();
llvm::SmallVector<Expr *> Exprs;

if (const RecordDecl *RD = Ty->getAsRecordDecl()) {
for (auto *F : RD->fields()) {
if (Expr *NewExpr =
GenerateReductionInitRecipeExpr(Context, ExprRange, F->getType()))
Exprs.push_back(NewExpr);
else
return nullptr;
}
} else if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we ever get here with a non-constant array type? Is the type always constant because it's an initializer?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ConstantArrayType means 'not a VLA' in this context (not that it is constant, it is that it is a constant size).

At the moment, we CAN get here with a pointer/VLA, but I haven't figured out how to implement that yet, and will probably do so next (for a few things). I probably could use a NYI in the normal init generation for pointer types at the moment. BUT since that is not Reduction specific, I'll do that in a separate patch if thats OK.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's code in emitCXXNewAllocSize (in CIRGenExprCXX.cpp in the incubator) to handle variable array length if you want to reuse that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, well... its more than that. The length of the VLA component is going to come in from a different place, via a variable in the recipe, so we have to figure out how to get that, what to loop over, etc. It is more than just emitting the alloca, we have to do a full alloca of the right sizes then do the init. But that is a good thing to know about for when I have to figure that out.

for (uint64_t Idx = 0; Idx < AT->getZExtSize(); ++Idx) {
if (Expr *NewExpr = GenerateReductionInitRecipeExpr(Context, ExprRange,
AT->getElementType()))
Exprs.push_back(NewExpr);
else
return nullptr;
}

} else if (Ty->isPointerType()) {
// For now, we are going to punt/not initialize pointer types, as
// discussions/designs are ongoing on how to express this behavior,
// particularly since they probably need the 'bounds' passed to them
// correctly. A future patch/patch set will go through all of the pointer
// values for all of the recipes to make sure we have a sane behavior.

// For now, this will result in a NYI during code generation for
// no-initializer.
return nullptr;
} else {
assert(Ty->isScalarType());

// TODO: OpenACC: This currently only works for '1', but we need to figure
// out a way to do least/largest/all-1s.
if (Ty->isFloatingType()) {
Exprs.push_back(FloatingLiteral::Create(
Context, llvm::APFloat::getOne(Context.getFloatTypeSemantics(Ty)),
/*isExact=*/true, Ty, ExprRange.getBegin()));
} else {
Exprs.push_back(IntegerLiteral::Create(
Context, llvm::APInt(Context.getTypeSize(Ty), 1), Ty,
ExprRange.getBegin()));
}
}

Expr *InitExpr = new (Context)
InitListExpr(Context, ExprRange.getBegin(), Exprs, ExprRange.getEnd());
InitExpr->setType(Ty);
return InitExpr;
}

std::pair<VarDecl *, VarDecl *>
SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK,
OpenACCReductionOperator ReductionOperator,
Expand Down Expand Up @@ -2637,13 +2694,24 @@ SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK,
Sema::TentativeAnalysisScope Trap{SemaRef};
InitializedEntity Entity = InitializedEntity::InitializeVariable(Recipe);

auto FinishValueInit = [&](Expr *InitExpr) {
if (InitExpr) {
InitializationKind Kind = InitializationKind::CreateForInit(
Recipe->getLocation(), /*DirectInit=*/true, InitExpr);
InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, InitExpr,
/*TopLevelOfInitList=*/false,
/*TreatUnavailableAsInvalid=*/false);
return InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, InitExpr, &VarTy);
}
return ExprEmpty();
};

if (CK == OpenACCClauseKind::Private) {
InitializationKind Kind =
InitializationKind::CreateDefault(Recipe->getLocation());

InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, {});
Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, {});

} else if (CK == OpenACCClauseKind::FirstPrivate) {
// Create a VarDecl to be the 'copied-from' for the copy section of the
// recipe. This allows us to make the association so that we can use the
Expand Down Expand Up @@ -2717,12 +2785,7 @@ SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK,
InitExpr = TemporaryDRE;
}

InitializationKind Kind = InitializationKind::CreateForInit(
Recipe->getLocation(), /*DirectInit=*/true, InitExpr);
InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, InitExpr,
/*TopLevelOfInitList=*/false,
/*TreatUnavailableAsInvalid=*/false);
Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, InitExpr, &VarTy);
Init = FinishValueInit(InitExpr);
} else if (CK == OpenACCClauseKind::Reduction) {
// How we initialize the reduction variable depends on the operator used,
// according to the chart in OpenACC 3.3 section 2.6.15.
Expand All @@ -2733,14 +2796,24 @@ SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK,
// are used for code generation, we can just ignore/not bother doing any
// initialization here.
break;
case OpenACCReductionOperator::Multiplication:
case OpenACCReductionOperator::Max:
case OpenACCReductionOperator::Min:
case OpenACCReductionOperator::BitwiseAnd:
case OpenACCReductionOperator::And:
// TODO: OpenACC: figure out init for these.
break;

case OpenACCReductionOperator::Multiplication:
case OpenACCReductionOperator::And: {
// '&&' initializes every field to 1. However, we need to loop through
// every field/element and generate an initializer for each of the
// elements.

Expr *InitExpr = GenerateReductionInitRecipeExpr(
getASTContext(), VarExpr->getSourceRange(), VarTy);

Init = FinishValueInit(InitExpr);
break;
}
case OpenACCReductionOperator::Addition:
case OpenACCReductionOperator::BitwiseOr:
case OpenACCReductionOperator::BitwiseXOr:
Expand All @@ -2754,12 +2827,7 @@ SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK,
// will get this type correct/etc.
InitExpr->setType(getASTContext().VoidTy);

InitializationKind Kind = InitializationKind::CreateForInit(
Recipe->getLocation(), /*DirectInit=*/true, InitExpr);
InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, InitExpr,
/*TopLevelOfInitList=*/false,
/*TreatUnavailableAsInvalid=*/false);
Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, InitExpr, &VarTy);
Init = FinishValueInit(InitExpr);
break;
}
}
Expand Down
Loading
Loading