diff --git a/flang/include/flang/Optimizer/Dialect/FIROps.td b/flang/include/flang/Optimizer/Dialect/FIROps.td index bae52d63fda45..98448d2591b29 100644 --- a/flang/include/flang/Optimizer/Dialect/FIROps.td +++ b/flang/include/flang/Optimizer/Dialect/FIROps.td @@ -80,8 +80,8 @@ def AnyRefOfConstantSizeAggregateType : TypeConstraint< // Memory SSA operations //===----------------------------------------------------------------------===// -def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments, - MemoryEffects<[MemAlloc]>]> { +def fir_AllocaOp : fir_Op<"alloca", + [AttrSizedOperandSegments, DeclareOpInterfaceMethods]> { let summary = "allocate storage for a temporary on the stack given a type"; let description = [{ This primitive operation is used to allocate an object on the stack. A @@ -213,7 +213,7 @@ def fir_AllocaOp : fir_Op<"alloca", [AttrSizedOperandSegments, } def fir_AllocMemOp : fir_Op<"allocmem", - [MemoryEffects<[MemAlloc]>, AttrSizedOperandSegments]> { + [DeclareOpInterfaceMethods, AttrSizedOperandSegments]> { let summary = "allocate storage on the heap for an object of a given type"; let description = [{ diff --git a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp index 73ddd1ff80126..a0972d0fb09e7 100644 --- a/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp +++ b/flang/lib/Optimizer/Analysis/AliasAnalysis.cpp @@ -27,6 +27,29 @@ using namespace mlir; #define DEBUG_TYPE "fir-alias-analysis" +static bool classifyAllocateFromEffects(mlir::Operation *op, + mlir::Value candidate, mlir::Value &v, + mlir::Operation *&defOp, + fir::AliasAnalysis::SourceKind &type) { + if (!op) + return false; + auto interface = llvm::dyn_cast(op); + if (!interface) + return false; + llvm::SmallVector effects; + interface.getEffects(effects); + for (mlir::MemoryEffects::EffectInstance &e : effects) { + if (mlir::isa(e.getEffect()) && + e.getValue() && e.getValue() == candidate) { + v = candidate; + defOp = op; + type = fir::AliasAnalysis::SourceKind::Allocate; + return true; + } + } + return false; +} + //===----------------------------------------------------------------------===// // AliasAnalysis: alias //===----------------------------------------------------------------------===// @@ -535,6 +558,9 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, mlir::Operation *instantiationPoint{nullptr}; while (defOp && !breakFromLoop) { ty = defOp->getResultTypes()[0]; + // Value-scoped allocation detection via effects. + if (classifyAllocateFromEffects(defOp, v, v, defOp, type)) + break; llvm::TypeSwitch(defOp) .Case([&](auto op) { v = op.getVar(); @@ -554,11 +580,6 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, defOp = v.getDefiningOp(); } }) - .Case([&](auto op) { - // Unique memory allocation. - type = SourceKind::Allocate; - breakFromLoop = true; - }) .Case([&](auto op) { // Skip ConvertOp's and track further through the operand. v = op->getOperand(0); @@ -628,16 +649,17 @@ AliasAnalysis::Source AliasAnalysis::getSource(mlir::Value v, type = SourceKind::Global; } else { auto def = llvm::cast(boxSrc.origin.u); - // TODO: Add support to fir.allocmem - if (auto allocOp = def.template getDefiningOp()) { - v = def; - defOp = v.getDefiningOp(); - type = SourceKind::Allocate; - } else if (isDummyArgument(def)) { - defOp = nullptr; - v = def; - } else { - type = SourceKind::Indirect; + bool classified = false; + if (auto defDefOp = def.getDefiningOp()) + classified = + classifyAllocateFromEffects(defDefOp, def, v, defOp, type); + if (!classified) { + if (isDummyArgument(def)) { + defOp = nullptr; + v = def; + } else { + type = SourceKind::Indirect; + } } } breakFromLoop = true; diff --git a/flang/lib/Optimizer/Dialect/FIROps.cpp b/flang/lib/Optimizer/Dialect/FIROps.cpp index 4f97acaa88b7a..9d182a699c634 100644 --- a/flang/lib/Optimizer/Dialect/FIROps.cpp +++ b/flang/lib/Optimizer/Dialect/FIROps.cpp @@ -285,6 +285,21 @@ llvm::LogicalResult fir::AllocaOp::verify() { return mlir::success(); } +void fir::AllocaOp::getEffects( + llvm::SmallVectorImpl< + mlir::SideEffects::EffectInstance> + &effects) { + // Value-scoped Allocate for AA. + effects.emplace_back( + mlir::MemoryEffects::Allocate::get(), + mlir::cast(getOperation()->getResult(0)), + mlir::SideEffects::AutomaticAllocationScopeResource::get()); + // Preserve previous behavior: op-scoped Allocate for passes relying on it. + effects.emplace_back( + mlir::MemoryEffects::Allocate::get(), + mlir::SideEffects::AutomaticAllocationScopeResource::get()); +} + bool fir::AllocaOp::ownsNestedAlloca(mlir::Operation *op) { return op->hasTrait() || op->hasTrait() || @@ -384,6 +399,19 @@ llvm::LogicalResult fir::AllocMemOp::verify() { return mlir::success(); } +void fir::AllocMemOp::getEffects( + llvm::SmallVectorImpl< + mlir::SideEffects::EffectInstance> + &effects) { + // Value-scoped Allocate for AA. + effects.emplace_back(mlir::MemoryEffects::Allocate::get(), + mlir::cast(getOperation()->getResult(0)), + mlir::SideEffects::DefaultResource::get()); + // Preserve previous behavior: op-scoped Allocate for passes relying on it. + effects.emplace_back(mlir::MemoryEffects::Allocate::get(), + mlir::SideEffects::DefaultResource::get()); +} + //===----------------------------------------------------------------------===// // ArrayCoorOp //===----------------------------------------------------------------------===//