@@ -104,7 +104,7 @@ struct IncrementLoopInfo {
104
104
105
105
bool hasLocalitySpecs () const {
106
106
return !localSymList.empty () || !localInitSymList.empty () ||
107
- !sharedSymList.empty ();
107
+ !reduceSymList. empty () || ! sharedSymList.empty ();
108
108
}
109
109
110
110
// Data members common to both structured and unstructured loops.
@@ -116,6 +116,9 @@ struct IncrementLoopInfo {
116
116
bool isUnordered; // do concurrent, forall
117
117
llvm::SmallVector<const Fortran::semantics::Symbol *> localSymList;
118
118
llvm::SmallVector<const Fortran::semantics::Symbol *> localInitSymList;
119
+ llvm::SmallVector<
120
+ std::pair<fir::ReduceOperationEnum, const Fortran::semantics::Symbol *>>
121
+ reduceSymList;
119
122
llvm::SmallVector<const Fortran::semantics::Symbol *> sharedSymList;
120
123
mlir::Value loopVariable = nullptr ;
121
124
@@ -1741,6 +1744,35 @@ class FirConverter : public Fortran::lower::AbstractConverter {
1741
1744
builder->create <fir::UnreachableOp>(loc);
1742
1745
}
1743
1746
1747
+ fir::ReduceOperationEnum
1748
+ getReduceOperationEnum (const Fortran::parser::ReductionOperator &rOpr) {
1749
+ switch (rOpr.v ) {
1750
+ case Fortran::parser::ReductionOperator::Operator::Plus:
1751
+ return fir::ReduceOperationEnum::Add;
1752
+ case Fortran::parser::ReductionOperator::Operator::Multiply:
1753
+ return fir::ReduceOperationEnum::Multiply;
1754
+ case Fortran::parser::ReductionOperator::Operator::And:
1755
+ return fir::ReduceOperationEnum::AND;
1756
+ case Fortran::parser::ReductionOperator::Operator::Or:
1757
+ return fir::ReduceOperationEnum::OR;
1758
+ case Fortran::parser::ReductionOperator::Operator::Eqv:
1759
+ return fir::ReduceOperationEnum::EQV;
1760
+ case Fortran::parser::ReductionOperator::Operator::Neqv:
1761
+ return fir::ReduceOperationEnum::NEQV;
1762
+ case Fortran::parser::ReductionOperator::Operator::Max:
1763
+ return fir::ReduceOperationEnum::MAX;
1764
+ case Fortran::parser::ReductionOperator::Operator::Min:
1765
+ return fir::ReduceOperationEnum::MIN;
1766
+ case Fortran::parser::ReductionOperator::Operator::Iand:
1767
+ return fir::ReduceOperationEnum::IAND;
1768
+ case Fortran::parser::ReductionOperator::Operator::Ior:
1769
+ return fir::ReduceOperationEnum::IOR;
1770
+ case Fortran::parser::ReductionOperator::Operator::Ieor:
1771
+ return fir::ReduceOperationEnum::EIOR;
1772
+ }
1773
+ llvm_unreachable (" illegal reduction operator" );
1774
+ }
1775
+
1744
1776
// / Collect DO CONCURRENT or FORALL loop control information.
1745
1777
IncrementLoopNestInfo getConcurrentControl (
1746
1778
const Fortran::parser::ConcurrentHeader &header,
@@ -1763,6 +1795,16 @@ class FirConverter : public Fortran::lower::AbstractConverter {
1763
1795
std::get_if<Fortran::parser::LocalitySpec::LocalInit>(&x.u ))
1764
1796
for (const Fortran::parser::Name &x : localInitList->v )
1765
1797
info.localInitSymList .push_back (x.symbol );
1798
+ if (const auto *reduceList =
1799
+ std::get_if<Fortran::parser::LocalitySpec::Reduce>(&x.u )) {
1800
+ fir::ReduceOperationEnum reduce_operation = getReduceOperationEnum (
1801
+ std::get<Fortran::parser::ReductionOperator>(reduceList->t ));
1802
+ for (const Fortran::parser::Name &x :
1803
+ std::get<std::list<Fortran::parser::Name>>(reduceList->t )) {
1804
+ info.reduceSymList .push_back (
1805
+ std::make_pair (reduce_operation, x.symbol ));
1806
+ }
1807
+ }
1766
1808
if (const auto *sharedList =
1767
1809
std::get_if<Fortran::parser::LocalitySpec::Shared>(&x.u ))
1768
1810
for (const Fortran::parser::Name &x : sharedList->v )
@@ -1955,9 +1997,23 @@ class FirConverter : public Fortran::lower::AbstractConverter {
1955
1997
mlir::Type loopVarType = info.getLoopVariableType ();
1956
1998
mlir::Value loopValue;
1957
1999
if (info.isUnordered ) {
2000
+ llvm::SmallVector<mlir::Value> reduceOperands;
2001
+ llvm::SmallVector<mlir::Attribute> reduceAttrs;
2002
+ // Create DO CONCURRENT reduce operands and attributes
2003
+ for (const auto reduceSym : info.reduceSymList ) {
2004
+ const fir::ReduceOperationEnum reduce_operation = reduceSym.first ;
2005
+ const Fortran::semantics::Symbol *sym = reduceSym.second ;
2006
+ fir::ExtendedValue exv = getSymbolExtendedValue (*sym, nullptr );
2007
+ reduceOperands.push_back (fir::getBase (exv));
2008
+ auto reduce_attr =
2009
+ fir::ReduceAttr::get (builder->getContext (), reduce_operation);
2010
+ reduceAttrs.push_back (reduce_attr);
2011
+ }
1958
2012
// The loop variable value is explicitly updated.
1959
2013
info.doLoop = builder->create <fir::DoLoopOp>(
1960
- loc, lowerValue, upperValue, stepValue, /* unordered=*/ true );
2014
+ loc, lowerValue, upperValue, stepValue, /* unordered=*/ true ,
2015
+ /* finalCountValue=*/ false , /* iterArgs=*/ std::nullopt,
2016
+ llvm::ArrayRef<mlir::Value>(reduceOperands), reduceAttrs);
1961
2017
builder->setInsertionPointToStart (info.doLoop .getBody ());
1962
2018
loopValue = builder->createConvert (loc, loopVarType,
1963
2019
info.doLoop .getInductionVar ());
0 commit comments