[llvm-branch-commits] [flang] [flang][fir] Basic PFT to MLIR lowering for do concurrent locality specifiers (PR #138534)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon May 5 07:05:19 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-fir-hlfir
Author: Kareem Ergawy (ergawy)
<details>
<summary>Changes</summary>
Extends support for `fir.do_concurrent` locality specifiers to the PFT to MLIR level. This adds code-gen for generating the newly added `fir.local` ops and referencing these ops from `fir.do_concurrent.loop` ops that have locality specifiers attached to them. This reuses the `DataSharingProcessor` component and generalizes it a bit more to allow for handling `omp.private` ops and `fir.local` ops as well.
---
Patch is 21.37 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/138534.diff
7 Files Affected:
- (modified) flang/include/flang/Lower/AbstractConverter.h (+4)
- (modified) flang/include/flang/Optimizer/Dialect/FIROps.h (+4)
- (modified) flang/include/flang/Optimizer/Dialect/FIROps.td (+15)
- (modified) flang/lib/Lower/Bridge.cpp (+50-9)
- (modified) flang/lib/Lower/OpenMP/DataSharingProcessor.cpp (+77-27)
- (modified) flang/lib/Lower/OpenMP/DataSharingProcessor.h (+10-4)
- (added) flang/test/Lower/do_concurrent_delayed_locality.f90 (+59)
``````````diff
diff --git a/flang/include/flang/Lower/AbstractConverter.h b/flang/include/flang/Lower/AbstractConverter.h
index 1d1323642bf9c..8ae68e143cd2f 100644
--- a/flang/include/flang/Lower/AbstractConverter.h
+++ b/flang/include/flang/Lower/AbstractConverter.h
@@ -348,6 +348,10 @@ class AbstractConverter {
virtual Fortran::lower::SymbolBox
lookupOneLevelUpSymbol(const Fortran::semantics::Symbol &sym) = 0;
+ /// Find the symbol in the inner-most level of the local map or return null.
+ virtual Fortran::lower::SymbolBox
+ shallowLookupSymbol(const Fortran::semantics::Symbol &sym) = 0;
+
/// Return the mlir::SymbolTable associated to the ModuleOp.
/// Look-ups are faster using it than using module.lookup<>,
/// but the module op should be queried in case of failure
diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.h b/flang/include/flang/Optimizer/Dialect/FIROps.h
index 1bed227afb50d..62ef8b4b502f2 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.h
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.h
@@ -147,6 +147,10 @@ class CoordinateIndicesAdaptor {
mlir::ValueRange values;
};
+struct LocalitySpecifierOperands {
+ llvm::SmallVector<::mlir::Value> privateVars;
+ llvm::SmallVector<::mlir::Attribute> privateSyms;
+};
} // namespace fir
#endif // FORTRAN_OPTIMIZER_DIALECT_FIROPS_H
diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td
index 01248aa0095ec..5c0fc95a47a8e 100644
--- a/flang/include/flang/Optimizer/Dialect/FIROps.td
+++ b/flang/include/flang/Optimizer/Dialect/FIROps.td
@@ -3600,6 +3600,21 @@ def fir_LocalitySpecifierOp : fir_Op<"local", [IsolatedFromAbove]> {
];
let extraClassDeclaration = [{
+ mlir::BlockArgument getInitMoldArg() {
+ auto ®ion = getInitRegion();
+ return region.empty() ? nullptr : region.getArgument(0);
+ }
+ mlir::BlockArgument getInitPrivateArg() {
+ auto ®ion = getInitRegion();
+ return region.empty() ? nullptr : region.getArgument(1);
+ }
+
+ /// Returns true if the init region might read from the mold argument
+ bool initReadsFromMold() {
+ mlir::BlockArgument moldArg = getInitMoldArg();
+ return moldArg && !moldArg.use_empty();
+ }
+
/// Get the type for arguments to nested regions. This should
/// generally be either the same as getType() or some pointer
/// type (pointing to the type allocated by this op).
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 0a61f61ab8f75..bf55402ec4714 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -12,6 +12,8 @@
#include "flang/Lower/Bridge.h"
+#include "OpenMP/DataSharingProcessor.h"
+#include "OpenMP/Utils.h"
#include "flang/Lower/Allocatable.h"
#include "flang/Lower/CallInterface.h"
#include "flang/Lower/Coarray.h"
@@ -1144,6 +1146,14 @@ class FirConverter : public Fortran::lower::AbstractConverter {
return name;
}
+ /// Find the symbol in the inner-most level of the local map or return null.
+ Fortran::lower::SymbolBox
+ shallowLookupSymbol(const Fortran::semantics::Symbol &sym) override {
+ if (Fortran::lower::SymbolBox v = localSymbols.shallowLookupSymbol(sym))
+ return v;
+ return {};
+ }
+
private:
FirConverter() = delete;
FirConverter(const FirConverter &) = delete;
@@ -1218,14 +1228,6 @@ class FirConverter : public Fortran::lower::AbstractConverter {
return {};
}
- /// Find the symbol in the inner-most level of the local map or return null.
- Fortran::lower::SymbolBox
- shallowLookupSymbol(const Fortran::semantics::Symbol &sym) {
- if (Fortran::lower::SymbolBox v = localSymbols.shallowLookupSymbol(sym))
- return v;
- return {};
- }
-
/// Find the symbol in one level up of symbol map such as for host-association
/// in OpenMP code or return null.
Fortran::lower::SymbolBox
@@ -2029,9 +2031,30 @@ class FirConverter : public Fortran::lower::AbstractConverter {
void handleLocalitySpecs(const IncrementLoopInfo &info) {
Fortran::semantics::SemanticsContext &semanticsContext =
bridge.getSemanticsContext();
- for (const Fortran::semantics::Symbol *sym : info.localSymList)
+ Fortran::lower::omp::DataSharingProcessor dsp(
+ *this, semanticsContext, getEval(),
+ /*useDelayedPrivatization=*/true, localSymbols);
+ fir::LocalitySpecifierOperands privateClauseOps;
+ auto doConcurrentLoopOp =
+ mlir::dyn_cast_if_present<fir::DoConcurrentLoopOp>(info.loopOp);
+ bool useDelayedPriv =
+ enableDelayedPrivatizationStaging && doConcurrentLoopOp;
+
+ for (const Fortran::semantics::Symbol *sym : info.localSymList) {
+ if (useDelayedPriv) {
+ dsp.privatizeSymbol<fir::LocalitySpecifierOp>(sym, &privateClauseOps);
+ continue;
+ }
+
createHostAssociateVarClone(*sym, /*skipDefaultInit=*/false);
+ }
+
for (const Fortran::semantics::Symbol *sym : info.localInitSymList) {
+ if (useDelayedPriv) {
+ dsp.privatizeSymbol<fir::LocalitySpecifierOp>(sym, &privateClauseOps);
+ continue;
+ }
+
createHostAssociateVarClone(*sym, /*skipDefaultInit=*/true);
const auto *hostDetails =
sym->detailsIf<Fortran::semantics::HostAssocDetails>();
@@ -2050,6 +2073,24 @@ class FirConverter : public Fortran::lower::AbstractConverter {
sym->detailsIf<Fortran::semantics::HostAssocDetails>();
copySymbolBinding(hostDetails->symbol(), *sym);
}
+
+ if (useDelayedPriv) {
+ doConcurrentLoopOp.getLocalVarsMutable().assign(
+ privateClauseOps.privateVars);
+ doConcurrentLoopOp.setLocalSymsAttr(
+ builder->getArrayAttr(privateClauseOps.privateSyms));
+
+ for (auto [sym, privateVar] : llvm::zip_equal(
+ dsp.getAllSymbolsToPrivatize(), privateClauseOps.privateVars)) {
+ auto arg = doConcurrentLoopOp.getRegion().begin()->addArgument(
+ privateVar.getType(), doConcurrentLoopOp.getLoc());
+ bindSymbol(*sym, hlfir::translateToExtendedValue(
+ privateVar.getLoc(), *builder, hlfir::Entity{arg},
+ /*contiguousHint=*/true)
+ .first);
+ }
+ }
+
// Note that allocatable, types with ultimate components, and type
// requiring finalization are forbidden in LOCAL/LOCAL_INIT (F2023 C1130),
// so no clean-up needs to be generated for these entities.
diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
index b88454c45da85..bedd8864a0bc2 100644
--- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
@@ -20,6 +20,7 @@
#include "flang/Optimizer/Builder/BoxValue.h"
#include "flang/Optimizer/Builder/HLFIRTools.h"
#include "flang/Optimizer/Builder/Todo.h"
+#include "flang/Optimizer/Dialect/FIROps.h"
#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
#include "flang/Semantics/attr.h"
@@ -53,6 +54,15 @@ DataSharingProcessor::DataSharingProcessor(
});
}
+DataSharingProcessor::DataSharingProcessor(lower::AbstractConverter &converter,
+ semantics::SemanticsContext &semaCtx,
+ lower::pft::Evaluation &eval,
+ bool useDelayedPrivatization,
+ lower::SymMap &symTable)
+ : DataSharingProcessor(converter, semaCtx, {}, eval,
+ /*shouldCollectPreDeterminedSymols=*/false,
+ useDelayedPrivatization, symTable) {}
+
void DataSharingProcessor::processStep1(
mlir::omp::PrivateClauseOps *clauseOps) {
collectSymbolsForPrivatization();
@@ -172,7 +182,8 @@ void DataSharingProcessor::cloneSymbol(const semantics::Symbol *sym) {
void DataSharingProcessor::copyFirstPrivateSymbol(
const semantics::Symbol *sym, mlir::OpBuilder::InsertPoint *copyAssignIP) {
- if (sym->test(semantics::Symbol::Flag::OmpFirstPrivate))
+ if (sym->test(semantics::Symbol::Flag::OmpFirstPrivate) ||
+ sym->test(semantics::Symbol::Flag::LocalityLocalInit))
converter.copyHostAssociateVar(*sym, copyAssignIP);
}
@@ -485,9 +496,9 @@ void DataSharingProcessor::privatize(mlir::omp::PrivateClauseOps *clauseOps) {
if (const auto *commonDet =
sym->detailsIf<semantics::CommonBlockDetails>()) {
for (const auto &mem : commonDet->objects())
- doPrivatize(&*mem, clauseOps);
+ privatizeSymbol(&*mem, clauseOps);
} else
- doPrivatize(sym, clauseOps);
+ privatizeSymbol(sym, clauseOps);
}
}
@@ -504,22 +515,30 @@ void DataSharingProcessor::copyLastPrivatize(mlir::Operation *op) {
}
}
-void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
- mlir::omp::PrivateClauseOps *clauseOps) {
+template <typename OpType, typename OperandsStructType>
+void DataSharingProcessor::privatizeSymbol(
+ const semantics::Symbol *symToPrivatize, OperandsStructType *clauseOps) {
if (!useDelayedPrivatization) {
- cloneSymbol(sym);
- copyFirstPrivateSymbol(sym);
+ cloneSymbol(symToPrivatize);
+ copyFirstPrivateSymbol(symToPrivatize);
return;
}
- lower::SymbolBox hsb = converter.lookupOneLevelUpSymbol(*sym);
+ const semantics::Symbol *sym = symToPrivatize->HasLocalLocality()
+ ? &symToPrivatize->GetUltimate()
+ : symToPrivatize;
+ lower::SymbolBox hsb = symToPrivatize->HasLocalLocality()
+ ? converter.shallowLookupSymbol(*sym)
+ : converter.lookupOneLevelUpSymbol(*sym);
assert(hsb && "Host symbol box not found");
hlfir::Entity entity{hsb.getAddr()};
bool cannotHaveNonDefaultLowerBounds = !entity.mayHaveNonDefaultLowerBounds();
mlir::Location symLoc = hsb.getAddr().getLoc();
std::string privatizerName = sym->name().ToString() + ".privatizer";
- bool isFirstPrivate = sym->test(semantics::Symbol::Flag::OmpFirstPrivate);
+ bool isFirstPrivate =
+ symToPrivatize->test(semantics::Symbol::Flag::OmpFirstPrivate) ||
+ symToPrivatize->test(semantics::Symbol::Flag::LocalityLocalInit);
mlir::Value privVal = hsb.getAddr();
mlir::Type allocType = privVal.getType();
@@ -553,7 +572,7 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
mlir::Type argType = privVal.getType();
- mlir::omp::PrivateClauseOp privatizerOp = [&]() {
+ OpType privatizerOp = [&]() {
auto moduleOp = firOpBuilder.getModule();
auto uniquePrivatizerName = fir::getTypeAsString(
allocType, converter.getKindMap(),
@@ -561,16 +580,25 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
(isFirstPrivate ? "_firstprivate" : "_private"));
if (auto existingPrivatizer =
- moduleOp.lookupSymbol<mlir::omp::PrivateClauseOp>(
- uniquePrivatizerName))
+ moduleOp.lookupSymbol<OpType>(uniquePrivatizerName))
return existingPrivatizer;
mlir::OpBuilder::InsertionGuard guard(firOpBuilder);
firOpBuilder.setInsertionPointToStart(moduleOp.getBody());
- auto result = firOpBuilder.create<mlir::omp::PrivateClauseOp>(
- symLoc, uniquePrivatizerName, allocType,
- isFirstPrivate ? mlir::omp::DataSharingClauseType::FirstPrivate
- : mlir::omp::DataSharingClauseType::Private);
+ OpType result;
+
+ if constexpr (std::is_same_v<OpType, mlir::omp::PrivateClauseOp>) {
+ result = firOpBuilder.create<OpType>(
+ symLoc, uniquePrivatizerName, allocType,
+ isFirstPrivate ? mlir::omp::DataSharingClauseType::FirstPrivate
+ : mlir::omp::DataSharingClauseType::Private);
+ } else {
+ result = firOpBuilder.create<OpType>(
+ symLoc, uniquePrivatizerName, allocType,
+ isFirstPrivate ? fir::LocalitySpecifierType::LocalInit
+ : fir::LocalitySpecifierType::Local);
+ }
+
fir::ExtendedValue symExV = converter.getSymbolExtendedValue(*sym);
lower::SymMapScope outerScope(symTable);
@@ -613,27 +641,36 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
©Region, /*insertPt=*/{}, {argType, argType}, {symLoc, symLoc});
firOpBuilder.setInsertionPointToEnd(copyEntryBlock);
- auto addSymbol = [&](unsigned argIdx, bool force = false) {
+ auto addSymbol = [&](unsigned argIdx, const semantics::Symbol *symToMap,
+ bool force = false) {
symExV.match(
[&](const fir::MutableBoxValue &box) {
symTable.addSymbol(
- *sym, fir::substBase(box, copyRegion.getArgument(argIdx)),
- force);
+ *symToMap,
+ fir::substBase(box, copyRegion.getArgument(argIdx)), force);
},
[&](const auto &box) {
- symTable.addSymbol(*sym, copyRegion.getArgument(argIdx), force);
+ symTable.addSymbol(*symToMap, copyRegion.getArgument(argIdx),
+ force);
});
};
- addSymbol(0, true);
+ addSymbol(0, sym, true);
lower::SymMapScope innerScope(symTable);
- addSymbol(1);
+ addSymbol(1, symToPrivatize);
auto ip = firOpBuilder.saveInsertionPoint();
- copyFirstPrivateSymbol(sym, &ip);
-
- firOpBuilder.create<mlir::omp::YieldOp>(
- hsb.getAddr().getLoc(), symTable.shallowLookupSymbol(*sym).getAddr());
+ copyFirstPrivateSymbol(symToPrivatize, &ip);
+
+ if constexpr (std::is_same_v<OpType, mlir::omp::PrivateClauseOp>) {
+ firOpBuilder.create<mlir::omp::YieldOp>(
+ hsb.getAddr().getLoc(),
+ symTable.shallowLookupSymbol(*symToPrivatize).getAddr());
+ } else {
+ firOpBuilder.create<fir::YieldOp>(
+ hsb.getAddr().getLoc(),
+ symTable.shallowLookupSymbol(*symToPrivatize).getAddr());
+ }
}
return result;
@@ -644,9 +681,22 @@ void DataSharingProcessor::doPrivatize(const semantics::Symbol *sym,
clauseOps->privateVars.push_back(privVal);
}
- symToPrivatizer[sym] = privatizerOp;
+ if (symToPrivatize->HasLocalLocality())
+ allPrivatizedSymbols.insert(symToPrivatize);
}
+template void
+DataSharingProcessor::privatizeSymbol<mlir::omp::PrivateClauseOp,
+ mlir::omp::PrivateClauseOps>(
+ const semantics::Symbol *symToPrivatize,
+ mlir::omp::PrivateClauseOps *clauseOps);
+
+template void
+DataSharingProcessor::privatizeSymbol<fir::LocalitySpecifierOp,
+ fir::LocalitySpecifierOperands>(
+ const semantics::Symbol *symToPrivatize,
+ fir::LocalitySpecifierOperands *clauseOps);
+
} // namespace omp
} // namespace lower
} // namespace Fortran
diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.h b/flang/lib/Lower/OpenMP/DataSharingProcessor.h
index 54a42fd199831..d3f543c3db75e 100644
--- a/flang/lib/Lower/OpenMP/DataSharingProcessor.h
+++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.h
@@ -77,8 +77,6 @@ class DataSharingProcessor {
llvm::SetVector<const semantics::Symbol *> preDeterminedSymbols;
llvm::SetVector<const semantics::Symbol *> allPrivatizedSymbols;
- llvm::DenseMap<const semantics::Symbol *, mlir::omp::PrivateClauseOp>
- symToPrivatizer;
lower::AbstractConverter &converter;
semantics::SemanticsContext &semaCtx;
fir::FirOpBuilder &firOpBuilder;
@@ -105,8 +103,6 @@ class DataSharingProcessor {
void collectImplicitSymbols();
void collectPreDeterminedSymbols();
void privatize(mlir::omp::PrivateClauseOps *clauseOps);
- void doPrivatize(const semantics::Symbol *sym,
- mlir::omp::PrivateClauseOps *clauseOps);
void copyLastPrivatize(mlir::Operation *op);
void insertLastPrivateCompare(mlir::Operation *op);
void cloneSymbol(const semantics::Symbol *sym);
@@ -125,6 +121,11 @@ class DataSharingProcessor {
bool shouldCollectPreDeterminedSymbols,
bool useDelayedPrivatization, lower::SymMap &symTable);
+ DataSharingProcessor(lower::AbstractConverter &converter,
+ semantics::SemanticsContext &semaCtx,
+ lower::pft::Evaluation &eval,
+ bool useDelayedPrivatization, lower::SymMap &symTable);
+
// Privatisation is split into two steps.
// Step1 performs cloning of all privatisation clauses and copying for
// firstprivates. Step1 is performed at the place where process/processStep1
@@ -151,6 +152,11 @@ class DataSharingProcessor {
? allPrivatizedSymbols.getArrayRef()
: llvm::ArrayRef<const semantics::Symbol *>();
}
+
+ template <typename OpType = mlir::omp::PrivateClauseOp,
+ typename OperandsStructType = mlir::omp::PrivateClauseOps>
+ void privatizeSymbol(const semantics::Symbol *symToPrivatize,
+ OperandsStructType *clauseOps);
};
} // namespace omp
diff --git a/flang/test/Lower/do_concurrent_delayed_locality.f90 b/flang/test/Lower/do_concurrent_delayed_locality.f90
new file mode 100644
index 0000000000000..422c83cffbf23
--- /dev/null
+++ b/flang/test/Lower/do_concurrent_delayed_locality.f90
@@ -0,0 +1,59 @@
+! RUN: %flang_fc1 -emit-hlfir -mmlir --openmp-enable-delayed-privatization-staging=true -o - %s | FileCheck %s
+
+subroutine do_concurrent_with_locality_specs
+ implicit none
+ integer :: i, local_var, local_init_var
+
+ do concurrent (i=1:10) local(local_var) local_init(local_init_var)
+ if (i < 5) then
+ local_var = 42
+ else
+ local_init_var = 84
+ end if
+ end do
+end subroutine
+
+! CHECK-LABEL: fir.local {type = local_init} @_QFdo_concurrent_with_locality_specsElocal_init_var_firstprivate_i32 : i32 copy {
+! CHECK: ^bb0(%[[VAL_0:.*]]: !fir.ref<i32>, %[[VAL_1:.*]]: !fir.ref<i32>):
+! CHECK: %[[VAL_2:.*]] = fir.load %[[VAL_0]] : !fir.ref<i32>
+! CHECK: hlfir.assign %[[VAL_2]] to %[[VAL_1]] : i32, !fir.ref<i32>
+! CHECK: fir.yield(%[[VAL_1]] : !fir.ref<i32>)
+! CHECK: }
+
+! CHECK: fir.local {type = local} @_QFdo_concurrent_with_locality_specsElocal_var_private_i32 : i32
+
+! CHECK-LABEL: func.func @_QPdo_concurrent_with_locality_specs() {
+! CHECK: %[[VAL_0:.*]] = fir.dummy_scope : !fir.dscope
+! CHECK: %[[VAL_1:.*]] = fir.alloca i32 {bindc_name = "i", uniq_name = "_QFdo_concurrent_with_locality_specsEi"}
+! CHECK: %[[VAL_2:.*]]:2 = hlfir.declare %[[VAL_1]] {uniq_name = "_QFdo_concurrent_with_locality_specsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_3:.*]] = fir.alloca i32 {bindc_name = "local_init_var", uniq_name = "_QFdo_concurrent_with_locality_specsElocal_init_var"}
+! CHECK: %[[VAL_4:.*]]:2 = hlfir.declare %[[VAL_3]] {uniq_name = "_QFdo_concurrent_with_locality_specsElocal_init_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_5:.*]] = fir.alloca i32 {bindc_name = "local_var", uniq_name = "_QFdo_concurrent_with_locality_specsElocal_var"}
+! CHECK: %[[VAL_6:.*]]:2 = hlfir.declare %[[VAL_5]] {uniq_name = "_QFdo_concurrent_with_locality_specsElocal_var"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: %[[VAL_7:.*]] = arith.constant 1 : i32
+! CHECK: %[[VAL_8:.*]] = fir.convert %[[VAL_7]] : (i32) -> index
+! CHECK: %[[VAL_9:.*]] = arith.constant 10 : i32
+! CHECK: %[[VAL_10:.*]] = fir.convert %[[VAL_9]] : (i32) -> index
+! CHECK: %[[VAL_11:.*]] = arith.constant 1 : index
+! CHECK: fir.do_concurrent {
+! CHECK: %[[VAL_12:.*]] = fir.alloca i32 {bindc_name = "i"}
+! CHECK: %[[VAL_13:.*]]:2 = hlfir.declare %[[VAL_12]] {uniq_name = "_QFdo_concurrent_with_locality_specsEi"} : (!fir.ref<i32>) -> (!fir.ref<i32>, !fir.ref<i32>)
+! CHECK: fir.do_concurrent.loop (%[[VAL_14:.*]]) = (%[[VAL_8]]) to (%[[VAL_10]]) step (%[[VAL_11]]) local(@_QFdo_concurrent_with_locality_specsElocal_var_private_i32 %[[VAL_6]]#0 -> %[[VAL_15:.*]], @_QF...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/138534
More information about the llvm-branch-commits
mailing list