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 builder.
create<LLVM::DbgValueOp>(declareOp.getLoc(), argument,
49 declareOp.getVarInfo(),
50 declareOp.getLocationExpr());
53 std::optional<PromotableAllocationOpInterface>
54 LLVM::AllocaOp::handlePromotionComplete(
const MemorySlot &slot,
57 if (defaultValue && defaultValue.
use_empty())
67 auto destructurable = dyn_cast<DestructurableTypeInterface>(getElemType());
71 std::optional<DenseMap<Attribute, Type>> destructuredType =
72 destructurable.getSubelementIndexMap();
73 if (!destructuredType)
84 assert(slot.
ptr == getResult());
87 auto destructurableType = cast<DestructurableTypeInterface>(getElemType());
90 Type elemType = destructurableType.getTypeAtIndex(index);
91 assert(elemType &&
"used index must exist");
92 auto subAlloca = builder.
create<LLVM::AllocaOp>(
95 newAllocators.push_back(subAlloca);
96 slotMap.try_emplace<
MemorySlot>(index, {subAlloca.getResult(), elemType});
102 std::optional<DestructurableAllocationOpInterface>
103 LLVM::AllocaOp::handleDestructuringComplete(
105 assert(slot.
ptr == getResult());
114 bool LLVM::LoadOp::loadsFrom(
const MemorySlot &slot) {
115 return getAddr() == slot.
ptr;
118 bool LLVM::LoadOp::storesTo(
const MemorySlot &slot) {
return false; }
122 llvm_unreachable(
"getStored should not be called on LoadOp");
125 bool LLVM::StoreOp::loadsFrom(
const MemorySlot &slot) {
return false; }
127 bool LLVM::StoreOp::storesTo(
const MemorySlot &slot) {
128 return getAddr() == slot.
ptr;
134 if (isa<LLVM::LLVMStructType, LLVM::LLVMArrayType>(type))
140 if (isa<LLVM::LLVMFixedVectorType, LLVM::LLVMScalableVectorType>(type))
144 if (
auto vectorType = dyn_cast<VectorType>(type))
145 return !vectorType.isScalable();
153 Type srcType,
bool narrowingConversion) {
154 if (targetType == srcType)
161 uint64_t targetSize = layout.
getTypeSize(targetType);
166 if (isa<LLVM::LLVMPointerType>(targetType) &&
167 isa<LLVM::LLVMPointerType>(srcType))
168 return targetSize == srcSize;
170 if (narrowingConversion)
171 return targetSize <= srcSize;
172 return targetSize >= srcSize;
177 auto endiannessStr = dyn_cast_or_null<StringAttr>(dataLayout.
getEndianness());
178 return endiannessStr && endiannessStr ==
"big";
187 "expected value to have a convertible type");
189 if (isa<IntegerType>(type))
193 IntegerType valueSizeInteger = builder.
getIntegerType(typeBitSize);
195 if (isa<LLVM::LLVMPointerType>(type))
196 return builder.
createOrFold<LLVM::PtrToIntOp>(loc, valueSizeInteger, val);
197 return builder.
createOrFold<LLVM::BitcastOp>(loc, valueSizeInteger, val);
203 assert(isa<IntegerType>(val.
getType()) &&
204 "expected value to have an integer type");
206 "expected the target type to be supported for conversions");
207 if (val.
getType() == targetType)
209 if (isa<LLVM::LLVMPointerType>(targetType))
210 return builder.
createOrFold<LLVM::IntToPtrOp>(loc, targetType, val);
211 return builder.
createOrFold<LLVM::BitcastOp>(loc, targetType, val);
222 "expected that the compatibility was checked before");
225 if (srcType == targetType)
232 if (isa<LLVM::LLVMPointerType>(targetType) &&
233 isa<LLVM::LLVMPointerType>(srcType))
234 return builder.
createOrFold<LLVM::AddrSpaceCastOp>(loc, targetType,
252 "expected that the compatibility was checked before");
256 if (srcTypeSize == targetTypeSize)
264 uint64_t shiftAmount = srcTypeSize - targetTypeSize;
265 auto shiftConstant = builder.
create<LLVM::ConstantOp>(
268 builder.
createOrFold<LLVM::LShrOp>(loc, srcValue, shiftConstant);
271 replacement = builder.
create<LLVM::TruncOp>(
288 "expected that the compatibility was checked before");
291 if (slotTypeSize == valueTypeSize)
304 uint64_t sizeDifference = slotTypeSize - valueTypeSize;
309 Value bigEndianShift = builder.
create<LLVM::ConstantOp>(
312 builder.
createOrFold<LLVM::ShlOp>(loc, valueAsInt, bigEndianShift);
321 maskValue = APInt::getAllOnes(sizeDifference).zext(slotTypeSize);
325 maskValue = APInt::getAllOnes(valueTypeSize).zext(slotTypeSize);
326 maskValue.flipAllBits();
345 "expected the reaching definition's type to match the slot's type");
350 bool LLVM::LoadOp::canUsesBeRemoved(
354 if (blockingUses.size() != 1)
356 Value blockingUse = (*blockingUses.begin())->
get();
360 return blockingUse == slot.
ptr && getAddr() == slot.
ptr &&
373 getResult().
getType(), dataLayout);
374 getResult().replaceAllUsesWith(newResult);
378 bool LLVM::StoreOp::canUsesBeRemoved(
382 if (blockingUses.size() != 1)
384 Value blockingUse = (*blockingUses.begin())->
get();
388 return blockingUse == slot.
ptr && getAddr() == slot.
ptr &&
389 getValue() != slot.
ptr &&
410 LogicalResult LLVM::LoadOp::ensureOnlySafeAccesses(
413 return success(getAddr() != slot.
ptr ||
417 LogicalResult LLVM::StoreOp::ensureOnlySafeAccesses(
420 return success(getAddr() != slot.
ptr ||
427 auto subelementIndexMap =
428 cast<DestructurableTypeInterface>(slot.
elemType).getSubelementIndexMap();
429 if (!subelementIndexMap)
431 assert(!subelementIndexMap->empty());
434 return subelementIndexMap->lookup(index);
454 usedIndices.insert(index);
463 auto it = subslots.find(index);
464 assert(it != subslots.end());
466 getAddrMutable().set(it->getSecond().ptr);
478 if (getValue() == slot.
ptr)
492 usedIndices.insert(index);
501 auto it = subslots.find(index);
502 assert(it != subslots.end());
504 getAddrMutable().set(it->getSecond().ptr);
517 newBlockingUses.push_back(&use);
521 bool LLVM::BitcastOp::canUsesBeRemoved(
533 bool LLVM::AddrSpaceCastOp::canUsesBeRemoved(
545 bool LLVM::LifetimeStartOp::canUsesBeRemoved(
557 bool LLVM::LifetimeEndOp::canUsesBeRemoved(
569 bool LLVM::InvariantStartOp::canUsesBeRemoved(
576 DeletionKind LLVM::InvariantStartOp::removeBlockingUses(
581 bool LLVM::InvariantEndOp::canUsesBeRemoved(
593 bool LLVM::DbgDeclareOp::canUsesBeRemoved(
605 bool LLVM::DbgValueOp::canUsesBeRemoved(
610 if (blockingUses.size() != 1)
613 return (*blockingUses.begin())->get() == getValue();
625 builder.
create<UndefOp>(getValue().getLoc(), getValue().getType());
626 getValueMutable().assign(undef);
630 bool LLVM::DbgDeclareOp::requiresReplacedValues() {
return true; }
632 void LLVM::DbgDeclareOp::visitReplacedValues(
634 for (
auto [op, value] : definitions) {
636 builder.
create<LLVM::DbgValueOp>(getLoc(), value, getVarInfo(),
646 return llvm::all_of(gepOp.getIndices(), [](
auto index) {
647 auto indexAttr = llvm::dyn_cast_if_present<IntegerAttr>(index);
648 return indexAttr && indexAttr.getValue() == 0;
652 bool LLVM::GEPOp::canUsesBeRemoved(
673 for (
auto index : gep.getIndices()) {
674 auto constIndex = dyn_cast<IntegerAttr>(index);
677 int64_t gepIndex = constIndex.getInt();
681 indices.push_back(gepIndex);
684 Type currentType = gep.getElemType();
685 uint64_t offset = indices[0] * dataLayout.
getTypeSize(currentType);
687 for (uint64_t index : llvm::drop_begin(indices)) {
690 .Case([&](LLVM::LLVMArrayType arrayType) {
692 index * dataLayout.
getTypeSize(arrayType.getElementType());
693 currentType = arrayType.getElementType();
698 assert(index < body.size() &&
"expected valid struct indexing");
699 for (uint32_t i : llvm::seq(index)) {
701 offset = llvm::alignTo(
708 offset = llvm::alignTo(
710 currentType = body[index];
713 .Default([&](
Type type) {
714 LLVM_DEBUG(llvm::dbgs()
715 <<
"[sroa] Unsupported type for offset computations"
730 struct SubslotAccessInfo {
734 uint64_t subslotOffset;
742 static std::optional<SubslotAccessInfo>
744 const DataLayout &dataLayout, LLVM::GEPOp gep) {
752 auto isOutOfBoundsGEPIndex = [](uint64_t index) {
760 .Case([&](LLVM::LLVMArrayType arrayType)
761 -> std::optional<SubslotAccessInfo> {
763 uint64_t elemSize = dataLayout.
getTypeSize(arrayType.getElementType());
764 uint64_t index = *offset / elemSize;
765 if (isOutOfBoundsGEPIndex(index))
767 return SubslotAccessInfo{
static_cast<uint32_t
>(index),
768 *offset - (index * elemSize)};
771 -> std::optional<SubslotAccessInfo> {
772 uint64_t distanceToStart = 0;
778 distanceToStart = llvm::alignTo(
781 if (offset < distanceToStart)
785 if (offset < distanceToStart + elemSize) {
786 if (isOutOfBoundsGEPIndex(index))
790 return SubslotAccessInfo{
static_cast<uint32_t
>(index),
791 *offset - distanceToStart};
796 distanceToStart += elemSize;
810 LogicalResult LLVM::GEPOp::ensureOnlySafeAccesses(
815 std::optional<uint64_t> gepOffset =
gepToByteOffset(dataLayout, *
this);
820 if (*gepOffset >= slotSize)
838 std::optional<SubslotAccessInfo> accessInfo =
845 usedIndices.insert(indexAttr);
850 uint64_t slotSize = dataLayout.
getTypeSize(subslotType);
851 LLVM::LLVMArrayType remainingSlotType =
853 mustBeSafelyUsed.emplace_back<
MemorySlot>({getRes(), remainingSlotType});
862 std::optional<SubslotAccessInfo> accessInfo =
864 assert(accessInfo &&
"expected access info to be checked before");
867 const MemorySlot &newSlot = subslots.at(indexAttr);
871 getLoc(), getResult().getType(), byteType, newSlot.
ptr,
873 getResult().replaceAllUsesWith(newPtr);
885 template <
class MemIntr>
886 std::optional<uint64_t> getStaticMemIntrLen(MemIntr op) {
890 if (memIntrLen.getBitWidth() > 64)
892 return memIntrLen.getZExtValue();
900 std::optional<uint64_t> getStaticMemIntrLen(LLVM::MemcpyInlineOp op) {
901 APInt memIntrLen = op.getLen();
902 if (memIntrLen.getBitWidth() > 64)
904 return memIntrLen.getZExtValue();
911 template <
class MemIntr>
914 if (!isa<LLVM::LLVMPointerType>(slot.
ptr.
getType()) ||
915 op.getDst() != slot.
ptr)
918 std::optional<uint64_t> memIntrLen = getStaticMemIntrLen(op);
928 auto intIndex = dyn_cast<IntegerAttr>(index);
929 return intIndex && intIndex.getType() == i32;
937 bool LLVM::MemsetOp::loadsFrom(
const MemorySlot &slot) {
return false; }
939 bool LLVM::MemsetOp::storesTo(
const MemorySlot &slot) {
940 return getDst() == slot.
ptr;
948 .Case([&](IntegerType intType) ->
Value {
949 if (intType.getWidth() == 8)
952 assert(intType.getWidth() % 8 == 0);
956 uint64_t coveredBits = 8;
958 builder.
create<LLVM::ZExtOp>(getLoc(), intType, getVal());
959 while (coveredBits < intType.getWidth()) {
961 builder.
create<LLVM::ConstantOp>(getLoc(), intType, coveredBits);
963 builder.
create<LLVM::ShlOp>(getLoc(), currentValue, shiftBy);
965 builder.
create<LLVM::OrOp>(getLoc(), currentValue, shifted);
973 "getStored should not be called on memset to unsupported type");
977 bool LLVM::MemsetOp::canUsesBeRemoved(
982 bool canConvertType =
984 .Case([](IntegerType intType) {
985 return intType.getWidth() % 8 == 0 && intType.getWidth() > 0;
987 .Default([](
Type) {
return false; });
1004 LogicalResult LLVM::MemsetOp::ensureOnlySafeAccesses(
1017 if (getIsVolatile())
1020 if (!cast<DestructurableTypeInterface>(slot.
elemType).getSubelementIndexMap())
1033 std::optional<DenseMap<Attribute, Type>> types =
1034 cast<DestructurableTypeInterface>(slot.
elemType).getSubelementIndexMap();
1036 IntegerAttr memsetLenAttr;
1037 bool successfulMatch =
1038 matchPattern(getLen(), m_Constant<IntegerAttr>(&memsetLenAttr));
1039 (void)successfulMatch;
1040 assert(successfulMatch);
1042 bool packed =
false;
1043 if (
auto structType = dyn_cast<LLVM::LLVMStructType>(slot.
elemType))
1044 packed = structType.isPacked();
1047 uint64_t memsetLen = memsetLenAttr.getValue().getZExtValue();
1048 uint64_t covered = 0;
1049 for (
size_t i = 0; i < types->size(); i++) {
1052 Type elemType = types->at(index);
1053 uint64_t typeSize = dataLayout.
getTypeSize(elemType);
1059 if (covered >= memsetLen)
1064 if (subslots.contains(index)) {
1065 uint64_t newMemsetSize =
std::min(memsetLen - covered, typeSize);
1067 Value newMemsetSizeValue =
1069 .
create<LLVM::ConstantOp>(
1074 builder.
create<LLVM::MemsetOp>(getLoc(), subslots.at(index).ptr, getVal(),
1075 newMemsetSizeValue, getIsVolatile());
1078 covered += typeSize;
1088 template <
class MemcpyLike>
1090 return op.getSrc() == slot.
ptr;
1093 template <
class MemcpyLike>
1095 return op.getDst() == slot.
ptr;
1098 template <
class MemcpyLike>
1104 template <
class MemcpyLike>
1113 if (op.getDst() == op.getSrc())
1116 if (op.getIsVolatile())
1122 template <
class MemcpyLike>
1127 if (op.loadsFrom(slot))
1128 builder.
create<LLVM::StoreOp>(op.
getLoc(), reachingDefinition, op.getDst());
1132 template <
class MemcpyLike>
1133 static LogicalResult
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 = builder.
create<LLVM::ConstantOp>(
1177 builder.
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 builder.
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();
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 = builder.
create<LLVM::GEPOp>(
1231 isDst ? op.getSrc() : op.getDst(), gepIndices);
1234 createMemcpyLikeToReplace(builder, 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);
1275 LogicalResult LLVM::MemcpyOp::ensureOnlySafeAccesses(
1293 return memcpyRewire(*
this, slot, subslots, builder, dataLayout);
1296 bool LLVM::MemcpyInlineOp::loadsFrom(
const MemorySlot &slot) {
1300 bool LLVM::MemcpyInlineOp::storesTo(
const MemorySlot &slot) {
1310 bool LLVM::MemcpyInlineOp::canUsesBeRemoved(
1323 reachingDefinition);
1326 LogicalResult LLVM::MemcpyInlineOp::ensureOnlySafeAccesses(
1332 bool LLVM::MemcpyInlineOp::canRewire(
1345 return memcpyRewire(*
this, slot, subslots, builder, dataLayout);
1348 bool LLVM::MemmoveOp::loadsFrom(
const MemorySlot &slot) {
1352 bool LLVM::MemmoveOp::storesTo(
const MemorySlot &slot) {
1362 bool LLVM::MemmoveOp::canUsesBeRemoved(
1375 reachingDefinition);
1378 LogicalResult LLVM::MemmoveOp::ensureOnlySafeAccesses(
1396 return memcpyRewire(*
this, slot, subslots, builder, dataLayout);
1403 std::optional<DenseMap<Attribute, Type>>
1409 return destructured;
1413 auto indexAttr = llvm::dyn_cast<IntegerAttr>(index);
1414 if (!indexAttr || !indexAttr.getType().isInteger(32))
1416 int32_t indexInt = indexAttr.getInt();
1418 if (indexInt < 0 || body.size() <=
static_cast<uint32_t
>(indexInt))
1420 return body[indexInt];
1423 std::optional<DenseMap<Attribute, Type>>
1424 LLVM::LLVMArrayType::getSubelementIndexMap()
const {
1425 constexpr
size_t maxArraySizeForDestructuring = 16;
1432 for (int32_t index = 0; index < numElements; ++index)
1433 destructured.insert({IntegerAttr::get(i32, index), getElementType()});
1434 return destructured;
1438 auto indexAttr = llvm::dyn_cast<IntegerAttr>(index);
1439 if (!indexAttr || !indexAttr.getType().isInteger(32))
1441 int32_t indexInt = indexAttr.getInt();
1442 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 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 castToSameSizedInt(OpBuilder &builder, Location loc, Value val, const DataLayout &dataLayout)
Converts a value to an integer type of the same size.
static Value castSameSizedTypes(OpBuilder &builder, Location loc, Value srcValue, Type targetType, const DataLayout &dataLayout)
Constructs operations that convert srcValue into a new value of type 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 bool isSupportedTypeForConversion(Type type)
Checks if type can be used in any kind of conversion sequences.
static Value createExtractAndCast(OpBuilder &builder, Location loc, Value srcValue, Type targetType, const DataLayout &dataLayout)
Constructs operations that convert srcValue into a new value of type targetType.
static Value createInsertAndCast(OpBuilder &builder, 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, OpBuilder &builder, Value reachingDefinition)
static bool memcpyCanUsesBeRemoved(MemcpyLike op, const MemorySlot &slot, const SmallPtrSetImpl< OpOperand * > &blockingUses, SmallVectorImpl< OpOperand * > &newBlockingUses, const DataLayout &dataLayout)
static bool isBigEndian(const DataLayout &dataLayout)
Checks if dataLayout describes a little endian layout.
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 memcpyGetStored(MemcpyLike op, const MemorySlot &slot, OpBuilder &builder)
static Value castIntValueToSameSizedType(OpBuilder &builder, Location loc, Value val, Type targetType)
Converts a value with an integer type to targetType.
static DeletionKind memcpyRewire(MemcpyLike op, const DestructurableMemorySlot &slot, DenseMap< Attribute, MemorySlot > &subslots, OpBuilder &builder, const DataLayout &dataLayout)
Rewires a memcpy-like operation.
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.
This class helps build 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()
void erase()
Remove this operation from its parent block and delete it.
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.
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...
Type getType(OpFoldResult ofr)
Returns the int type of the integer in ofr.
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 > subelementTypes
Maps an index within the memory slot to the corresponding subelement type.
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.