@@ -1804,27 +1804,38 @@ static void privatizeIv(Fortran::lower::AbstractConverter &converter,
1804
1804
builder.restoreInsertionPoint (insPt);
1805
1805
}
1806
1806
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
+ }
1812
1814
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 ();
1819
1829
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
+ }
1823
1834
1824
1835
// Map the new private iv to its symbol for the scope of the loop. bindSymbol
1825
1836
// might create a hlfir.declare op, if so, we map its result in order to
1826
1837
// use the sym value in the scope.
1827
- converter.bindSymbol (sym, op. getAccVar ());
1838
+ converter.bindSymbol (sym, mlir::acc:: getAccVar (privateOp ));
1828
1839
auto privateValue = converter.getSymbolAddress (sym);
1829
1840
if (auto declareOp =
1830
1841
mlir::dyn_cast<hlfir::DeclareOp>(privateValue.getDefiningOp ()))
@@ -1863,92 +1874,6 @@ static mlir::acc::LoopOp createLoopOp(
1863
1874
crtDeviceTypes.push_back (mlir::acc::DeviceTypeAttr::get (
1864
1875
builder.getContext (), mlir::acc::DeviceType::None));
1865
1876
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
-
1952
1877
for (const Fortran::parser::AccClause &clause : accClauseList.v ) {
1953
1878
mlir::Location clauseLocation = converter.genLocation (clause.source );
1954
1879
if (const auto *gangClause =
@@ -2101,6 +2026,91 @@ static mlir::acc::LoopOp createLoopOp(
2101
2026
}
2102
2027
}
2103
2028
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
+
2104
2114
// Prepare the operand segment size attribute and the operands value range.
2105
2115
llvm::SmallVector<mlir::Value> operands;
2106
2116
llvm::SmallVector<int32_t > operandSegments;
0 commit comments