@@ -4986,9 +4986,38 @@ void CGOpenMPRuntime::emitPrivateReduction(
4986
4986
auto EmitSharedInit = [&]() {
4987
4987
if (UDR) { // Check if it's a User-Defined Reduction
4988
4988
if (const Expr *UDRInitExpr = UDR->getInitializer()) {
4989
- // Use the initializer from the OMPDeclareReductionDecl
4990
- CGF.EmitAnyExprToMem(UDRInitExpr, SharedResult,
4991
- PrivateType.getQualifiers(), true);
4989
+ std::pair<llvm::Function *, llvm::Function *> FnPair =
4990
+ getUserDefinedReduction(UDR);
4991
+ llvm::Function *InitializerFn = FnPair.second;
4992
+ if (InitializerFn) {
4993
+ if (const auto *CE =
4994
+ dyn_cast<CallExpr>(UDRInitExpr->IgnoreParenImpCasts())) {
4995
+ const auto *OutDRE = cast<DeclRefExpr>(
4996
+ cast<UnaryOperator>(CE->getArg(0)->IgnoreParenImpCasts())
4997
+ ->getSubExpr());
4998
+ const VarDecl *OutVD = cast<VarDecl>(OutDRE->getDecl());
4999
+
5000
+ CodeGenFunction::OMPPrivateScope LocalScope(CGF);
5001
+ LocalScope.addPrivate(OutVD, SharedResult);
5002
+
5003
+ (void)LocalScope.Privatize();
5004
+ if (const auto *OVE = dyn_cast<OpaqueValueExpr>(
5005
+ CE->getCallee()->IgnoreParenImpCasts())) {
5006
+ CodeGenFunction::OpaqueValueMapping OpaqueMap(
5007
+ CGF, OVE, RValue::get(InitializerFn));
5008
+ CGF.EmitIgnoredExpr(CE);
5009
+ } else {
5010
+ CGF.EmitAnyExprToMem(UDRInitExpr, SharedResult,
5011
+ PrivateType.getQualifiers(), true);
5012
+ }
5013
+ } else {
5014
+ CGF.EmitAnyExprToMem(UDRInitExpr, SharedResult,
5015
+ PrivateType.getQualifiers(), true);
5016
+ }
5017
+ } else {
5018
+ CGF.EmitAnyExprToMem(UDRInitExpr, SharedResult,
5019
+ PrivateType.getQualifiers(), true);
5020
+ }
4992
5021
} else {
4993
5022
// EmitNullInitialization handles default construction for C++ classes
4994
5023
// and zeroing for scalars, which is a reasonable default.
0 commit comments