33template <
typename LoadStoreOp>
35 return llvm::isa<MemRefType>(cast<LoadStoreOp>(op).
getBase().
getType());
39template <
typename LoadStoreOp>
41 return std::is_same_v<LoadStoreOp, vector::LoadOp> ||
42 std::is_same_v<LoadStoreOp, vector::StoreOp>;
47 unsigned numLeadingUnitDims = 0;
48 for (
auto [size, scalable] :
49 llvm::zip_equal(vecTy.getShape(), vecTy.getScalableDims())) {
50 if (size != 1 || scalable)
54 return numLeadingUnitDims;
62 bool supportsRankZero) {
64 unsigned rank =
static_cast<unsigned>(vecTy.getRank());
65 if (!supportsRankZero && numLeadingUnitDims == rank)
67 return llvm::map_to_vector(
68 llvm::zip_equal(vecTy.getShape().drop_front(numLeadingUnitDims),
69 vecTy.getScalableDims().drop_front(numLeadingUnitDims)),
71 auto [size, scalable] = dim;
72 return scalable ? ShapedType::kDynamic : size;
78 return VectorType::get(vecTy.getShape().drop_front(numLeadingDims),
79 vecTy.getElementType(),
80 vecTy.getScalableDims().drop_front(numLeadingDims));
84static std::optional<VectorType>
86 unsigned numLeadingDims) {
87 auto operandTy = dyn_cast<VectorType>(operand.
getType());
88 if (!operandTy || operandTy.getShape() != vecTy.getShape() ||
89 operandTy.getScalableDims() != vecTy.getScalableDims())
95template <
typename LoadStoreOp>
96struct VectorLoadStoreLikeOpImpl final
97 : IndexedAccessOpInterface::ExternalModel<
98 VectorLoadStoreLikeOpImpl<LoadStoreOp>, LoadStoreOp> {
100 return cast<LoadStoreOp>(op).getBase();
104 return cast<LoadStoreOp>(op).getIndices();
107 SmallVector<int64_t> getAccessedShape(Operation *op)
const {
109 "expected vector op with memref semantics");
114 std::optional<SmallVector<Value>>
115 updateMemrefAndIndices(Operation *op, RewriterBase &rewriter, Value newMemref,
118 "expected vector op with memref semantics");
119 assert(llvm::isa<MemRefType>(newMemref.
getType()) &&
120 "expected replacement memref");
122 VectorType vecTy = cast<LoadStoreOp>(op).getVectorType();
123 if (
static_cast<int64_t
>(newIndices.size()) >= vecTy.getRank()) {
125 auto concreteOp = cast<LoadStoreOp>(op);
126 concreteOp.getBaseMutable().assign(newMemref);
127 concreteOp.getIndicesMutable().assign(newIndices);
132 unsigned numLeadingDimsToDrop =
static_cast<unsigned>(
133 vecTy.getRank() -
static_cast<int64_t
>(newIndices.size()));
135 "expected only redundant leading unit dimensions to be dropped");
137 IRMapping dropDimsMap;
139 std::optional<VectorType> castTy =
143 Value castedOperand = vector::ShapeCastOp::create(
144 rewriter, operand.getLoc(), *castTy, operand);
145 dropDimsMap.
map(operand, castedOperand);
152 VectorType droppedDimsTy =
dropLeadingDims(vecTy, numLeadingDimsToDrop);
153 Operation *newOp = rewriter.
clone(*op, dropDimsMap);
155 auto concreteOp = cast<LoadStoreOp>(newOp);
156 concreteOp.getBaseMutable().assign(newMemref);
157 concreteOp.getIndicesMutable().assign(newIndices);
160 Value castBack = vector::ShapeCastOp::create(rewriter, newOp->
getLoc(),
168 auto concreteOp = cast<LoadStoreOp>(op);
169 concreteOp.getBaseMutable().assign(newMemref);
170 concreteOp.getIndicesMutable().assign(newIndices);
182 bool hasInboundsIndices(Operation *op)
const {
184 "expected vector op with memref semantics");
189template <
typename... Ops>
191 (Ops::template attachInterface<VectorLoadStoreLikeOpImpl<Ops>>(*ctx), ...);
199 attachLoadStoreLike<vector::LoadOp, vector::StoreOp, vector::MaskedLoadOp,
200 vector::MaskedStoreOp, vector::ExpandLoadOp,
201 vector::CompressStoreOp>(ctx);
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
*if copies could not be generated due to yet unimplemented cases *copyInPlacementStart and copyOutPlacementStart in copyPlacementBlock *specify the insertion points where the incoming copies and outgoing should be the output argument nBegin is set to its * replacement(set to `begin` if no invalidation happens). Since outgoing *copies could have been inserted at `end`
static VectorType getVectorType(Type scalarTy, const VectorizationStrategy *strategy)
Returns the vector type resulting from applying the provided vectorization strategy on the scalar typ...
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
void map(Value from, Value to)
Inserts a new mapping for 'from' to 'to'.
auto lookupOrNull(T from) const
Lookup a mapped value within the map.
MLIRContext is the top-level object for a collection of MLIR operations.
Operation * clone(Operation &op, IRMapping &mapper)
Creates a deep copy of the specified operation, remapping any operands that use values outside of the...
Operation is the basic unit of execution within MLIR.
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Location getLoc()
The source location the operation was defined or derived from.
MutableArrayRef< OpOperand > getOpOperands()
OperandRange operand_range
operand_range getOperands()
Returns an iterator on the underlying Value's.
unsigned getNumResults()
Return the number of results held by this operation.
void modifyOpInPlace(Operation *root, CallableT &&callable)
This method is a utility wrapper around an in-place modification of an operation.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
void setType(Type newType)
Mutate the type of this Value to be of the specified type.
Type getType() const
Return the type of this value.
Operation::operand_range getIndices(Operation *op)
Get the indices that the given load/store operation is operating on.
void registerIndexedAccessOpInterfaceExternalModels(DialectRegistry ®istry)
Include the generated interface declarations.
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
std::conditional_t< std::is_same_v< Ty, mlir::Type >, mlir::Value, detail::TypedValue< Ty > > TypedValue
If Ty is mlir::Type this will select Value instead of having a wrapper around it.