25void PtrDialect::initialize() {
28#include "mlir/Dialect/Ptr/IR/PtrOps.cpp.inc"
31#define GET_ATTRDEF_LIST
32#include "mlir/Dialect/Ptr/IR/PtrOpsAttrs.cpp.inc"
35#define GET_TYPEDEF_LIST
36#include "mlir/Dialect/Ptr/IR/PtrOpsTypes.cpp.inc"
50 if (alignment.value() <= 0)
51 return emitError() <<
"alignment must be positive";
52 if (!llvm::isPowerOf2_64(alignment.value()))
53 return emitError() <<
"alignment must be a power of 2";
61OpFoldResult ConstantOp::fold(FoldAdaptor adaptor) {
return getValue(); }
75 FromPtrOp fromPtr = *
this;
76 while (fromPtr !=
nullptr) {
77 auto toPtr = fromPtr.getPtr().getDefiningOp<ToPtrOp>();
80 if (!toPtr || toPtr.getPtr().getType() != fromPtr.getType())
82 Value md = fromPtr.getMetadata();
84 if (!fromPtr.getType().hasPtrMetadata()) {
85 ptrLike = toPtr.getPtr();
89 mdOp && mdOp.getPtr() == toPtr.getPtr())
90 ptrLike = toPtr.getPtr();
98LogicalResult FromPtrOp::verify() {
100 return emitError() <<
"the result type cannot be `!ptr.ptr`";
101 if (
getType().getMemorySpace() != getPtr().
getType().getMemorySpace()) {
103 <<
"expected the input and output to have the same memory space";
112void GatherOp::getEffects(
119LogicalResult GatherOp::verify() {
123 MemorySpaceAttrInterface ms =
126 if (!ms.isValidLoad(getResult().
getType(), AtomicOrdering::not_atomic,
127 getAlignment(), &dataLayout,
emitDiag))
136 unsigned alignment) {
137 build(builder, state, resultType, ptrs, mask, passthrough,
138 alignment ? std::optional<int64_t>(alignment) : std::nullopt);
146template <
typename OpTy>
149 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
150 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
151 return memOp.emitOpError(
"unsupported ordering '")
152 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
153 if (!memOp.getAlignment())
154 return memOp.emitOpError(
"expected alignment for atomic access");
157 if (memOp.getSyncscope()) {
158 return memOp.emitOpError(
159 "expected syncscope to be null for non-atomic access");
164void LoadOp::getEffects(
173 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
174 getOrdering() != AtomicOrdering::unordered)) {
180LogicalResult LoadOp::verify() {
182 MemorySpaceAttrInterface ms = getPtr().getType().getMemorySpace();
184 if (!ms.isValidLoad(getResult().
getType(), getOrdering(), getAlignment(),
190 {AtomicOrdering::release, AtomicOrdering::acq_rel});
194 Value addr,
unsigned alignment,
bool isVolatile,
195 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
196 AtomicOrdering ordering, StringRef syncscope) {
197 build(builder, state, type, addr,
198 alignment ? std::optional<int64_t>(alignment) : std::nullopt,
199 isVolatile, isNonTemporal, isInvariant, isInvariantGroup, ordering,
200 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
206void MaskedLoadOp::getEffects(
213LogicalResult MaskedLoadOp::verify() {
216 MemorySpaceAttrInterface ms = getPtr().getType().getMemorySpace();
218 if (!ms.isValidLoad(getResult().
getType(), AtomicOrdering::not_atomic,
219 getAlignment(), &dataLayout,
emitDiag))
228 Value passthrough,
unsigned alignment) {
229 build(builder, state, resultType,
ptr, mask, passthrough,
230 alignment ? std::optional<int64_t>(alignment) : std::nullopt);
237void MaskedStoreOp::getEffects(
244LogicalResult MaskedStoreOp::verify() {
247 MemorySpaceAttrInterface ms = getPtr().getType().getMemorySpace();
249 if (!ms.isValidStore(getValue().
getType(), AtomicOrdering::not_atomic,
250 getAlignment(), &dataLayout,
emitDiag))
259 unsigned alignment) {
260 build(builder, state, value,
ptr, mask,
261 alignment ? std::optional<int64_t>(alignment) : std::nullopt);
268void ScatterOp::getEffects(
275LogicalResult ScatterOp::verify() {
279 MemorySpaceAttrInterface ms =
282 if (!ms.isValidStore(getValue().
getType(), AtomicOrdering::not_atomic,
283 getAlignment(), &dataLayout,
emitDiag))
292 build(builder, state, value, ptrs, mask,
293 alignment ? std::optional<int64_t>(alignment) : std::nullopt);
300void StoreOp::getEffects(
309 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
310 getOrdering() != AtomicOrdering::unordered)) {
316LogicalResult StoreOp::verify() {
318 MemorySpaceAttrInterface ms = getPtr().getType().getMemorySpace();
320 if (!ms.isValidStore(getValue().
getType(), getOrdering(), getAlignment(),
326 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
330 Value addr,
unsigned alignment,
bool isVolatile,
331 bool isNonTemporal,
bool isInvariantGroup,
332 AtomicOrdering ordering, StringRef syncscope) {
333 build(builder, state, value, addr,
334 alignment ? std::optional<int64_t>(alignment) : std::nullopt,
335 isVolatile, isNonTemporal, isInvariantGroup, ordering,
336 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
354LogicalResult PtrAddOp::inferReturnTypes(
362 auto offTy = dyn_cast<ShapedType>(offsetType);
365 inferredReturnTypes.push_back(baseType);
368 auto baseTy = dyn_cast<ShapedType>(baseType);
372 inferredReturnTypes.push_back(offTy.clone(baseType));
377 if (offTy.getShape() != baseTy.getShape()) {
389 inferredReturnTypes.push_back(baseType);
397LogicalResult PtrDiffOp::verify() {
399 if (!isa<ShapedType>(getLhs().
getType()))
404 if (getResult().
getType().getTypeID() != getLhs().
getType().getTypeID()) {
405 return emitError() <<
"expected the result to have the same container "
406 "type as the operands when operands are shaped";
412ptr::PtrType PtrDiffOp::getPtrType() {
413 Type lhsType = getLhs().getType();
414 if (
auto shapedType = dyn_cast<ShapedType>(lhsType))
415 return cast<ptr::PtrType>(shapedType.getElementType());
416 return cast<ptr::PtrType>(lhsType);
419Type PtrDiffOp::getIntType() {
420 Type resultType = getResult().getType();
421 if (
auto shapedType = dyn_cast<ShapedType>(resultType))
422 return shapedType.getElementType();
437 ToPtrOp toPtr = *
this;
438 while (toPtr !=
nullptr) {
439 auto fromPtr = toPtr.getPtr().getDefiningOp<FromPtrOp>();
443 ptr = fromPtr.getPtr();
445 toPtr =
ptr.getDefiningOp<ToPtrOp>();
450LogicalResult ToPtrOp::verify() {
451 if (isa<PtrType>(getPtr().
getType()))
452 return emitError() <<
"the input value cannot be of type `!ptr.ptr`";
453 if (
getType().getMemorySpace() != getPtr().
getType().getMemorySpace()) {
455 <<
"expected the input and output to have the same memory space";
464llvm::TypeSize TypeOffsetOp::getTypeSize(std::optional<DataLayout> layout) {
474#include "mlir/Dialect/Ptr/IR/PtrOpsDialect.cpp.inc"
476#define GET_ATTRDEF_CLASSES
477#include "mlir/Dialect/Ptr/IR/PtrOpsAttrs.cpp.inc"
479#include "mlir/Dialect/Ptr/IR/PtrOpsEnums.cpp.inc"
481#define GET_TYPEDEF_CLASSES
482#include "mlir/Dialect/Ptr/IR/PtrOpsTypes.cpp.inc"
484#define GET_OP_CLASSES
485#include "mlir/Dialect/Ptr/IR/PtrOps.cpp.inc"
static Value getBase(Value v)
Looks through known "view-like" ops to find the base memref.
static InFlightDiagnostic emitDiag(Location location, DiagnosticSeverity severity, const Twine &message)
Helper function used to emit a diagnostic with an optionally empty twine message.
static LogicalResult verifyAtomicMemOp(OpTy memOp, ArrayRef< AtomicOrdering > unsupportedOrderings)
Verifies the attributes and the type of atomic memory access operations.
static LogicalResult verifyAlignment(std::optional< int64_t > alignment, function_ref< InFlightDiagnostic()> emitError)
Verifies that the alignment attribute is a power of 2 if present.
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,...
Attributes are known-constant values of operations.
StringAttr getStringAttr(const Twine &bytes)
The main mechanism for performing data layout queries.
static DataLayout closest(Operation *op)
Returns the layout of the closest parent operation carrying layout info.
This class represents a diagnostic that is inflight and set to be reported.
MLIRContext is the top-level object for a collection of MLIR operations.
This class helps build Operations.
This class represents a single result from folding an operation.
Type-safe wrapper around a void* for passing properties, including the properties structs of operatio...
This class provides an abstraction over the different types of ranges over Regions.
This class represents a specific instance of an effect.
static DerivedEffect * get()
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
TypeID getTypeID()
Return a unique identifier for the concrete type.
This class provides an abstraction over the different types of ranges over Values.
type_range getType() const
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
Include the generated interface declarations.
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.
InFlightDiagnostic emitError(Location loc)
Utility method to emit an error message using this location.
llvm::function_ref< Fn > function_ref
This represents an operation in an abstracted form, suitable for use with the builder APIs.
bool match(Attribute attr)