16#include <mlir/Dialect/Arith/IR/Arith.h>
17#include <mlir/Dialect/Utils/IndexingUtils.h>
18#include <mlir/IR/Attributes.h>
19#include <mlir/IR/BuiltinOps.h>
20#include <mlir/IR/Diagnostics.h>
21#include <mlir/IR/OwningOpRef.h>
22#include <mlir/IR/SymbolTable.h>
23#include <mlir/IR/ValueRange.h>
24#include <mlir/Support/LogicalResult.h>
26#include <llvm/ADT/ArrayRef.h>
27#include <llvm/ADT/Twine.h>
45 OpBuilder &odsBuilder, OperationState &odsState,
ArrayType result, ValueRange elements
47 odsState.addTypes(result);
48 odsState.addOperands(elements);
52 odsBuilder, odsState,
static_cast<int32_t
>(elements.size())
57 OpBuilder &odsBuilder, OperationState &odsState,
ArrayType result,
58 ArrayRef<ValueRange> mapOperands, DenseI32ArrayAttr numDimsPerMap
60 odsState.addTypes(result);
62 odsBuilder, odsState, mapOperands, numDimsPerMap
75llvm::SmallVector<Type> CreateArrayOp::resultTypeToElementsTypes(Type resultType) {
77 ArrayType a = llvm::cast<ArrayType>(resultType);
78 return llvm::SmallVector<Type>(a.getNumElements(), a.
getElementType());
82 OpAsmParser &parser, llvm::SmallVector<Type, 1> &elementsTypes,
83 ArrayRef<OpAsmParser::UnresolvedOperand> elements, Type resultType
85 assert(elementsTypes.size() == 0);
88 if (elements.size() > 0) {
89 elementsTypes.append(resultTypeToElementsTypes(resultType));
95 OpAsmPrinter &printer,
CreateArrayOp, TypeRange, OperandRange, Type
102 assert(llvm::isa<ArrayType>(retTy));
105 SmallVector<AffineMapAttr> mapAttrs;
107 ArrayType arrTy = llvm::cast<ArrayType>(retTy);
109 if (AffineMapAttr m = dyn_cast<AffineMapAttr>(a)) {
110 mapAttrs.push_back(m);
120 assert(
getElements().empty() &&
"must run after initialization is split from allocation");
122 if (!arrType.hasStaticShape() || arrType.getNumElements() == 1) {
126 return {DestructurableMemorySlot {{
getResult(), arrType}, std::move(*destructured)}};
133 const DestructurableMemorySlot &slot,
const SmallPtrSetImpl<Attribute> &usedIndices,
134 RewriterBase &rewriter
137 assert(slot.elemType == getType());
139 rewriter.setInsertionPointAfter(*
this);
141 DenseMap<Attribute, MemorySlot> slotMap;
142 for (Attribute index : usedIndices) {
144 ArrayAttr indexAsArray = llvm::dyn_cast<ArrayAttr>(index);
145 assert(indexAsArray &&
"expected ArrayAttr");
147 Type destructAs = getType().getTypeAtIndex(indexAsArray);
148 assert(destructAs == slot.elementPtrs.lookup(indexAsArray));
150 ArrayType destructAsArrayTy = llvm::dyn_cast<ArrayType>(destructAs);
151 assert(destructAsArrayTy &&
"expected ArrayType");
153 auto subCreate = rewriter.create<
CreateArrayOp>(getLoc(), destructAsArrayTy);
154 slotMap.try_emplace<MemorySlot>(index, {subCreate.getResult(), destructAs});
162 const DestructurableMemorySlot &slot, RewriterBase &rewriter
165 rewriter.eraseOp(*
this);
171 if (!arrType.hasStaticShape()) {
176 if (arrType.getNumElements() != 1) {
192 const MemorySlot &slot, Value defaultValue, RewriterBase &rewriter
194 if (defaultValue.use_empty()) {
195 rewriter.eraseOp(defaultValue.getDefiningOp());
197 rewriter.eraseOp(*
this);
209 if (arrTy.hasStaticShape()) {
211 return ArrayAttr::get(getContext(), *converted);
219 const DestructurableMemorySlot &slot, SmallPtrSetImpl<Attribute> &usedIndices,
220 SmallVectorImpl<MemorySlot> &mustBeSafelyUsed
237 usedIndices.insert(indexAsAttr);
243 const DestructurableMemorySlot &slot, DenseMap<Attribute, MemorySlot> &subslots,
244 RewriterBase &rewriter
252 assert(indexAsAttr &&
"canRewire() should have returned false");
253 const MemorySlot &memorySlot = subslots.at(indexAsAttr);
256 auto idx0 = rewriter.create<arith::ConstantIndexOp>(getLoc(), 0);
257 rewriter.modifyOpInPlace(*
this, [&]() {
262 return DeletionKind::Keep;
275 auto compare = numIndices <=> dims.size();
277 return errFn().append(
278 "has ", (compare < 0 ?
"insufficient" :
"too many"),
" indexed dimensions: expected ",
279 dims.size(),
" but found ", numIndices
294 llvm::SmallVectorImpl<Type> &inferredReturnTypes
296 inferredReturnTypes.resize(1);
297 Type lvalType = adaptor.
getArrRef().getType();
298 assert(llvm::isa<ArrayType>(lvalType));
299 inferredReturnTypes[0] = llvm::cast<ArrayType>(lvalType).getElementType();
314 const MemorySlot &slot,
const SmallPtrSetImpl<OpOperand *> &blockingUses,
315 SmallVectorImpl<OpOperand *> &newBlockingUses
317 if (blockingUses.size() != 1) {
320 Value blockingUse = (*blockingUses.begin())->get();
321 return blockingUse == slot.ptr &&
getArrRef() == slot.ptr &&
327 const MemorySlot &slot,
const SmallPtrSetImpl<OpOperand *> &blockingUses,
328 RewriterBase &rewriter, Value reachingDefinition
331 rewriter.replaceAllUsesWith(
getResult(), reachingDefinition);
332 return DeletionKind::Delete;
353 const MemorySlot &slot,
const SmallPtrSetImpl<OpOperand *> &blockingUses,
354 SmallVectorImpl<OpOperand *> &newBlockingUses
356 if (blockingUses.size() != 1) {
359 Value blockingUse = (*blockingUses.begin())->get();
360 return blockingUse == slot.ptr &&
getArrRef() == slot.ptr &&
getRvalue() != slot.ptr &&
366 const MemorySlot &slot,
const SmallPtrSetImpl<OpOperand *> &blockingUses,
367 RewriterBase &rewriter, Value reachingDefinition
369 return DeletionKind::Delete;
383 llvm::SmallVectorImpl<Type> &inferredReturnTypes
385 size_t numToSkip = adaptor.
getIndices().size();
386 Type arrRefType = adaptor.
getArrRef().getType();
387 assert(llvm::isa<ArrayType>(arrRefType));
388 ArrayType arrRefArrType = llvm::cast<ArrayType>(arrRefType);
392 auto compare = numToSkip <=> arrRefDimSizes.size();
394 return mlir::emitOptionalError(
399 }
else if (compare > 0) {
400 return mlir::emitOptionalError(
402 "' op cannot select more dimensions than exist in the source array"
407 inferredReturnTypes.resize(1);
408 inferredReturnTypes[0] =
434 assert(llvm::isa<ArrayType>(rValueType));
435 ArrayType rValueArrType = llvm::cast<ArrayType>(rValueType);
439 if (numIndices > dimsFromBase.size()) {
440 return emitOpError(
"cannot select more dimensions than exist in the source array");
444 ArrayRef<Attribute> dimsFromBaseReduced = dimsFromBase.drop_front(numIndices);
446 auto compare = dimsFromRValue.size() <=> dimsFromBaseReduced.size();
448 return emitOpError().append(
449 "has ", (compare < 0 ?
"insufficient" :
"too many"),
" indexed dimensions: expected ",
450 (dimsFromBase.size() - dimsFromRValue.size()),
" but found ", numIndices
457 llvm::raw_string_ostream ss(message);
459 ss <<
"cannot unify array dimensions [";
460 llvm::interleaveComma(dimsFromBaseReduced, ss, appendOne);
462 llvm::interleaveComma(dimsFromRValue, ss, appendOne);
464 return emitOpError().append(message);
469 return emitOpError().append(
470 "incorrect array element type; expected: ", baseArrRefArrType.
getElementType(),
::mlir::Operation::operand_range getIndices()
Gets the operand range containing the index for each dimension.
::mlir::OpOperand & getArrRefMutable()
Gets the mutable operand slot holding the SSA Value for the referenced array.
inline ::mlir::ArrayRef<::mlir::Attribute > getValueOperandDims()
Compute the dimensions of the read/write value.
bool canRewire(const ::mlir::DestructurableMemorySlot &slot, ::llvm::SmallPtrSetImpl<::mlir::Attribute > &usedIndices, ::mlir::SmallVectorImpl<::mlir::MemorySlot > &mustBeSafelyUsed)
Required by companion interface DestructurableAccessorOpInterface / SROA pass.
::mlir::DeletionKind rewire(const ::mlir::DestructurableMemorySlot &slot, ::llvm::DenseMap<::mlir::Attribute, ::mlir::MemorySlot > &subslots, ::mlir::RewriterBase &rewriter)
Required by companion interface DestructurableAccessorOpInterface / SROA pass.
::mlir::ArrayAttr indexOperandsToAttributeArray()
Returns the multi-dimensional indices of the array access as an Attribute array or a null pointer if ...
::mlir::TypedValue<::llzk::array::ArrayType > getArrRef()
Gets the SSA Value for the referenced array.
inline ::llzk::array::ArrayType getArrRefType()
Gets the type of the referenced array.
::mlir::MutableOperandRange getIndicesMutable()
Gets the mutable operand range containing the index for each dimension.
static ArrayIndexGen from(ArrayType)
Construct new ArrayIndexGen. Will assert if hasStaticShape() is false.
inline ::llzk::array::ArrayType getArrRefType()
Gets the type of the referenced base array.
::mlir::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
::mlir::Type getElementType() const
::std::optional<::llvm::DenseMap<::mlir::Attribute, ::mlir::Type > > getSubelementIndexMap() const
Required by DestructurableTypeInterface / SROA pass.
static ArrayType get(::mlir::Type elementType, ::llvm::ArrayRef<::mlir::Attribute > dimensionSizes)
::llvm::ArrayRef<::mlir::Attribute > getDimensionSizes() const
static void printInferredArrayType(::mlir::OpAsmPrinter &printer, CreateArrayOp, ::mlir::TypeRange, ::mlir::OperandRange, ::mlir::Type)
static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::llzk::array::ArrayType result, ::mlir::ValueRange elements={})
void handlePromotionComplete(const ::mlir::MemorySlot &slot, ::mlir::Value defaultValue, ::mlir::RewriterBase &rewriter)
Required by PromotableAllocationOpInterface / mem2reg pass.
::llvm::DenseMap<::mlir::Attribute, ::mlir::MemorySlot > destructure(const ::mlir::DestructurableMemorySlot &slot, const ::llvm::SmallPtrSetImpl<::mlir::Attribute > &usedIndices, ::mlir::RewriterBase &rewriter)
Required by DestructurableAllocationOpInterface / SROA pass.
::mlir::ParseResult parseInferredArrayType(::mlir::OpAsmParser &parser, ::llvm::SmallVector<::mlir::Type, 1 > &elementsTypes, ::mlir::ArrayRef<::mlir::OpAsmParser::UnresolvedOperand > elements, ::mlir::Type resultType)
::llvm::SmallVector<::mlir::DestructurableMemorySlot > getDestructurableSlots()
Required by DestructurableAllocationOpInterface / SROA pass.
::mlir::Value getDefaultValue(const ::mlir::MemorySlot &slot, ::mlir::RewriterBase &rewriter)
Required by PromotableAllocationOpInterface / mem2reg pass.
::mlir::LogicalResult verify()
void handleDestructuringComplete(const ::mlir::DestructurableMemorySlot &slot, ::mlir::RewriterBase &rewriter)
Required by DestructurableAllocationOpInterface / SROA pass.
::llvm::SmallVector<::mlir::MemorySlot > getPromotableSlots()
Required by PromotableAllocationOpInterface / mem2reg pass.
void handleBlockArgument(const ::mlir::MemorySlot &slot, ::mlir::BlockArgument argument, ::mlir::RewriterBase &rewriter)
Required by PromotableAllocationOpInterface / mem2reg pass.
::llvm::ArrayRef< int32_t > getNumDimsPerMap()
void getAsmResultNames(::mlir::OpAsmSetValueNameFn setNameFn)
::mlir::OperandRangeRange getMapOperands()
::mlir::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
::mlir::Operation::operand_range getElements()
::mlir::TypedValue<::llzk::array::ArrayType > getResult()
inline ::llzk::array::ArrayType getArrRefType()
Gets the type of the referenced base array.
::mlir::TypedValue<::llzk::array::ArrayType > getRvalue()
::mlir::Operation::operand_range getIndices()
::mlir::LogicalResult verify()
::mlir::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
inline ::llzk::array::ArrayType getArrRefType()
Gets the type of the referenced base array.
::mlir::Operation::operand_range getIndices()
::mlir::TypedValue<::llzk::array::ArrayType > getArrRef()
::mlir::LogicalResult inferReturnTypes(::mlir::MLIRContext *context, ::std::optional<::mlir::Location > location, ::mlir::ValueRange operands, ::mlir::DictionaryAttr attributes, ::mlir::OpaqueProperties properties, ::mlir::RegionRange regions, ::llvm::SmallVectorImpl<::mlir::Type > &inferredReturnTypes)
::mlir::LogicalResult verify()
::mlir::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
bool canUsesBeRemoved(const ::mlir::MemorySlot &slot, const ::llvm::SmallPtrSetImpl<::mlir::OpOperand * > &blockingUses, ::llvm::SmallVectorImpl<::mlir::OpOperand * > &newBlockingUses)
Required by PromotableMemOpInterface / mem2reg pass.
static constexpr ::llvm::StringLiteral getOperationName()
static bool isCompatibleReturnTypes(::mlir::TypeRange l, ::mlir::TypeRange r)
::mlir::DeletionKind removeBlockingUses(const ::mlir::MemorySlot &slot, const ::llvm::SmallPtrSetImpl< mlir::OpOperand * > &blockingUses, ::mlir::RewriterBase &rewriter, ::mlir::Value reachingDefinition)
Required by PromotableMemOpInterface / mem2reg pass.
::mlir::Value getResult()
bool canUsesBeRemoved(const ::mlir::MemorySlot &slot, const ::llvm::SmallPtrSetImpl<::mlir::OpOperand * > &blockingUses, ::llvm::SmallVectorImpl<::mlir::OpOperand * > &newBlockingUses)
Required by PromotableMemOpInterface / mem2reg pass.
::mlir::Operation::operand_range getIndices()
::mlir::LogicalResult verify()
::mlir::DeletionKind removeBlockingUses(const ::mlir::MemorySlot &slot, const ::llvm::SmallPtrSetImpl< mlir::OpOperand * > &blockingUses, ::mlir::RewriterBase &rewriter, ::mlir::Value reachingDefinition)
Required by PromotableMemOpInterface / mem2reg pass.
::mlir::Value getRvalue()
inline ::llzk::array::ArrayType getArrRefType()
Gets the type of the referenced base array.
::mlir::TypedValue<::llzk::array::ArrayType > getArrRef()
::mlir::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
OpClass::Properties & buildInstantiationAttrs(mlir::OpBuilder &odsBuilder, mlir::OperationState &odsState, mlir::ArrayRef< mlir::ValueRange > mapOperands, mlir::DenseI32ArrayAttr numDimsPerMap, int32_t firstSegmentSize=0)
Utility for build() functions that initializes the operandSegmentSizes, mapOpGroupSizes,...
LogicalResult verifyAffineMapInstantiations(OperandRangeRange mapOps, ArrayRef< int32_t > numDimsPerMap, ArrayRef< AffineMapAttr > mapAttrs, Operation *origin)
OpClass::Properties & buildInstantiationAttrsEmpty(mlir::OpBuilder &odsBuilder, mlir::OperationState &odsState, int32_t firstSegmentSize=0)
Utility for build() functions that initializes the operandSegmentSizes, mapOpGroupSizes,...
bool singletonTypeListsUnify(Iter1 lhs, Iter2 rhs, mlir::ArrayRef< llvm::StringRef > rhsReversePrefix={}, UnificationMap *unifications=nullptr)
std::function< mlir::InFlightDiagnostic()> OwningEmitErrorFn
LogicalResult verifyTypeResolution(SymbolTableCollection &tables, Operation *origin, Type ty)
OwningEmitErrorFn getEmitOpErrFn(mlir::Operation *op)
bool typesUnify(Type lhs, Type rhs, ArrayRef< StringRef > rhsReversePrefix, UnificationMap *unifications)
bool typeParamsUnify(const ArrayRef< Attribute > &lhsParams, const ArrayRef< Attribute > &rhsParams, UnificationMap *unifications)
void appendWithoutType(mlir::raw_ostream &os, mlir::Attribute a)