================ @@ -4899,6 +4899,150 @@ void CGOpenMPRuntime::emitSingleReductionCombiner(CodeGenFunction &CGF, } } +void CGOpenMPRuntime::emitPrivateReduction( + CodeGenFunction &CGF, SourceLocation Loc, ArrayRef<const Expr *> Privates, + ArrayRef<const Expr *> LHSExprs, ArrayRef<const Expr *> RHSExprs, + ArrayRef<const Expr *> ReductionOps) { + + if (LHSExprs.empty() || Privates.empty() || ReductionOps.empty()) + return; + + if (LHSExprs.size() != Privates.size() || + LHSExprs.size() != ReductionOps.size()) + return; + + QualType PrivateType = Privates[0]->getType(); + llvm::Type *LLVMType = CGF.ConvertTypeForMem(PrivateType); + + BinaryOperatorKind MainBO = BO_Comma; + if (const auto *BinOp = dyn_cast<BinaryOperator>(ReductionOps[0])) { + if (const auto *RHSExpr = BinOp->getRHS()) { + if (const auto *BORHS = + dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { + MainBO = BORHS->getOpcode(); + } + } + } + + llvm::Constant *InitVal = llvm::Constant::getNullValue(LLVMType); + const Expr *Private = Privates[0]; + + if (const auto *DRE = dyn_cast<DeclRefExpr>(Private)) { + if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) { + if (const Expr *Init = VD->getInit()) { + if (Init->isConstantInitializer(CGF.getContext(), false)) { + Expr::EvalResult Result; + if (Init->EvaluateAsRValue(Result, CGF.getContext())) { + APValue &InitValue = Result.Val; + if (InitValue.isInt()) { + InitVal = llvm::ConstantInt::get(LLVMType, InitValue.getInt()); + } + } + } + } + } + } + + // Create an internal shared variable + std::string SharedName = getName({"internal_private_var"}); + llvm::GlobalVariable *SharedVar = new llvm::GlobalVariable( + CGM.getModule(), LLVMType, false, llvm::GlobalValue::CommonLinkage, + InitVal, ".omp.reduction." + SharedName, nullptr, + llvm::GlobalVariable::NotThreadLocal); + + SharedVar->setAlignment( + llvm::MaybeAlign(CGF.getContext().getTypeAlign(PrivateType) / 8)); + + Address SharedResult(SharedVar, SharedVar->getValueType(), + CGF.getContext().getTypeAlignInChars(PrivateType)); + + llvm::Value *ThreadId = getThreadID(CGF, Loc); + llvm::Value *BarrierLoc = emitUpdateLocation(CGF, Loc, OMP_ATOMIC_REDUCE); + llvm::Value *BarrierArgs[] = {BarrierLoc, ThreadId}; + + CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( + CGM.getModule(), OMPRTL___kmpc_barrier), + BarrierArgs); + + llvm::BasicBlock *InitBB = CGF.createBasicBlock("init"); + llvm::BasicBlock *InitEndBB = CGF.createBasicBlock("init.end"); + + llvm::Value *IsWorker = CGF.Builder.CreateICmpEQ( + ThreadId, llvm::ConstantInt::get(ThreadId->getType(), 0)); + CGF.Builder.CreateCondBr(IsWorker, InitBB, InitEndBB); + + CGF.EmitBlock(InitBB); + CGF.Builder.CreateStore(InitVal, SharedResult); + CGF.Builder.CreateBr(InitEndBB); + + CGF.EmitBlock(InitEndBB); + + CGF.EmitRuntimeCall(OMPBuilder.getOrCreateRuntimeFunction( + CGM.getModule(), OMPRTL___kmpc_barrier), + BarrierArgs); + + for (unsigned I = 0; I < ReductionOps.size(); ++I) { + if (I >= LHSExprs.size()) { + break; + } + + const auto *BinOp = dyn_cast<BinaryOperator>(ReductionOps[I]); + if (!BinOp || BinOp->getOpcode() != BO_Assign) + continue; + + const Expr *RHSExpr = BinOp->getRHS(); + if (!RHSExpr) + continue; + + BinaryOperatorKind BO = BO_Comma; + if (const auto *BORHS = + dyn_cast<BinaryOperator>(RHSExpr->IgnoreParenImpCasts())) { + BO = BORHS->getOpcode(); + } + + LValue SharedLV = CGF.MakeAddrLValue(SharedResult, PrivateType); + LValue LHSLV = CGF.EmitLValue(LHSExprs[I]); + RValue PrivateRV = CGF.EmitLoadOfLValue(LHSLV, Loc); + auto &&UpdateOp = [&CGF, PrivateRV, BinOp, BO](RValue OldVal) { ---------------- alexey-bataev wrote:
`auto UpdateOp = [&](RValue OldVal) {` https://github.com/llvm/llvm-project/pull/134709 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits