LLZK 3.0.0
An open-source IR for Zero Knowledge (ZK) circuits
Loading...
Searching...
No Matches
Ops.cpp
Go to the documentation of this file.
1//===-- Ops.cpp - Array operation implementations ---------------*- C++ -*-===//
2//
3// Part of the LLZK Project, under the Apache License v2.0.
4// See LICENSE.txt for license information.
5// Copyright 2025 Veridise Inc.
6// SPDX-License-Identifier: Apache-2.0
7//
8//===----------------------------------------------------------------------===//
9
11
15#include "llzk/Util/Compare.h"
17
18#include <mlir/Dialect/Arith/IR/Arith.h>
19#include <mlir/Dialect/Utils/IndexingUtils.h>
20#include <mlir/IR/Attributes.h>
21#include <mlir/IR/BuiltinOps.h>
22#include <mlir/IR/Diagnostics.h>
23#include <mlir/IR/Matchers.h>
24#include <mlir/IR/OwningOpRef.h>
25#include <mlir/IR/SymbolTable.h>
26#include <mlir/IR/ValueRange.h>
27#include <mlir/Support/LogicalResult.h>
28
29#include <llvm/ADT/ArrayRef.h>
30#include <llvm/ADT/Twine.h>
31
32#include <optional>
33
34// TableGen'd implementation files
36
37// TableGen'd implementation files
38#define GET_OP_CLASSES
40
41using namespace mlir;
42
43namespace llzk::array {
44
45//===------------------------------------------------------------------===//
46// CreateArrayOp
47//===------------------------------------------------------------------===//
48
50 OpBuilder &odsBuilder, OperationState &odsState, ArrayType result, ValueRange elements
51) {
52 odsState.addTypes(result);
53 odsState.addOperands(elements);
54 // This builds CreateArrayOp from a list of elements. In that case, the dimensions of the array
55 // type cannot be defined via an affine map which means there are no affine map operands.
57 odsBuilder, odsState, llzk::checkedCast<int32_t>(elements.size())
58 );
59}
60
62 OpBuilder &odsBuilder, OperationState &odsState, ArrayType result,
63 ArrayRef<ValueRange> mapOperands, DenseI32ArrayAttr numDimsPerMap
64) {
65 odsState.addTypes(result);
67 odsBuilder, odsState, mapOperands, numDimsPerMap
68 );
69}
70
71LogicalResult CreateArrayOp::verifySymbolUses(SymbolTableCollection &tables) {
72 // Ensure any SymbolRef used in the type are valid
73 return verifyTypeResolution(tables, *this, llvm::cast<Type>(getType()));
74}
75
76void CreateArrayOp::getAsmResultNames(OpAsmSetValueNameFn setNameFn) {
77 setNameFn(getResult(), "array");
78}
79
80llvm::SmallVector<Type> CreateArrayOp::resultTypeToElementsTypes(Type resultType) {
81 // The ODS restricts $result with LLZK_ArrayType so this cast is safe.
82 ArrayType a = llvm::cast<ArrayType>(resultType);
83 return llvm::SmallVector<Type>(a.getNumElements(), a.getElementType());
84}
85
86ParseResult CreateArrayOp::parseInferredArrayType(
87 OpAsmParser & /*parser*/, llvm::SmallVector<Type, 1> &elementsTypes,
88 ArrayRef<OpAsmParser::UnresolvedOperand> elements, Type resultType
89) {
90 assert(elementsTypes.size() == 0); // it was not yet initialized
91 // If the '$elements' operand is not empty, then the expected type for the operand
92 // is computed to match the type of the '$result'. Otherwise, it remains empty.
93 if (elements.size() > 0) {
94 elementsTypes.append(resultTypeToElementsTypes(resultType));
95 }
96 return success();
97}
98
99void CreateArrayOp::printInferredArrayType(
100 OpAsmPrinter &printer, CreateArrayOp, TypeRange, OperandRange, Type
101) {
102 // nothing to print, it's derived and therefore not represented in the output
103}
104
105LogicalResult CreateArrayOp::verify() {
106 Type retTy = getResult().getType();
107 assert(llvm::isa<ArrayType>(retTy)); // per ODS spec of CreateArrayOp
108
109 // Collect the array dimensions that are defined via AffineMapAttr
110 SmallVector<AffineMapAttr> mapAttrs;
111 // Extend the lifetime of the temporary to suppress warnings.
112 ArrayType arrTy = llvm::cast<ArrayType>(retTy);
113 for (Attribute a : arrTy.getDimensionSizes()) {
114 if (AffineMapAttr m = dyn_cast<AffineMapAttr>(a)) {
115 mapAttrs.push_back(m);
116 }
117 }
119 getMapOperands(), getNumDimsPerMap(), mapAttrs, *this
120 );
121}
122
124SmallVector<DestructurableMemorySlot> CreateArrayOp::getDestructurableSlots() {
125 assert(getElements().empty() && "must run after initialization is split from allocation");
126 ArrayType arrType = getType();
127 if (!arrType.hasStaticShape() || arrType.getNumElements() == 1) {
128 return {};
129 }
130 if (auto destructured = arrType.getSubelementIndexMap()) {
131 return {DestructurableMemorySlot {{getResult(), arrType}, std::move(*destructured)}};
132 }
133 return {};
134}
135
137DenseMap<Attribute, MemorySlot> CreateArrayOp::destructure(
138 const DestructurableMemorySlot &slot, const SmallPtrSetImpl<Attribute> &usedIndices,
139 OpBuilder &builder, SmallVectorImpl<DestructurableAllocationOpInterface> &newAllocators
140) {
141 assert(slot.ptr == getResult());
142 assert(slot.elemType == getType());
143
144 builder.setInsertionPointAfter(*this);
145
146 DenseMap<Attribute, MemorySlot> slotMap; // result
147 for (Attribute index : usedIndices) {
148 // This is an ArrayAttr since indexing is multi-dimensional
149 ArrayAttr indexAsArray = llvm::dyn_cast<ArrayAttr>(index);
150 assert(indexAsArray && "expected ArrayAttr");
151
152 Type destructAs = getType().getTypeAtIndex(indexAsArray);
153 assert(destructAs == slot.subelementTypes.lookup(indexAsArray));
154
155 ArrayType destructAsArrayTy = llvm::dyn_cast<ArrayType>(destructAs);
156 assert(destructAsArrayTy && "expected ArrayType");
157
158 auto subCreate = builder.create<CreateArrayOp>(getLoc(), destructAsArrayTy);
159 newAllocators.push_back(subCreate);
160 slotMap.try_emplace<MemorySlot>(index, {subCreate.getResult(), destructAs});
161 }
162
163 return slotMap;
164}
165
167std::optional<DestructurableAllocationOpInterface> CreateArrayOp::handleDestructuringComplete(
168 const DestructurableMemorySlot &slot, OpBuilder & /*builder*/
169) {
170 assert(slot.ptr == getResult());
171 this->erase();
172 return std::nullopt;
173}
174
176SmallVector<MemorySlot> CreateArrayOp::getPromotableSlots() {
177 ArrayType arrType = getType();
178 if (!arrType.hasStaticShape()) {
179 return {};
180 }
181 // Can only support arrays containing a single element (the SROA pass can be run first to
182 // destructure all arrays into size-1 arrays).
183 if (arrType.getNumElements() != 1) {
184 return {};
185 }
186 return {MemorySlot {getResult(), arrType.getElementType()}};
187}
188
190Value CreateArrayOp::getDefaultValue(const MemorySlot &slot, OpBuilder &builder) {
191 return builder.create<llzk::NonDetOp>(getLoc(), slot.elemType);
192}
193
195void CreateArrayOp::handleBlockArgument(const MemorySlot &, BlockArgument, OpBuilder &) {}
196
198std::optional<PromotableAllocationOpInterface> CreateArrayOp::handlePromotionComplete(
199 const MemorySlot & /*slot*/, Value defaultValue, OpBuilder & /*builder*/
200) {
201 if (defaultValue.use_empty()) {
202 defaultValue.getDefiningOp()->erase();
203 } else {
204 this->erase();
205 }
206 // Return `nullopt` because it produces only a single slot
207 return std::nullopt;
208}
209
210//===------------------------------------------------------------------===//
211// ArrayAccessOpInterface
212//===------------------------------------------------------------------===//
213
217 ArrayType arrTy = getArrRefType();
218 if (arrTy.hasStaticShape()) {
219 if (auto converted = ArrayIndexGen::from(arrTy).checkAndConvert(getIndices())) {
220 return ArrayAttr::get(getContext(), *converted);
221 }
222 }
223 return nullptr;
224}
225
227SmallVector<Value>
228ArrayAccessOpInterface::genIndexConstants(OpBuilder &bldr, Location loc, ArrayAttr index) {
229 SmallVector<Value> indices;
230 indices.reserve(index.size());
231 for (Attribute attr : index) {
232 // Note: array index must be an integer attribute.
233 indices.push_back(bldr.create<arith::ConstantOp>(loc, llvm::cast<IntegerAttr>(attr)));
234 }
235 return indices;
236}
237
240 OpBuilder &bldr, Location loc, Value arrayRef, ValueRange indices
241) {
242 ArrayType arrTy = llvm::cast<ArrayType>(arrayRef.getType());
243 Type selectedType = arrTy.getSelectionType(indices.size());
244 if (llvm::isa<ArrayType>(selectedType)) {
245 return bldr.create<ExtractArrayOp>(loc, selectedType, arrayRef, indices);
246 }
247 return bldr.create<ReadArrayOp>(loc, selectedType, arrayRef, indices);
248}
249
252 OpBuilder &bldr, Location loc, Value arrayRef, ArrayAttr index
253) {
254 SmallVector<Value> indices = genIndexConstants(bldr, loc, index);
255 return genRead(bldr, loc, arrayRef, indices);
256}
257
260 OpBuilder &bldr, Location loc, Value arrayRef, ValueRange indices, Value value
261) {
262 ArrayType arrTy = llvm::cast<ArrayType>(arrayRef.getType());
263 Type selectedType = arrTy.getSelectionType(indices.size());
264 if (llvm::isa<ArrayType>(selectedType)) {
265 bldr.create<InsertArrayOp>(loc, arrayRef, indices, value);
266 return;
267 }
268 bldr.create<WriteArrayOp>(loc, arrayRef, indices, value);
269}
270
273 OpBuilder &bldr, Location loc, Value arrayRef, ArrayAttr index, Value value
274) {
275 SmallVector<Value> indices = genIndexConstants(bldr, loc, index);
276 genWrite(bldr, loc, arrayRef, indices, value);
277}
278
281 const DestructurableMemorySlot &slot, SmallPtrSetImpl<Attribute> &usedIndices,
282 SmallVectorImpl<MemorySlot> & /*mustBeSafelyUsed*/, const DataLayout & /*dataLayout*/
283) {
284 if (slot.ptr != getArrRef()) {
285 return false;
286 }
287
288 ArrayAttr indexAsAttr = indexOperandsToAttributeArray();
289 if (!indexAsAttr) {
290 return false;
291 }
292
293 // Scalar read/write case has 0 dimensions in the read/write value.
294 if (!getValueOperandDims().empty()) {
295 return false;
296 }
297
298 // Just insert the index.
299 usedIndices.insert(indexAsAttr);
300 return true;
301}
302
305 const DestructurableMemorySlot &slot, DenseMap<Attribute, MemorySlot> &subslots,
306 OpBuilder &builder, const DataLayout & /*dataLayout*/
307) {
308 assert(slot.ptr == getArrRef());
309 assert(slot.elemType == getArrRefType());
310 // ASSERT: non-scalar read/write should have been desugared earlier
311 assert(getValueOperandDims().empty() && "only scalar read/write supported");
312
313 ArrayAttr indexAsAttr = indexOperandsToAttributeArray();
314 assert(indexAsAttr && "canRewire() should have returned false");
315 const MemorySlot &memorySlot = subslots.at(indexAsAttr);
316
317 // Temporarily set insertion point before the current op for what's built below
318 OpBuilder::InsertionGuard guard(builder);
319 builder.setInsertionPoint(this->getOperation());
320
321 // Write to the sub-slot created for the index of `this`, using index 0
322 getArrRefMutable().set(memorySlot.ptr);
323 getIndicesMutable().clear();
324 getIndicesMutable().assign(builder.create<arith::ConstantIndexOp>(getLoc(), 0));
325
326 return DeletionKind::Keep;
327}
328
329//===------------------------------------------------------------------===//
330// ReadArrayOp
331//===------------------------------------------------------------------===//
332
333namespace {
334
335LogicalResult
336ensureNumIndicesMatchDims(ArrayType ty, size_t numIndices, const OwningEmitErrorFn &errFn) {
337 ArrayRef<Attribute> dims = ty.getDimensionSizes();
338 // Ensure the number of provided indices matches the array dimensions
339 auto compare = numIndices <=> dims.size();
340 if (compare != 0) {
341 return errFn().append(
342 "has ", (compare < 0 ? "insufficient" : "too many"), " indexed dimensions: expected ",
343 dims.size(), " but found ", numIndices
344 );
345 }
346 return success();
347}
348
349LogicalResult
350verifyScalarArrayAccess(ArrayType ty, size_t numIndices, const OwningEmitErrorFn &errFn) {
351 if (llvm::isa<NoneType>(ty.getElementType())) {
352 return errFn().append("cannot access a scalar element from array with none element type");
353 }
354 return ensureNumIndicesMatchDims(ty, numIndices, errFn);
355}
356
357} // namespace
358
359LogicalResult ReadArrayOp::verifySymbolUses(SymbolTableCollection &tables) {
360 // Ensure any SymbolRef used in the type are valid
361 return verifyTypeResolution(tables, *this, ArrayRef<Type> {getArrRef().getType(), getType()});
362}
363
365 MLIRContext * /*context*/, std::optional<Location> /*location*/, ReadArrayOpAdaptor adaptor,
366 llvm::SmallVectorImpl<Type> &inferredReturnTypes
367) {
368 inferredReturnTypes.resize(1);
369 Type lvalType = adaptor.getArrRef().getType();
370 assert(llvm::isa<ArrayType>(lvalType)); // per ODS spec of ReadArrayOp
371 inferredReturnTypes[0] = llvm::cast<ArrayType>(lvalType).getElementType();
372 return success();
373}
374
375bool ReadArrayOp::isCompatibleReturnTypes(TypeRange l, TypeRange r) {
376 return singletonTypeListsUnify(l, r);
377}
378
379LogicalResult ReadArrayOp::verify() {
380 return verifyScalarArrayAccess(getArrRefType(), getIndices().size(), getEmitOpErrFn(this));
381}
382
385 const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses,
386 SmallVectorImpl<OpOperand *> & /*newBlockingUses*/, const DataLayout & /*datalayout*/
387) {
388 if (blockingUses.size() != 1) {
389 return false;
390 }
391 Value blockingUse = (*blockingUses.begin())->get();
392 return blockingUse == slot.ptr && getArrRef() == slot.ptr &&
393 getResult().getType() == slot.elemType;
394}
395
398 const MemorySlot & /*slot*/, const SmallPtrSetImpl<OpOperand *> & /*blockingUses*/,
399 OpBuilder & /*builder*/, Value reachingDefinition, const DataLayout & /*dataLayout*/
400) {
401 // `canUsesBeRemoved` checked this blocking use must be the loaded `slot.ptr`
402 getResult().replaceAllUsesWith(reachingDefinition);
403 return DeletionKind::Delete;
404}
405
406//===------------------------------------------------------------------===//
407// WriteArrayOp
408//===------------------------------------------------------------------===//
409
410LogicalResult WriteArrayOp::verifySymbolUses(SymbolTableCollection &tables) {
411 // Ensure any SymbolRef used in the type are valid
413 tables, *this, ArrayRef<Type> {getArrRefType(), getRvalue().getType()}
414 );
415}
416
417LogicalResult WriteArrayOp::verify() {
418 return verifyScalarArrayAccess(getArrRefType(), getIndices().size(), getEmitOpErrFn(this));
419}
420
423 const MemorySlot &slot, const SmallPtrSetImpl<OpOperand *> &blockingUses,
424 SmallVectorImpl<OpOperand *> & /*newBlockingUses*/, const DataLayout & /*datalayout*/
425) {
426 if (blockingUses.size() != 1) {
427 return false;
428 }
429 Value blockingUse = (*blockingUses.begin())->get();
430 return blockingUse == slot.ptr && getArrRef() == slot.ptr && getRvalue() != slot.ptr &&
431 getRvalue().getType() == slot.elemType;
432}
433
436 const MemorySlot &, const SmallPtrSetImpl<OpOperand *> &, OpBuilder &, Value, const DataLayout &
437) {
438 return DeletionKind::Delete;
439}
440
441//===------------------------------------------------------------------===//
442// ExtractArrayOp
443//===------------------------------------------------------------------===//
444
445LogicalResult ExtractArrayOp::verifySymbolUses(SymbolTableCollection &tables) {
446 // Ensure any SymbolRef used in the type are valid
447 return verifyTypeResolution(tables, *this, getArrRefType());
448}
449
451 MLIRContext * /*context*/, std::optional<Location> location, ExtractArrayOpAdaptor adaptor,
452 llvm::SmallVectorImpl<Type> &inferredReturnTypes
453) {
454 size_t numToSkip = adaptor.getIndices().size();
455 Type arrRefType = adaptor.getArrRef().getType();
456 assert(llvm::isa<ArrayType>(arrRefType)); // per ODS spec of ExtractArrayOp
457 ArrayType arrRefArrType = llvm::cast<ArrayType>(arrRefType);
458
459 // Check for invalid cases
460 auto compare = numToSkip <=> arrRefArrType.getDimensionSizes().size();
461 if (compare == 0) {
462 return mlir::emitOptionalError(
463 location, '\'', ExtractArrayOp::getOperationName(),
464 "' op cannot select all dimensions of an array. Use '", ReadArrayOp::getOperationName(),
465 "' instead."
466 );
467 } else if (compare > 0) {
468 return mlir::emitOptionalError(
469 location, '\'', ExtractArrayOp::getOperationName(),
470 "' op cannot select more dimensions than exist in the source array"
471 );
472 }
473
474 // Generate and store reduced array type
475 inferredReturnTypes.resize(1);
476 inferredReturnTypes[0] = arrRefArrType.getSelectionType(numToSkip);
477 return success();
478}
479
480bool ExtractArrayOp::isCompatibleReturnTypes(TypeRange l, TypeRange r) {
481 return singletonTypeListsUnify(l, r);
482}
483
484//===------------------------------------------------------------------===//
485// InsertArrayOp
486//===------------------------------------------------------------------===//
487
488LogicalResult InsertArrayOp::verifySymbolUses(SymbolTableCollection &tables) {
489 // Ensure any SymbolRef used in the types are valid
491 tables, *this, ArrayRef<Type> {getArrRefType(), getRvalue().getType()}
492 );
493}
494
495LogicalResult InsertArrayOp::verify() {
496 ArrayType baseArrRefArrType = getArrRefType();
497 Type rValueType = getRvalue().getType();
498 assert(llvm::isa<ArrayType>(rValueType)); // per ODS spec of InsertArrayOp
499 ArrayType rValueArrType = llvm::cast<ArrayType>(rValueType);
500
501 // size of lhs dimensions == numIndices + size of rhs dimensions
502 size_t lhsDims = baseArrRefArrType.getDimensionSizes().size();
503 size_t numIndices = getIndices().size();
504 size_t rhsDims = rValueArrType.getDimensionSizes().size();
505
506 // Ensure the number of indices specified does not exceed base dimension count.
507 if (numIndices > lhsDims) {
508 return emitOpError("cannot select more dimensions than exist in the source array");
509 }
510
511 // Ensure the rValue dimension count equals the base reduced dimension count
512 auto compare = (numIndices + rhsDims) <=> lhsDims;
513 if (compare != 0) {
514 return emitOpError().append(
515 "has ", (compare < 0 ? "insufficient" : "too many"), " indexed dimensions: expected ",
516 (lhsDims - rhsDims), " but found ", numIndices
517 );
518 }
519
520 // Having verified the indices are of appropriate size, we verify the subarray type.
521 // This will verify the dimensions of the subarray, which is why we only check the
522 // size of the indices above.
523 return verifySubArrayType(getEmitOpErrFn(this), baseArrRefArrType, rValueArrType);
524}
525
526//===------------------------------------------------------------------===//
527// ArrayLengthOp
528//===------------------------------------------------------------------===//
529
530LogicalResult ArrayLengthOp::verifySymbolUses(SymbolTableCollection &tables) {
531 // Ensure any SymbolRef used in the type are valid
532 if (failed(verifyTypeResolution(tables, *this, getArrRefType()))) {
533 return failure();
534 }
535
536 auto dimValue = getDim();
537 llvm::APInt dim;
538 if (!matchPattern(dimValue, m_ConstantInt(&dim))) {
539 return success();
540 }
541
542 std::optional<int64_t> idxOpt = dim.trySExtValue();
543 if (!idxOpt || *idxOpt < 0) {
544 auto diag = emitOpError("dimension must be a non-negative 64-bit integer");
545 if (!llvm::isa<UnknownLoc>(dimValue.getLoc())) {
546 diag.attachNote(dimValue.getLoc()).append("dimension defined here");
547 }
548 return diag;
549 }
550 size_t idx = checkedCast<size_t>(*idxOpt);
551 size_t rank = getArrRefType().getDimensionSizes().size();
552 if (idx >= rank) {
553 InFlightDiagnostic diag = emitOpError().append(
554 "dimension index ", idx, " is not valid for array with ", rank, " dimensions"
555 );
556 if (!llvm::isa<UnknownLoc>(getArrRef().getLoc())) {
557 diag.attachNote(getArrRef().getLoc()).append("array defined here");
558 }
559 if (!llvm::isa<UnknownLoc>(dimValue.getLoc())) {
560 diag.attachNote(dimValue.getLoc()).append("dimension defined here");
561 }
562 return diag;
563 }
564 return success();
565}
566
567} // namespace llzk::array
::mlir::DeletionKind rewire(const ::mlir::DestructurableMemorySlot &slot, ::llvm::DenseMap<::mlir::Attribute, ::mlir::MemorySlot > &subslots, ::mlir::OpBuilder &builder, const ::mlir::DataLayout &dataLayout)
Required by companion interface DestructurableAccessorOpInterface / SROA pass.
Definition Ops.cpp:304
static void genWrite(::mlir::OpBuilder &bldr, ::mlir::Location loc, ::mlir::Value arrayRef, ::mlir::ValueRange indices, ::mlir::Value value)
Create an array.write or array.insert for one concrete element or subarray.
::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.
::mlir::Value genRead(::mlir::OpBuilder &bldr, ::mlir::Location loc, ::mlir::Value arrayRef, ::mlir::ValueRange indices)
Create an array.read or array.extract for one concrete element or subarray.
inline ::mlir::ArrayRef<::mlir::Attribute > getValueOperandDims()
Compute the dimensions of the read/write value.
::mlir::ArrayAttr indexOperandsToAttributeArray()
Returns the multi-dimensional indices of the array access as an Attribute array or a null pointer if ...
Definition Ops.cpp:216
static ::llvm::SmallVector<::mlir::Value > genIndexConstants(::mlir::OpBuilder &bldr, ::mlir::Location loc, ::mlir::ArrayAttr index)
Generate arith.constant indices for one static array element position.
Definition Ops.cpp:228
::mlir::TypedValue<::llzk::array::ArrayType > getArrRef()
Gets the SSA Value for the referenced array.
bool canRewire(const ::mlir::DestructurableMemorySlot &slot, ::llvm::SmallPtrSetImpl<::mlir::Attribute > &usedIndices, ::mlir::SmallVectorImpl<::mlir::MemorySlot > &mustBeSafelyUsed, const ::mlir::DataLayout &dataLayout)
Required by companion interface DestructurableAccessorOpInterface / SROA pass.
Definition Ops.cpp:280
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.
Definition Ops.h.inc:192
::mlir::TypedValue<::llzk::array::ArrayType > getArrRef()
Definition Ops.h.inc:146
::llvm::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
Definition Ops.cpp:530
::mlir::TypedValue<::mlir::IndexType > getDim()
Definition Ops.h.inc:150
::mlir::Type getElementType() const
::std::optional<::llvm::DenseMap<::mlir::Attribute, ::mlir::Type > > getSubelementIndexMap() const
Required by DestructurableTypeInterface / SROA pass.
Definition Types.cpp:120
::mlir::Type getSelectionType(size_t numIndices) const
Return the type produced by selecting/removing numIndices leading dimensions.
Definition Types.cpp:145
::llvm::ArrayRef<::mlir::Attribute > getDimensionSizes() const
static void build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::llzk::array::ArrayType result, ::mlir::ValueRange elements={})
::mlir::TypedValue<::llzk::array::ArrayType > getResult()
Definition Ops.h.inc:408
::llvm::SmallVector<::mlir::DestructurableMemorySlot > getDestructurableSlots()
Required by DestructurableAllocationOpInterface / SROA pass.
Definition Ops.cpp:124
::std::optional<::mlir::PromotableAllocationOpInterface > handlePromotionComplete(const ::mlir::MemorySlot &slot, ::mlir::Value defaultValue, ::mlir::OpBuilder &builder)
Required by PromotableAllocationOpInterface / mem2reg pass.
Definition Ops.cpp:198
::std::optional<::mlir::DestructurableAllocationOpInterface > handleDestructuringComplete(const ::mlir::DestructurableMemorySlot &slot, ::mlir::OpBuilder &builder)
Required by DestructurableAllocationOpInterface / SROA pass.
Definition Ops.cpp:167
::llvm::LogicalResult verify()
Definition Ops.cpp:105
::mlir::Value getDefaultValue(const ::mlir::MemorySlot &slot, ::mlir::OpBuilder &builder)
Required by PromotableAllocationOpInterface / mem2reg pass.
Definition Ops.cpp:190
::llvm::SmallVector<::mlir::MemorySlot > getPromotableSlots()
Required by PromotableAllocationOpInterface / mem2reg pass.
Definition Ops.cpp:176
::llvm::DenseMap<::mlir::Attribute, ::mlir::MemorySlot > destructure(const ::mlir::DestructurableMemorySlot &slot, const ::llvm::SmallPtrSetImpl<::mlir::Attribute > &usedIndices, ::mlir::OpBuilder &builder, ::mlir::SmallVectorImpl<::mlir::DestructurableAllocationOpInterface > &newAllocators)
Required by DestructurableAllocationOpInterface / SROA pass.
Definition Ops.cpp:137
::llvm::ArrayRef< int32_t > getNumDimsPerMap()
Definition Ops.cpp.inc:541
void getAsmResultNames(::mlir::OpAsmSetValueNameFn setNameFn)
Definition Ops.cpp:76
void handleBlockArgument(const ::mlir::MemorySlot &slot, ::mlir::BlockArgument argument, ::mlir::OpBuilder &builder)
Required by PromotableAllocationOpInterface / mem2reg pass.
Definition Ops.cpp:195
::mlir::OperandRangeRange getMapOperands()
Definition Ops.h.inc:392
::mlir::Operation::operand_range getElements()
Definition Ops.h.inc:388
::llvm::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
Definition Ops.cpp:71
static bool isCompatibleReturnTypes(::mlir::TypeRange l, ::mlir::TypeRange r)
Definition Ops.cpp:480
::llvm::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
Definition Ops.cpp:445
::llvm::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)
inline ::llzk::array::ArrayType getArrRefType()
Gets the type of the referenced base array.
Definition Ops.h.inc:640
static constexpr ::llvm::StringLiteral getOperationName()
Definition Ops.h.inc:578
inline ::llzk::array::ArrayType getArrRefType()
Gets the type of the referenced base array.
Definition Ops.h.inc:794
::mlir::Operation::operand_range getIndices()
Definition Ops.h.inc:753
::llvm::LogicalResult verify()
Definition Ops.cpp:495
::mlir::TypedValue<::llzk::array::ArrayType > getRvalue()
Definition Ops.h.inc:757
::llvm::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
Definition Ops.cpp:488
::mlir::DeletionKind removeBlockingUses(const ::mlir::MemorySlot &slot, const ::llvm::SmallPtrSetImpl< mlir::OpOperand * > &blockingUses, ::mlir::OpBuilder &builder, ::mlir::Value reachingDefinition, const ::mlir::DataLayout &dataLayout)
Required by PromotableMemOpInterface / mem2reg pass.
Definition Ops.cpp:397
inline ::llzk::array::ArrayType getArrRefType()
Gets the type of the referenced base array.
Definition Ops.h.inc:961
::mlir::TypedValue<::mlir::Type > getResult()
Definition Ops.h.inc:923
::mlir::TypedValue<::llzk::array::ArrayType > getArrRef()
Definition Ops.h.inc:899
::mlir::Operation::operand_range getIndices()
Definition Ops.h.inc:903
::llvm::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)
::llvm::LogicalResult verify()
Definition Ops.cpp:379
::llvm::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
Definition Ops.cpp:359
static constexpr ::llvm::StringLiteral getOperationName()
Definition Ops.h.inc:888
static bool isCompatibleReturnTypes(::mlir::TypeRange l, ::mlir::TypeRange r)
Definition Ops.cpp:375
bool canUsesBeRemoved(const ::mlir::MemorySlot &slot, const ::llvm::SmallPtrSetImpl<::mlir::OpOperand * > &blockingUses, ::llvm::SmallVectorImpl<::mlir::OpOperand * > &newBlockingUses, const ::mlir::DataLayout &datalayout)
Required by PromotableMemOpInterface / mem2reg pass.
Definition Ops.cpp:384
::llvm::LogicalResult verify()
Definition Ops.cpp:417
::mlir::Operation::operand_range getIndices()
Definition Ops.h.inc:1074
inline ::llzk::array::ArrayType getArrRefType()
Gets the type of the referenced base array.
Definition Ops.h.inc:1125
bool canUsesBeRemoved(const ::mlir::MemorySlot &slot, const ::llvm::SmallPtrSetImpl<::mlir::OpOperand * > &blockingUses, ::llvm::SmallVectorImpl<::mlir::OpOperand * > &newBlockingUses, const ::mlir::DataLayout &datalayout)
Required by PromotableMemOpInterface / mem2reg pass.
Definition Ops.cpp:422
::mlir::DeletionKind removeBlockingUses(const ::mlir::MemorySlot &slot, const ::llvm::SmallPtrSetImpl< mlir::OpOperand * > &blockingUses, ::mlir::OpBuilder &builder, ::mlir::Value reachingDefinition, const ::mlir::DataLayout &dataLayout)
Required by PromotableMemOpInterface / mem2reg pass.
Definition Ops.cpp:435
::mlir::TypedValue<::llzk::array::ArrayType > getArrRef()
Definition Ops.h.inc:1070
::llvm::LogicalResult verifySymbolUses(::mlir::SymbolTableCollection &symbolTable)
Definition Ops.cpp:410
::mlir::TypedValue<::mlir::Type > getRvalue()
Definition Ops.h.inc:1078
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,...
LogicalResult verifySubArrayType(EmitErrorFn emitError, ArrayType arrayType, ArrayType subArrayType)
Determine if the subArrayType is a valid subarray of arrayType.
bool singletonTypeListsUnify(Iter1 lhs, Iter2 rhs, mlir::ArrayRef< llvm::StringRef > rhsReversePrefix={}, UnificationMap *unifications=nullptr)
Definition TypeHelper.h:288
constexpr T checkedCast(U u) noexcept
Definition Compare.h:81
LogicalResult verifyTypeResolution(SymbolTableCollection &tables, Operation *origin, Type ty)
OwningEmitErrorFn getEmitOpErrFn(mlir::Operation *op)
std::function< InFlightDiagnosticWrapper()> OwningEmitErrorFn
This type is required in cases like the functions below to take ownership of the lambda so it is not ...