14d4af15cSKareem Ergawy //===-- ReductionProcessor.cpp ----------------------------------*- C++ -*-===// 24d4af15cSKareem Ergawy // 34d4af15cSKareem Ergawy // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 44d4af15cSKareem Ergawy // See https://llvm.org/LICENSE.txt for license information. 54d4af15cSKareem Ergawy // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 64d4af15cSKareem Ergawy // 74d4af15cSKareem Ergawy //===----------------------------------------------------------------------===// 84d4af15cSKareem Ergawy // 94d4af15cSKareem Ergawy // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ 104d4af15cSKareem Ergawy // 114d4af15cSKareem Ergawy //===----------------------------------------------------------------------===// 124d4af15cSKareem Ergawy 134d4af15cSKareem Ergawy #include "ReductionProcessor.h" 144d4af15cSKareem Ergawy 15*8557a57cSTom Eccles #include "PrivateReductionUtils.h" 164d4af15cSKareem Ergawy #include "flang/Lower/AbstractConverter.h" 17221f438aSMats Petersson #include "flang/Lower/ConvertType.h" 18698bf3daSSourabh Singh Tomar #include "flang/Lower/SymbolMap.h" 19221f438aSMats Petersson #include "flang/Optimizer/Builder/Complex.h" 20197f3ecfSTom Eccles #include "flang/Optimizer/Builder/HLFIRTools.h" 214d4af15cSKareem Ergawy #include "flang/Optimizer/Builder/Todo.h" 22f46f5a01STom Eccles #include "flang/Optimizer/Dialect/FIRType.h" 234d4af15cSKareem Ergawy #include "flang/Optimizer/HLFIR/HLFIROps.h" 246f068b9cSTom Eccles #include "flang/Optimizer/Support/FatalError.h" 254d4af15cSKareem Ergawy #include "flang/Parser/tools.h" 264d4af15cSKareem Ergawy #include "mlir/Dialect/OpenMP/OpenMPDialect.h" 27f46f5a01STom Eccles #include "llvm/Support/CommandLine.h" 28f46f5a01STom Eccles 29f46f5a01STom Eccles static llvm::cl::opt<bool> forceByrefReduction( 30f46f5a01STom Eccles "force-byref-reduction", 31f46f5a01STom Eccles llvm::cl::desc("Pass all reduction arguments by reference"), 32f46f5a01STom Eccles llvm::cl::Hidden); 334d4af15cSKareem Ergawy 344d4af15cSKareem Ergawy namespace Fortran { 354d4af15cSKareem Ergawy namespace lower { 364d4af15cSKareem Ergawy namespace omp { 374d4af15cSKareem Ergawy 384d4af15cSKareem Ergawy ReductionProcessor::ReductionIdentifier ReductionProcessor::getReductionType( 3963e70c05SKrzysztof Parzyszek const omp::clause::ProcedureDesignator &pd) { 404d4af15cSKareem Ergawy auto redType = llvm::StringSwitch<std::optional<ReductionIdentifier>>( 418b18f2feSKrzysztof Parzyszek getRealName(pd.v.sym()).ToString()) 424d4af15cSKareem Ergawy .Case("max", ReductionIdentifier::MAX) 434d4af15cSKareem Ergawy .Case("min", ReductionIdentifier::MIN) 444d4af15cSKareem Ergawy .Case("iand", ReductionIdentifier::IAND) 454d4af15cSKareem Ergawy .Case("ior", ReductionIdentifier::IOR) 464d4af15cSKareem Ergawy .Case("ieor", ReductionIdentifier::IEOR) 474d4af15cSKareem Ergawy .Default(std::nullopt); 484d4af15cSKareem Ergawy assert(redType && "Invalid Reduction"); 494d4af15cSKareem Ergawy return *redType; 504d4af15cSKareem Ergawy } 514d4af15cSKareem Ergawy 524d4af15cSKareem Ergawy ReductionProcessor::ReductionIdentifier ReductionProcessor::getReductionType( 5363e70c05SKrzysztof Parzyszek omp::clause::DefinedOperator::IntrinsicOperator intrinsicOp) { 544d4af15cSKareem Ergawy switch (intrinsicOp) { 5563e70c05SKrzysztof Parzyszek case omp::clause::DefinedOperator::IntrinsicOperator::Add: 564d4af15cSKareem Ergawy return ReductionIdentifier::ADD; 5763e70c05SKrzysztof Parzyszek case omp::clause::DefinedOperator::IntrinsicOperator::Subtract: 584d4af15cSKareem Ergawy return ReductionIdentifier::SUBTRACT; 5963e70c05SKrzysztof Parzyszek case omp::clause::DefinedOperator::IntrinsicOperator::Multiply: 604d4af15cSKareem Ergawy return ReductionIdentifier::MULTIPLY; 6163e70c05SKrzysztof Parzyszek case omp::clause::DefinedOperator::IntrinsicOperator::AND: 624d4af15cSKareem Ergawy return ReductionIdentifier::AND; 6363e70c05SKrzysztof Parzyszek case omp::clause::DefinedOperator::IntrinsicOperator::EQV: 644d4af15cSKareem Ergawy return ReductionIdentifier::EQV; 6563e70c05SKrzysztof Parzyszek case omp::clause::DefinedOperator::IntrinsicOperator::OR: 664d4af15cSKareem Ergawy return ReductionIdentifier::OR; 6763e70c05SKrzysztof Parzyszek case omp::clause::DefinedOperator::IntrinsicOperator::NEQV: 684d4af15cSKareem Ergawy return ReductionIdentifier::NEQV; 694d4af15cSKareem Ergawy default: 704d4af15cSKareem Ergawy llvm_unreachable("unexpected intrinsic operator in reduction"); 714d4af15cSKareem Ergawy } 724d4af15cSKareem Ergawy } 734d4af15cSKareem Ergawy 744d4af15cSKareem Ergawy bool ReductionProcessor::supportedIntrinsicProcReduction( 7563e70c05SKrzysztof Parzyszek const omp::clause::ProcedureDesignator &pd) { 768b18f2feSKrzysztof Parzyszek semantics::Symbol *sym = pd.v.sym(); 777a66e420SKrzysztof Parzyszek if (!sym->GetUltimate().attrs().test(semantics::Attr::INTRINSIC)) 784d4af15cSKareem Ergawy return false; 7963e70c05SKrzysztof Parzyszek auto redType = llvm::StringSwitch<bool>(getRealName(sym).ToString()) 804d4af15cSKareem Ergawy .Case("max", true) 814d4af15cSKareem Ergawy .Case("min", true) 824d4af15cSKareem Ergawy .Case("iand", true) 834d4af15cSKareem Ergawy .Case("ior", true) 844d4af15cSKareem Ergawy .Case("ieor", true) 854d4af15cSKareem Ergawy .Default(false); 864d4af15cSKareem Ergawy return redType; 874d4af15cSKareem Ergawy } 884d4af15cSKareem Ergawy 893deaa77fSTom Eccles std::string 903deaa77fSTom Eccles ReductionProcessor::getReductionName(llvm::StringRef name, 913deaa77fSTom Eccles const fir::KindMapping &kindMap, 92f46f5a01STom Eccles mlir::Type ty, bool isByRef) { 93f46f5a01STom Eccles ty = fir::unwrapRefType(ty); 94f46f5a01STom Eccles 95f46f5a01STom Eccles // extra string to distinguish reduction functions for variables passed by 96f46f5a01STom Eccles // reference 97f46f5a01STom Eccles llvm::StringRef byrefAddition{""}; 98f46f5a01STom Eccles if (isByRef) 99f46f5a01STom Eccles byrefAddition = "_byref"; 100f46f5a01STom Eccles 1013deaa77fSTom Eccles return fir::getTypeAsString(ty, kindMap, (name + byrefAddition).str()); 1024d4af15cSKareem Ergawy } 1034d4af15cSKareem Ergawy 1044d4af15cSKareem Ergawy std::string ReductionProcessor::getReductionName( 1053deaa77fSTom Eccles omp::clause::DefinedOperator::IntrinsicOperator intrinsicOp, 1063deaa77fSTom Eccles const fir::KindMapping &kindMap, mlir::Type ty, bool isByRef) { 1074d4af15cSKareem Ergawy std::string reductionName; 1084d4af15cSKareem Ergawy 1094d4af15cSKareem Ergawy switch (intrinsicOp) { 11063e70c05SKrzysztof Parzyszek case omp::clause::DefinedOperator::IntrinsicOperator::Add: 1114d4af15cSKareem Ergawy reductionName = "add_reduction"; 1124d4af15cSKareem Ergawy break; 11363e70c05SKrzysztof Parzyszek case omp::clause::DefinedOperator::IntrinsicOperator::Multiply: 1144d4af15cSKareem Ergawy reductionName = "multiply_reduction"; 1154d4af15cSKareem Ergawy break; 11663e70c05SKrzysztof Parzyszek case omp::clause::DefinedOperator::IntrinsicOperator::AND: 1174d4af15cSKareem Ergawy return "and_reduction"; 11863e70c05SKrzysztof Parzyszek case omp::clause::DefinedOperator::IntrinsicOperator::EQV: 1194d4af15cSKareem Ergawy return "eqv_reduction"; 12063e70c05SKrzysztof Parzyszek case omp::clause::DefinedOperator::IntrinsicOperator::OR: 1214d4af15cSKareem Ergawy return "or_reduction"; 12263e70c05SKrzysztof Parzyszek case omp::clause::DefinedOperator::IntrinsicOperator::NEQV: 1234d4af15cSKareem Ergawy return "neqv_reduction"; 1244d4af15cSKareem Ergawy default: 1254d4af15cSKareem Ergawy reductionName = "other_reduction"; 1264d4af15cSKareem Ergawy break; 1274d4af15cSKareem Ergawy } 1284d4af15cSKareem Ergawy 1293deaa77fSTom Eccles return getReductionName(reductionName, kindMap, ty, isByRef); 1304d4af15cSKareem Ergawy } 1314d4af15cSKareem Ergawy 1324d4af15cSKareem Ergawy mlir::Value 1334d4af15cSKareem Ergawy ReductionProcessor::getReductionInitValue(mlir::Location loc, mlir::Type type, 1344d4af15cSKareem Ergawy ReductionIdentifier redId, 1354d4af15cSKareem Ergawy fir::FirOpBuilder &builder) { 136f46f5a01STom Eccles type = fir::unwrapRefType(type); 1373deaa77fSTom Eccles if (!fir::isa_integer(type) && !fir::isa_real(type) && 138221f438aSMats Petersson !fir::isa_complex(type) && !mlir::isa<fir::LogicalType>(type)) 1393deaa77fSTom Eccles TODO(loc, "Reduction of some types is not supported"); 1404d4af15cSKareem Ergawy switch (redId) { 1414d4af15cSKareem Ergawy case ReductionIdentifier::MAX: { 142fac349a1SChristian Sigg if (auto ty = mlir::dyn_cast<mlir::FloatType>(type)) { 1434d4af15cSKareem Ergawy const llvm::fltSemantics &sem = ty.getFloatSemantics(); 1444d4af15cSKareem Ergawy return builder.createRealConstant( 1454d4af15cSKareem Ergawy loc, type, llvm::APFloat::getLargest(sem, /*Negative=*/true)); 1464d4af15cSKareem Ergawy } 1474d4af15cSKareem Ergawy unsigned bits = type.getIntOrFloatBitWidth(); 1484d4af15cSKareem Ergawy int64_t minInt = llvm::APInt::getSignedMinValue(bits).getSExtValue(); 1494d4af15cSKareem Ergawy return builder.createIntegerConstant(loc, type, minInt); 1504d4af15cSKareem Ergawy } 1514d4af15cSKareem Ergawy case ReductionIdentifier::MIN: { 152fac349a1SChristian Sigg if (auto ty = mlir::dyn_cast<mlir::FloatType>(type)) { 1534d4af15cSKareem Ergawy const llvm::fltSemantics &sem = ty.getFloatSemantics(); 1544d4af15cSKareem Ergawy return builder.createRealConstant( 1554d4af15cSKareem Ergawy loc, type, llvm::APFloat::getLargest(sem, /*Negative=*/false)); 1564d4af15cSKareem Ergawy } 1574d4af15cSKareem Ergawy unsigned bits = type.getIntOrFloatBitWidth(); 1584d4af15cSKareem Ergawy int64_t maxInt = llvm::APInt::getSignedMaxValue(bits).getSExtValue(); 1594d4af15cSKareem Ergawy return builder.createIntegerConstant(loc, type, maxInt); 1604d4af15cSKareem Ergawy } 1614d4af15cSKareem Ergawy case ReductionIdentifier::IOR: { 1624d4af15cSKareem Ergawy unsigned bits = type.getIntOrFloatBitWidth(); 1634d4af15cSKareem Ergawy int64_t zeroInt = llvm::APInt::getZero(bits).getSExtValue(); 1644d4af15cSKareem Ergawy return builder.createIntegerConstant(loc, type, zeroInt); 1654d4af15cSKareem Ergawy } 1664d4af15cSKareem Ergawy case ReductionIdentifier::IEOR: { 1674d4af15cSKareem Ergawy unsigned bits = type.getIntOrFloatBitWidth(); 1684d4af15cSKareem Ergawy int64_t zeroInt = llvm::APInt::getZero(bits).getSExtValue(); 1694d4af15cSKareem Ergawy return builder.createIntegerConstant(loc, type, zeroInt); 1704d4af15cSKareem Ergawy } 1714d4af15cSKareem Ergawy case ReductionIdentifier::IAND: { 1724d4af15cSKareem Ergawy unsigned bits = type.getIntOrFloatBitWidth(); 1734d4af15cSKareem Ergawy int64_t allOnInt = llvm::APInt::getAllOnes(bits).getSExtValue(); 1744d4af15cSKareem Ergawy return builder.createIntegerConstant(loc, type, allOnInt); 1754d4af15cSKareem Ergawy } 1764d4af15cSKareem Ergawy case ReductionIdentifier::ADD: 1774d4af15cSKareem Ergawy case ReductionIdentifier::MULTIPLY: 1784d4af15cSKareem Ergawy case ReductionIdentifier::AND: 1794d4af15cSKareem Ergawy case ReductionIdentifier::OR: 1804d4af15cSKareem Ergawy case ReductionIdentifier::EQV: 1814d4af15cSKareem Ergawy case ReductionIdentifier::NEQV: 182c4204c0bSjeanPerier if (auto cplxTy = mlir::dyn_cast<mlir::ComplexType>(type)) { 183c4204c0bSjeanPerier mlir::Type realTy = cplxTy.getElementType(); 184221f438aSMats Petersson mlir::Value initRe = builder.createRealConstant( 185221f438aSMats Petersson loc, realTy, getOperationIdentity(redId, loc)); 186221f438aSMats Petersson mlir::Value initIm = builder.createRealConstant(loc, realTy, 0); 187221f438aSMats Petersson 188221f438aSMats Petersson return fir::factory::Complex{builder, loc}.createComplex(type, initRe, 189221f438aSMats Petersson initIm); 190221f438aSMats Petersson } 191fac349a1SChristian Sigg if (mlir::isa<mlir::FloatType>(type)) 1924d4af15cSKareem Ergawy return builder.create<mlir::arith::ConstantOp>( 1934d4af15cSKareem Ergawy loc, type, 1944d4af15cSKareem Ergawy builder.getFloatAttr(type, (double)getOperationIdentity(redId, loc))); 1954d4af15cSKareem Ergawy 196fac349a1SChristian Sigg if (mlir::isa<fir::LogicalType>(type)) { 1974d4af15cSKareem Ergawy mlir::Value intConst = builder.create<mlir::arith::ConstantOp>( 1984d4af15cSKareem Ergawy loc, builder.getI1Type(), 1994d4af15cSKareem Ergawy builder.getIntegerAttr(builder.getI1Type(), 2004d4af15cSKareem Ergawy getOperationIdentity(redId, loc))); 2014d4af15cSKareem Ergawy return builder.createConvert(loc, type, intConst); 2024d4af15cSKareem Ergawy } 2034d4af15cSKareem Ergawy 2044d4af15cSKareem Ergawy return builder.create<mlir::arith::ConstantOp>( 2054d4af15cSKareem Ergawy loc, type, 2064d4af15cSKareem Ergawy builder.getIntegerAttr(type, getOperationIdentity(redId, loc))); 2074d4af15cSKareem Ergawy case ReductionIdentifier::ID: 2084d4af15cSKareem Ergawy case ReductionIdentifier::USER_DEF_OP: 2094d4af15cSKareem Ergawy case ReductionIdentifier::SUBTRACT: 2104d4af15cSKareem Ergawy TODO(loc, "Reduction of some identifier types is not supported"); 2114d4af15cSKareem Ergawy } 2124d4af15cSKareem Ergawy llvm_unreachable("Unhandled Reduction identifier : getReductionInitValue"); 2134d4af15cSKareem Ergawy } 2144d4af15cSKareem Ergawy 2154d4af15cSKareem Ergawy mlir::Value ReductionProcessor::createScalarCombiner( 2164d4af15cSKareem Ergawy fir::FirOpBuilder &builder, mlir::Location loc, ReductionIdentifier redId, 2174d4af15cSKareem Ergawy mlir::Type type, mlir::Value op1, mlir::Value op2) { 2184d4af15cSKareem Ergawy mlir::Value reductionOp; 219f46f5a01STom Eccles type = fir::unwrapRefType(type); 2204d4af15cSKareem Ergawy switch (redId) { 2214d4af15cSKareem Ergawy case ReductionIdentifier::MAX: 2224d4af15cSKareem Ergawy reductionOp = 2230c455ee3SJan Leyonberg getReductionOperation<mlir::arith::MaxNumFOp, mlir::arith::MaxSIOp>( 2244d4af15cSKareem Ergawy builder, type, loc, op1, op2); 2254d4af15cSKareem Ergawy break; 2264d4af15cSKareem Ergawy case ReductionIdentifier::MIN: 2274d4af15cSKareem Ergawy reductionOp = 2280c455ee3SJan Leyonberg getReductionOperation<mlir::arith::MinNumFOp, mlir::arith::MinSIOp>( 2294d4af15cSKareem Ergawy builder, type, loc, op1, op2); 2304d4af15cSKareem Ergawy break; 2314d4af15cSKareem Ergawy case ReductionIdentifier::IOR: 2324d4af15cSKareem Ergawy assert((type.isIntOrIndex()) && "only integer is expected"); 2334d4af15cSKareem Ergawy reductionOp = builder.create<mlir::arith::OrIOp>(loc, op1, op2); 2344d4af15cSKareem Ergawy break; 2354d4af15cSKareem Ergawy case ReductionIdentifier::IEOR: 2364d4af15cSKareem Ergawy assert((type.isIntOrIndex()) && "only integer is expected"); 2374d4af15cSKareem Ergawy reductionOp = builder.create<mlir::arith::XOrIOp>(loc, op1, op2); 2384d4af15cSKareem Ergawy break; 2394d4af15cSKareem Ergawy case ReductionIdentifier::IAND: 2404d4af15cSKareem Ergawy assert((type.isIntOrIndex()) && "only integer is expected"); 2414d4af15cSKareem Ergawy reductionOp = builder.create<mlir::arith::AndIOp>(loc, op1, op2); 2424d4af15cSKareem Ergawy break; 2434d4af15cSKareem Ergawy case ReductionIdentifier::ADD: 2444d4af15cSKareem Ergawy reductionOp = 245221f438aSMats Petersson getReductionOperation<mlir::arith::AddFOp, mlir::arith::AddIOp, 246221f438aSMats Petersson fir::AddcOp>(builder, type, loc, op1, op2); 2474d4af15cSKareem Ergawy break; 2484d4af15cSKareem Ergawy case ReductionIdentifier::MULTIPLY: 2494d4af15cSKareem Ergawy reductionOp = 250221f438aSMats Petersson getReductionOperation<mlir::arith::MulFOp, mlir::arith::MulIOp, 251221f438aSMats Petersson fir::MulcOp>(builder, type, loc, op1, op2); 2524d4af15cSKareem Ergawy break; 2534d4af15cSKareem Ergawy case ReductionIdentifier::AND: { 2544d4af15cSKareem Ergawy mlir::Value op1I1 = builder.createConvert(loc, builder.getI1Type(), op1); 2554d4af15cSKareem Ergawy mlir::Value op2I1 = builder.createConvert(loc, builder.getI1Type(), op2); 2564d4af15cSKareem Ergawy 2574d4af15cSKareem Ergawy mlir::Value andiOp = builder.create<mlir::arith::AndIOp>(loc, op1I1, op2I1); 2584d4af15cSKareem Ergawy 2594d4af15cSKareem Ergawy reductionOp = builder.createConvert(loc, type, andiOp); 2604d4af15cSKareem Ergawy break; 2614d4af15cSKareem Ergawy } 2624d4af15cSKareem Ergawy case ReductionIdentifier::OR: { 2634d4af15cSKareem Ergawy mlir::Value op1I1 = builder.createConvert(loc, builder.getI1Type(), op1); 2644d4af15cSKareem Ergawy mlir::Value op2I1 = builder.createConvert(loc, builder.getI1Type(), op2); 2654d4af15cSKareem Ergawy 2664d4af15cSKareem Ergawy mlir::Value oriOp = builder.create<mlir::arith::OrIOp>(loc, op1I1, op2I1); 2674d4af15cSKareem Ergawy 2684d4af15cSKareem Ergawy reductionOp = builder.createConvert(loc, type, oriOp); 2694d4af15cSKareem Ergawy break; 2704d4af15cSKareem Ergawy } 2714d4af15cSKareem Ergawy case ReductionIdentifier::EQV: { 2724d4af15cSKareem Ergawy mlir::Value op1I1 = builder.createConvert(loc, builder.getI1Type(), op1); 2734d4af15cSKareem Ergawy mlir::Value op2I1 = builder.createConvert(loc, builder.getI1Type(), op2); 2744d4af15cSKareem Ergawy 2754d4af15cSKareem Ergawy mlir::Value cmpiOp = builder.create<mlir::arith::CmpIOp>( 2764d4af15cSKareem Ergawy loc, mlir::arith::CmpIPredicate::eq, op1I1, op2I1); 2774d4af15cSKareem Ergawy 2784d4af15cSKareem Ergawy reductionOp = builder.createConvert(loc, type, cmpiOp); 2794d4af15cSKareem Ergawy break; 2804d4af15cSKareem Ergawy } 2814d4af15cSKareem Ergawy case ReductionIdentifier::NEQV: { 2824d4af15cSKareem Ergawy mlir::Value op1I1 = builder.createConvert(loc, builder.getI1Type(), op1); 2834d4af15cSKareem Ergawy mlir::Value op2I1 = builder.createConvert(loc, builder.getI1Type(), op2); 2844d4af15cSKareem Ergawy 2854d4af15cSKareem Ergawy mlir::Value cmpiOp = builder.create<mlir::arith::CmpIOp>( 2864d4af15cSKareem Ergawy loc, mlir::arith::CmpIPredicate::ne, op1I1, op2I1); 2874d4af15cSKareem Ergawy 2884d4af15cSKareem Ergawy reductionOp = builder.createConvert(loc, type, cmpiOp); 2894d4af15cSKareem Ergawy break; 2904d4af15cSKareem Ergawy } 2914d4af15cSKareem Ergawy default: 2924d4af15cSKareem Ergawy TODO(loc, "Reduction of some intrinsic operators is not supported"); 2934d4af15cSKareem Ergawy } 2944d4af15cSKareem Ergawy 2954d4af15cSKareem Ergawy return reductionOp; 2964d4af15cSKareem Ergawy } 2974d4af15cSKareem Ergawy 298197f3ecfSTom Eccles /// Create reduction combiner region for reduction variables which are boxed 299197f3ecfSTom Eccles /// arrays 300197f3ecfSTom Eccles static void genBoxCombiner(fir::FirOpBuilder &builder, mlir::Location loc, 301197f3ecfSTom Eccles ReductionProcessor::ReductionIdentifier redId, 302197f3ecfSTom Eccles fir::BaseBoxType boxTy, mlir::Value lhs, 303197f3ecfSTom Eccles mlir::Value rhs) { 3048cc34fadSTom Eccles fir::SequenceType seqTy = mlir::dyn_cast_or_null<fir::SequenceType>( 3058cc34fadSTom Eccles fir::unwrapRefType(boxTy.getEleTy())); 3068cc34fadSTom Eccles fir::HeapType heapTy = 3078cc34fadSTom Eccles mlir::dyn_cast_or_null<fir::HeapType>(boxTy.getEleTy()); 308b6b0f975STom Eccles fir::PointerType ptrTy = 309b6b0f975STom Eccles mlir::dyn_cast_or_null<fir::PointerType>(boxTy.getEleTy()); 310b6b0f975STom Eccles if ((!seqTy || seqTy.hasUnknownShape()) && !heapTy && !ptrTy) 311197f3ecfSTom Eccles TODO(loc, "Unsupported boxed type in OpenMP reduction"); 312197f3ecfSTom Eccles 313197f3ecfSTom Eccles // load fir.ref<fir.box<...>> 314197f3ecfSTom Eccles mlir::Value lhsAddr = lhs; 315197f3ecfSTom Eccles lhs = builder.create<fir::LoadOp>(loc, lhs); 316197f3ecfSTom Eccles rhs = builder.create<fir::LoadOp>(loc, rhs); 317197f3ecfSTom Eccles 318b6b0f975STom Eccles if ((heapTy || ptrTy) && !seqTy) { 3198cc34fadSTom Eccles // get box contents (heap pointers) 3208cc34fadSTom Eccles lhs = builder.create<fir::BoxAddrOp>(loc, lhs); 3218cc34fadSTom Eccles rhs = builder.create<fir::BoxAddrOp>(loc, rhs); 3228cc34fadSTom Eccles mlir::Value lhsValAddr = lhs; 3238cc34fadSTom Eccles 3248cc34fadSTom Eccles // load heap pointers 3258cc34fadSTom Eccles lhs = builder.create<fir::LoadOp>(loc, lhs); 3268cc34fadSTom Eccles rhs = builder.create<fir::LoadOp>(loc, rhs); 3278cc34fadSTom Eccles 328b6b0f975STom Eccles mlir::Type eleTy = heapTy ? heapTy.getEleTy() : ptrTy.getEleTy(); 329b6b0f975STom Eccles 3308cc34fadSTom Eccles mlir::Value result = ReductionProcessor::createScalarCombiner( 331b6b0f975STom Eccles builder, loc, redId, eleTy, lhs, rhs); 3328cc34fadSTom Eccles builder.create<fir::StoreOp>(loc, result, lhsValAddr); 3338cc34fadSTom Eccles builder.create<mlir::omp::YieldOp>(loc, lhsAddr); 3348cc34fadSTom Eccles return; 3358cc34fadSTom Eccles } 3368cc34fadSTom Eccles 33718bf0c3cSTom Eccles fir::ShapeShiftOp shapeShift = getShapeShift(builder, loc, lhs); 338197f3ecfSTom Eccles 339197f3ecfSTom Eccles // Iterate over array elements, applying the equivalent scalar reduction: 340197f3ecfSTom Eccles 3418cc34fadSTom Eccles // F2018 5.4.10.2: Unallocated allocatable variables may not be referenced 3428cc34fadSTom Eccles // and so no null check is needed here before indexing into the (possibly 3438cc34fadSTom Eccles // allocatable) arrays. 3448cc34fadSTom Eccles 345197f3ecfSTom Eccles // A hlfir::elemental here gets inlined with a temporary so create the 346197f3ecfSTom Eccles // loop nest directly. 347197f3ecfSTom Eccles // This function already controls all of the code in this region so we 348197f3ecfSTom Eccles // know this won't miss any opportuinties for clever elemental inlining 34918bf0c3cSTom Eccles hlfir::LoopNest nest = hlfir::genLoopNest( 35018bf0c3cSTom Eccles loc, builder, shapeShift.getExtents(), /*isUnordered=*/true); 3518bb21ae6SIvan R. Ivanov builder.setInsertionPointToStart(nest.body); 352197f3ecfSTom Eccles mlir::Type refTy = fir::ReferenceType::get(seqTy.getEleTy()); 353197f3ecfSTom Eccles auto lhsEleAddr = builder.create<fir::ArrayCoorOp>( 354197f3ecfSTom Eccles loc, refTy, lhs, shapeShift, /*slice=*/mlir::Value{}, 355197f3ecfSTom Eccles nest.oneBasedIndices, /*typeparms=*/mlir::ValueRange{}); 356197f3ecfSTom Eccles auto rhsEleAddr = builder.create<fir::ArrayCoorOp>( 357197f3ecfSTom Eccles loc, refTy, rhs, shapeShift, /*slice=*/mlir::Value{}, 358197f3ecfSTom Eccles nest.oneBasedIndices, /*typeparms=*/mlir::ValueRange{}); 359197f3ecfSTom Eccles auto lhsEle = builder.create<fir::LoadOp>(loc, lhsEleAddr); 360197f3ecfSTom Eccles auto rhsEle = builder.create<fir::LoadOp>(loc, rhsEleAddr); 361197f3ecfSTom Eccles mlir::Value scalarReduction = ReductionProcessor::createScalarCombiner( 362197f3ecfSTom Eccles builder, loc, redId, refTy, lhsEle, rhsEle); 363197f3ecfSTom Eccles builder.create<fir::StoreOp>(loc, scalarReduction, lhsEleAddr); 364197f3ecfSTom Eccles 3658bb21ae6SIvan R. Ivanov builder.setInsertionPointAfter(nest.outerOp); 366197f3ecfSTom Eccles builder.create<mlir::omp::YieldOp>(loc, lhsAddr); 367197f3ecfSTom Eccles } 368197f3ecfSTom Eccles 369197f3ecfSTom Eccles // generate combiner region for reduction operations 370197f3ecfSTom Eccles static void genCombiner(fir::FirOpBuilder &builder, mlir::Location loc, 371197f3ecfSTom Eccles ReductionProcessor::ReductionIdentifier redId, 372197f3ecfSTom Eccles mlir::Type ty, mlir::Value lhs, mlir::Value rhs, 373197f3ecfSTom Eccles bool isByRef) { 374197f3ecfSTom Eccles ty = fir::unwrapRefType(ty); 375197f3ecfSTom Eccles 376197f3ecfSTom Eccles if (fir::isa_trivial(ty)) { 377197f3ecfSTom Eccles mlir::Value lhsLoaded = builder.loadIfRef(loc, lhs); 378197f3ecfSTom Eccles mlir::Value rhsLoaded = builder.loadIfRef(loc, rhs); 379197f3ecfSTom Eccles 380197f3ecfSTom Eccles mlir::Value result = ReductionProcessor::createScalarCombiner( 381197f3ecfSTom Eccles builder, loc, redId, ty, lhsLoaded, rhsLoaded); 382197f3ecfSTom Eccles if (isByRef) { 383197f3ecfSTom Eccles builder.create<fir::StoreOp>(loc, result, lhs); 384197f3ecfSTom Eccles builder.create<mlir::omp::YieldOp>(loc, lhs); 385197f3ecfSTom Eccles } else { 386197f3ecfSTom Eccles builder.create<mlir::omp::YieldOp>(loc, result); 387197f3ecfSTom Eccles } 388197f3ecfSTom Eccles return; 389197f3ecfSTom Eccles } 390197f3ecfSTom Eccles // all arrays should have been boxed 391197f3ecfSTom Eccles if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty)) { 392197f3ecfSTom Eccles genBoxCombiner(builder, loc, redId, boxTy, lhs, rhs); 393197f3ecfSTom Eccles return; 394197f3ecfSTom Eccles } 395197f3ecfSTom Eccles 396197f3ecfSTom Eccles TODO(loc, "OpenMP genCombiner for unsupported reduction variable type"); 397197f3ecfSTom Eccles } 398197f3ecfSTom Eccles 3998cc34fadSTom Eccles // like fir::unwrapSeqOrBoxedSeqType except it also works for non-sequence boxes 4008cc34fadSTom Eccles static mlir::Type unwrapSeqOrBoxedType(mlir::Type ty) { 401fac349a1SChristian Sigg if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(ty)) 4028cc34fadSTom Eccles return seqTy.getEleTy(); 403fac349a1SChristian Sigg if (auto boxTy = mlir::dyn_cast<fir::BaseBoxType>(ty)) { 4048cc34fadSTom Eccles auto eleTy = fir::unwrapRefType(boxTy.getEleTy()); 405fac349a1SChristian Sigg if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(eleTy)) 4068cc34fadSTom Eccles return seqTy.getEleTy(); 4078cc34fadSTom Eccles return eleTy; 4088cc34fadSTom Eccles } 4098cc34fadSTom Eccles return ty; 4108cc34fadSTom Eccles } 4118cc34fadSTom Eccles 412f2027a93STom Eccles static void createReductionAllocAndInitRegions( 413f2027a93STom Eccles fir::FirOpBuilder &builder, mlir::Location loc, 4146f068b9cSTom Eccles mlir::omp::DeclareReductionOp &reductionDecl, 415f2027a93STom Eccles const ReductionProcessor::ReductionIdentifier redId, mlir::Type type, 416f2027a93STom Eccles bool isByRef) { 417f2027a93STom Eccles auto yield = [&](mlir::Value ret) { 418f2027a93STom Eccles builder.create<mlir::omp::YieldOp>(loc, ret); 419f2027a93STom Eccles }; 420f2027a93STom Eccles 421f2027a93STom Eccles mlir::Block *allocBlock = nullptr; 422f2027a93STom Eccles mlir::Block *initBlock = nullptr; 423f2027a93STom Eccles if (isByRef) { 424f2027a93STom Eccles allocBlock = 425f2027a93STom Eccles builder.createBlock(&reductionDecl.getAllocRegion(), 426f2027a93STom Eccles reductionDecl.getAllocRegion().end(), {}, {}); 427f2027a93STom Eccles initBlock = builder.createBlock(&reductionDecl.getInitializerRegion(), 428f2027a93STom Eccles reductionDecl.getInitializerRegion().end(), 429f2027a93STom Eccles {type, type}, {loc, loc}); 430f2027a93STom Eccles } else { 431f2027a93STom Eccles initBlock = builder.createBlock(&reductionDecl.getInitializerRegion(), 432f2027a93STom Eccles reductionDecl.getInitializerRegion().end(), 433f2027a93STom Eccles {type}, {loc}); 434f2027a93STom Eccles } 435f2027a93STom Eccles 436197f3ecfSTom Eccles mlir::Type ty = fir::unwrapRefType(type); 437f2027a93STom Eccles builder.setInsertionPointToEnd(initBlock); 438197f3ecfSTom Eccles mlir::Value initValue = ReductionProcessor::getReductionInitValue( 4398cc34fadSTom Eccles loc, unwrapSeqOrBoxedType(ty), redId, builder); 440197f3ecfSTom Eccles 441*8557a57cSTom Eccles if (isByRef) { 442*8557a57cSTom Eccles populateByRefInitAndCleanupRegions(builder, loc, type, initValue, initBlock, 443*8557a57cSTom Eccles reductionDecl.getInitializerAllocArg(), 444*8557a57cSTom Eccles reductionDecl.getInitializerMoldArg(), 445*8557a57cSTom Eccles reductionDecl.getCleanupRegion()); 446*8557a57cSTom Eccles } 447*8557a57cSTom Eccles 448197f3ecfSTom Eccles if (fir::isa_trivial(ty)) { 449197f3ecfSTom Eccles if (isByRef) { 450f2027a93STom Eccles // alloc region 451f2027a93STom Eccles builder.setInsertionPointToEnd(allocBlock); 452197f3ecfSTom Eccles mlir::Value alloca = builder.create<fir::AllocaOp>(loc, ty); 453f2027a93STom Eccles yield(alloca); 454f2027a93STom Eccles return; 455197f3ecfSTom Eccles } 456197f3ecfSTom Eccles // by val 457f2027a93STom Eccles yield(initValue); 458f2027a93STom Eccles return; 459197f3ecfSTom Eccles } 460*8557a57cSTom Eccles assert(isByRef && "passing non-trivial types by val is unsupported"); 461f2027a93STom Eccles 462f2027a93STom Eccles // alloc region 463f2027a93STom Eccles builder.setInsertionPointToEnd(allocBlock); 4648cc34fadSTom Eccles mlir::Value boxAlloca = builder.create<fir::AllocaOp>(loc, ty); 465f2027a93STom Eccles yield(boxAlloca); 466f2027a93STom Eccles } 467f2027a93STom Eccles 468d84252e0SSergio Afonso mlir::omp::DeclareReductionOp ReductionProcessor::createDeclareReduction( 4694d4af15cSKareem Ergawy fir::FirOpBuilder &builder, llvm::StringRef reductionOpName, 470f46f5a01STom Eccles const ReductionIdentifier redId, mlir::Type type, mlir::Location loc, 471f46f5a01STom Eccles bool isByRef) { 4724d4af15cSKareem Ergawy mlir::OpBuilder::InsertionGuard guard(builder); 4734d4af15cSKareem Ergawy mlir::ModuleOp module = builder.getModule(); 4744d4af15cSKareem Ergawy 4753deaa77fSTom Eccles assert(!reductionOpName.empty()); 476197f3ecfSTom Eccles 4774d4af15cSKareem Ergawy auto decl = 478d84252e0SSergio Afonso module.lookupSymbol<mlir::omp::DeclareReductionOp>(reductionOpName); 4794d4af15cSKareem Ergawy if (decl) 4804d4af15cSKareem Ergawy return decl; 4814d4af15cSKareem Ergawy 4824d4af15cSKareem Ergawy mlir::OpBuilder modBuilder(module.getBodyRegion()); 483f46f5a01STom Eccles mlir::Type valTy = fir::unwrapRefType(type); 484f46f5a01STom Eccles if (!isByRef) 485f46f5a01STom Eccles type = valTy; 4864d4af15cSKareem Ergawy 487d84252e0SSergio Afonso decl = modBuilder.create<mlir::omp::DeclareReductionOp>(loc, reductionOpName, 4884d4af15cSKareem Ergawy type); 489f2027a93STom Eccles createReductionAllocAndInitRegions(builder, loc, decl, redId, type, isByRef); 4904d4af15cSKareem Ergawy 4914d4af15cSKareem Ergawy builder.createBlock(&decl.getReductionRegion(), 4924d4af15cSKareem Ergawy decl.getReductionRegion().end(), {type, type}, 4934d4af15cSKareem Ergawy {loc, loc}); 4944d4af15cSKareem Ergawy 4954d4af15cSKareem Ergawy builder.setInsertionPointToEnd(&decl.getReductionRegion().back()); 4964d4af15cSKareem Ergawy mlir::Value op1 = decl.getReductionRegion().front().getArgument(0); 4974d4af15cSKareem Ergawy mlir::Value op2 = decl.getReductionRegion().front().getArgument(1); 498197f3ecfSTom Eccles genCombiner(builder, loc, redId, type, op1, op2, isByRef); 4994d4af15cSKareem Ergawy 5004d4af15cSKareem Ergawy return decl; 5014d4af15cSKareem Ergawy } 5024d4af15cSKareem Ergawy 50374a87548STom Eccles static bool doReductionByRef(mlir::Value reductionVar) { 504f46f5a01STom Eccles if (forceByrefReduction) 505f46f5a01STom Eccles return true; 506f46f5a01STom Eccles 507f46f5a01STom Eccles if (auto declare = 508f46f5a01STom Eccles mlir::dyn_cast<hlfir::DeclareOp>(reductionVar.getDefiningOp())) 509f46f5a01STom Eccles reductionVar = declare.getMemref(); 510f46f5a01STom Eccles 511f46f5a01STom Eccles if (!fir::isa_trivial(fir::unwrapRefType(reductionVar.getType()))) 512f46f5a01STom Eccles return true; 51374a87548STom Eccles 514f46f5a01STom Eccles return false; 515f46f5a01STom Eccles } 516f46f5a01STom Eccles 517d84252e0SSergio Afonso void ReductionProcessor::addDeclareReduction( 5187a66e420SKrzysztof Parzyszek mlir::Location currentLocation, lower::AbstractConverter &converter, 51963e70c05SKrzysztof Parzyszek const omp::clause::Reduction &reduction, 5204d4af15cSKareem Ergawy llvm::SmallVectorImpl<mlir::Value> &reductionVars, 52174a87548STom Eccles llvm::SmallVectorImpl<bool> &reduceVarByRef, 5224d4af15cSKareem Ergawy llvm::SmallVectorImpl<mlir::Attribute> &reductionDeclSymbols, 52388478a89SSergio Afonso llvm::SmallVectorImpl<const semantics::Symbol *> &reductionSymbols) { 5244d4af15cSKareem Ergawy fir::FirOpBuilder &firOpBuilder = converter.getFirOpBuilder(); 52517cb8a53SKiran Chandramohan 52617cb8a53SKiran Chandramohan if (std::get<std::optional<omp::clause::Reduction::ReductionModifier>>( 52717cb8a53SKiran Chandramohan reduction.t)) 52817cb8a53SKiran Chandramohan TODO(currentLocation, "Reduction modifiers are not supported"); 52917cb8a53SKiran Chandramohan 530d84252e0SSergio Afonso mlir::omp::DeclareReductionOp decl; 531148a5579SKrzysztof Parzyszek const auto &redOperatorList{ 532148a5579SKrzysztof Parzyszek std::get<omp::clause::Reduction::ReductionIdentifiers>(reduction.t)}; 533148a5579SKrzysztof Parzyszek assert(redOperatorList.size() == 1 && "Expecting single operator"); 534148a5579SKrzysztof Parzyszek const auto &redOperator = redOperatorList.front(); 53563e70c05SKrzysztof Parzyszek const auto &objectList{std::get<omp::ObjectList>(reduction.t)}; 536f46f5a01STom Eccles 53763e70c05SKrzysztof Parzyszek if (!std::holds_alternative<omp::clause::DefinedOperator>(redOperator.u)) { 538f46f5a01STom Eccles if (const auto *reductionIntrinsic = 53963e70c05SKrzysztof Parzyszek std::get_if<omp::clause::ProcedureDesignator>(&redOperator.u)) { 540f46f5a01STom Eccles if (!ReductionProcessor::supportedIntrinsicProcReduction( 541f46f5a01STom Eccles *reductionIntrinsic)) { 542f46f5a01STom Eccles return; 543f46f5a01STom Eccles } 544f46f5a01STom Eccles } else { 545f46f5a01STom Eccles return; 546f46f5a01STom Eccles } 547f46f5a01STom Eccles } 548f46f5a01STom Eccles 5491002c08cSTom Eccles // Reduction variable processing common to both intrinsic operators and 5501002c08cSTom Eccles // procedure designators 551197f3ecfSTom Eccles fir::FirOpBuilder &builder = converter.getFirOpBuilder(); 55263e70c05SKrzysztof Parzyszek for (const Object &object : objectList) { 5538b18f2feSKrzysztof Parzyszek const semantics::Symbol *symbol = object.sym(); 55488478a89SSergio Afonso reductionSymbols.push_back(symbol); 555f46f5a01STom Eccles mlir::Value symVal = converter.getSymbolAddress(*symbol); 556dbd6eb67STom Eccles mlir::Type eleType; 557dbd6eb67STom Eccles auto refType = mlir::dyn_cast_or_null<fir::ReferenceType>(symVal.getType()); 558dbd6eb67STom Eccles if (refType) 559dbd6eb67STom Eccles eleType = refType.getEleTy(); 560dbd6eb67STom Eccles else 561dbd6eb67STom Eccles eleType = symVal.getType(); 562197f3ecfSTom Eccles 563197f3ecfSTom Eccles // all arrays must be boxed so that we have convenient access to all the 564197f3ecfSTom Eccles // information needed to iterate over the array 565dbd6eb67STom Eccles if (mlir::isa<fir::SequenceType>(eleType)) { 566698bf3daSSourabh Singh Tomar // For Host associated symbols, use `SymbolBox` instead 5677a66e420SKrzysztof Parzyszek lower::SymbolBox symBox = converter.lookupOneLevelUpSymbol(*symbol); 568698bf3daSSourabh Singh Tomar hlfir::Entity entity{symBox.getAddr()}; 569197f3ecfSTom Eccles entity = genVariableBox(currentLocation, builder, entity); 570197f3ecfSTom Eccles mlir::Value box = entity.getBase(); 571197f3ecfSTom Eccles 572197f3ecfSTom Eccles // Always pass the box by reference so that the OpenMP dialect 573197f3ecfSTom Eccles // verifiers don't need to know anything about fir.box 574197f3ecfSTom Eccles auto alloca = 575197f3ecfSTom Eccles builder.create<fir::AllocaOp>(currentLocation, box.getType()); 576197f3ecfSTom Eccles builder.create<fir::StoreOp>(currentLocation, box, alloca); 577197f3ecfSTom Eccles 578197f3ecfSTom Eccles symVal = alloca; 579dbd6eb67STom Eccles } else if (mlir::isa<fir::BaseBoxType>(symVal.getType())) { 580dbd6eb67STom Eccles // boxed arrays are passed as values not by reference. Unfortunately, 581dbd6eb67STom Eccles // we can't pass a box by value to omp.redution_declare, so turn it 582dbd6eb67STom Eccles // into a reference 583dbd6eb67STom Eccles 584dbd6eb67STom Eccles auto alloca = 585dbd6eb67STom Eccles builder.create<fir::AllocaOp>(currentLocation, symVal.getType()); 586dbd6eb67STom Eccles builder.create<fir::StoreOp>(currentLocation, symVal, alloca); 587dbd6eb67STom Eccles symVal = alloca; 588197f3ecfSTom Eccles } else if (auto declOp = symVal.getDefiningOp<hlfir::DeclareOp>()) { 589f46f5a01STom Eccles symVal = declOp.getBase(); 590197f3ecfSTom Eccles } 591197f3ecfSTom Eccles 592dbd6eb67STom Eccles // this isn't the same as the by-val and by-ref passing later in the 593dbd6eb67STom Eccles // pipeline. Both styles assume that the variable is a reference at 594dbd6eb67STom Eccles // this point 595dbd6eb67STom Eccles assert(mlir::isa<fir::ReferenceType>(symVal.getType()) && 596dbd6eb67STom Eccles "reduction input var is a reference"); 597dbd6eb67STom Eccles 598f46f5a01STom Eccles reductionVars.push_back(symVal); 59974a87548STom Eccles reduceVarByRef.push_back(doReductionByRef(symVal)); 600f46f5a01STom Eccles } 601f46f5a01STom Eccles 6021002c08cSTom Eccles for (auto [symVal, isByRef] : llvm::zip(reductionVars, reduceVarByRef)) { 6031002c08cSTom Eccles auto redType = mlir::cast<fir::ReferenceType>(symVal.getType()); 6041002c08cSTom Eccles const auto &kindMap = firOpBuilder.getKindMap(); 6051002c08cSTom Eccles std::string reductionName; 6061002c08cSTom Eccles ReductionIdentifier redId; 6071002c08cSTom Eccles mlir::Type redNameTy = redType; 6081002c08cSTom Eccles if (mlir::isa<fir::LogicalType>(redType.getEleTy())) 6091002c08cSTom Eccles redNameTy = builder.getI1Type(); 6101002c08cSTom Eccles 6114d4af15cSKareem Ergawy if (const auto &redDefinedOp = 61263e70c05SKrzysztof Parzyszek std::get_if<omp::clause::DefinedOperator>(&redOperator.u)) { 6134d4af15cSKareem Ergawy const auto &intrinsicOp{ 61463e70c05SKrzysztof Parzyszek std::get<omp::clause::DefinedOperator::IntrinsicOperator>( 6154d4af15cSKareem Ergawy redDefinedOp->u)}; 6161002c08cSTom Eccles redId = getReductionType(intrinsicOp); 6174d4af15cSKareem Ergawy switch (redId) { 6184d4af15cSKareem Ergawy case ReductionIdentifier::ADD: 6194d4af15cSKareem Ergawy case ReductionIdentifier::MULTIPLY: 6204d4af15cSKareem Ergawy case ReductionIdentifier::AND: 6214d4af15cSKareem Ergawy case ReductionIdentifier::EQV: 6224d4af15cSKareem Ergawy case ReductionIdentifier::OR: 6234d4af15cSKareem Ergawy case ReductionIdentifier::NEQV: 6244d4af15cSKareem Ergawy break; 6254d4af15cSKareem Ergawy default: 6264d4af15cSKareem Ergawy TODO(currentLocation, 6274d4af15cSKareem Ergawy "Reduction of some intrinsic operators is not supported"); 6284d4af15cSKareem Ergawy break; 6294d4af15cSKareem Ergawy } 63063e70c05SKrzysztof Parzyszek 6311002c08cSTom Eccles reductionName = 6321002c08cSTom Eccles getReductionName(intrinsicOp, kindMap, redNameTy, isByRef); 6334d4af15cSKareem Ergawy } else if (const auto *reductionIntrinsic = 63463e70c05SKrzysztof Parzyszek std::get_if<omp::clause::ProcedureDesignator>( 6354d4af15cSKareem Ergawy &redOperator.u)) { 6361002c08cSTom Eccles if (!ReductionProcessor::supportedIntrinsicProcReduction( 6374d4af15cSKareem Ergawy *reductionIntrinsic)) { 6381002c08cSTom Eccles TODO(currentLocation, "Unsupported intrinsic proc reduction"); 6394d4af15cSKareem Ergawy } 6401002c08cSTom Eccles redId = getReductionType(*reductionIntrinsic); 6411002c08cSTom Eccles reductionName = 6421002c08cSTom Eccles getReductionName(getRealName(*reductionIntrinsic).ToString(), kindMap, 6431002c08cSTom Eccles redNameTy, isByRef); 6441002c08cSTom Eccles } else { 6451002c08cSTom Eccles TODO(currentLocation, "Unexpected reduction type"); 6464d4af15cSKareem Ergawy } 6471002c08cSTom Eccles 6481002c08cSTom Eccles decl = createDeclareReduction(firOpBuilder, reductionName, redId, redType, 6491002c08cSTom Eccles currentLocation, isByRef); 6501002c08cSTom Eccles reductionDeclSymbols.push_back( 6511002c08cSTom Eccles mlir::SymbolRefAttr::get(firOpBuilder.getContext(), decl.getSymName())); 6524d4af15cSKareem Ergawy } 6534d4af15cSKareem Ergawy } 65463e70c05SKrzysztof Parzyszek 6557a66e420SKrzysztof Parzyszek const semantics::SourceName 6567a66e420SKrzysztof Parzyszek ReductionProcessor::getRealName(const semantics::Symbol *symbol) { 65763e70c05SKrzysztof Parzyszek return symbol->GetUltimate().name(); 6584d4af15cSKareem Ergawy } 6594d4af15cSKareem Ergawy 6607a66e420SKrzysztof Parzyszek const semantics::SourceName 66163e70c05SKrzysztof Parzyszek ReductionProcessor::getRealName(const omp::clause::ProcedureDesignator &pd) { 6628b18f2feSKrzysztof Parzyszek return getRealName(pd.v.sym()); 6634d4af15cSKareem Ergawy } 6644d4af15cSKareem Ergawy 6654d4af15cSKareem Ergawy int ReductionProcessor::getOperationIdentity(ReductionIdentifier redId, 6664d4af15cSKareem Ergawy mlir::Location loc) { 6674d4af15cSKareem Ergawy switch (redId) { 6684d4af15cSKareem Ergawy case ReductionIdentifier::ADD: 6694d4af15cSKareem Ergawy case ReductionIdentifier::OR: 6704d4af15cSKareem Ergawy case ReductionIdentifier::NEQV: 6714d4af15cSKareem Ergawy return 0; 6724d4af15cSKareem Ergawy case ReductionIdentifier::MULTIPLY: 6734d4af15cSKareem Ergawy case ReductionIdentifier::AND: 6744d4af15cSKareem Ergawy case ReductionIdentifier::EQV: 6754d4af15cSKareem Ergawy return 1; 6764d4af15cSKareem Ergawy default: 6774d4af15cSKareem Ergawy TODO(loc, "Reduction of some intrinsic operators is not supported"); 6784d4af15cSKareem Ergawy } 6794d4af15cSKareem Ergawy } 6804d4af15cSKareem Ergawy 6814d4af15cSKareem Ergawy } // namespace omp 6824d4af15cSKareem Ergawy } // namespace lower 6834d4af15cSKareem Ergawy } // namespace Fortran 684