[flang-commits] [flang] [flang][HLFIR] Relax InlineElementals to support more than two users (PR #186916)
Tom Eccles via flang-commits
flang-commits at lists.llvm.org
Mon Jun 15 08:44:15 PDT 2026
================
@@ -31,29 +33,291 @@ namespace hlfir {
#include "flang/Optimizer/HLFIR/Passes.h.inc"
} // namespace hlfir
+/// Collects all memory values (buffers/references) that the elemental body
+/// reads from. Use MemoryEffectOpInterface for a fail-safe implementation.
+static mlir::LogicalResult
+getReadDependencies(hlfir::ElementalOp elemental,
+ llvm::SmallVectorImpl<mlir::Value> &deps) {
+ llvm::SmallPtrSet<mlir::Value, 8> seen;
+
+ mlir::WalkResult walkResult =
+ elemental.getRegion().walk([&](mlir::Operation *op) {
+ if (mlir::isMemoryEffectFree(op))
+ return mlir::WalkResult::advance();
+
+ if (auto memInterface =
+ mlir::dyn_cast<mlir::MemoryEffectOpInterface>(op)) {
+ llvm::SmallVector<mlir::MemoryEffects::EffectInstance, 4> effects;
+ memInterface.getEffects(effects);
+ bool hasUnspecifiedRead = false;
+
+ for (const auto &effect : effects) {
+ if (mlir::isa<mlir::MemoryEffects::Read>(effect.getEffect())) {
+ if (mlir::Value val = effect.getValue()) {
+ if (seen.insert(val).second)
+ deps.push_back(val);
+ } else {
+ // Read effect on an unspecified resource (e.g., global state).
+ hasUnspecifiedRead = true;
+ }
+ }
+ }
+
+ // If the op has a read effect but the specific value is unknown,
+ // conservatively capture all potential reference operands.
+ if (hasUnspecifiedRead) {
+ // If there are no operands to track, we can't reason about
+ // the dependency.
+ if (op->getNumOperands() == 0)
+ return mlir::WalkResult::interrupt();
+ for (mlir::Value operand : op->getOperands()) {
+ if (operand.getParentRegion() != &elemental.getRegion()) {
+ if (mlir::isa<fir::ReferenceType, fir::PointerType,
+ fir::HeapType, fir::BoxType>(operand.getType())) {
+ if (seen.insert(operand).second)
+ deps.push_back(operand);
+ }
+ }
+ }
+ }
+ return mlir::WalkResult::advance();
+ }
+
+ // Fail-safe: For operations without the interface, conservatively
+ // assume we cannot reason about the dependency.
+ return mlir::WalkResult::interrupt();
+ });
+
+ return mlir::success(!walkResult.wasInterrupted());
+}
+
+/// Checks if an operation 'op' potentially modifies any memory location that
+/// the elemental reads from (captured in 'deps').
+static bool isConflictingWrite(mlir::Operation *op,
+ const llvm::SmallVectorImpl<mlir::Value> &deps,
+ mlir::AliasAnalysis &aa) {
+ // Use walk to handle nested regions (fir.if, fir.do_loop, etc.) recursively.
+ mlir::WalkResult result = op->walk([&](mlir::Operation *nestedOp) {
+ // Operations explicitly marked as having no memory effects are safe.
+ if (mlir::isMemoryEffectFree(nestedOp))
+ return mlir::WalkResult::advance();
+
+ // Explicitly allow safe HLFIR/FIR metadata/lifetime operations.
+ if (mlir::isa<hlfir::DeclareOp, hlfir::AssociateOp, hlfir::EndAssociateOp,
+ fir::AllocaOp, hlfir::NoReassocOp>(nestedOp))
+ return mlir::WalkResult::advance();
+
+ // Check for explicit memory effects via the interface.
+ if (auto memInterface =
+ mlir::dyn_cast<mlir::MemoryEffectOpInterface>(nestedOp)) {
+ llvm::SmallVector<mlir::MemoryEffects::EffectInstance, 4> effects;
+ memInterface.getEffects(effects);
+
+ for (const auto &effect : effects) {
+ // Analyze effects that modify memory or release resources.
+ if (mlir::isa<mlir::MemoryEffects::Write, mlir::MemoryEffects::Free>(
+ effect.getEffect())) {
+ mlir::Value accessedValue = effect.getValue();
+ // Fail-safe: Assuming conflict for Unknown resource (e.g. external
+ // call).
+ if (!accessedValue)
+ return mlir::WalkResult::interrupt();
+
+ // Perform alias analysis against all read dependencies.
+ for (mlir::Value dep : deps) {
+ if (!aa.alias(accessedValue, dep).isNo())
+ return mlir::WalkResult::interrupt();
+ }
+ }
+ }
+ } else if (nestedOp->getNumRegions() == 0) {
+ // Conservative Fallback: If an operation doesn't have interface and
+ // has no regions (e.g. a fir.call), assume it can modify anything.
+ return mlir::WalkResult::interrupt();
+ }
+
+ return mlir::WalkResult::advance();
+ });
+
+ // Conflict found as walk interrupted.
+ return result.wasInterrupted();
+}
+
+bool isSafeToInline(hlfir::ElementalOp producer, hlfir::ApplyOp applySite,
----------------
tblah wrote:
nit: `static`
https://github.com/llvm/llvm-project/pull/186916
More information about the flang-commits
mailing list