Skip to content

Commit 5e924fa

Browse files
authored
[OpenACC] Reduction 'init' lowering for all-ones/least/largest (#156535)
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 9f9b480 commit 5e924fa

20 files changed

+6101
-661
lines changed

clang/lib/Sema/SemaOpenACC.cpp

Lines changed: 107 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2589,26 +2589,67 @@ 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 { Zero, One, AllOnes, Least, Largest };
2594+
llvm::APFloat getInitFloatValue(ASTContext &Context, InitKind IK, QualType Ty) {
2595+
switch (IK) {
2596+
case InitKind::Zero:
2597+
return llvm::APFloat::getZero(Context.getFloatTypeSemantics(Ty));
2598+
case InitKind::One:
2599+
return llvm::APFloat::getOne(Context.getFloatTypeSemantics(Ty));
2600+
case InitKind::AllOnes:
2601+
return llvm::APFloat::getAllOnesValue(Context.getFloatTypeSemantics(Ty));
2602+
case InitKind::Least:
2603+
return llvm::APFloat::getLargest(Context.getFloatTypeSemantics(Ty),
2604+
/*Negative=*/true);
2605+
case InitKind::Largest:
2606+
return llvm::APFloat::getLargest(Context.getFloatTypeSemantics(Ty));
2607+
break;
2608+
}
2609+
llvm_unreachable("unknown init kind");
2610+
}
2611+
2612+
llvm::APInt getInitIntValue(ASTContext &Context, InitKind IK, QualType Ty) {
2613+
switch (IK) {
2614+
case InitKind::Zero:
2615+
return llvm::APInt(Context.getIntWidth(Ty), 0);
2616+
case InitKind::One:
2617+
return llvm::APInt(Context.getIntWidth(Ty), 1);
2618+
case InitKind::AllOnes:
2619+
return llvm::APInt::getAllOnes(Context.getIntWidth(Ty));
2620+
case InitKind::Least:
2621+
if (Ty->isSignedIntegerOrEnumerationType())
2622+
return llvm::APInt::getSignedMinValue(Context.getIntWidth(Ty));
2623+
return llvm::APInt::getMinValue(Context.getIntWidth(Ty));
2624+
case InitKind::Largest:
2625+
if (Ty->isSignedIntegerOrEnumerationType())
2626+
return llvm::APInt::getSignedMaxValue(Context.getIntWidth(Ty));
2627+
return llvm::APInt::getMaxValue(Context.getIntWidth(Ty));
2628+
break;
2629+
}
2630+
llvm_unreachable("unknown init kind");
2631+
}
2632+
2633+
/// Loops through a type and generates an appropriate InitListExpr to
2634+
/// generate type initialization.
2635+
Expr *GenerateReductionInitRecipeExpr(ASTContext &Context,
2636+
SourceRange ExprRange, QualType Ty,
2637+
InitKind IK) {
25972638
Ty = Ty.getCanonicalType();
25982639
llvm::SmallVector<Expr *> Exprs;
25992640

26002641
if (const RecordDecl *RD = Ty->getAsRecordDecl()) {
26012642
for (auto *F : RD->fields()) {
2602-
if (Expr *NewExpr =
2603-
GenerateReductionInitRecipeExpr(Context, ExprRange, F->getType()))
2643+
if (Expr *NewExpr = GenerateReductionInitRecipeExpr(Context, ExprRange,
2644+
F->getType(), IK))
26042645
Exprs.push_back(NewExpr);
26052646
else
26062647
return nullptr;
26072648
}
26082649
} else if (const ConstantArrayType *AT = Context.getAsConstantArrayType(Ty)) {
26092650
for (uint64_t Idx = 0; Idx < AT->getZExtSize(); ++Idx) {
2610-
if (Expr *NewExpr = GenerateReductionInitRecipeExpr(Context, ExprRange,
2611-
AT->getElementType()))
2651+
if (Expr *NewExpr = GenerateReductionInitRecipeExpr(
2652+
Context, ExprRange, AT->getElementType(), IK))
26122653
Exprs.push_back(NewExpr);
26132654
else
26142655
return nullptr;
@@ -2627,16 +2668,41 @@ static Expr *GenerateReductionInitRecipeExpr(ASTContext &Context,
26272668
} else {
26282669
assert(Ty->isScalarType());
26292670

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()));
2671+
if (const auto *Cplx = Ty->getAs<ComplexType>()) {
2672+
// we can get here in error cases, so make sure we generate something that
2673+
// will work if we find ourselves wanting to enable this, so emit '0,0'
2674+
// for both ints and floats.
2675+
2676+
QualType EltTy = Cplx->getElementType();
2677+
if (EltTy->isFloatingType()) {
2678+
Exprs.push_back(FloatingLiteral::Create(
2679+
Context, getInitFloatValue(Context, InitKind::Zero, EltTy),
2680+
/*isExact=*/true, EltTy, ExprRange.getBegin()));
2681+
Exprs.push_back(FloatingLiteral::Create(
2682+
Context, getInitFloatValue(Context, InitKind::Zero, EltTy),
2683+
/*isExact=*/true, EltTy, ExprRange.getBegin()));
2684+
} else {
2685+
Exprs.push_back(IntegerLiteral::Create(
2686+
Context, getInitIntValue(Context, InitKind::Zero, EltTy), EltTy,
2687+
ExprRange.getBegin()));
2688+
Exprs.push_back(IntegerLiteral::Create(
2689+
Context, getInitIntValue(Context, InitKind::Zero, EltTy), EltTy,
2690+
ExprRange.getBegin()));
2691+
}
2692+
2693+
} else if (Ty->isFloatingType()) {
2694+
Exprs.push_back(
2695+
FloatingLiteral::Create(Context, getInitFloatValue(Context, IK, Ty),
2696+
/*isExact=*/true, Ty, ExprRange.getBegin()));
2697+
} else if (Ty->isBooleanType()) {
2698+
Exprs.push_back(CXXBoolLiteralExpr::Create(Context,
2699+
(IK == InitKind::One ||
2700+
IK == InitKind::AllOnes ||
2701+
IK == InitKind::Largest),
2702+
Ty, ExprRange.getBegin()));
26362703
} else {
26372704
Exprs.push_back(IntegerLiteral::Create(
2638-
Context, llvm::APInt(Context.getTypeSize(Ty), 1), Ty,
2639-
ExprRange.getBegin()));
2705+
Context, getInitIntValue(Context, IK, Ty), Ty, ExprRange.getBegin()));
26402706
}
26412707
}
26422708

@@ -2646,6 +2712,8 @@ static Expr *GenerateReductionInitRecipeExpr(ASTContext &Context,
26462712
return InitExpr;
26472713
}
26482714

2715+
} // namespace
2716+
26492717
std::pair<VarDecl *, VarDecl *>
26502718
SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK,
26512719
OpenACCReductionOperator ReductionOperator,
@@ -2796,20 +2864,37 @@ SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK,
27962864
// are used for code generation, we can just ignore/not bother doing any
27972865
// initialization here.
27982866
break;
2799-
case OpenACCReductionOperator::Max:
2800-
case OpenACCReductionOperator::Min:
2801-
case OpenACCReductionOperator::BitwiseAnd:
2802-
// TODO: OpenACC: figure out init for these.
2867+
case OpenACCReductionOperator::Max: {
2868+
Expr *InitExpr = GenerateReductionInitRecipeExpr(
2869+
getASTContext(), VarExpr->getSourceRange(), VarTy, InitKind::Least);
2870+
2871+
Init = FinishValueInit(InitExpr);
2872+
break;
2873+
}
2874+
case OpenACCReductionOperator::Min: {
2875+
Expr *InitExpr = GenerateReductionInitRecipeExpr(
2876+
getASTContext(), VarExpr->getSourceRange(), VarTy,
2877+
InitKind::Largest);
2878+
2879+
Init = FinishValueInit(InitExpr);
28032880
break;
2881+
}
2882+
case OpenACCReductionOperator::BitwiseAnd: {
2883+
Expr *InitExpr = GenerateReductionInitRecipeExpr(
2884+
getASTContext(), VarExpr->getSourceRange(), VarTy,
2885+
InitKind::AllOnes);
28042886

2887+
Init = FinishValueInit(InitExpr);
2888+
break;
2889+
}
28052890
case OpenACCReductionOperator::Multiplication:
28062891
case OpenACCReductionOperator::And: {
28072892
// '&&' initializes every field to 1. However, we need to loop through
28082893
// every field/element and generate an initializer for each of the
28092894
// elements.
28102895

28112896
Expr *InitExpr = GenerateReductionInitRecipeExpr(
2812-
getASTContext(), VarExpr->getSourceRange(), VarTy);
2897+
getASTContext(), VarExpr->getSourceRange(), VarTy, InitKind::One);
28132898

28142899
Init = FinishValueInit(InitExpr);
28152900
break;

0 commit comments

Comments
 (0)