@@ -1804,27 +1804,38 @@ static void privatizeIv(Fortran::lower::AbstractConverter &converter,
18041804 builder.restoreInsertionPoint (insPt);
18051805 }
18061806
1807- std::string recipeName =
1808- fir::getTypeAsString (ivValue.getType (), converter.getKindMap (),
1809- Fortran::lower::privatizationRecipePrefix);
1810- auto recipe = Fortran::lower::createOrGetPrivateRecipe (
1811- builder, recipeName, loc, ivValue.getType ());
1807+ mlir::Operation *privateOp = nullptr ;
1808+ for (auto privateVal : privateOperands) {
1809+ if (mlir::acc::getVar (privateVal.getDefiningOp ()) == ivValue) {
1810+ privateOp = privateVal.getDefiningOp ();
1811+ break ;
1812+ }
1813+ }
18121814
1813- std::stringstream asFortran;
1814- asFortran << Fortran::lower::mangle::demangleName (toStringRef (sym.name ()));
1815- auto op = createDataEntryOp<mlir::acc::PrivateOp>(
1816- builder, loc, ivValue, asFortran, {}, true , /* implicit=*/ true ,
1817- mlir::acc::DataClause::acc_private, ivValue.getType (),
1818- /* async=*/ {}, /* asyncDeviceTypes=*/ {}, /* asyncOnlyDeviceTypes=*/ {});
1815+ if (privateOp == nullptr ) {
1816+ std::string recipeName =
1817+ fir::getTypeAsString (ivValue.getType (), converter.getKindMap (),
1818+ Fortran::lower::privatizationRecipePrefix);
1819+ auto recipe = Fortran::lower::createOrGetPrivateRecipe (
1820+ builder, recipeName, loc, ivValue.getType ());
1821+
1822+ std::stringstream asFortran;
1823+ asFortran << Fortran::lower::mangle::demangleName (toStringRef (sym.name ()));
1824+ auto op = createDataEntryOp<mlir::acc::PrivateOp>(
1825+ builder, loc, ivValue, asFortran, {}, true , /* implicit=*/ true ,
1826+ mlir::acc::DataClause::acc_private, ivValue.getType (),
1827+ /* async=*/ {}, /* asyncDeviceTypes=*/ {}, /* asyncOnlyDeviceTypes=*/ {});
1828+ privateOp = op.getOperation ();
18191829
1820- privateOperands.push_back (op.getAccVar ());
1821- privatizations.push_back (mlir::SymbolRefAttr::get (builder.getContext (),
1822- recipe.getSymName ().str ()));
1830+ privateOperands.push_back (op.getAccVar ());
1831+ privatizations.push_back (mlir::SymbolRefAttr::get (
1832+ builder.getContext (), recipe.getSymName ().str ()));
1833+ }
18231834
18241835 // Map the new private iv to its symbol for the scope of the loop. bindSymbol
18251836 // might create a hlfir.declare op, if so, we map its result in order to
18261837 // use the sym value in the scope.
1827- converter.bindSymbol (sym, op. getAccVar ());
1838+ converter.bindSymbol (sym, mlir::acc:: getAccVar (privateOp ));
18281839 auto privateValue = converter.getSymbolAddress (sym);
18291840 if (auto declareOp =
18301841 mlir::dyn_cast<hlfir::DeclareOp>(privateValue.getDefiningOp ()))
@@ -1863,92 +1874,6 @@ static mlir::acc::LoopOp createLoopOp(
18631874 crtDeviceTypes.push_back (mlir::acc::DeviceTypeAttr::get (
18641875 builder.getContext (), mlir::acc::DeviceType::None));
18651876
1866- llvm::SmallVector<mlir::Type> ivTypes;
1867- llvm::SmallVector<mlir::Location> ivLocs;
1868- llvm::SmallVector<bool > inclusiveBounds;
1869-
1870- llvm::SmallVector<mlir::Location> locs;
1871- locs.push_back (currentLocation); // Location of the directive
1872- Fortran::lower::pft::Evaluation *crtEval = &eval.getFirstNestedEvaluation ();
1873- bool isDoConcurrent = outerDoConstruct.IsDoConcurrent ();
1874- if (isDoConcurrent) {
1875- locs.push_back (converter.genLocation (
1876- Fortran::parser::FindSourceLocation (outerDoConstruct)));
1877- const Fortran::parser::LoopControl *loopControl =
1878- &*outerDoConstruct.GetLoopControl ();
1879- const auto &concurrent =
1880- std::get<Fortran::parser::LoopControl::Concurrent>(loopControl->u );
1881- if (!std::get<std::list<Fortran::parser::LocalitySpec>>(concurrent.t )
1882- .empty ())
1883- TODO (currentLocation, " DO CONCURRENT with locality spec" );
1884-
1885- const auto &concurrentHeader =
1886- std::get<Fortran::parser::ConcurrentHeader>(concurrent.t );
1887- const auto &controls =
1888- std::get<std::list<Fortran::parser::ConcurrentControl>>(
1889- concurrentHeader.t );
1890- for (const auto &control : controls) {
1891- lowerbounds.push_back (fir::getBase (converter.genExprValue (
1892- *Fortran::semantics::GetExpr (std::get<1 >(control.t )), stmtCtx)));
1893- upperbounds.push_back (fir::getBase (converter.genExprValue (
1894- *Fortran::semantics::GetExpr (std::get<2 >(control.t )), stmtCtx)));
1895- if (const auto &expr =
1896- std::get<std::optional<Fortran::parser::ScalarIntExpr>>(
1897- control.t ))
1898- steps.push_back (fir::getBase (converter.genExprValue (
1899- *Fortran::semantics::GetExpr (*expr), stmtCtx)));
1900- else // If `step` is not present, assume it is `1`.
1901- steps.push_back (builder.createIntegerConstant (
1902- currentLocation, upperbounds[upperbounds.size () - 1 ].getType (), 1 ));
1903-
1904- const auto &name = std::get<Fortran::parser::Name>(control.t );
1905- privatizeIv (converter, *name.symbol , currentLocation, ivTypes, ivLocs,
1906- privateOperands, ivPrivate, privatizations, isDoConcurrent);
1907-
1908- inclusiveBounds.push_back (true );
1909- }
1910- } else {
1911- int64_t collapseValue = Fortran::lower::getCollapseValue (accClauseList);
1912- for (unsigned i = 0 ; i < collapseValue; ++i) {
1913- const Fortran::parser::LoopControl *loopControl;
1914- if (i == 0 ) {
1915- loopControl = &*outerDoConstruct.GetLoopControl ();
1916- locs.push_back (converter.genLocation (
1917- Fortran::parser::FindSourceLocation (outerDoConstruct)));
1918- } else {
1919- auto *doCons = crtEval->getIf <Fortran::parser::DoConstruct>();
1920- assert (doCons && " expect do construct" );
1921- loopControl = &*doCons->GetLoopControl ();
1922- locs.push_back (converter.genLocation (
1923- Fortran::parser::FindSourceLocation (*doCons)));
1924- }
1925-
1926- const Fortran::parser::LoopControl::Bounds *bounds =
1927- std::get_if<Fortran::parser::LoopControl::Bounds>(&loopControl->u );
1928- assert (bounds && " Expected bounds on the loop construct" );
1929- lowerbounds.push_back (fir::getBase (converter.genExprValue (
1930- *Fortran::semantics::GetExpr (bounds->lower ), stmtCtx)));
1931- upperbounds.push_back (fir::getBase (converter.genExprValue (
1932- *Fortran::semantics::GetExpr (bounds->upper ), stmtCtx)));
1933- if (bounds->step )
1934- steps.push_back (fir::getBase (converter.genExprValue (
1935- *Fortran::semantics::GetExpr (bounds->step ), stmtCtx)));
1936- else // If `step` is not present, assume it is `1`.
1937- steps.push_back (builder.createIntegerConstant (
1938- currentLocation, upperbounds[upperbounds.size () - 1 ].getType (), 1 ));
1939-
1940- Fortran::semantics::Symbol &ivSym =
1941- bounds->name .thing .symbol ->GetUltimate ();
1942- privatizeIv (converter, ivSym, currentLocation, ivTypes, ivLocs,
1943- privateOperands, ivPrivate, privatizations);
1944-
1945- inclusiveBounds.push_back (true );
1946-
1947- if (i < collapseValue - 1 )
1948- crtEval = &*std::next (crtEval->getNestedEvaluations ().begin ());
1949- }
1950- }
1951-
19521877 for (const Fortran::parser::AccClause &clause : accClauseList.v ) {
19531878 mlir::Location clauseLocation = converter.genLocation (clause.source );
19541879 if (const auto *gangClause =
@@ -2101,6 +2026,91 @@ static mlir::acc::LoopOp createLoopOp(
21012026 }
21022027 }
21032028
2029+ llvm::SmallVector<mlir::Type> ivTypes;
2030+ llvm::SmallVector<mlir::Location> ivLocs;
2031+ llvm::SmallVector<bool > inclusiveBounds;
2032+ llvm::SmallVector<mlir::Location> locs;
2033+ locs.push_back (currentLocation); // Location of the directive
2034+ Fortran::lower::pft::Evaluation *crtEval = &eval.getFirstNestedEvaluation ();
2035+ bool isDoConcurrent = outerDoConstruct.IsDoConcurrent ();
2036+ if (isDoConcurrent) {
2037+ locs.push_back (converter.genLocation (
2038+ Fortran::parser::FindSourceLocation (outerDoConstruct)));
2039+ const Fortran::parser::LoopControl *loopControl =
2040+ &*outerDoConstruct.GetLoopControl ();
2041+ const auto &concurrent =
2042+ std::get<Fortran::parser::LoopControl::Concurrent>(loopControl->u );
2043+ if (!std::get<std::list<Fortran::parser::LocalitySpec>>(concurrent.t )
2044+ .empty ())
2045+ TODO (currentLocation, " DO CONCURRENT with locality spec" );
2046+
2047+ const auto &concurrentHeader =
2048+ std::get<Fortran::parser::ConcurrentHeader>(concurrent.t );
2049+ const auto &controls =
2050+ std::get<std::list<Fortran::parser::ConcurrentControl>>(
2051+ concurrentHeader.t );
2052+ for (const auto &control : controls) {
2053+ lowerbounds.push_back (fir::getBase (converter.genExprValue (
2054+ *Fortran::semantics::GetExpr (std::get<1 >(control.t )), stmtCtx)));
2055+ upperbounds.push_back (fir::getBase (converter.genExprValue (
2056+ *Fortran::semantics::GetExpr (std::get<2 >(control.t )), stmtCtx)));
2057+ if (const auto &expr =
2058+ std::get<std::optional<Fortran::parser::ScalarIntExpr>>(
2059+ control.t ))
2060+ steps.push_back (fir::getBase (converter.genExprValue (
2061+ *Fortran::semantics::GetExpr (*expr), stmtCtx)));
2062+ else // If `step` is not present, assume it is `1`.
2063+ steps.push_back (builder.createIntegerConstant (
2064+ currentLocation, upperbounds[upperbounds.size () - 1 ].getType (), 1 ));
2065+
2066+ const auto &name = std::get<Fortran::parser::Name>(control.t );
2067+ privatizeIv (converter, *name.symbol , currentLocation, ivTypes, ivLocs,
2068+ privateOperands, ivPrivate, privatizations, isDoConcurrent);
2069+
2070+ inclusiveBounds.push_back (true );
2071+ }
2072+ } else {
2073+ int64_t collapseValue = Fortran::lower::getCollapseValue (accClauseList);
2074+ for (unsigned i = 0 ; i < collapseValue; ++i) {
2075+ const Fortran::parser::LoopControl *loopControl;
2076+ if (i == 0 ) {
2077+ loopControl = &*outerDoConstruct.GetLoopControl ();
2078+ locs.push_back (converter.genLocation (
2079+ Fortran::parser::FindSourceLocation (outerDoConstruct)));
2080+ } else {
2081+ auto *doCons = crtEval->getIf <Fortran::parser::DoConstruct>();
2082+ assert (doCons && " expect do construct" );
2083+ loopControl = &*doCons->GetLoopControl ();
2084+ locs.push_back (converter.genLocation (
2085+ Fortran::parser::FindSourceLocation (*doCons)));
2086+ }
2087+
2088+ const Fortran::parser::LoopControl::Bounds *bounds =
2089+ std::get_if<Fortran::parser::LoopControl::Bounds>(&loopControl->u );
2090+ assert (bounds && " Expected bounds on the loop construct" );
2091+ lowerbounds.push_back (fir::getBase (converter.genExprValue (
2092+ *Fortran::semantics::GetExpr (bounds->lower ), stmtCtx)));
2093+ upperbounds.push_back (fir::getBase (converter.genExprValue (
2094+ *Fortran::semantics::GetExpr (bounds->upper ), stmtCtx)));
2095+ if (bounds->step )
2096+ steps.push_back (fir::getBase (converter.genExprValue (
2097+ *Fortran::semantics::GetExpr (bounds->step ), stmtCtx)));
2098+ else // If `step` is not present, assume it is `1`.
2099+ steps.push_back (builder.createIntegerConstant (
2100+ currentLocation, upperbounds[upperbounds.size () - 1 ].getType (), 1 ));
2101+
2102+ Fortran::semantics::Symbol &ivSym =
2103+ bounds->name .thing .symbol ->GetUltimate ();
2104+ privatizeIv (converter, ivSym, currentLocation, ivTypes, ivLocs,
2105+ privateOperands, ivPrivate, privatizations);
2106+
2107+ inclusiveBounds.push_back (true );
2108+
2109+ if (i < collapseValue - 1 )
2110+ crtEval = &*std::next (crtEval->getNestedEvaluations ().begin ());
2111+ }
2112+ }
2113+
21042114 // Prepare the operand segment size attribute and the operands value range.
21052115 llvm::SmallVector<mlir::Value> operands;
21062116 llvm::SmallVector<int32_t > operandSegments;
0 commit comments