[Mlir-commits] [mlir] 6d83e3b - [MLIR] Extract buffer alias analysis for reuse
Frederik Gossen
llvmlistbot at llvm.org
Fri Oct 23 06:23:56 PDT 2020
Author: Frederik Gossen
Date: 2020-10-23T13:23:32Z
New Revision: 6d83e3b443358ca735c40b6edcba0c6b095dd4f2
URL: https://github.com/llvm/llvm-project/commit/6d83e3b443358ca735c40b6edcba0c6b095dd4f2
DIFF: https://github.com/llvm/llvm-project/commit/6d83e3b443358ca735c40b6edcba0c6b095dd4f2.diff
LOG: [MLIR] Extract buffer alias analysis for reuse
Extract buffer alias analysis from buffer placement.
Differential Revision: https://reviews.llvm.org/D89902
Added:
mlir/include/mlir/Analysis/BufferAliasAnalysis.h
mlir/lib/Analysis/BufferAliasAnalysis.cpp
Modified:
mlir/include/mlir/Interfaces/ControlFlowInterfaces.td
mlir/include/mlir/Transforms/Bufferize.h
mlir/lib/Analysis/CMakeLists.txt
mlir/lib/Transforms/BufferDeallocation.cpp
Removed:
################################################################################
diff --git a/mlir/include/mlir/Analysis/BufferAliasAnalysis.h b/mlir/include/mlir/Analysis/BufferAliasAnalysis.h
new file mode 100644
index 000000000000..4c9d717671d3
--- /dev/null
+++ b/mlir/include/mlir/Analysis/BufferAliasAnalysis.h
@@ -0,0 +1,59 @@
+//===- BufferAliasAnalysis.h - Buffer alias analysis for MLIR ---*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_ANALYSIS_BUFFERALIASANALYSIS_H
+#define MLIR_ANALYSIS_BUFFERALIASANALYSIS_H
+
+#include "mlir/IR/Operation.h"
+#include "llvm/ADT/SmallPtrSet.h"
+
+namespace mlir {
+
+/// A straight-forward alias analysis which ensures that all aliases of all
+/// values will be determined. This is a requirement for the BufferPlacement
+/// class since you need to determine safe positions to place alloc and
+/// deallocs.
+class BufferAliasAnalysis {
+public:
+ using ValueSetT = SmallPtrSet<Value, 16>;
+ using ValueMapT = llvm::DenseMap<Value, ValueSetT>;
+
+public:
+ /// Constructs a new alias analysis using the op provided.
+ BufferAliasAnalysis(Operation *op);
+
+ /// Find all immediate aliases this value could potentially have.
+ ValueMapT::const_iterator find(Value value) const {
+ return aliases.find(value);
+ }
+
+ /// Returns the begin iterator to iterate over all aliases.
+ ValueMapT::const_iterator begin() const { return aliases.begin(); }
+
+ /// Returns the end iterator that can be used in combination with find.
+ ValueMapT::const_iterator end() const { return aliases.end(); }
+
+ /// Find all immediate and indirect aliases this value could potentially
+ /// have. Note that the resulting set will also contain the value provided as
+ /// it is an alias of itself.
+ ValueSetT resolve(Value value) const;
+
+ /// Removes the given values from all alias sets.
+ void remove(const SmallPtrSetImpl<Value> &aliasValues);
+
+private:
+ /// This function constructs a mapping from values to its immediate aliases.
+ void build(Operation *op);
+
+ /// Maps values to all immediate aliases this value can have.
+ ValueMapT aliases;
+};
+
+} // namespace mlir
+
+#endif // MLIR_ANALYSIS_BUFFERALIASANALYSIS_H
diff --git a/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td b/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td
index 2cd2b9cb8b43..217ab263877f 100644
--- a/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td
+++ b/mlir/include/mlir/Interfaces/ControlFlowInterfaces.td
@@ -140,6 +140,13 @@ def RegionBranchOpInterface : OpInterface<"RegionBranchOpInterface"> {
}];
let extraClassDeclaration = [{
+ /// Convenience helper in case none of the operands is known.
+ void getSuccessorRegions(Optional<unsigned> index,
+ SmallVectorImpl<RegionSuccessor> ®ions) {
+ SmallVector<Attribute, 2> nullAttrs(getOperation()->getNumOperands());
+ getSuccessorRegions(index, nullAttrs, regions);
+ }
+
/// Verify types along control flow edges described by this interface.
static LogicalResult verifyTypes(Operation *op) {
return detail::verifyTypesAlongControlFlowEdges(op);
diff --git a/mlir/include/mlir/Transforms/Bufferize.h b/mlir/include/mlir/Transforms/Bufferize.h
index 5bee53ef01ce..e40c1bccdd9b 100644
--- a/mlir/include/mlir/Transforms/Bufferize.h
+++ b/mlir/include/mlir/Transforms/Bufferize.h
@@ -28,6 +28,7 @@
#ifndef MLIR_TRANSFORMS_BUFFERIZE_H
#define MLIR_TRANSFORMS_BUFFERIZE_H
+#include "mlir/Analysis/BufferAliasAnalysis.h"
#include "mlir/Analysis/Liveness.h"
#include "mlir/Dialect/StandardOps/IR/Ops.h"
#include "mlir/IR/Builders.h"
@@ -288,46 +289,6 @@ populateWithBufferizeOpConversionPatterns(MLIRContext *context,
// clang-format on
}
-/// A straight-forward alias analysis which ensures that all aliases of all
-/// values will be determined. This is a requirement for the BufferPlacement
-/// class since you need to determine safe positions to place alloc and
-/// deallocs.
-class BufferPlacementAliasAnalysis {
-public:
- using ValueSetT = SmallPtrSet<Value, 16>;
- using ValueMapT = llvm::DenseMap<Value, ValueSetT>;
-
-public:
- /// Constructs a new alias analysis using the op provided.
- BufferPlacementAliasAnalysis(Operation *op);
-
- /// Find all immediate aliases this value could potentially have.
- ValueMapT::const_iterator find(Value value) const {
- return aliases.find(value);
- }
-
- /// Returns the begin iterator to iterate over all aliases.
- ValueMapT::const_iterator begin() const { return aliases.begin(); }
-
- /// Returns the end iterator that can be used in combination with find.
- ValueMapT::const_iterator end() const { return aliases.end(); }
-
- /// Find all immediate and indirect aliases this value could potentially
- /// have. Note that the resulting set will also contain the value provided as
- /// it is an alias of itself.
- ValueSetT resolve(Value value) const;
-
- /// Removes the given values from all alias sets.
- void remove(const SmallPtrSetImpl<Value> &aliasValues);
-
-private:
- /// This function constructs a mapping from values to its immediate aliases.
- void build(Operation *op);
-
- /// Maps values to all immediate aliases this value can have.
- ValueMapT aliases;
-};
-
/// A simple analysis that detects allocation operations.
class BufferPlacementAllocs {
public:
@@ -378,7 +339,7 @@ class BufferPlacementAllocs {
/// The base class for all BufferPlacement transformations.
class BufferPlacementTransformationBase {
public:
- using ValueSetT = BufferPlacementAliasAnalysis::ValueSetT;
+ using ValueSetT = BufferAliasAnalysis::ValueSetT;
/// Finds a common dominator for the given value while taking the positions
/// of the values in the value set into account. It supports dominator and
@@ -413,7 +374,7 @@ class BufferPlacementTransformationBase {
protected:
/// Alias information that can be updated during the insertion of copies.
- BufferPlacementAliasAnalysis aliases;
+ BufferAliasAnalysis aliases;
/// Stores all internally managed allocations.
BufferPlacementAllocs allocs;
diff --git a/mlir/lib/Analysis/BufferAliasAnalysis.cpp b/mlir/lib/Analysis/BufferAliasAnalysis.cpp
new file mode 100644
index 000000000000..9d5def4aad23
--- /dev/null
+++ b/mlir/lib/Analysis/BufferAliasAnalysis.cpp
@@ -0,0 +1,115 @@
+//===- BufferAliasAnalysis.cpp - Buffer alias analysis for MLIR -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Analysis/BufferAliasAnalysis.h"
+
+#include "mlir/Interfaces/ControlFlowInterfaces.h"
+#include "mlir/Interfaces/ViewLikeInterface.h"
+#include "llvm/ADT/SetOperations.h"
+
+using namespace mlir;
+
+/// Constructs a new alias analysis using the op provided.
+BufferAliasAnalysis::BufferAliasAnalysis(Operation *op) { build(op); }
+
+/// Find all immediate and indirect aliases this value could potentially
+/// have. Note that the resulting set will also contain the value provided as
+/// it is an alias of itself.
+BufferAliasAnalysis::ValueSetT
+BufferAliasAnalysis::resolve(Value rootValue) const {
+ ValueSetT result;
+ SmallVector<Value, 8> queue;
+ queue.push_back(rootValue);
+ while (!queue.empty()) {
+ Value currentValue = queue.pop_back_val();
+ if (result.insert(currentValue).second) {
+ auto it = aliases.find(currentValue);
+ if (it != aliases.end()) {
+ for (Value aliasValue : it->second)
+ queue.push_back(aliasValue);
+ }
+ }
+ }
+ return result;
+}
+
+/// Removes the given values from all alias sets.
+void BufferAliasAnalysis::remove(const SmallPtrSetImpl<Value> &aliasValues) {
+ for (auto &entry : aliases)
+ llvm::set_subtract(entry.second, aliasValues);
+}
+
+/// This function constructs a mapping from values to its immediate aliases.
+/// It iterates over all blocks, gets their predecessors, determines the
+/// values that will be passed to the corresponding block arguments and
+/// inserts them into the underlying map. Furthermore, it wires successor
+/// regions and branch-like return operations from nested regions.
+void BufferAliasAnalysis::build(Operation *op) {
+ // Registers all aliases of the given values.
+ auto registerAliases = [&](auto values, auto aliases) {
+ for (auto entry : llvm::zip(values, aliases))
+ this->aliases[std::get<0>(entry)].insert(std::get<1>(entry));
+ };
+
+ // Add additional aliases created by view changes to the alias list.
+ op->walk([&](ViewLikeOpInterface viewInterface) {
+ aliases[viewInterface.getViewSource()].insert(
+ viewInterface.getOperation()->getResult(0));
+ });
+
+ // Query all branch interfaces to link block argument aliases.
+ op->walk([&](BranchOpInterface branchInterface) {
+ Block *parentBlock = branchInterface.getOperation()->getBlock();
+ for (auto it = parentBlock->succ_begin(), e = parentBlock->succ_end();
+ it != e; ++it) {
+ // Query the branch op interface to get the successor operands.
+ auto successorOperands =
+ branchInterface.getSuccessorOperands(it.getIndex());
+ if (!successorOperands.hasValue())
+ continue;
+ // Build the actual mapping of values to their immediate aliases.
+ registerAliases(successorOperands.getValue(), (*it)->getArguments());
+ }
+ });
+
+ // Query the RegionBranchOpInterface to find potential successor regions.
+ op->walk([&](RegionBranchOpInterface regionInterface) {
+ // Extract all entry regions and wire all initial entry successor inputs.
+ SmallVector<RegionSuccessor, 2> entrySuccessors;
+ regionInterface.getSuccessorRegions(/*index=*/llvm::None, entrySuccessors);
+ for (RegionSuccessor &entrySuccessor : entrySuccessors) {
+ // Wire the entry region's successor arguments with the initial
+ // successor inputs.
+ assert(entrySuccessor.getSuccessor() &&
+ "Invalid entry region without an attached successor region");
+ registerAliases(regionInterface.getSuccessorEntryOperands(
+ entrySuccessor.getSuccessor()->getRegionNumber()),
+ entrySuccessor.getSuccessorInputs());
+ }
+
+ // Wire flow between regions and from region exits.
+ for (Region ®ion : regionInterface.getOperation()->getRegions()) {
+ // Iterate over all successor region entries that are reachable from the
+ // current region.
+ SmallVector<RegionSuccessor, 2> successorRegions;
+ regionInterface.getSuccessorRegions(region.getRegionNumber(),
+ successorRegions);
+ for (RegionSuccessor &successorRegion : successorRegions) {
+ // Iterate over all immediate terminator operations and wire the
+ // successor inputs with the operands of each terminator.
+ for (Block &block : region) {
+ for (Operation &operation : block) {
+ if (operation.hasTrait<OpTrait::ReturnLike>())
+ registerAliases(operation.getOperands(),
+ successorRegion.getSuccessorInputs());
+ }
+ }
+ }
+ }
+ });
+}
diff --git a/mlir/lib/Analysis/CMakeLists.txt b/mlir/lib/Analysis/CMakeLists.txt
index 4e334c94bd83..632310bc5f13 100644
--- a/mlir/lib/Analysis/CMakeLists.txt
+++ b/mlir/lib/Analysis/CMakeLists.txt
@@ -1,6 +1,7 @@
set(LLVM_OPTIONAL_SOURCES
AffineAnalysis.cpp
AffineStructures.cpp
+ BufferAliasAnalysis.cpp
CallGraph.cpp
Liveness.cpp
LoopAnalysis.cpp
@@ -11,6 +12,7 @@ set(LLVM_OPTIONAL_SOURCES
)
add_mlir_library(MLIRAnalysis
+ BufferAliasAnalysis.cpp
CallGraph.cpp
Liveness.cpp
SliceAnalysis.cpp
@@ -52,4 +54,4 @@ add_mlir_library(MLIRLoopAnalysis
MLIRSCF
)
-add_subdirectory(Presburger)
\ No newline at end of file
+add_subdirectory(Presburger)
diff --git a/mlir/lib/Transforms/BufferDeallocation.cpp b/mlir/lib/Transforms/BufferDeallocation.cpp
index 5461f27ff275..2dfa10000dbb 100644
--- a/mlir/lib/Transforms/BufferDeallocation.cpp
+++ b/mlir/lib/Transforms/BufferDeallocation.cpp
@@ -15,7 +15,7 @@
// liveness analysis does not pay attention to aliases, which can occur due to
// branches (and their associated block arguments) in general. For this purpose,
// BufferDeallocation firstly finds all possible aliases for a single value
-// (using the BufferPlacementAliasAnalysis class). Consider the following
+// (using the BufferAliasAnalysis class). Consider the following
// example:
//
// ^bb0(%arg0):
@@ -31,7 +31,7 @@
// We should place the dealloc for %new_value in exit. However, we have to free
// the buffer in the same block, because it cannot be freed in the post
// dominator. However, this requires a new copy buffer for %arg1 that will
-// contain the actual contents. Using the class BufferPlacementAliasAnalysis, we
+// contain the actual contents. Using the class BufferAliasAnalysis, we
// will find out that %new_value has a potential alias %arg1. In order to find
// the dealloc position we have to find all potential aliases, iterate over
// their uses and find the common post-dominator block (note that additional
@@ -91,112 +91,6 @@ static void getSuccessorRegions(RegionBranchOpInterface regionInterface,
regionInterface.getSuccessorRegions(index, operandAttributes, successors);
}
-//===----------------------------------------------------------------------===//
-// BufferPlacementAliasAnalysis
-//===----------------------------------------------------------------------===//
-
-/// Constructs a new alias analysis using the op provided.
-BufferPlacementAliasAnalysis::BufferPlacementAliasAnalysis(Operation *op) {
- build(op);
-}
-
-/// Find all immediate and indirect aliases this value could potentially
-/// have. Note that the resulting set will also contain the value provided as
-/// it is an alias of itself.
-BufferPlacementAliasAnalysis::ValueSetT
-BufferPlacementAliasAnalysis::resolve(Value value) const {
- ValueSetT result;
-
- /// Recursively determines alias information for the given value. It stores
- /// all newly found potential aliases in the given result set.
- std::function<void(Value)> resolveRecursive = [&](Value current) {
- if (!result.insert(current).second)
- return;
- auto it = aliases.find(current);
- if (it == aliases.end())
- return;
- for (Value alias : it->second)
- resolveRecursive(alias);
- };
-
- resolveRecursive(value);
- return result;
-}
-
-/// Removes the given values from all alias sets.
-void BufferPlacementAliasAnalysis::remove(
- const SmallPtrSetImpl<Value> &aliasValues) {
- for (auto &entry : aliases)
- llvm::set_subtract(entry.second, aliasValues);
-}
-
-/// This function constructs a mapping from values to its immediate aliases.
-/// It iterates over all blocks, gets their predecessors, determines the
-/// values that will be passed to the corresponding block arguments and
-/// inserts them into the underlying map. Furthermore, it wires successor
-/// regions and branch-like return operations from nested regions.
-void BufferPlacementAliasAnalysis::build(Operation *op) {
- // Registers all aliases of the given values.
- auto registerAliases = [&](auto values, auto aliases) {
- for (auto entry : llvm::zip(values, aliases))
- this->aliases[std::get<0>(entry)].insert(std::get<1>(entry));
- };
-
- // Add additional aliases created by view changes to the alias list.
- op->walk([&](ViewLikeOpInterface viewInterface) {
- aliases[viewInterface.getViewSource()].insert(
- viewInterface.getOperation()->getResult(0));
- });
-
- // Query all branch interfaces to link block argument aliases.
- op->walk([&](BranchOpInterface branchInterface) {
- Block *parentBlock = branchInterface.getOperation()->getBlock();
- for (auto it = parentBlock->succ_begin(), e = parentBlock->succ_end();
- it != e; ++it) {
- // Query the branch op interface to get the successor operands.
- auto successorOperands =
- branchInterface.getSuccessorOperands(it.getIndex());
- if (!successorOperands.hasValue())
- continue;
- // Build the actual mapping of values to their immediate aliases.
- registerAliases(successorOperands.getValue(), (*it)->getArguments());
- }
- });
-
- // Query the RegionBranchOpInterface to find potential successor regions.
- op->walk([&](RegionBranchOpInterface regionInterface) {
- // Extract all entry regions and wire all initial entry successor inputs.
- SmallVector<RegionSuccessor, 2> entrySuccessors;
- getSuccessorRegions(regionInterface, /*index=*/llvm::None, entrySuccessors);
- for (RegionSuccessor &entrySuccessor : entrySuccessors) {
- // Wire the entry region's successor arguments with the initial
- // successor inputs.
- assert(entrySuccessor.getSuccessor() &&
- "Invalid entry region without an attached successor region");
- registerAliases(regionInterface.getSuccessorEntryOperands(
- entrySuccessor.getSuccessor()->getRegionNumber()),
- entrySuccessor.getSuccessorInputs());
- }
-
- // Wire flow between regions and from region exits.
- for (Region ®ion : regionInterface.getOperation()->getRegions()) {
- // Iterate over all successor region entries that are reachable from the
- // current region.
- SmallVector<RegionSuccessor, 2> successorRegions;
- getSuccessorRegions(regionInterface, region.getRegionNumber(),
- successorRegions);
- for (RegionSuccessor &successorRegion : successorRegions) {
- // Iterate over all immediate terminator operations and wire the
- // successor inputs with the operands of each terminator.
- walkReturnOperations(®ion, [&](Operation *terminator) {
- registerAliases(terminator->getOperands(),
- successorRegion.getSuccessorInputs());
- });
- }
- }
- });
-}
-
//===----------------------------------------------------------------------===//
// BufferPlacementAllocs
//===----------------------------------------------------------------------===//
More information about the Mlir-commits
mailing list