Skip to content

Commit a176d3e

Browse files
committed
[OpenACC] Reduction 'init' lowering for all-ones/least/largest
As a follow on to the last patches of this form, this patch does the init section for all of the reduction operators that weren't previously covered, which is '&' as all-ones, 'max' as 'least', and 'min' as 'largest'.
1 parent a24e11f commit a176d3e

20 files changed

+6096
-661
lines changed

clang/lib/Sema/SemaOpenACC.cpp

Lines changed: 102 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2589,26 +2589,63 @@ SemaOpenACC::ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) {
25892589
return BuildOpenACCAsteriskSizeExpr(AsteriskLoc);
25902590
}
25912591

2592-
/// Loops through a type and generates an appropriate InitListExpr to generate
2593-
/// type initialization.
2594-
static Expr *GenerateReductionInitRecipeExpr(ASTContext &Context,
2595-
SourceRange ExprRange,
2596-
QualType Ty) {
2592+
namespace {
2593+
enum class InitKind { One, AllOnes, Least, Largest };
2594+
llvm::APFloat getInitFloatValue(ASTContext &Context, InitKind IK, QualType Ty) {
2595+
switch (IK) {
2596+
case InitKind::One:
2597+
return llvm::APFloat::getOne(Context.getFloatTypeSemantics(Ty));
2598+
case InitKind::AllOnes:
2599+
return llvm::APFloat::getAllOnesValue(Context.getFloatTypeSemantics(Ty));
2600+
case InitKind::Least:
2601+
return llvm::APFloat::getSmallestNormalized(
2602+
Context.getFloatTypeSemantics(Ty), /*Negative=*/true);
2603+
case InitKind::Largest:
2604+
return llvm::APFloat::getLargest(Context.getFloatTypeSemantics(Ty));
2605+
break;
2606+
}
2607+
llvm_unreachable("unknown init kind");
2608+
}
2609+
2610+
llvm::APInt getInitIntValue(ASTContext &Context, InitKind IK, QualType Ty) {
2611+
switch (IK) {
2612+
case InitKind::One:
2613+
return llvm::APInt(Context.getIntWidth(Ty), 1);
2614+
case InitKind::AllOnes:
2615+
return llvm::APInt::getAllOnes(Context.getIntWidth(Ty));
2616+
case InitKind::Least:
2617+
if (Ty->isSignedIntegerOrEnumerationType())
2618+
return llvm::APInt::getSignedMinValue(Context.getIntWidth(Ty));
2619+
return llvm::APInt::getMinValue(Context.getIntWidth(Ty));
2620+
case InitKind::Largest:
2621+
if (Ty->isSignedIntegerOrEnumerationType())
2622+
return llvm::APInt::getSignedMaxValue(Context.getIntWidth(Ty));
2623+
return llvm::APInt::getMaxValue(Context.getIntWidth(Ty));
2624+
break;
2625+
}
2626+
llvm_unreachable("unknown init kind");
2627+
}
2628+
2629+
/// Loops through a type and generates an appropriate InitListExpr to
2630+
/// generate type initialization.
2631+
Expr *GenerateReductionInitRecipeExpr(ASTContext &Context,
2632+
SourceRange ExprRange, QualType Ty,
2633+
InitKind IK) {
25972634
Ty = Ty.getCanonicalType();
25982635
llvm::SmallVector<Expr *> Exprs;
25992636

26002637
if (const RecordDecl *RD = Ty->getAsRecordDecl()) {
26012638
for (auto *F : RD->fields()) {
2602-
if (Expr *NewExpr =
2603-
GenerateReductionInitRecipeExpr(Context, ExprRange, F->getType()))
2639+
if (Expr *NewExpr = GenerateReductionInitRecipeExpr(Context, ExprRange,
2640+
F->getType(), IK))
26042641
Exprs.push_back(NewExpr);
26052642
else
26062643
return nullptr;
26072644
}
26082645
} else if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
26092646
for (uint64_t Idx = 0; Idx < AT->getZExtSize(); ++Idx) {
2610-
if (Expr *NewExpr = GenerateReductionInitRecipeExpr(Context, ExprRange,
2611-
AT->getElementType()))
2647+
if (Expr *NewExpr = GenerateReductionInitRecipeExpr(
2648+
Context, ExprRange, AT->getElementType(), IK))
26122649
Exprs.push_back(NewExpr);
26132650
else
26142651
return nullptr;
@@ -2627,16 +2664,40 @@ static Expr *GenerateReductionInitRecipeExpr(ASTContext &Context,
26272664
} else {
26282665
assert(Ty->isScalarType());
26292666

2630-
// TODO: OpenACC: This currently only works for '1', but we need to figure
2631-
// out a way to do least/largest/all-1s.
2632-
if (Ty->isFloatingType()) {
2633-
Exprs.push_back(FloatingLiteral::Create(
2634-
Context, llvm::APFloat::getOne(Context.getFloatTypeSemantics(Ty)),
2635-
/*isExact=*/true, Ty, ExprRange.getBegin()));
2667+
if (const auto *Cplx = Ty->getAs<ComplexType>()) {
2668+
// we can get here in error cases, so make sure we generate something that
2669+
// will work if we find ourselves wanting to enable this.
2670+
2671+
QualType EltTy = Cplx->getElementType();
2672+
if (EltTy->isFloatingType()) {
2673+
Exprs.push_back(FloatingLiteral::Create(
2674+
Context, getInitFloatValue(Context, IK, EltTy),
2675+
/*isExact=*/true, EltTy, ExprRange.getBegin()));
2676+
Exprs.push_back(FloatingLiteral::Create(
2677+
Context, getInitFloatValue(Context, IK, EltTy),
2678+
/*isExact=*/true, EltTy, ExprRange.getBegin()));
2679+
} else {
2680+
Exprs.push_back(
2681+
IntegerLiteral::Create(Context, getInitIntValue(Context, IK, EltTy),
2682+
EltTy, ExprRange.getBegin()));
2683+
Exprs.push_back(
2684+
IntegerLiteral::Create(Context, getInitIntValue(Context, IK, EltTy),
2685+
EltTy, ExprRange.getBegin()));
2686+
}
2687+
2688+
} else if (Ty->isFloatingType()) {
2689+
Exprs.push_back(
2690+
FloatingLiteral::Create(Context, getInitFloatValue(Context, IK, Ty),
2691+
/*isExact=*/true, Ty, ExprRange.getBegin()));
2692+
} else if (Ty->isBooleanType()) {
2693+
Exprs.push_back(CXXBoolLiteralExpr::Create(Context,
2694+
(IK == InitKind::One ||
2695+
IK == InitKind::AllOnes ||
2696+
IK == InitKind::Largest),
2697+
Ty, ExprRange.getBegin()));
26362698
} else {
26372699
Exprs.push_back(IntegerLiteral::Create(
2638-
Context, llvm::APInt(Context.getTypeSize(Ty), 1), Ty,
2639-
ExprRange.getBegin()));
2700+
Context, getInitIntValue(Context, IK, Ty), Ty, ExprRange.getBegin()));
26402701
}
26412702
}
26422703

@@ -2646,6 +2707,8 @@ static Expr *GenerateReductionInitRecipeExpr(ASTContext &Context,
26462707
return InitExpr;
26472708
}
26482709

2710+
} // namespace
2711+
26492712
std::pair<VarDecl *, VarDecl *>
26502713
SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK,
26512714
OpenACCReductionOperator ReductionOperator,
@@ -2796,20 +2859,37 @@ SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK,
27962859
// are used for code generation, we can just ignore/not bother doing any
27972860
// initialization here.
27982861
break;
2799-
case OpenACCReductionOperator::Max:
2800-
case OpenACCReductionOperator::Min:
2801-
case OpenACCReductionOperator::BitwiseAnd:
2802-
// TODO: OpenACC: figure out init for these.
2862+
case OpenACCReductionOperator::Max: {
2863+
Expr *InitExpr = GenerateReductionInitRecipeExpr(
2864+
getASTContext(), VarExpr->getSourceRange(), VarTy, InitKind::Least);
2865+
2866+
Init = FinishValueInit(InitExpr);
2867+
break;
2868+
}
2869+
case OpenACCReductionOperator::Min: {
2870+
Expr *InitExpr = GenerateReductionInitRecipeExpr(
2871+
getASTContext(), VarExpr->getSourceRange(), VarTy,
2872+
InitKind::Largest);
2873+
2874+
Init = FinishValueInit(InitExpr);
28032875
break;
2876+
}
2877+
case OpenACCReductionOperator::BitwiseAnd: {
2878+
Expr *InitExpr = GenerateReductionInitRecipeExpr(
2879+
getASTContext(), VarExpr->getSourceRange(), VarTy,
2880+
InitKind::AllOnes);
28042881

2882+
Init = FinishValueInit(InitExpr);
2883+
break;
2884+
}
28052885
case OpenACCReductionOperator::Multiplication:
28062886
case OpenACCReductionOperator::And: {
28072887
// '&&' initializes every field to 1. However, we need to loop through
28082888
// every field/element and generate an initializer for each of the
28092889
// elements.
28102890

28112891
Expr *InitExpr = GenerateReductionInitRecipeExpr(
2812-
getASTContext(), VarExpr->getSourceRange(), VarTy);
2892+
getASTContext(), VarExpr->getSourceRange(), VarTy, InitKind::One);
28132893

28142894
Init = FinishValueInit(InitExpr);
28152895
break;

0 commit comments

Comments
 (0)