20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/ADT/TypeSwitch.h"
23 #define DEBUG_TYPE "sroa"
32 if (!getOperation()->getBlock()->isEntryBlock())
35 return {
MemorySlot{getResult(), getElemType()}};
43 void LLVM::AllocaOp::handleBlockArgument(
const MemorySlot &slot,
46 for (
Operation *user : getOperation()->getUsers())
47 if (
auto declareOp = llvm::dyn_cast<LLVM::DbgDeclareOp>(user))
48 rewriter.
create<LLVM::DbgValueOp>(declareOp.getLoc(), argument,
49 declareOp.getVarInfo(),
50 declareOp.getLocationExpr());
53 void LLVM::AllocaOp::handlePromotionComplete(
const MemorySlot &slot,
56 if (defaultValue && defaultValue.
use_empty())
65 auto destructurable = dyn_cast<DestructurableTypeInterface>(getElemType());
69 std::optional<DenseMap<Attribute, Type>> destructuredType =
70 destructurable.getSubelementIndexMap();
71 if (!destructuredType)
82 assert(slot.
ptr == getResult());
85 auto destructurableType = cast<DestructurableTypeInterface>(getElemType());
88 Type elemType = destructurableType.getTypeAtIndex(index);
89 assert(elemType &&
"used index must exist");
90 auto subAlloca = rewriter.
create<LLVM::AllocaOp>(
93 slotMap.try_emplace<
MemorySlot>(index, {subAlloca.getResult(), elemType});
99 void LLVM::AllocaOp::handleDestructuringComplete(
101 assert(slot.
ptr == getResult());
109 bool LLVM::LoadOp::loadsFrom(
const MemorySlot &slot) {
110 return getAddr() == slot.
ptr;
113 bool LLVM::LoadOp::storesTo(
const MemorySlot &slot) {
return false; }
117 llvm_unreachable(
"getStored should not be called on LoadOp");
120 bool LLVM::StoreOp::loadsFrom(
const MemorySlot &slot) {
return false; }
122 bool LLVM::StoreOp::storesTo(
const MemorySlot &slot) {
123 return getAddr() == slot.
ptr;
129 if (isa<LLVM::LLVMStructType, LLVM::LLVMArrayType>(type))
135 if (isa<LLVM::LLVMFixedVectorType, LLVM::LLVMScalableVectorType>(type))
139 if (
auto vectorType = dyn_cast<VectorType>(type))
140 return !vectorType.isScalable();
148 Type srcType,
bool narrowingConversion) {
149 if (targetType == srcType)
156 uint64_t targetSize = layout.
getTypeSize(targetType);
161 if (isa<LLVM::LLVMPointerType>(targetType) &&
162 isa<LLVM::LLVMPointerType>(srcType))
163 return targetSize == srcSize;
165 if (narrowingConversion)
166 return targetSize <= srcSize;
167 return targetSize >= srcSize;
172 auto endiannessStr = dyn_cast_or_null<StringAttr>(dataLayout.
getEndianness());
173 return endiannessStr && endiannessStr ==
"big";
182 "expected value to have a convertible type");
184 if (isa<IntegerType>(type))
188 IntegerType valueSizeInteger = rewriter.
getIntegerType(typeBitSize);
190 if (isa<LLVM::LLVMPointerType>(type))
191 return rewriter.
createOrFold<LLVM::PtrToIntOp>(loc, valueSizeInteger, val);
192 return rewriter.
createOrFold<LLVM::BitcastOp>(loc, valueSizeInteger, val);
198 assert(isa<IntegerType>(val.
getType()) &&
199 "expected value to have an integer type");
201 "expected the target type to be supported for conversions");
202 if (val.
getType() == targetType)
204 if (isa<LLVM::LLVMPointerType>(targetType))
205 return rewriter.
createOrFold<LLVM::IntToPtrOp>(loc, targetType, val);
206 return rewriter.
createOrFold<LLVM::BitcastOp>(loc, targetType, val);
217 "expected that the compatibility was checked before");
220 if (srcType == targetType)
227 if (isa<LLVM::LLVMPointerType>(targetType) &&
228 isa<LLVM::LLVMPointerType>(srcType))
229 return rewriter.
createOrFold<LLVM::AddrSpaceCastOp>(loc, targetType,
247 "expected that the compatibility was checked before");
251 if (srcTypeSize == targetTypeSize)
259 uint64_t shiftAmount = srcTypeSize - targetTypeSize;
260 auto shiftConstant = rewriter.
create<LLVM::ConstantOp>(
263 rewriter.
createOrFold<LLVM::LShrOp>(loc, srcValue, shiftConstant);
266 replacement = rewriter.
create<LLVM::TruncOp>(
283 "expected that the compatibility was checked before");
286 if (slotTypeSize == valueTypeSize)
299 uint64_t sizeDifference = slotTypeSize - valueTypeSize;
304 Value bigEndianShift = rewriter.
create<LLVM::ConstantOp>(
307 rewriter.
createOrFold<LLVM::ShlOp>(loc, valueAsInt, bigEndianShift);
316 maskValue = APInt::getAllOnes(sizeDifference).zext(slotTypeSize);
320 maskValue = APInt::getAllOnes(valueTypeSize).zext(slotTypeSize);
321 maskValue.flipAllBits();
340 "expected the reaching definition's type to match the slot's type");
345 bool LLVM::LoadOp::canUsesBeRemoved(
349 if (blockingUses.size() != 1)
351 Value blockingUse = (*blockingUses.begin())->
get();
355 return blockingUse == slot.
ptr && getAddr() == slot.
ptr &&
368 getResult().getType(), dataLayout);
373 bool LLVM::StoreOp::canUsesBeRemoved(
377 if (blockingUses.size() != 1)
379 Value blockingUse = (*blockingUses.begin())->
get();
383 return blockingUse == slot.
ptr && getAddr() == slot.
ptr &&
384 getValue() != slot.
ptr &&
386 getValue().getType(),
422 auto subelementIndexMap =
423 cast<DestructurableTypeInterface>(slot.
elemType).getSubelementIndexMap();
424 if (!subelementIndexMap)
426 assert(!subelementIndexMap->empty());
429 return subelementIndexMap->lookup(index);
449 usedIndices.insert(index);
458 auto it = subslots.find(index);
459 assert(it != subslots.end());
462 *
this, [&]() { getAddrMutable().set(it->getSecond().ptr); });
474 if (getValue() == slot.
ptr)
488 usedIndices.insert(index);
497 auto it = subslots.find(index);
498 assert(it != subslots.end());
501 *
this, [&]() { getAddrMutable().set(it->getSecond().ptr); });
514 newBlockingUses.push_back(&use);
518 bool LLVM::BitcastOp::canUsesBeRemoved(
530 bool LLVM::AddrSpaceCastOp::canUsesBeRemoved(
542 bool LLVM::LifetimeStartOp::canUsesBeRemoved(
554 bool LLVM::LifetimeEndOp::canUsesBeRemoved(
566 bool LLVM::InvariantStartOp::canUsesBeRemoved(
573 DeletionKind LLVM::InvariantStartOp::removeBlockingUses(
578 bool LLVM::InvariantEndOp::canUsesBeRemoved(
590 bool LLVM::DbgDeclareOp::canUsesBeRemoved(
602 bool LLVM::DbgValueOp::canUsesBeRemoved(
607 if (blockingUses.size() != 1)
610 return (*blockingUses.begin())->get() == getValue();
622 rewriter.
create<UndefOp>(getValue().getLoc(), getValue().getType());
623 rewriter.
modifyOpInPlace(*
this, [&] { getValueMutable().assign(undef); });
627 bool LLVM::DbgDeclareOp::requiresReplacedValues() {
return true; }
629 void LLVM::DbgDeclareOp::visitReplacedValues(
630 ArrayRef<std::pair<Operation *, Value>> definitions,
632 for (
auto [op, value] : definitions) {
634 rewriter.
create<LLVM::DbgValueOp>(getLoc(), value, getVarInfo(),
644 return llvm::all_of(gepOp.getIndices(), [](
auto index) {
645 auto indexAttr = llvm::dyn_cast_if_present<IntegerAttr>(index);
646 return indexAttr && indexAttr.getValue() == 0;
650 bool LLVM::GEPOp::canUsesBeRemoved(
671 for (
auto index : gep.getIndices()) {
672 auto constIndex = dyn_cast<IntegerAttr>(index);
675 int64_t gepIndex = constIndex.getInt();
679 indices.push_back(gepIndex);
682 Type currentType = gep.getElemType();
683 uint64_t offset = indices[0] * dataLayout.
getTypeSize(currentType);
685 for (uint64_t index : llvm::drop_begin(indices)) {
688 .Case([&](LLVM::LLVMArrayType arrayType) {
690 index * dataLayout.
getTypeSize(arrayType.getElementType());
691 currentType = arrayType.getElementType();
696 assert(index < body.size() &&
"expected valid struct indexing");
697 for (uint32_t i : llvm::seq(index)) {
699 offset = llvm::alignTo(
706 offset = llvm::alignTo(
708 currentType = body[index];
711 .Default([&](
Type type) {
712 LLVM_DEBUG(llvm::dbgs()
713 <<
"[sroa] Unsupported type for offset computations"
728 struct SubslotAccessInfo {
732 uint64_t subslotOffset;
740 static std::optional<SubslotAccessInfo>
742 const DataLayout &dataLayout, LLVM::GEPOp gep) {
750 auto isOutOfBoundsGEPIndex = [](uint64_t index) {
758 .Case([&](LLVM::LLVMArrayType arrayType)
759 -> std::optional<SubslotAccessInfo> {
761 uint64_t elemSize = dataLayout.
getTypeSize(arrayType.getElementType());
762 uint64_t index = *offset / elemSize;
763 if (isOutOfBoundsGEPIndex(index))
765 return SubslotAccessInfo{
static_cast<uint32_t
>(index),
766 *offset - (index * elemSize)};
769 -> std::optional<SubslotAccessInfo> {
770 uint64_t distanceToStart = 0;
776 distanceToStart = llvm::alignTo(
779 if (offset < distanceToStart)
783 if (offset < distanceToStart + elemSize) {
784 if (isOutOfBoundsGEPIndex(index))
788 return SubslotAccessInfo{
static_cast<uint32_t
>(index),
789 *offset - distanceToStart};
794 distanceToStart += elemSize;
813 std::optional<uint64_t> gepOffset =
gepToByteOffset(dataLayout, *
this);
818 if (*gepOffset >= slotSize)
831 if (!isa<LLVM::LLVMPointerType>(
getBase().getType()))
836 std::optional<SubslotAccessInfo> accessInfo =
843 usedIndices.insert(indexAttr);
848 uint64_t slotSize = dataLayout.
getTypeSize(subslotType);
849 LLVM::LLVMArrayType remainingSlotType =
851 mustBeSafelyUsed.emplace_back<
MemorySlot>({getRes(), remainingSlotType});
860 std::optional<SubslotAccessInfo> accessInfo =
862 assert(accessInfo &&
"expected access info to be checked before");
865 const MemorySlot &newSlot = subslots.at(indexAttr);
869 getLoc(), getResult().getType(), byteType, newSlot.
ptr,
883 template <
class MemIntr>
884 std::optional<uint64_t> getStaticMemIntrLen(MemIntr op) {
888 if (memIntrLen.getBitWidth() > 64)
890 return memIntrLen.getZExtValue();
898 std::optional<uint64_t> getStaticMemIntrLen(LLVM::MemcpyInlineOp op) {
899 APInt memIntrLen = op.getLen();
900 if (memIntrLen.getBitWidth() > 64)
902 return memIntrLen.getZExtValue();
909 template <
class MemIntr>
912 if (!isa<LLVM::LLVMPointerType>(slot.
ptr.
getType()) ||
913 op.getDst() != slot.
ptr)
916 std::optional<uint64_t> memIntrLen = getStaticMemIntrLen(op);
924 return llvm::all_of(llvm::make_first_range(slot.
elementPtrs),
926 auto intIndex = dyn_cast<IntegerAttr>(index);
927 return intIndex && intIndex.getType() == i32;
935 bool LLVM::MemsetOp::loadsFrom(
const MemorySlot &slot) {
return false; }
937 bool LLVM::MemsetOp::storesTo(
const MemorySlot &slot) {
938 return getDst() == slot.
ptr;
946 .Case([&](IntegerType intType) ->
Value {
947 if (intType.getWidth() == 8)
950 assert(intType.getWidth() % 8 == 0);
954 uint64_t coveredBits = 8;
956 rewriter.
create<LLVM::ZExtOp>(getLoc(), intType, getVal());
957 while (coveredBits < intType.getWidth()) {
959 rewriter.
create<LLVM::ConstantOp>(getLoc(), intType, coveredBits);
961 rewriter.
create<LLVM::ShlOp>(getLoc(), currentValue, shiftBy);
963 rewriter.
create<LLVM::OrOp>(getLoc(), currentValue, shifted);
971 "getStored should not be called on memset to unsupported type");
975 bool LLVM::MemsetOp::canUsesBeRemoved(
980 bool canConvertType =
982 .Case([](IntegerType intType) {
983 return intType.getWidth() % 8 == 0 && intType.getWidth() > 0;
985 .Default([](
Type) {
return false; });
1015 if (getIsVolatile())
1018 if (!cast<DestructurableTypeInterface>(slot.
elemType).getSubelementIndexMap())
1031 std::optional<DenseMap<Attribute, Type>> types =
1032 cast<DestructurableTypeInterface>(slot.
elemType).getSubelementIndexMap();
1034 IntegerAttr memsetLenAttr;
1035 bool successfulMatch =
1036 matchPattern(getLen(), m_Constant<IntegerAttr>(&memsetLenAttr));
1037 (void)successfulMatch;
1038 assert(successfulMatch);
1040 bool packed =
false;
1041 if (
auto structType = dyn_cast<LLVM::LLVMStructType>(slot.
elemType))
1042 packed = structType.isPacked();
1045 uint64_t memsetLen = memsetLenAttr.getValue().getZExtValue();
1046 uint64_t covered = 0;
1047 for (
size_t i = 0; i < types->size(); i++) {
1050 Type elemType = types->at(index);
1051 uint64_t typeSize = dataLayout.
getTypeSize(elemType);
1057 if (covered >= memsetLen)
1062 if (subslots.contains(index)) {
1063 uint64_t newMemsetSize =
std::min(memsetLen - covered, typeSize);
1065 Value newMemsetSizeValue =
1067 .
create<LLVM::ConstantOp>(
1072 rewriter.
create<LLVM::MemsetOp>(getLoc(), subslots.at(index).ptr,
1073 getVal(), newMemsetSizeValue,
1077 covered += typeSize;
1087 template <
class MemcpyLike>
1089 return op.getSrc() == slot.
ptr;
1092 template <
class MemcpyLike>
1094 return op.getDst() == slot.
ptr;
1097 template <
class MemcpyLike>
1103 template <
class MemcpyLike>
1112 if (op.getDst() == op.getSrc())
1115 if (op.getIsVolatile())
1121 template <
class MemcpyLike>
1126 if (op.loadsFrom(slot))
1127 rewriter.
create<LLVM::StoreOp>(op.
getLoc(), reachingDefinition,
1132 template <
class MemcpyLike>
1143 template <
class MemcpyLike>
1148 if (op.getIsVolatile())
1151 if (!cast<DestructurableTypeInterface>(slot.
elemType).getSubelementIndexMap())
1161 if (op.getSrc() == slot.
ptr)
1163 usedIndices.insert(index);
1170 template <
class MemcpyLike>
1173 Type toCpy,
bool isVolatile) {
1174 Value memcpySize = rewriter.
create<LLVM::ConstantOp>(
1177 rewriter.
create<MemcpyLike>(toReplace.getLoc(), dst, src, memcpySize,
1183 LLVM::MemcpyInlineOp toReplace,
Value dst,
1184 Value src,
Type toCpy,
bool isVolatile) {
1186 toReplace.getLen().getBitWidth());
1187 rewriter.
create<LLVM::MemcpyInlineOp>(
1188 toReplace.getLoc(), dst, src,
1196 template <
class MemcpyLike>
1201 if (subslots.empty())
1204 assert((slot.
ptr == op.getDst()) != (slot.
ptr == op.getSrc()));
1205 bool isDst = slot.
ptr == op.getDst();
1208 size_t slotsTreated = 0;
1213 Type indexType = cast<IntegerAttr>(subslots.begin()->first).getType();
1214 for (
size_t i = 0, e = slot.
elementPtrs.size(); i != e; i++) {
1216 if (!subslots.contains(index))
1218 const MemorySlot &subslot = subslots.at(index);
1227 0,
static_cast<int32_t
>(
1228 cast<IntegerAttr>(index).getValue().getZExtValue())};
1229 Value subslotPtrInOther = rewriter.
create<LLVM::GEPOp>(
1231 isDst ? op.getSrc() : op.getDst(), gepIndices);
1234 createMemcpyLikeToReplace(rewriter, dataLayout, op,
1235 isDst ? subslot.
ptr : subslotPtrInOther,
1236 isDst ? subslotPtrInOther : subslot.
ptr,
1237 subslot.
elemType, op.getIsVolatile());
1240 assert(subslots.size() == slotsTreated);
1245 bool LLVM::MemcpyOp::loadsFrom(
const MemorySlot &slot) {
1249 bool LLVM::MemcpyOp::storesTo(
const MemorySlot &slot) {
1259 bool LLVM::MemcpyOp::canUsesBeRemoved(
1272 reachingDefinition);
1293 return memcpyRewire(*
this, slot, subslots, rewriter, dataLayout);
1296 bool LLVM::MemcpyInlineOp::loadsFrom(
const MemorySlot &slot) {
1300 bool LLVM::MemcpyInlineOp::storesTo(
const MemorySlot &slot) {
1310 bool LLVM::MemcpyInlineOp::canUsesBeRemoved(
1323 reachingDefinition);
1332 bool LLVM::MemcpyInlineOp::canRewire(
1346 return memcpyRewire(*
this, slot, subslots, rewriter, dataLayout);
1349 bool LLVM::MemmoveOp::loadsFrom(
const MemorySlot &slot) {
1353 bool LLVM::MemmoveOp::storesTo(
const MemorySlot &slot) {
1363 bool LLVM::MemmoveOp::canUsesBeRemoved(
1376 reachingDefinition);
1397 return memcpyRewire(*
this, slot, subslots, rewriter, dataLayout);
1404 std::optional<DenseMap<Attribute, Type>>
1410 return destructured;
1414 auto indexAttr = llvm::dyn_cast<IntegerAttr>(index);
1415 if (!indexAttr || !indexAttr.getType().isInteger(32))
1417 int32_t indexInt = indexAttr.getInt();
1419 if (indexInt < 0 || body.size() <=
static_cast<uint32_t
>(indexInt))
1421 return body[indexInt];
1424 std::optional<DenseMap<Attribute, Type>>
1425 LLVM::LLVMArrayType::getSubelementIndexMap()
const {
1426 constexpr
size_t maxArraySizeForDestructuring = 16;
1433 for (int32_t index = 0; index < numElements; ++index)
1434 destructured.insert({IntegerAttr::get(i32, index), getElementType()});
1435 return destructured;
1439 auto indexAttr = llvm::dyn_cast<IntegerAttr>(index);
1440 if (!indexAttr || !indexAttr.getType().isInteger(32))
1442 int32_t indexInt = indexAttr.getInt();
1443 if (indexInt < 0 ||
getNumElements() <=
static_cast<uint32_t
>(indexInt))
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
static MLIRContext * getContext(OpFoldResult val)
static LLVM::LLVMArrayType getByteArrayType(MLIRContext *context, unsigned size)
Constructs a byte array type of the given size.
static LogicalResult memcpyEnsureOnlySafeAccesses(MemcpyLike op, const MemorySlot &slot, SmallVectorImpl< MemorySlot > &mustBeSafelyUsed)
static Value createInsertAndCast(RewriterBase &rewriter, Location loc, Value srcValue, Value reachingDef, const DataLayout &dataLayout)
Constructs operations that insert the bits of srcValue into the "beginning" of reachingDef (beginning...
static DeletionKind memcpyRemoveBlockingUses(MemcpyLike op, const MemorySlot &slot, const SmallPtrSetImpl< OpOperand * > &blockingUses, RewriterBase &rewriter, Value reachingDefinition)
static std::optional< uint64_t > gepToByteOffset(const DataLayout &dataLayout, LLVM::GEPOp gep)
Returns the amount of bytes the provided GEP elements will offset the pointer by.
static bool areAllIndicesI32(const DestructurableMemorySlot &slot)
Checks whether all indices are i32.
static Value castIntValueToSameSizedType(RewriterBase &rewriter, Location loc, Value val, Type targetType)
Converts a value with an integer type to targetType.
static std::optional< SubslotAccessInfo > getSubslotAccessInfo(const DestructurableMemorySlot &slot, const DataLayout &dataLayout, LLVM::GEPOp gep)
Computes subslot access information for an access into slot with the given offset.
static bool memcpyStoresTo(MemcpyLike op, const MemorySlot &slot)
static Type getTypeAtIndex(const DestructurableMemorySlot &slot, Attribute index)
Returns the subslot's type at the requested index.
static bool areConversionCompatible(const DataLayout &layout, Type targetType, Type srcType, bool narrowingConversion)
Checks that rhs can be converted to lhs by a sequence of casts and truncations.
static bool forwardToUsers(Operation *op, SmallVectorImpl< OpOperand * > &newBlockingUses)
Conditions the deletion of the operation to the removal of all its uses.
static bool memcpyLoadsFrom(MemcpyLike op, const MemorySlot &slot)
static Value createExtractAndCast(RewriterBase &rewriter, Location loc, Value srcValue, Type targetType, const DataLayout &dataLayout)
Constructs operations that convert srcValue into a new value of type targetType.
static bool isSupportedTypeForConversion(Type type)
Checks if type can be used in any kind of conversion sequences.
static bool memcpyCanUsesBeRemoved(MemcpyLike op, const MemorySlot &slot, const SmallPtrSetImpl< OpOperand * > &blockingUses, SmallVectorImpl< OpOperand * > &newBlockingUses, const DataLayout &dataLayout)
static DeletionKind memcpyRewire(MemcpyLike op, const DestructurableMemorySlot &slot, DenseMap< Attribute, MemorySlot > &subslots, RewriterBase &rewriter, const DataLayout &dataLayout)
Rewires a memcpy-like operation.
static bool isBigEndian(const DataLayout &dataLayout)
Checks if dataLayout describes a little endian layout.
static Value castSameSizedTypes(RewriterBase &rewriter, Location loc, Value srcValue, Type targetType, const DataLayout &dataLayout)
Constructs operations that convert srcValue into a new value of type targetType.
static bool hasAllZeroIndices(LLVM::GEPOp gepOp)
static bool isValidAccessType(const MemorySlot &slot, Type accessType, const DataLayout &dataLayout)
Checks if slot can be accessed through the provided access type.
static Value castToSameSizedInt(RewriterBase &rewriter, Location loc, Value val, const DataLayout &dataLayout)
Converts a value to an integer type of the same size.
static Value memcpyGetStored(MemcpyLike op, const MemorySlot &slot, RewriterBase &rewriter)
static bool definitelyWritesOnlyWithinSlot(MemIntr op, const MemorySlot &slot, const DataLayout &dataLayout)
Returns whether one can be sure the memory intrinsic does not write outside of the bounds of the give...
static bool memcpyCanRewire(MemcpyLike op, const DestructurableMemorySlot &slot, SmallPtrSetImpl< Attribute > &usedIndices, SmallVectorImpl< MemorySlot > &mustBeSafelyUsed, const DataLayout &dataLayout)
static Value min(ImplicitLocOpBuilder &builder, Value value, Value bound)
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
static int64_t getNumElements(ShapedType type)
Attributes are known-constant values of operations.
This class represents an argument of a Block.
IntegerAttr getIntegerAttr(Type type, int64_t value)
IntegerType getIntegerType(unsigned width)
MLIRContext * getContext() const
The main mechanism for performing data layout queries.
static DataLayout closest(Operation *op)
Returns the layout of the closest parent operation carrying layout info.
llvm::TypeSize getTypeSize(Type t) const
Returns the size of the given type in the current scope.
uint64_t getTypeABIAlignment(Type t) const
Returns the required alignment of the given type in the current scope.
llvm::TypeSize getTypeSizeInBits(Type t) const
Returns the size in bits of the given type in the current scope.
Attribute getEndianness() const
Returns the specified endianness.
LLVM dialect structure type representing a collection of different-typed elements manipulated togethe...
Type getTypeAtIndex(Attribute index)
Returns which type is stored at a given integer index within the struct.
bool isPacked() const
Checks if a struct is packed.
ArrayRef< Type > getBody() const
Returns the list of element types contained in a non-opaque struct.
std::optional< DenseMap< Attribute, Type > > getSubelementIndexMap()
Destructs the struct into its indexed field types.
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
MLIRContext is the top-level object for a collection of MLIR operations.
void setInsertionPoint(Block *block, Block::iterator insertPoint)
Set the insertion point to the specified location.
void createOrFold(SmallVectorImpl< Value > &results, Location location, Args &&...args)
Create an operation of specific op type at the current insertion point, and immediately try to fold i...
Operation * create(const OperationState &state)
Creates an operation given the fields represented as an OperationState.
void setInsertionPointAfter(Operation *op)
Sets the insertion point to the node after the specified operation, which will cause subsequent inser...
This class represents an operand of an operation.
Operation is the basic unit of execution within MLIR.
MLIRContext * getContext()
Return the context this operation is associated with.
Location getLoc()
The source location the operation was defined or derived from.
result_range getResults()
This class coordinates the application of a rewrite on a set of IR, providing a way for clients to tr...
void replaceAllUsesWith(Value from, Value to)
Find uses of from and replace them with to.
virtual void eraseOp(Operation *op)
This method erases an operation that is known to have no uses.
void modifyOpInPlace(Operation *root, CallableT &&callable)
This method is a utility wrapper around an in-place modification of an operation.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Dialect & getDialect() const
Get the dialect this type is registered to.
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
bool use_empty() const
Returns true if this value has no uses.
MLIRContext * getContext() const
Utility to get the associated MLIRContext that this value is defined in.
Type getType() const
Return the type of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
constexpr int kGEPConstantBitWidth
Bit-width of a 'GEPConstantIndex' within GEPArg.
constexpr void enumerate(std::tuple< Tys... > &tuple, CallbackT &&callback)
Include the generated interface declarations.
bool matchPattern(Value value, const Pattern &pattern)
Entry point for matching a pattern over a Value.
LogicalResult failure(bool isFailure=true)
Utility function to generate a LogicalResult.
detail::constant_int_value_binder m_ConstantInt(IntegerAttr::ValueType *bind_value)
Matches a constant holding a scalar/vector/tensor integer (splat) and writes the integer value to bin...
LogicalResult success(bool isSuccess=true)
Utility function to generate a LogicalResult.
detail::constant_int_predicate_matcher m_One()
Matches a constant scalar / vector splat / tensor splat integer one.
DeletionKind
Returned by operation promotion logic requesting the deletion of an operation.
@ Keep
Keep the operation after promotion.
@ Delete
Delete the operation after promotion.
auto get(MLIRContext *context, Ts &&...params)
Helper method that injects context only if needed, this helps unify some of the attribute constructio...
Memory slot attached with information about its destructuring procedure.
DenseMap< Attribute, Type > elementPtrs
Maps an index within the memory slot to the corresponding subelement type.
This class represents an efficient way to signal success or failure.
Represents a slot in memory.
Value ptr
Pointer to the memory slot, used by operations to refer to it.
Type elemType
Type of the value contained in the slot.