The patch adds operations to `BlockAndValueMapping` and renames it to `IRMapping`. When operations are cloned, old operations are mapped to the cloned operations. This allows mapping from an operation to a cloned operation. Example:
```
Operation *opWithRegion = ...
Operation *opInsideRegion = &opWithRegion->front().front();
IRMapping map
Operation *newOpWithRegion = opWithRegion->clone(map);
Operation *newOpInsideRegion = map.lookupOrNull(opInsideRegion);
```
Migration instructions:
All includes to `mlir/IR/BlockAndValueMapping.h` should be replaced with `mlir/IR/IRMapping.h`. All uses of `BlockAndValueMapping` need to be renamed to `IRMapping`.
Reviewed By: rriddle, mehdi_amini
Differential Revision: https://reviews.llvm.org/D139665
#include "mlir/IR/Dialect.h"
namespace mlir {
-class BlockAndValueMapping;
+class IRMapping;
} // namespace mlir
namespace fir {
/// Support for inlining on FIR.
bool canLegallyInline(mlir::Operation *op, mlir::Region *reg, bool,
- mlir::BlockAndValueMapping &map);
+ mlir::IRMapping &map);
bool canLegallyInline(mlir::Operation *, mlir::Operation *, bool);
} // namespace fir
#include <memory>
namespace mlir {
-class BlockAndValueMapping;
+class IRMapping;
class GreedyRewriteConfig;
class Operation;
class Pass;
#include "flang/Optimizer/Builder/MutableBox.h"
#include "flang/Optimizer/Builder/Todo.h"
#include "flang/Optimizer/HLFIR/HLFIROps.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include <optional>
// Return explicit extents. If the base is a fir.box, this won't read it to
// hlfir.elemental region is a SizedRegion<1>.
assert(elemental.getRegion().hasOneBlock() &&
"expect elemental region to have one block");
- mlir::BlockAndValueMapping mapper;
+ mlir::IRMapping mapper;
mapper.map(elemental.getIndices(), oneBasedIndices);
mlir::Operation *newOp;
for (auto &op : elemental.getRegion().back().getOperations())
/// This hook checks to see if the operation `op` is legal to inline into the
/// given region `reg`.
bool isLegalToInline(mlir::Operation *op, mlir::Region *reg,
- bool wouldBeCloned,
- mlir::BlockAndValueMapping &map) const final {
+ bool wouldBeCloned, mlir::IRMapping &map) const final {
return fir::canLegallyInline(op, reg, wouldBeCloned, map);
}
/// Should we inline the callable `op` into region `reg`?
bool fir::canLegallyInline(mlir::Operation *, mlir::Region *, bool,
- mlir::BlockAndValueMapping &) {
+ mlir::IRMapping &) {
return aggressivelyInline;
}
/// This can be used to examine what values will replace entry arguments into
/// the 'src' region, for example.
virtual bool isLegalToInline(Region *dest, Region *src,
- BlockAndValueMapping &valueMapping) const {
+ IRMapping &valueMapping) const {
return false;
}
};
struct AffineInlinerInterface : public DialectInlinerInterface {
/// Affine structures have specific inlining constraints.
bool isLegalToInline(Region *dest, Region *src,
- BlockAndValueMapping &valueMapping) const final {
+ IRMapping &valueMapping) const final {
...
}
};
/// with default implementations that call the hook on the interface for a
/// given dialect.
virtual bool isLegalToInline(Region *dest, Region *src,
- BlockAndValueMapping &valueMapping) const {
+ IRMapping &valueMapping) const {
auto *handler = getInterfaceFor(dest->getContainingOp());
return handler ? handler->isLegalToInline(dest, src, valueMapping) : false;
}
cloning methods are defined on `Operation` like this:
```C++
-Operation *clone(BlockAndValueMapping &mapper, MLIRContext *context) const;
+Operation *clone(IRMapping &mapper, MLIRContext *context) const;
Operation *clone(MLIRContext *context) const;
```
1. Types like `OpPointer` and `ConstOpPointer` that exist solely to propagate
const can be entirely removed from the codebase.
1. We can close bugs complaining about const incorrectness in the IR.
-
/// given region. For Toy this hook can simply return true, as all Toy
/// operations are inlinable.
bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ IRMapping &) const final {
return true;
}
/// region. The regions here are the bodies of the callable functions. For
/// Toy, any function can be inlined, so we simply return true.
bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
- BlockAndValueMapping &valueMapping) const final {
+ IRMapping &valueMapping) const final {
return true;
}
}
/// All operations within toy can be inlined.
- bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
return true;
}
// All functions within toy can be inlined.
- bool isLegalToInline(Region *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Region *, Region *, bool, IRMapping &) const final {
return true;
}
}
/// All operations within toy can be inlined.
- bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
return true;
}
// All functions within toy can be inlined.
- bool isLegalToInline(Region *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Region *, Region *, bool, IRMapping &) const final {
return true;
}
}
/// All operations within toy can be inlined.
- bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
return true;
}
// All functions within toy can be inlined.
- bool isLegalToInline(Region *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Region *, Region *, bool, IRMapping &) const final {
return true;
}
}
/// All operations within toy can be inlined.
- bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
return true;
}
// All functions within toy can be inlined.
- bool isLegalToInline(Region *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Region *, Region *, bool, IRMapping &) const final {
return true;
}
/// included in the new function. Replaces references to cloned sub-values
/// with the corresponding value that is copied, and adds those mappings to
/// the mapper.
- FuncOp clone(BlockAndValueMapping &mapper);
+ FuncOp clone(IRMapping &mapper);
FuncOp clone();
/// Clone the internal blocks and attributes from this function into dest.
/// Any cloned blocks are appended to the back of dest. This function
/// asserts that the attributes of the current function and dest are
/// compatible.
- void cloneInto(FuncOp dest, BlockAndValueMapping &mapper);
+ void cloneInto(FuncOp dest, IRMapping &mapper);
//===------------------------------------------------------------------===//
// CallableOpInterface
#include "mlir/Dialect/Utils/StructuredOpsUtils.h"
#include "mlir/IR/AffineMap.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/ImplicitLocOpBuilder.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/Interfaces/DestinationStyleOpInterface.h"
+++ /dev/null
-//===- BlockAndValueMapping.h -----------------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a utility class for maintaining a mapping for multiple
-// value types.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef MLIR_IR_BLOCKANDVALUEMAPPING_H
-#define MLIR_IR_BLOCKANDVALUEMAPPING_H
-
-#include "mlir/IR/Block.h"
-
-namespace mlir {
-// This is a utility class for mapping one set of values to another. New
-// mappings can be inserted via 'map'. Existing mappings can be
-// found via the 'lookup*' functions. There are two variants that differ only in
-// return value when an existing is not found for the provided key.
-// 'lookupOrNull' returns nullptr where as 'lookupOrDefault' will return the
-// lookup key.
-class BlockAndValueMapping {
-public:
- /// Inserts a new mapping for 'from' to 'to'. If there is an existing mapping,
- /// it is overwritten.
- void map(Block *from, Block *to) { blockMap[from] = to; }
- void map(Value from, Value to) { valueMap[from] = to; }
-
- template <
- typename S, typename T,
- std::enable_if_t<!std::is_assignable<Value, S>::value &&
- !std::is_assignable<Block *, S>::value> * = nullptr>
- void map(S &&from, T &&to) {
- for (auto pair : llvm::zip(from, to))
- map(std::get<0>(pair), std::get<1>(pair));
- }
-
- /// Erases a mapping for 'from'.
- void erase(Block *from) { blockMap.erase(from); }
- void erase(Value from) { valueMap.erase(from); }
-
- /// Checks to see if a mapping for 'from' exists.
- bool contains(Block *from) const { return blockMap.count(from); }
- bool contains(Value from) const { return valueMap.count(from); }
-
- /// Lookup a mapped value within the map. If a mapping for the provided value
- /// does not exist then return nullptr.
- Block *lookupOrNull(Block *from) const {
- return lookupOrValue(from, (Block *)nullptr);
- }
- Value lookupOrNull(Value from) const { return lookupOrValue(from, Value()); }
-
- /// Lookup a mapped value within the map. If a mapping for the provided value
- /// does not exist then return the provided value.
- Block *lookupOrDefault(Block *from) const {
- return lookupOrValue(from, from);
- }
- Value lookupOrDefault(Value from) const { return lookupOrValue(from, from); }
-
- /// Lookup a mapped value within the map. This asserts the provided value
- /// exists within the map.
- Block *lookup(Block *from) const { return lookupImpl(from); }
- Value lookup(Value from) const { return lookupImpl(from); }
-
- /// Clears all mappings held by the mapper.
- void clear() { valueMap.clear(); }
-
- /// Return the held value mapping.
- const DenseMap<Value, Value> &getValueMap() const { return valueMap; }
-
- /// Return the held block mapping.
- const DenseMap<Block *, Block *> &getBlockMap() const { return blockMap; }
-
-private:
- template<typename T>
- T lookupImpl(T from) const {
- T result = lookupOrNull(from);
- assert(result && "expected 'from' to be contained within the map");
- return result;
- }
-
- /// Utility lookupOrValue that looks up an existing key or returns the
- /// provided value.
- Block *lookupOrValue(Block *from, Block *value) const {
- auto it = blockMap.find(from);
- return it != blockMap.end() ? it->second : value;
- }
- Value lookupOrValue(Value from, Value value) const {
- auto it = valueMap.find(from);
- return it != valueMap.end() ? it->second : value;
- }
-
- DenseMap<Value, Value> valueMap;
- DenseMap<Block *, Block *> blockMap;
-};
-
-} // namespace mlir
-
-#endif // MLIR_IR_BLOCKANDVALUEMAPPING_H
namespace mlir {
class AffineExpr;
-class BlockAndValueMapping;
+class IRMapping;
class UnknownLoc;
class FileLineColLoc;
class Type;
/// ( leaving them alone if no entry is present). Replaces references to
/// cloned sub-operations to the corresponding operation that is copied,
/// and adds those mappings to the map.
- Operation *clone(Operation &op, BlockAndValueMapping &mapper);
+ Operation *clone(Operation &op, IRMapping &mapper);
Operation *clone(Operation &op);
/// Creates a deep copy of this operation but keep the operation regions
/// empty. Operands are remapped using `mapper` (if present), and `mapper` is
/// updated to contain the results.
- Operation *cloneWithoutRegions(Operation &op, BlockAndValueMapping &mapper) {
+ Operation *cloneWithoutRegions(Operation &op, IRMapping &mapper) {
return insert(op.cloneWithoutRegions(mapper));
}
Operation *cloneWithoutRegions(Operation &op) {
--- /dev/null
+//===- IRMapping.h ----------------------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a utility class for maintaining a mapping of SSA values,
+// blocks, and operations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_IR_IRMAPPING_H
+#define MLIR_IR_IRMAPPING_H
+
+#include "mlir/IR/Block.h"
+
+namespace mlir {
+/// This is a utility class for mapping one set of IR entities to another. New
+/// mappings can be inserted via 'map'. Existing mappings can be
+/// found via the 'lookup*' functions. There are three variants that differ only
+/// in return value when an existing is not found for the provided key: SSA
+/// values, blocks, and operations. 'lookupOrNull' returns nullptr where as
+/// 'lookupOrDefault' will return the lookup key.
+class IRMapping {
+public:
+ /// Inserts a new mapping for 'from' to 'to'. If there is an existing mapping,
+ /// it is overwritten.
+ void map(Value from, Value to) { valueMap[from] = to; }
+ void map(Block *from, Block *to) { blockMap[from] = to; }
+ void map(Operation *from, Operation *to) { operationMap[from] = to; }
+
+ template <typename S, typename T,
+ std::enable_if_t<!std::is_assignable_v<Value, S> &&
+ !std::is_assignable_v<Block *, S> &&
+ !std::is_assignable_v<Operation *, S>> * = nullptr>
+ void map(S &&from, T &&to) {
+ for (auto [fromValue, toValue] : llvm::zip(from, to))
+ map(fromValue, toValue);
+ }
+
+ /// Erases a mapping for 'from'.
+ template <typename T>
+ void erase(T from) {
+ getMap<T>().erase(from);
+ }
+
+ /// Checks to see if a mapping for 'from' exists.
+ template <typename T>
+ bool contains(T from) const {
+ return getMap<T>().count(from);
+ }
+
+ /// Lookup a mapped value within the map. If a mapping for the provided value
+ /// does not exist then return nullptr.
+ template <typename T>
+ auto lookupOrNull(T from) const {
+ return lookupOrValue(from, T(nullptr));
+ }
+
+ /// Lookup a mapped value within the map. If a mapping for the provided value
+ /// does not exist then return the provided value.
+ template <typename T>
+ auto lookupOrDefault(T from) const {
+ return lookupOrValue(from, from);
+ }
+
+ /// Lookup a mapped value within the map. This asserts the provided value
+ /// exists within the map.
+ template <typename T>
+ auto lookup(T from) const {
+ auto result = lookupOrNull(from);
+ assert(result && "expected 'from' to be contained within the map");
+ return result;
+ }
+
+ /// Clears all mappings held by the mapper.
+ void clear() { valueMap.clear(); }
+
+ /// Return the held value mapping.
+ const DenseMap<Value, Value> &getValueMap() const { return valueMap; }
+
+ /// Return the held block mapping.
+ const DenseMap<Block *, Block *> &getBlockMap() const { return blockMap; }
+
+ /// Return the held operation mapping.
+ const DenseMap<Operation *, Operation *> &getOperationMap() const {
+ return operationMap;
+ }
+
+private:
+ /// Return the map for the given value type.
+ template <typename T>
+ auto &getMap() const {
+ if constexpr (std::is_convertible_v<T, Value>)
+ return const_cast<DenseMap<Value, Value> &>(valueMap);
+ else if constexpr (std::is_convertible_v<T, Block *>)
+ return const_cast<DenseMap<Block *, Block *> &>(blockMap);
+ else
+ return const_cast<DenseMap<Operation *, Operation *> &>(operationMap);
+ }
+
+ /// Utility lookupOrValue that looks up an existing key or returns the
+ /// provided value.
+ template <typename T>
+ auto lookupOrValue(T from, T value) const {
+ auto &map = getMap<T>();
+ auto it = map.find(from);
+ return it != map.end() ? it->second : value;
+ }
+
+ DenseMap<Value, Value> valueMap;
+ DenseMap<Block *, Block *> blockMap;
+ DenseMap<Operation *, Operation *> operationMap;
+};
+
+} // namespace mlir
+
+#endif // MLIR_IR_IRMAPPING_H
/// as top level function operations, is therefore always safe. Using the
/// mapper, it is possible to avoid adding uses to outside operands by
/// remapping them to 'Value's owned by the caller thread.
- Operation *clone(BlockAndValueMapping &mapper,
+ Operation *clone(IRMapping &mapper,
CloneOptions options = CloneOptions::all());
Operation *clone(CloneOptions options = CloneOptions::all());
/// original one, but they will be left empty.
/// Operands are remapped using `mapper` (if present), and `mapper` is updated
/// to contain the results.
- Operation *cloneWithoutRegions(BlockAndValueMapping &mapper);
+ Operation *cloneWithoutRegions(IRMapping &mapper);
/// Create a partial copy of this operation without traversing into attached
/// regions. The new operation will have the same number of regions as the
/// responsible for creating or updating the operation transferring flow of
/// control to the region and passing it the correct block arguments.
virtual void cloneRegionBefore(Region ®ion, Region &parent,
- Region::iterator before,
- BlockAndValueMapping &mapping);
+ Region::iterator before, IRMapping &mapping);
void cloneRegionBefore(Region ®ion, Region &parent,
Region::iterator before);
void cloneRegionBefore(Region ®ion, Block *before);
class TypeRange;
template <typename ValueRangeT>
class ValueTypeRange;
-class BlockAndValueMapping;
+class IRMapping;
/// This class contains a list of basic blocks and a link to the parent
/// operation it is attached to.
/// process of cloning, no new uses of 'Value's from outside the region are
/// created. Using the mapper, it is possible to avoid adding uses to outside
/// operands by remapping them to 'Value's owned by the caller thread.
- void cloneInto(Region *dest, BlockAndValueMapping &mapper);
+ void cloneInto(Region *dest, IRMapping &mapper);
/// Clone this region into 'dest' before the given position in 'dest'.
- void cloneInto(Region *dest, Region::iterator destPos,
- BlockAndValueMapping &mapper);
+ void cloneInto(Region *dest, Region::iterator destPos, IRMapping &mapper);
/// Takes body of another region (that region will have no body after this
/// operation completes). The current body of this region is cleared.
#ifndef MLIR_INTERFACES_DESTINATIONSTYLEOPINTERFACE_H_
#define MLIR_INTERFACES_DESTINATIONSTYLEOPINTERFACE_H_
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/Value.h"
#include "llvm/ADT/SmallVector.h"
/// yet, i.e. it must be within an operation that is either in the process of
/// conversion, or has not yet been converted.
void cloneRegionBefore(Region ®ion, Region &parent,
- Region::iterator before,
- BlockAndValueMapping &mapping) override;
+ Region::iterator before, IRMapping &mapping) override;
using PatternRewriter::cloneRegionBefore;
/// PatternRewriter hook for inserting a new operation.
namespace mlir {
class Block;
-class BlockAndValueMapping;
+class IRMapping;
class CallableOpInterface;
class CallOpInterface;
class OpBuilder;
/// used to examine what values will replace entry arguments into the 'src'
/// region for example.
virtual bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
- BlockAndValueMapping &valueMapping) const {
+ IRMapping &valueMapping) const {
return false;
}
/// remapped values from within the 'src' region. This can be used to examine
/// what values may potentially replace the operands to 'op'.
virtual bool isLegalToInline(Operation *op, Region *dest, bool wouldBeCloned,
- BlockAndValueMapping &valueMapping) const {
+ IRMapping &valueMapping) const {
return false;
}
virtual bool isLegalToInline(Operation *call, Operation *callable,
bool wouldBeCloned) const;
virtual bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
- BlockAndValueMapping &valueMapping) const;
+ IRMapping &valueMapping) const;
virtual bool isLegalToInline(Operation *op, Region *dest, bool wouldBeCloned,
- BlockAndValueMapping &valueMapping) const;
+ IRMapping &valueMapping) const;
virtual bool shouldAnalyzeRecursively(Operation *op) const;
//===--------------------------------------------------------------------===//
/// information. 'shouldCloneInlinedRegion' corresponds to whether the source
/// region should be cloned into the 'inlinePoint' or spliced directly.
LogicalResult inlineRegion(InlinerInterface &interface, Region *src,
- Operation *inlinePoint, BlockAndValueMapping &mapper,
+ Operation *inlinePoint, IRMapping &mapper,
ValueRange resultsToReplace,
TypeRange regionResultTypes,
Optional<Location> inlineLoc = std::nullopt,
bool shouldCloneInlinedRegion = true);
LogicalResult inlineRegion(InlinerInterface &interface, Region *src,
Block *inlineBlock, Block::iterator inlinePoint,
- BlockAndValueMapping &mapper,
- ValueRange resultsToReplace,
+ IRMapping &mapper, ValueRange resultsToReplace,
TypeRange regionResultTypes,
Optional<Location> inlineLoc = std::nullopt,
bool shouldCloneInlinedRegion = true);
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/Dialect/Vector/IR/VectorOps.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/IntegerSet.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/Transforms/DialectConversion.h"
#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
#include "mlir/Dialect/Utils/StaticValueUtils.h"
#include "mlir/IR/Attributes.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributeInterfaces.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/IR/TypeUtilities.h"
#include "mlir/Support/LogicalResult.h"
#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/IR/AffineMap.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/Pass/Pass.h"
#include "llvm/ADT/SmallBitVector.h"
#include <optional>
// Clone the GenericAtomicRMWOp region and extract the result.
auto loopArgument = loopBlock->getArgument(0);
- BlockAndValueMapping mapping;
+ IRMapping mapping;
mapping.map(atomicOp.getCurrentValue(), loopArgument);
Block &entryBlock = atomicOp.body().front();
for (auto &nestedOp : entryBlock.without_terminator()) {
void moveOpsRange(ValueRange oldResult, ValueRange newResult,
Block::iterator start, Block::iterator end,
ConversionPatternRewriter &rewriter) const {
- BlockAndValueMapping mapping;
+ IRMapping mapping;
mapping.map(oldResult, newResult);
SmallVector<Operation *, 2> opsToErase;
for (auto it = start; it != end; ++it) {
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/MLIRContext.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Transforms/DialectConversion.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/IR/AffineExpr.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"
/// worklist. This signals the processor of the worklist to pop the rewriter
/// one scope-level up.
static LogicalResult processParallelLoop(
- ParallelOp parallelOp, gpu::LaunchOp launchOp,
- BlockAndValueMapping &cloningMap, SmallVectorImpl<Operation *> &worklist,
+ ParallelOp parallelOp, gpu::LaunchOp launchOp, IRMapping &cloningMap,
+ SmallVectorImpl<Operation *> &worklist,
DenseMap<gpu::Processor, Value> &bounds, PatternRewriter &rewriter) {
// TODO: Verify that this is a valid GPU mapping.
// processor ids: 0-2 block [x/y/z], 3-5 -> thread [x/y/z], 6-> sequential
rewriter.create<gpu::TerminatorOp>(loc);
rewriter.setInsertionPointToStart(&launchOp.getBody().front());
- BlockAndValueMapping cloningMap;
+ IRMapping cloningMap;
llvm::DenseMap<gpu::Processor, Value> launchBounds;
SmallVector<Operation *, 16> worklist;
if (failed(processParallelLoop(parallelOp, launchOp, cloningMap, worklist,
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/Dialect/Shape/IR/Shape.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/ImplicitLocOpBuilder.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"
SmallVector<Value, 2> mappedValues{iv, extent};
mappedValues.append(args.begin(), args.end());
- BlockAndValueMapping mapping;
+ IRMapping mapping;
Block *reduceBody = op.getBody();
mapping.map(reduceBody->getArguments(), mappedValues);
for (auto &nested : reduceBody->without_terminator())
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/Dialect/Tosa/IR/TosaOps.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "mlir/Dialect/Affine/IR/AffineValueMap.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/IR/AffineExprVisitor.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/IntegerSet.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/OpDefinition.h"
/// dimension or symbol.
static bool
remainsLegalAfterInline(Value value, Region *src, Region *dest,
- const BlockAndValueMapping &mapping,
+ const IRMapping &mapping,
function_ref<bool(Value, Region *)> legalityCheck) {
// If the value is a valid dimension for any other reason than being
// a top-level value, it will remain valid: constants get inlined
/// remain so if their respective users are inlined into `dest`.
static bool
remainsLegalAfterInline(ValueRange values, Region *src, Region *dest,
- const BlockAndValueMapping &mapping,
+ const IRMapping &mapping,
function_ref<bool(Value, Region *)> legalityCheck) {
return llvm::all_of(values, [&](Value v) {
return remainsLegalAfterInline(v, src, dest, mapping, legalityCheck);
/// from `src` to `dest`.
template <typename OpTy>
static bool remainsLegalAfterInline(OpTy op, Region *src, Region *dest,
- const BlockAndValueMapping &mapping) {
+ const IRMapping &mapping) {
static_assert(llvm::is_one_of<OpTy, AffineReadOpInterface,
AffineWriteOpInterface>::value,
"only ops with affine read/write interface are supported");
// Use "unused attribute" marker to silence clang-tidy warning stemming from
// the inability to see through "llvm::TypeSwitch".
template <>
-bool LLVM_ATTRIBUTE_UNUSED
-remainsLegalAfterInline(AffineApplyOp op, Region *src, Region *dest,
- const BlockAndValueMapping &mapping) {
+bool LLVM_ATTRIBUTE_UNUSED remainsLegalAfterInline(AffineApplyOp op,
+ Region *src, Region *dest,
+ const IRMapping &mapping) {
// If it's a valid dimension, we need to check that it remains so.
if (isValidDim(op.getResult(), src))
return remainsLegalAfterInline(
/// 'wouldBeCloned' is set if the region is cloned into its new location
/// rather than moved, indicating there may be other users.
bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
- BlockAndValueMapping &valueMapping) const final {
+ IRMapping &valueMapping) const final {
// We can inline into affine loops and conditionals if this doesn't break
// affine value categorization rules.
Operation *destOp = dest->getParentOp();
/// Returns true if the given operation 'op', that is registered to this
/// dialect, can be inlined into the given region, false otherwise.
bool isLegalToInline(Operation *op, Region *region, bool wouldBeCloned,
- BlockAndValueMapping &valueMapping) const final {
+ IRMapping &valueMapping) const final {
// Always allow inlining affine operations into a region that is marked as
// affine scope, or into affine loops and conditionals. There are some edge
// cases when inlining *into* affine structures, but that is handled in the
#include "mlir/Dialect/Affine/LoopUtils.h"
#include "mlir/Dialect/Affine/Utils.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/IRMapping.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/IRMapping.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/CommandLine.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/Vector/IR/VectorOps.h"
#include "mlir/Dialect/Vector/Utils/VectorUtils.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Support/LLVM.h"
#include "llvm/ADT/STLExtras.h"
// Maps input scalar operations to their vector counterparts.
DenseMap<Operation *, Operation *> opVectorReplacement;
// Maps input scalar values to their vector counterparts.
- BlockAndValueMapping valueVectorReplacement;
+ IRMapping valueVectorReplacement;
// Maps input scalar values to their new scalar counterparts in the vector
// loop nest.
- BlockAndValueMapping valueScalarReplacement;
+ IRMapping valueScalarReplacement;
// Maps results of reduction loops to their new scalar counterparts.
DenseMap<Value, Value> loopResultScalarReplacement;
#include "mlir/Dialect/Affine/Analysis/Utils.h"
#include "mlir/Dialect/Affine/IR/AffineOps.h"
#include "mlir/Dialect/Affine/LoopUtils.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Operation.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
bool isInnermostSiblingInsertion) {
// Clone 'srcForOp' into 'dstForOp' at 'srcSlice->insertPoint'.
OpBuilder b(srcSlice.insertPoint->getBlock(), srcSlice.insertPoint);
- BlockAndValueMapping mapper;
+ IRMapping mapper;
b.clone(*srcForOp, mapper);
// Update 'sliceLoopNest' upper and lower bounds from computed 'srcSlice'.
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/IntegerSet.h"
#include "mlir/Support/MathExtras.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
auto loopChunkIV = loopChunk.getInductionVar();
auto srcIV = srcForOp.getInductionVar();
- BlockAndValueMapping operandMap;
+ IRMapping operandMap;
auto bodyBuilder = OpBuilder::atBlockTerminator(loopChunk.getBody());
for (const auto &it : llvm::drop_begin(opGroupQueue, offset)) {
SmallVector<Value, 4> lastYielded(yieldedValues);
for (unsigned i = 1; i < unrollFactor; i++) {
- BlockAndValueMapping operandMap;
+ IRMapping operandMap;
// Prepare operand map.
operandMap.map(iterArgs, lastYielded);
// `operandMaps[i - 1]` carries old->new operand mapping for the ith unrolled
// iteration. There are (`unrollJamFactor` - 1) iterations.
- SmallVector<BlockAndValueMapping, 4> operandMaps(unrollJamFactor - 1);
+ SmallVector<IRMapping, 4> operandMaps(unrollJamFactor - 1);
// For any loop with iter_args, replace it with a new loop that has
// `unrollJamFactor` copies of its iterOperands, iter_args and yield
}
// Add the body for the full tile loop nest.
- BlockAndValueMapping operandMap;
+ IRMapping operandMap;
for (const auto &loopEn : llvm::enumerate(inputNest))
operandMap.map(loopEn.value().getInductionVar(),
fullTileLoops[loopEn.index()].getInductionVar());
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/IR/AffineExprVisitor.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Dominance.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/IntegerSet.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
// branch while promoting its then block, and analogously drop the 'then'
// block of the original 'if' from the 'else' branch while promoting its else
// block.
- BlockAndValueMapping operandMap;
+ IRMapping operandMap;
OpBuilder b(hoistOverOp);
auto hoistedIfOp = b.create<AffineIfOp>(ifOp.getLoc(), ifOp.getIntegerSet(),
ifOp.getOperands(),
using DialectInlinerInterface::DialectInlinerInterface;
/// All arithmetic dialect ops can be inlined.
- bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
return true;
}
};
#include "mlir/Dialect/Async/IR/Async.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/DialectImplementation.h"
#include "mlir/IR/FunctionImplementation.h"
+#include "mlir/IR/IRMapping.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/TypeSwitch.h"
#include "mlir/Dialect/Async/Transforms.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/ImplicitLocOpBuilder.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/PatternMatch.h"
}
// Copy the body of the parallel op into the inner-most loop.
- BlockAndValueMapping mapping;
+ IRMapping mapping;
mapping.map(op.getInductionVars(), computeBlockInductionVars);
mapping.map(computeFuncType.captures, captures);
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/ImplicitLocOpBuilder.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Transforms/DialectConversion.h"
// Map from function inputs defined above the execute op to the function
// arguments.
- BlockAndValueMapping valueMapping;
+ IRMapping valueMapping;
valueMapping.map(functionInputs, func.getArguments());
valueMapping.map(execute.getBodyRegion().getArguments(), unwrappedOperands);
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/IR/AsmState.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Operation.h"
#include "mlir/IR/TypeUtilities.h"
#include "mlir/IR/Value.h"
}
//===----------------------------------------------------------------------===//
-// Bufferization-specific BlockAndValueMapping support with debugging.
+// Bufferization-specific IRMapping support with debugging.
//===----------------------------------------------------------------------===//
bool bufferization::isFunctionArgument(Value value) {
using DialectInlinerInterface::DialectInlinerInterface;
/// Operations in Bufferization dialect are always legal to inline.
- bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
return true;
}
};
#include "mlir/Dialect/CommonFolders.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/PatternMatch.h"
bool wouldBeCloned) const final {
return true;
}
- bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
return true;
}
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/FunctionImplementation.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/PatternMatch.h"
}
/// All operations can be inlined.
- bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
return true;
}
/// All functions can be inlined.
- bool isLegalToInline(Region *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Region *, Region *, bool, IRMapping &) const final {
return true;
}
/// Clone the internal blocks from this function into dest and all attributes
/// from this function to dest.
-void FuncOp::cloneInto(FuncOp dest, BlockAndValueMapping &mapper) {
+void FuncOp::cloneInto(FuncOp dest, IRMapping &mapper) {
// Add the attributes of this function to dest.
llvm::MapVector<StringAttr, Attribute> newAttrMap;
for (const auto &attr : dest->getAttrs())
/// provided (leaving them alone if no entry is present). Replaces references
/// to cloned sub-values with the corresponding value that is copied, and adds
/// those mappings to the mapper.
-FuncOp FuncOp::clone(BlockAndValueMapping &mapper) {
+FuncOp FuncOp::clone(IRMapping &mapper) {
// Create the new function.
FuncOp newFunc = cast<FuncOp>(getOperation()->cloneWithoutRegions());
return newFunc;
}
FuncOp FuncOp::clone() {
- BlockAndValueMapping mapper;
+ IRMapping mapper;
return clone(mapper);
}
using DialectInlinerInterface::DialectInlinerInterface;
/// All gpu dialect ops can be inlined.
- bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
return true;
}
};
#include "mlir/Dialect/Transform/IR/TransformDialect.h"
#include "mlir/Dialect/Transform/IR/TransformInterfaces.h"
#include "mlir/Dialect/Transform/IR/TransformUtils.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
using namespace mlir;
using namespace mlir::gpu;
// induction variables to the newly created ops.
SmallVector<Value> blockOps;
blockIdGenerator(rewriter, foreachThreadOp, blockOps);
- BlockAndValueMapping bvm;
+ IRMapping bvm;
for (auto [blockIdx, blockDim] :
llvm::zip(foreachThreadOp.getThreadIndices(), blockMapping)) {
bvm.map(blockIdx,
rewriter.create<ThreadIdOp>(loc, indexType, Dimension::x),
rewriter.create<ThreadIdOp>(loc, indexType, Dimension::y),
rewriter.create<ThreadIdOp>(loc, indexType, Dimension::z)};
- BlockAndValueMapping bvm;
+ IRMapping bvm;
for (auto [blockIdx, blockDim] :
llvm::zip(foreachThreadOp.getThreadIndices(), threadMapping)) {
bvm.map(
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
#include "mlir/Dialect/GPU/Transforms/Passes.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Pass/Pass.h"
Block *split = rewriter.splitBlock(block, rewriter.getInsertionPoint());
// Insert accumulator body between split block.
- BlockAndValueMapping mapping;
+ IRMapping mapping;
mapping.map(body.getArgument(0), lhs);
mapping.map(body.getArgument(1), rhs);
rewriter.cloneRegionBefore(body, *split->getParent(),
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
#include "mlir/Dialect/GPU/Transforms/Utils.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
op->getSuccessors(), op->getNumRegions());
// Clone regions into new op.
- BlockAndValueMapping mapping;
+ IRMapping mapping;
for (auto pair : llvm::zip_first(op->getRegions(), newOp->getRegions()))
std::get<0>(pair).cloneInto(&std::get<1>(pair), mapping);
auto newOp = builder.create<async::ExecuteOp>(
executeOp.getLoc(), TypeRange{resultTypes}.drop_front() /*drop token*/,
executeOp.getDependencies(), executeOp.getBodyOperands());
- BlockAndValueMapping mapper;
+ IRMapping mapper;
newOp.getRegion().getBlocks().clear();
executeOp.getRegion().cloneInto(&newOp.getRegion(), mapper);
#include "mlir/Dialect/GPU/IR/GPUDialect.h"
#include "mlir/Dialect/GPU/Transforms/Utils.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/SymbolTable.h"
#include "mlir/Support/LLVM.h"
/// entry block of `launchOpBody`, to the corresponding result value of the
/// added operations.
static void injectGpuIndexOperations(Location loc, Region &launchFuncOpBody,
- Region &launchOpBody,
- BlockAndValueMapping &map) {
+ Region &launchOpBody, IRMapping &map) {
OpBuilder builder(loc->getContext());
Block &firstBlock = launchOpBody.front();
builder.setInsertionPointToStart(&launchFuncOpBody.front());
}
// Insert operations so that the defs get cloned before uses.
- BlockAndValueMapping map;
+ IRMapping map;
OpBuilder builder(launchOpBody);
for (Operation *op : toBeSunk) {
Operation *clonedOp = builder.clone(*op, map);
outlinedFunc->setAttr(gpu::GPUFuncOp::getKnownGridSizeAttrName(),
gridBounds);
- BlockAndValueMapping map;
+ IRMapping map;
// Map the arguments corresponding to the launch parameters like blockIdx,
// threadIdx, etc.
using DialectInlinerInterface::DialectInlinerInterface;
/// Conservative allowlist-based inlining of operations supported so far.
- bool isLegalToInline(Operation *op, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *op, Region *, bool, IRMapping &) const final {
if (isPure(op))
return true;
return llvm::TypeSwitch<Operation *, bool>(op)
// We don't have any special restrictions on what can be inlined into
// destination regions (e.g. while/conditional bodies). Always allow it.
bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
- BlockAndValueMapping &valueMapping) const final {
+ IRMapping &valueMapping) const final {
return true;
}
// Operations in Linalg dialect are always legal to inline.
- bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
return true;
}
// Handle the given inlined terminator by replacing it with a new operation
return nullptr;
}
- BlockAndValueMapping bvm;
+ IRMapping bvm;
bvm.map(destinationTensors[resultNumber], bbArg);
auto tileableProducerClone =
cast<TilingInterface>(rewriter.clone(*tileableProducer, bvm));
Region ®ion = newOp.getRegion();
Block *block = new Block();
region.push_back(block);
- BlockAndValueMapping mapper;
+ IRMapping mapper;
OpBuilder::InsertionGuard guard(rewriter);
rewriter.setInsertionPointToStart(block);
for (auto bbarg : genericOp.getRegionInputArgs())
Block &consumerBlock = consumer->getRegion(0).front();
Block *fusedBlock = new Block();
fusedOp.getRegion().push_back(fusedBlock);
- BlockAndValueMapping mapper;
+ IRMapping mapper;
OpBuilder::InsertionGuard guard(rewriter);
rewriter.setInsertionPointToStart(fusedBlock);
// scalar constant.
Region ®ion = genericOp->getRegion(0);
Block &entryBlock = *region.begin();
- BlockAndValueMapping mapping;
+ IRMapping mapping;
mapping.map(entryBlock.getArgument(opOperand->getOperandNumber()),
scalarConstant);
Region &fusedRegion = fusedOp->getRegion(0);
SmallVector<Value> clonedLoopIvs, leadingPackedTensorIndexings;
clonedLoopIvs.reserve(nPackedLoops);
leadingPackedTensorIndexings.reserve(nPackedLoops);
- BlockAndValueMapping bvm;
+ IRMapping bvm;
// Stack step 1. iteratively clone loops and push `packedTensor`.
for (Operation *op : analysis.backwardSlice) {
// Specifically sit out in the extract_slice(packedTensor) case: this is the
#include "mlir/Dialect/SCF/Utils/AffineCanonicalizationUtils.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/Support/LLVM.h"
#include "mlir/Transforms/DialectConversion.h"
#include "mlir/Transforms/FoldUtils.h"
ArrayRef<SmallVector<Value>> indexing,
ArrayRef<Value> outputBuffers) {
auto &block = op->getRegion(0).front();
- BlockAndValueMapping map;
+ IRMapping map;
map.map(block.getArguments(), indexedValues);
for (auto &op : block.without_terminator()) {
auto *newOp = b.clone(op, map);
}
// 4.b. Clone the op and update init operands.
- // We cannot use a BlockAndValueMapping here because it can replace
+ // We cannot use a IRMapping here because it can replace
// different OpOperands with the same value.
Operation *clonedOp = b.clone(*op.getOperation());
b.updateRootInPlace(clonedOp, [&]() {
static LogicalResult inlinePayload(OpBuilder &b, LinalgOp linalgOp,
ValueRange ivs, ValueRange argValues) {
Block *body = linalgOp.getBlock();
- BlockAndValueMapping map;
+ IRMapping map;
map.map(body->getArguments(), argValues);
for (auto &op : body->without_terminator()) {
if (auto indexOp = dyn_cast<IndexOp>(&op)) {
auto genericOp =
b.create<GenericOp>(loc, TypeRange({out.getType()}), tiledOperands,
ValueRange({out}), newMaps, newIteratorTypes);
- BlockAndValueMapping mapping;
+ IRMapping mapping;
op->getRegion(0).cloneInto(&genericOp.getRegion(),
genericOp.getRegion().begin(), mapping);
return genericOp.getOperation();
auto generateOp = rewriter.create<tensor::GenerateOp>(
padOp.getLoc(), padOp.getResultType(), dynSizes);
// Copy region to new op.
- BlockAndValueMapping bvm;
+ IRMapping bvm;
padOp.getRegion().cloneInto(&generateOp.getRegion(), bvm);
return generateOp;
}
std::function<LogicalResult(Operation *, bool)>;
// Custom vectorization function type. Produce a vector form of Operation*
-// assuming all its vectorized operands are already in the BlockAndValueMapping.
+// assuming all its vectorized operands are already in the IRMapping.
// Return nullptr if the Operation cannot be vectorized.
-using CustomVectorizationHook = std::function<VectorizationResult(
- Operation *, const BlockAndValueMapping &)>;
+using CustomVectorizationHook =
+ std::function<VectorizationResult(Operation *, const IRMapping &)>;
/// Helper function to vectorize the terminator of a `linalgOp`. New result
/// vector values are appended to `newResults`. Return
/// CustomVectorizationHook.
static VectorizationResult
vectorizeLinalgYield(RewriterBase &rewriter, Operation *op,
- const BlockAndValueMapping &bvm, VectorizationState &state,
+ const IRMapping &bvm, VectorizationState &state,
LinalgOp linalgOp, SmallVectorImpl<Value> &newResults) {
auto yieldOp = dyn_cast<linalg::YieldOp>(op);
if (!yieldOp)
/// offset = ( ( 1 ) * 80 + 2 ) * 15 + 3
static Value
calculateGatherOffset(OpBuilder &b, tensor::ExtractOp extractOp,
- const BlockAndValueMapping &bvm,
+ const IRMapping &bvm,
const SmallVectorImpl<int64_t> &targetShape) {
// The vector of indices for GatherOp should be shaped as the output vector
auto indexVecType = VectorType::get(targetShape, b.getIndexType());
/// VectorizationStatus::NewOp to signal the vectorization algorithm that it
/// should map the produced operations. This function is meant to be used as a
/// CustomVectorizationHook.
-static VectorizationResult
-vectorizeTensorExtract(RewriterBase &rewriter, Operation *op, LinalgOp linalgOp,
- const BlockAndValueMapping &bvm) {
+static VectorizationResult vectorizeTensorExtract(RewriterBase &rewriter,
+ Operation *op,
+ LinalgOp linalgOp,
+ const IRMapping &bvm) {
tensor::ExtractOp extractOp = dyn_cast<tensor::ExtractOp>(op);
if (!extractOp)
return VectorizationResult{VectorizationStatus::Failure, nullptr};
/// that the result shape.
// Note: this is a true builder that notifies the OpBuilder listener.
// TODO: Consider moving as a static helper on the ReduceOp.
-static Operation *reduceIfNeeded(OpBuilder &b, LinalgOp linalgOp,
- Operation *op, Value reduceValue,
- Value initialValue,
- const BlockAndValueMapping &bvm) {
+static Operation *reduceIfNeeded(OpBuilder &b, LinalgOp linalgOp, Operation *op,
+ Value reduceValue, Value initialValue,
+ const IRMapping &bvm) {
Value reduceVec = bvm.lookup(reduceValue);
Value outputVec = bvm.lookup(initialValue);
auto reduceType = reduceVec.getType().dyn_cast<VectorType>();
/// instructs the caller what `bvm` update needs to occur.
static VectorizationResult
vectorizeOneOp(RewriterBase &rewriter, LinalgOp linalgOp, Operation *op,
- const BlockAndValueMapping &bvm,
+ const IRMapping &bvm,
ArrayRef<CustomVectorizationHook> customVectorizationHooks) {
LDBG("vectorize op " << *op << "\n");
// 2. Values defined above the region can only be broadcast for now. Make them
// map to themselves.
- BlockAndValueMapping bvm;
+ IRMapping bvm;
SetVector<Value> valuesSet;
mlir::getUsedValuesDefinedAbove(linalgOp->getRegion(0), valuesSet);
bvm.map(valuesSet.getArrayRef(), valuesSet.getArrayRef());
SmallVector<CustomVectorizationHook> hooks;
// 4a. Register CustomVectorizationHook for yieldOp.
CustomVectorizationHook vectorizeYield =
- [&](Operation *op,
- const BlockAndValueMapping &bvm) -> VectorizationResult {
+ [&](Operation *op, const IRMapping &bvm) -> VectorizationResult {
return vectorizeLinalgYield(rewriter, op, bvm, state, linalgOp, newResults);
};
hooks.push_back(vectorizeYield);
// 4b. Register CustomVectorizationHook for indexOp.
CustomVectorizationHook vectorizeIndex =
- [&](Operation *op,
- const BlockAndValueMapping &bvm) -> VectorizationResult {
+ [&](Operation *op, const IRMapping &bvm) -> VectorizationResult {
return vectorizeLinalgIndex(rewriter, op, linalgOp);
};
hooks.push_back(vectorizeIndex);
// 4c. Register CustomVectorizationHook for extractOp.
CustomVectorizationHook vectorizeExtract =
- [&](Operation *op,
- const BlockAndValueMapping &bvm) -> VectorizationResult {
+ [&](Operation *op, const IRMapping &bvm) -> VectorizationResult {
return vectorizeTensorExtract(rewriter, op, linalgOp, bvm);
};
hooks.push_back(vectorizeExtract);
using DialectInlinerInterface::DialectInlinerInterface;
/// All operations within math ops can be inlined.
- bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
return true;
}
};
struct MemRefInlinerInterface : public DialectInlinerInterface {
using DialectInlinerInterface::DialectInlinerInterface;
bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
- BlockAndValueMapping &valueMapping) const final {
+ IRMapping &valueMapping) const final {
return true;
}
bool isLegalToInline(Operation *, Region *, bool wouldBeCloned,
- BlockAndValueMapping &) const final {
+ IRMapping &) const final {
return true;
}
};
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/SCF/IR/DeviceMappingInterface.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/FunctionInterfaces.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Support/MathExtras.h"
// We don't have any special restrictions on what can be inlined into
// destination regions (e.g. while/conditional bodies). Always allow it.
bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
- BlockAndValueMapping &valueMapping) const final {
+ IRMapping &valueMapping) const final {
return true;
}
// Operations in scf dialect are always legal to inline since they are
// pure.
- bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
return true;
}
// Handle the given inlined terminator by replacing it with a new operation
// An internal flat vector of block transfer
// arguments `newBlockTransferArgs` keeps the 1-1 mapping of original to
// transformed block argument mappings. This plays the role of a
- // BlockAndValueMapping for the particular use case of calling into
+ // IRMapping for the particular use case of calling into
// `mergeBlockBefore`.
SmallVector<bool, 4> keepMask;
keepMask.reserve(yieldOp.getNumOperands());
LogicalResult matchAndRewrite(ParallelOp op,
PatternRewriter &rewriter) const override {
- BlockAndValueMapping mapping;
+ IRMapping mapping;
// Compute new loop bounds that omit all single-iteration loop dimensions.
SmallVector<Value, 2> newLowerBounds;
SmallVector<Value, 2> newUpperBounds;
Block &innerBody = innerOp.getLoopBody().front();
assert(iterVals.size() ==
(outerBody.getNumArguments() + innerBody.getNumArguments()));
- BlockAndValueMapping mapping;
+ IRMapping mapping;
mapping.map(outerBody.getArguments(),
iterVals.take_front(outerBody.getNumArguments()));
mapping.map(innerBody.getArguments(),
#include "mlir/Dialect/SCF/Transforms/Patterns.h"
#include "mlir/Dialect/SCF/Transforms/Transforms.h"
#include "mlir/Dialect/SCF/Utils/Utils.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Support/MathExtras.h"
#include "mlir/Transforms/RegionUtils.h"
/// If the value is a loop carried value coming from stage N + 1 remap, it will
/// become a direct use.
-static void updateIterArgUses(RewriterBase &rewriter, BlockAndValueMapping &bvm,
+static void updateIterArgUses(RewriterBase &rewriter, IRMapping &bvm,
Operation *newOp, ForOp oldForOp, ForOp newForOp,
unsigned useStage,
const DenseMap<Operation *, unsigned> &stages) {
/// correct region argument. We look for the right version of the Value based
/// on the stage where it is used.
static void updateCrossStageUses(
- RewriterBase &rewriter, Operation *newOp, BlockAndValueMapping &bvm,
- ForOp newForOp, unsigned useStage,
- const DenseMap<Operation *, unsigned> &stages,
+ RewriterBase &rewriter, Operation *newOp, IRMapping &bvm, ForOp newForOp,
+ unsigned useStage, const DenseMap<Operation *, unsigned> &stages,
const llvm::DenseMap<std::pair<Value, unsigned>, unsigned> &loopArgMap) {
// Because we automatically cloned the sub-regions, there's no simple way
// to walk the nested regions in pairs of (oldOps, newOps), so we just
// Create the kernel, we clone instruction based on the order given by
// user and remap operands coming from a previous stages.
rewriter.setInsertionPoint(newForOp.getBody(), newForOp.getBody()->begin());
- BlockAndValueMapping mapping;
+ IRMapping mapping;
mapping.map(forOp.getInductionVar(), newForOp.getInductionVar());
for (const auto &arg : llvm::enumerate(forOp.getRegionIterArgs())) {
mapping.map(arg.value(), newForOp.getRegionIterArgs()[arg.index()]);
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/Dialect/SCF/Transforms/Transforms.h"
#include "mlir/Dialect/SCF/Utils/Utils.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
namespace mlir {
#define GEN_PASS_DEF_SCFFORLOOPRANGEFOLDING
break;
OpBuilder b(op);
- BlockAndValueMapping lbMap;
+ IRMapping lbMap;
lbMap.map(indVar, op.getLowerBound());
- BlockAndValueMapping ubMap;
+ IRMapping ubMap;
ubMap.map(indVar, op.getUpperBound());
- BlockAndValueMapping stepMap;
+ IRMapping stepMap;
stepMap.map(indVar, op.getStep());
if (isa<arith::AddIOp>(user)) {
#include "mlir/Dialect/SCF/Utils/AffineCanonicalizationUtils.h"
#include "mlir/Dialect/Utils/StaticValueUtils.h"
#include "mlir/IR/AffineExpr.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Transforms/GreedyPatternRewriteDriver.h"
#include "llvm/ADT/DenseMap.h"
}
OpBuilder b(op);
- BlockAndValueMapping map;
+ IRMapping map;
Value cond;
for (auto bound : llvm::zip(op.getUpperBound(), constantIndices)) {
Value constant =
return;
OpBuilder b(op);
- BlockAndValueMapping map;
+ IRMapping map;
Value constant = b.create<arith::ConstantIndexOp>(op.getLoc(), minConstant);
Value cond = b.create<arith::CmpIOp>(op.getLoc(), arith::CmpIPredicate::eq,
bound, constant);
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/Dialect/SCF/Transforms/Transforms.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
/// loop reads.
static bool haveNoReadsAfterWriteExceptSameIndex(
ParallelOp firstPloop, ParallelOp secondPloop,
- const BlockAndValueMapping &firstToSecondPloopIndices) {
+ const IRMapping &firstToSecondPloopIndices) {
DenseMap<Value, SmallVector<ValueRange, 1>> bufferStores;
firstPloop.getBody()->walk([&](memref::StoreOp store) {
bufferStores[store.getMemRef()].push_back(store.getIndices());
/// write patterns.
static LogicalResult
verifyDependencies(ParallelOp firstPloop, ParallelOp secondPloop,
- const BlockAndValueMapping &firstToSecondPloopIndices) {
+ const IRMapping &firstToSecondPloopIndices) {
if (!haveNoReadsAfterWriteExceptSameIndex(firstPloop, secondPloop,
firstToSecondPloopIndices))
return failure();
- BlockAndValueMapping secondToFirstPloopIndices;
+ IRMapping secondToFirstPloopIndices;
secondToFirstPloopIndices.map(secondPloop.getBody()->getArguments(),
firstPloop.getBody()->getArguments());
return success(haveNoReadsAfterWriteExceptSameIndex(
secondPloop, firstPloop, secondToFirstPloopIndices));
}
-static bool
-isFusionLegal(ParallelOp firstPloop, ParallelOp secondPloop,
- const BlockAndValueMapping &firstToSecondPloopIndices) {
+static bool isFusionLegal(ParallelOp firstPloop, ParallelOp secondPloop,
+ const IRMapping &firstToSecondPloopIndices) {
return !hasNestedParallelOp(firstPloop) &&
!hasNestedParallelOp(secondPloop) &&
equalIterationSpaces(firstPloop, secondPloop) &&
/// Prepends operations of firstPloop's body into secondPloop's body.
static void fuseIfLegal(ParallelOp firstPloop, ParallelOp secondPloop,
OpBuilder b) {
- BlockAndValueMapping firstToSecondPloopIndices;
+ IRMapping firstToSecondPloopIndices;
firstToSecondPloopIndices.map(firstPloop.getBody()->getArguments(),
secondPloop.getBody()->getArguments());
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Support/MathExtras.h"
// `originalTerminator` was moved to `outlinedFuncBody` and is still valid.
// Clone `originalTerminator` to take the callOp results then erase it from
// `outlinedFuncBody`.
- BlockAndValueMapping bvm;
+ IRMapping bvm;
bvm.map(originalTerminator->getOperands(), call->getResults());
rewriter.clone(*originalTerminator, bvm);
rewriter.eraseOp(originalTerminator);
OpBuilder::InsertionGuard g(rewriter);
rewriter.setInsertionPointToStart(outlinedFuncBody);
if (Operation *cst = orig.getDefiningOp<arith::ConstantIndexOp>()) {
- BlockAndValueMapping bvm;
+ IRMapping bvm;
repl = rewriter.clone(*cst, bvm)->getResult(0);
}
}
SmallVector<Value, 4> lastYielded(yieldedValues);
for (unsigned i = 1; i < unrollFactor; i++) {
- BlockAndValueMapping operandMap;
+ IRMapping operandMap;
// Prepare operand map.
operandMap.map(iterArgs, lastYielded);
/// Returns true if the given region 'src' can be inlined into the region
/// 'dest' that is attached to an operation registered to the current dialect.
bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
- BlockAndValueMapping &) const final {
+ IRMapping &) const final {
// Return true here when inlining into spirv.func, spirv.mlir.selection, and
// spirv.mlir.loop operations.
auto *op = dest->getParentOp();
/// dialect, can be inlined into the region 'dest' that is attached to an
/// operation registered to the current dialect.
bool isLegalToInline(Operation *op, Region *dest, bool wouldBeCloned,
- BlockAndValueMapping &) const final {
+ IRMapping &) const final {
// TODO: Enable inlining structured control flows with return.
if ((isa<spirv::SelectionOp, spirv::LoopOp>(op)) &&
containsReturn(op->getRegion(0)))
// Returns true if the given region 'src' can be inlined into the region
// 'dest' that is attached to an operation registered to the current dialect.
bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
- BlockAndValueMapping &) const final {
+ IRMapping &) const final {
return true;
}
// dialect, can be inlined into the region 'dest' that is attached to an
// operation registered to the current dialect.
bool isLegalToInline(Operation *op, Region *dest, bool wouldBeCloned,
- BlockAndValueMapping &) const final {
+ IRMapping &) const final {
return true;
}
};
#include "mlir/Dialect/Shape/IR/Shape.h"
#include "mlir/Dialect/Shape/Transforms/Passes.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Matchers.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"
shape::FuncOp fnOp = b.create<shape::FuncOp>(loc, fnName, fnType);
Block *block = fnOp.addEntryBlock();
b.setInsertionPoint(block, block->end());
- BlockAndValueMapping bvm;
+ IRMapping bvm;
if (cluster.empty()) {
bvm.map(shape, fnOp.getArgument(0));
} else {
/*doc=*/nullptr, /*library_call=*/nullptr);
Block &prodBlock = prod.getRegion().front();
Block &consBlock = op.getRegion().front();
- BlockAndValueMapping mapper;
+ IRMapping mapper;
Block *fusedBlock = new Block();
fusedOp.getRegion().push_back(fusedBlock);
unsigned num = prodBlock.getNumArguments();
private:
// Helper to add argument and record the mapping.
- static void addArg(BlockAndValueMapping &mapper, Block *b, BlockArgument a) {
+ static void addArg(IRMapping &mapper, Block *b, BlockArgument a) {
mapper.map(a, b->addArgument(a.getType(), a.getLoc()));
}
};
ValueRange vals) {
// Make a clone of overlap region.
Region tmpRegion;
- BlockAndValueMapping mapper;
+ IRMapping mapper;
region.cloneInto(&tmpRegion, tmpRegion.begin(), mapper);
Block &clonedBlock = tmpRegion.front();
YieldOp clonedYield = cast<YieldOp>(clonedBlock.getTerminator());
struct TensorInlinerInterface : public DialectInlinerInterface {
using DialectInlinerInterface::DialectInlinerInterface;
bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
- BlockAndValueMapping &valueMapping) const final {
+ IRMapping &valueMapping) const final {
return true;
}
bool isLegalToInline(Operation *, Region *, bool wouldBeCloned,
- BlockAndValueMapping &) const final {
+ IRMapping &) const final {
return true;
}
};
#include "mlir/Dialect/Utils/IndexingUtils.h"
#include "mlir/Dialect/Utils/ReshapeOpsUtils.h"
#include "mlir/Dialect/Utils/StaticValueUtils.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributeInterfaces.h"
#include "mlir/IR/BuiltinTypes.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/TypeUtilities.h"
if (!tensorFromElements || !wouldOpBeTriviallyDead(tensorFromElements))
return failure();
- BlockAndValueMapping mapping;
+ IRMapping mapping;
Block *body = &tensorFromElements.getBody().front();
mapping.map(body->getArguments(), extract.getIndices());
for (auto &op : body->without_terminator())
padTensorOp.getLow(), padTensorOp.getHigh(),
padTensorOp.getStaticLow(), padTensorOp.getStaticHigh(),
padTensorOp.getNofold());
- BlockAndValueMapping mapper;
+ IRMapping mapper;
padTensorOp.getRegion().cloneInto(&newOp.getRegion(), mapper);
rewriter.replaceOpWithNewOp<tensor::CastOp>(
return true;
}
return shape == constTileSize.value();
-
+
})) {
return op->emitError("mismatch in inner tile sizes specified and shaped of "
"tiled dimension in the packed type");
staticNewHighs, newLows, newHighs);
// Copy region to new PadOp.
- BlockAndValueMapping bvm;
+ IRMapping bvm;
padOp.getRegion().cloneInto(&newPadOp.getRegion(), bvm);
// Cast result and return.
/// All operations can be inlined by default.
bool isLegalToInline(Operation *op, Region *region, bool wouldBeCloned,
- BlockAndValueMapping &map) const final {
+ IRMapping &map) const final {
return true;
}
/// All regions with If and While parent operators can be inlined.
bool isLegalToInline(Region *dest, Region *src, bool wouldBeCloned,
- BlockAndValueMapping &map) const final {
+ IRMapping &map) const final {
return (isa<tosa::IfOp>(dest->getParentOp()) ||
isa<tosa::WhileOp>(dest->getParentOp()));
}
#include "mlir/Dialect/Tensor/IR/Tensor.h"
#include "mlir/Dialect/Tosa/IR/TosaOps.h"
#include "mlir/Dialect/Tosa/Utils/ShapeUtils.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Matchers.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"
#include "mlir/Dialect/Utils/StructuredOpsUtils.h"
#include "mlir/IR/AffineMap.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/Dialect/Utils/DialectUtilsEnums.cpp.inc"
Operation *mlir::clone(OpBuilder &b, Operation *op, TypeRange newResultTypes,
ValueRange newOperands) {
- BlockAndValueMapping bvm;
+ IRMapping bvm;
OperationState state(op->getLoc(), op->getName(), newOperands, newResultTypes,
op->getAttrs());
for (Region &r : op->getRegions())
#include "mlir/Dialect/Utils/StructuredOpsUtils.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinAttributes.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/DialectImplementation.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/IR/TypeUtilities.h"
contractionOp.getAcc().getDefiningOp())) {
if (maybeZero.getValue() ==
rewriter.getZeroAttr(contractionOp.getAcc().getType())) {
- BlockAndValueMapping bvm;
+ IRMapping bvm;
bvm.map(contractionOp.getAcc(), otherOperand);
auto newContraction =
cast<vector::ContractionOp>(rewriter.clone(*contractionOp, bvm));
auto notInBounds = b.create<arith::XOrIOp>(
loc, inBoundsCond, b.create<arith::ConstantIntOp>(loc, true, 1));
b.create<scf::IfOp>(loc, notInBounds, [&](OpBuilder &b, Location loc) {
- BlockAndValueMapping mapping;
+ IRMapping mapping;
Value load = b.create<memref::LoadOp>(
loc,
b.create<vector::TypeCastOp>(
// Do an in bounds write to either the output or the extra allocated buffer.
// The operation is cloned to prevent deleting information needed for the
// later IR creation.
- BlockAndValueMapping mapping;
+ IRMapping mapping;
mapping.map(xferWriteOp.getSource(), memrefAndIndices.front());
mapping.map(xferWriteOp.getIndices(), memrefAndIndices.drop_front());
auto *clone = b.clone(*xferWriteOp, mapping);
#include "mlir/IR/Builders.h"
#include "mlir/IR/AffineExpr.h"
#include "mlir/IR/AffineMap.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Dialect.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/IntegerSet.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/SymbolTable.h"
return success();
}
-Operation *OpBuilder::clone(Operation &op, BlockAndValueMapping &mapper) {
+Operation *OpBuilder::clone(Operation &op, IRMapping &mapper) {
Operation *newOp = op.clone(mapper);
// The `insert` call below handles the notification for inserting `newOp`
// itself. But if `newOp` has any regions, we need to notify the listener
}
Operation *OpBuilder::clone(Operation &op) {
- BlockAndValueMapping mapper;
+ IRMapping mapper;
return clone(op, mapper);
}
#include "mlir/IR/BuiltinDialect.h"
#include "BuiltinDialectBytecode.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/DialectResourceBlobManager.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/IR/TypeRange.h"
//===----------------------------------------------------------------------===//
#include "mlir/IR/Operation.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/BuiltinTypes.h"
#include "mlir/IR/Dialect.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/OpImplementation.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/IR/TypeUtilities.h"
/// Operands are remapped using `mapper` (if present), and `mapper` is updated
/// to contain the results. The `mapResults` flag specifies whether the results
/// of the cloned operation should be added to the map.
-Operation *Operation::cloneWithoutRegions(BlockAndValueMapping &mapper) {
+Operation *Operation::cloneWithoutRegions(IRMapping &mapper) {
return clone(mapper, CloneOptions::all().cloneRegions(false));
}
Operation *Operation::cloneWithoutRegions() {
- BlockAndValueMapping mapper;
+ IRMapping mapper;
return cloneWithoutRegions(mapper);
}
/// them alone if no entry is present). Replaces references to cloned
/// sub-operations to the corresponding operation that is copied, and adds
/// those mappings to the map.
-Operation *Operation::clone(BlockAndValueMapping &mapper,
- CloneOptions options) {
+Operation *Operation::clone(IRMapping &mapper, CloneOptions options) {
SmallVector<Value, 8> operands;
SmallVector<Block *, 2> successors;
// Create the new operation.
auto *newOp = create(getLoc(), getName(), getResultTypes(), operands, attrs,
successors, getNumRegions());
+ mapper.map(this, newOp);
// Clone the regions.
if (options.shouldCloneRegions()) {
}
Operation *Operation::clone(CloneOptions options) {
- BlockAndValueMapping mapper;
+ IRMapping mapper;
return clone(mapper, options);
}
//===----------------------------------------------------------------------===//
#include "mlir/IR/PatternMatch.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
using namespace mlir;
/// control to the region and passing it the correct block arguments.
void RewriterBase::cloneRegionBefore(Region ®ion, Region &parent,
Region::iterator before,
- BlockAndValueMapping &mapping) {
+ IRMapping &mapping) {
region.cloneInto(&parent, before, mapping);
}
void RewriterBase::cloneRegionBefore(Region ®ion, Region &parent,
Region::iterator before) {
- BlockAndValueMapping mapping;
+ IRMapping mapping;
cloneRegionBefore(region, parent, before, mapping);
}
void RewriterBase::cloneRegionBefore(Region ®ion, Block *before) {
//===----------------------------------------------------------------------===//
#include "mlir/IR/Region.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Operation.h"
using namespace mlir;
/// Clone the internal blocks from this region into `dest`. Any
/// cloned blocks are appended to the back of dest.
-void Region::cloneInto(Region *dest, BlockAndValueMapping &mapper) {
+void Region::cloneInto(Region *dest, IRMapping &mapper) {
assert(dest && "expected valid region to clone into");
cloneInto(dest, dest->end(), mapper);
}
/// Clone this region into 'dest' before the given position in 'dest'.
void Region::cloneInto(Region *dest, Region::iterator destPos,
- BlockAndValueMapping &mapper) {
+ IRMapping &mapper) {
assert(dest && "expected valid region to clone into");
assert(this != dest && "cannot clone region into itself");
//===----------------------------------------------------------------------===//
#include "mlir/Reducer/ReductionNode.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "llvm/ADT/STLExtras.h"
#include <algorithm>
LogicalResult ReductionNode::initialize(ModuleOp parentModule,
Region &targetRegion) {
// Use the mapper help us find the corresponding region after module clone.
- BlockAndValueMapping mapper;
+ IRMapping mapper;
module = cast<ModuleOp>(parentModule->clone(mapper));
// Use the first block of targetRegion to locate the cloned region.
Block *block = mapper.lookup(&*targetRegion.begin());
//===----------------------------------------------------------------------===//
#include "mlir/Target/LLVMIR/Dialect/OpenMP/OpenMPToLLVMIRTranslation.h"
#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Operation.h"
#include "mlir/Support/LLVM.h"
#include "mlir/Target/LLVMIR/ModuleTranslation.h"
#include "mlir/Dialect/SPIRV/IR/SPIRVEnums.h"
#include "mlir/Dialect/SPIRV/IR/SPIRVOps.h"
#include "mlir/Dialect/SPIRV/IR/SPIRVTypes.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Location.h"
#include "mlir/Support/LogicalResult.h"
#include "mlir/Target/SPIRV/SPIRVBinaryUtils.h"
return failure();
Region &body = op->getRegion(0);
- BlockAndValueMapping mapper;
+ IRMapping mapper;
// All references to the old merge block should be directed to the
// selection/loop merge block in the SelectionOp/LoopOp's region.
mapper.map(mergeBlock, &body.back());
#include "mlir/Transforms/DialectConversion.h"
#include "mlir/IR/Block.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
#include "mlir/IR/BuiltinOps.h"
#include "mlir/IR/FunctionInterfaces.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/Rewrite/PatternApplicator.h"
#include "llvm/ADT/ScopeExit.h"
#include "llvm/ADT/SetVector.h"
//===----------------------------------------------------------------------===//
namespace {
-/// This class wraps a BlockAndValueMapping to provide recursive lookup
+/// This class wraps a IRMapping to provide recursive lookup
/// functionality, i.e. we will traverse if the mapped value also has a mapping.
struct ConversionValueMapping {
/// Lookup a mapped value within the map. If a mapping for the provided value
private:
/// Current value mappings.
- BlockAndValueMapping mapping;
+ IRMapping mapping;
};
} // namespace
PatternRewriter::inlineRegionBefore(region, parent, before);
}
-void ConversionPatternRewriter::cloneRegionBefore(
- Region ®ion, Region &parent, Region::iterator before,
- BlockAndValueMapping &mapping) {
+void ConversionPatternRewriter::cloneRegionBefore(Region ®ion,
+ Region &parent,
+ Region::iterator before,
+ IRMapping &mapping) {
if (region.empty())
return;
PatternRewriter::cloneRegionBefore(region, parent, before, mapping);
#include "mlir/Transforms/InliningUtils.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/Builders.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Operation.h"
#include "mlir/Interfaces/CallInterfaces.h"
#include "llvm/ADT/MapVector.h"
}
static void remapInlinedOperands(iterator_range<Region::iterator> inlinedBlocks,
- BlockAndValueMapping &mapper) {
+ IRMapping &mapper) {
auto remapOperands = [&](Operation *op) {
for (auto &operand : op->getOpOperands())
if (auto mappedOp = mapper.lookupOrNull(operand.get()))
return false;
}
-bool InlinerInterface::isLegalToInline(
- Region *dest, Region *src, bool wouldBeCloned,
- BlockAndValueMapping &valueMapping) const {
+bool InlinerInterface::isLegalToInline(Region *dest, Region *src,
+ bool wouldBeCloned,
+ IRMapping &valueMapping) const {
if (auto *handler = getInterfaceFor(dest->getParentOp()))
return handler->isLegalToInline(dest, src, wouldBeCloned, valueMapping);
return false;
}
-bool InlinerInterface::isLegalToInline(
- Operation *op, Region *dest, bool wouldBeCloned,
- BlockAndValueMapping &valueMapping) const {
+bool InlinerInterface::isLegalToInline(Operation *op, Region *dest,
+ bool wouldBeCloned,
+ IRMapping &valueMapping) const {
if (auto *handler = getInterfaceFor(op))
return handler->isLegalToInline(op, dest, wouldBeCloned, valueMapping);
return false;
/// Utility to check that all of the operations within 'src' can be inlined.
static bool isLegalToInline(InlinerInterface &interface, Region *src,
Region *insertRegion, bool shouldCloneInlinedRegion,
- BlockAndValueMapping &valueMapping) {
+ IRMapping &valueMapping) {
for (auto &block : *src) {
for (auto &op : block) {
// Check this operation.
static LogicalResult
inlineRegionImpl(InlinerInterface &interface, Region *src, Block *inlineBlock,
- Block::iterator inlinePoint, BlockAndValueMapping &mapper,
+ Block::iterator inlinePoint, IRMapping &mapper,
ValueRange resultsToReplace, TypeRange regionResultTypes,
Optional<Location> inlineLoc, bool shouldCloneInlinedRegion,
Operation *call = nullptr) {
return failure();
// Map the provided call operands to the arguments of the region.
- BlockAndValueMapping mapper;
+ IRMapping mapper;
for (unsigned i = 0, e = inlinedOperands.size(); i != e; ++i) {
// Verify that the types of the provided values match the function argument
// types.
}
LogicalResult mlir::inlineRegion(InlinerInterface &interface, Region *src,
- Operation *inlinePoint,
- BlockAndValueMapping &mapper,
+ Operation *inlinePoint, IRMapping &mapper,
ValueRange resultsToReplace,
TypeRange regionResultTypes,
Optional<Location> inlineLoc,
++inlinePoint->getIterator(), mapper, resultsToReplace,
regionResultTypes, inlineLoc, shouldCloneInlinedRegion);
}
-LogicalResult
-mlir::inlineRegion(InlinerInterface &interface, Region *src, Block *inlineBlock,
- Block::iterator inlinePoint, BlockAndValueMapping &mapper,
- ValueRange resultsToReplace, TypeRange regionResultTypes,
- Optional<Location> inlineLoc,
- bool shouldCloneInlinedRegion) {
+LogicalResult mlir::inlineRegion(InlinerInterface &interface, Region *src,
+ Block *inlineBlock,
+ Block::iterator inlinePoint, IRMapping &mapper,
+ ValueRange resultsToReplace,
+ TypeRange regionResultTypes,
+ Optional<Location> inlineLoc,
+ bool shouldCloneInlinedRegion) {
return inlineRegionImpl(interface, src, inlineBlock, inlinePoint, mapper,
resultsToReplace, regionResultTypes, inlineLoc,
shouldCloneInlinedRegion);
const auto *callInterface = interface.getInterfaceFor(call->getDialect());
// Map the provided call operands to the arguments of the region.
- BlockAndValueMapping mapper;
+ IRMapping mapper;
for (unsigned i = 0, e = callOperands.size(); i != e; ++i) {
BlockArgument regionArg = entryBlock->getArgument(i);
Value operand = callOperands[i];
// Don't allow inlining calls that are marked `noinline`.
return !call->hasAttr("noinline");
}
- bool isLegalToInline(Region *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Region *, Region *, bool, IRMapping &) const final {
// Inlining into test dialect regions is legal.
return true;
}
- bool isLegalToInline(Operation *, Region *, bool,
- BlockAndValueMapping &) const final {
+ bool isLegalToInline(Operation *, Region *, bool, IRMapping &) const final {
return true;
}
if (terminator->getNumOperands() != regionEntry.getNumArguments())
return;
- BlockAndValueMapping map;
+ IRMapping map;
for (auto tup :
llvm::zip(terminator->getOperands(), regionEntry.getArguments())) {
if (std::get<0>(tup).getType() != std::get<1>(tup).getType())
#include "mlir/Analysis/SliceAnalysis.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
#include "mlir/Dialect/Linalg/IR/Linalg.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Support/LLVM.h"
std::string clonedFuncOpName = parentFuncOp.getName().str() + suffix.str();
func::FuncOp clonedFuncOp = builder.create<func::FuncOp>(
loc, clonedFuncOpName, parentFuncOp.getFunctionType());
- BlockAndValueMapping mapper;
+ IRMapping mapper;
builder.setInsertionPointToEnd(clonedFuncOp.addEntryBlock());
for (const auto &arg : enumerate(parentFuncOp.getArguments()))
mapper.map(arg.value(), clonedFuncOp.getArgument(arg.index()));
#include "TestDialect.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
-#include "mlir/IR/BlockAndValueMapping.h"
#include "mlir/IR/BuiltinOps.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/InliningUtils.h"
#include "llvm/ADT/StringSet.h"
add_mlir_unittest(MLIRIRTests
AdaptorTest.cpp
AttributeTest.cpp
- BlockAndValueMapping.cpp
DialectTest.cpp
InterfaceTest.cpp
+ IRMapping.cpp
InterfaceAttachmentTest.cpp
OperationSupportTest.cpp
PatternMatchTest.cpp
-//===- BlockAndValueMapping.h -----------------------------------*- C++ -*-===//
+//===- IRMapping.cpp --------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
//
//===----------------------------------------------------------------------===//
-#include "mlir/IR/BlockAndValueMapping.h"
+#include "mlir/IR/IRMapping.h"
#include "mlir/IR/Builders.h"
#include "gtest/gtest.h"
using namespace mlir;
-TEST(BlockAndValueMapping, TypedValue) {
+TEST(IRMapping, TypedValue) {
MLIRContext context;
context.loadDialect<test::TestDialect>();
Value f64Val = builder.create<test::TestOpConstant>(
loc, builder.getF64Type(), builder.getF64FloatAttr(0.0));
- BlockAndValueMapping mapping;
+ IRMapping mapping;
mapping.map(i64Val, f64Val);
TypedValue<IntegerType> typedI64Val = i64Val;
- mapping.lookup(typedI64Val);
+ EXPECT_EQ(mapping.lookup(typedI64Val), f64Val);
+}
+
+TEST(IRMapping, OperationClone) {
+ MLIRContext ctx;
+ ctx.allowUnregisteredDialects();
+
+ OperationState state(UnknownLoc::get(&ctx), "no_results");
+ Operation *noResultsOp = Operation::create(state);
+
+ OperationState owner(UnknownLoc::get(&ctx), "owner");
+ owner.addRegion()->emplaceBlock().push_back(noResultsOp);
+ OwningOpRef<Operation *> ownerOp = Operation::create(owner);
+
+ IRMapping irMap;
+ OwningOpRef<Operation *> clonedOwnerOp = (*ownerOp)->clone(irMap);
+
+ EXPECT_EQ(irMap.lookupOrNull(*ownerOp), *clonedOwnerOp);
+ EXPECT_EQ(irMap.lookupOrNull(noResultsOp),
+ &(*clonedOwnerOp)->getRegion(0).front().front());
}