18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/TypeSwitch.h"
28 void PtrDialect::initialize() {
31 #include "mlir/Dialect/Ptr/IR/PtrOps.cpp.inc"
34 #define GET_ATTRDEF_LIST
35 #include "mlir/Dialect/Ptr/IR/PtrOpsAttrs.cpp.inc"
38 #define GET_TYPEDEF_LIST
39 #include "mlir/Dialect/Ptr/IR/PtrOpsTypes.cpp.inc"
53 if (alignment.value() <= 0)
54 return emitError() <<
"alignment must be positive";
55 if (!llvm::isPowerOf2_64(alignment.value()))
56 return emitError() <<
"alignment must be a power of 2";
64 OpFoldResult ConstantOp::fold(FoldAdaptor adaptor) {
return getValue(); }
78 FromPtrOp fromPtr = *
this;
79 while (fromPtr !=
nullptr) {
83 if (!toPtr || toPtr.getPtr().getType() != fromPtr.getType())
85 Value md = fromPtr.getMetadata();
87 if (!fromPtr.getType().hasPtrMetadata()) {
88 ptrLike = toPtr.getPtr();
92 mdOp && mdOp.getPtr() == toPtr.getPtr())
93 ptrLike = toPtr.getPtr();
96 fromPtr = ptrLike ? ptrLike.
getDefiningOp<FromPtrOp>() :
nullptr;
103 return emitError() <<
"the result type cannot be `!ptr.ptr`";
104 if (
getType().getMemorySpace() != getPtr().
getType().getMemorySpace()) {
106 <<
"expected the input and output to have the same memory space";
115 void GatherOp::getEffects(
126 MemorySpaceAttrInterface ms =
129 if (!ms.isValidLoad(getResult().
getType(), AtomicOrdering::not_atomic,
130 getAlignment(), &dataLayout,
emitDiag))
139 unsigned alignment) {
140 build(builder, state, resultType, ptrs, mask, passthrough,
141 alignment ? std::optional<int64_t>(alignment) : std::nullopt);
149 template <
typename OpTy>
152 if (memOp.getOrdering() != AtomicOrdering::not_atomic) {
153 if (llvm::is_contained(unsupportedOrderings, memOp.getOrdering()))
154 return memOp.emitOpError(
"unsupported ordering '")
155 << stringifyAtomicOrdering(memOp.getOrdering()) <<
"'";
156 if (!memOp.getAlignment())
157 return memOp.emitOpError(
"expected alignment for atomic access");
160 if (memOp.getSyncscope()) {
161 return memOp.emitOpError(
162 "expected syncscope to be null for non-atomic access");
167 void LoadOp::getEffects(
176 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
177 getOrdering() != AtomicOrdering::unordered)) {
185 MemorySpaceAttrInterface ms = getPtr().getType().getMemorySpace();
187 if (!ms.isValidLoad(getResult().
getType(), getOrdering(), getAlignment(),
193 {AtomicOrdering::release, AtomicOrdering::acq_rel});
197 Value addr,
unsigned alignment,
bool isVolatile,
198 bool isNonTemporal,
bool isInvariant,
bool isInvariantGroup,
199 AtomicOrdering ordering, StringRef syncscope) {
200 build(builder, state, type, addr,
201 alignment ? std::optional<int64_t>(alignment) : std::nullopt,
202 isVolatile, isNonTemporal, isInvariant, isInvariantGroup, ordering,
203 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
209 void MaskedLoadOp::getEffects(
219 MemorySpaceAttrInterface ms = getPtr().getType().getMemorySpace();
221 if (!ms.isValidLoad(getResult().
getType(), AtomicOrdering::not_atomic,
222 getAlignment(), &dataLayout,
emitDiag))
231 Value passthrough,
unsigned alignment) {
232 build(builder, state, resultType, ptr, mask, passthrough,
233 alignment ? std::optional<int64_t>(alignment) : std::nullopt);
240 void MaskedStoreOp::getEffects(
250 MemorySpaceAttrInterface ms = getPtr().getType().getMemorySpace();
252 if (!ms.isValidStore(getValue().
getType(), AtomicOrdering::not_atomic,
253 getAlignment(), &dataLayout,
emitDiag))
262 unsigned alignment) {
263 build(builder, state, value, ptr, mask,
264 alignment ? std::optional<int64_t>(alignment) : std::nullopt);
271 void ScatterOp::getEffects(
282 MemorySpaceAttrInterface ms =
285 if (!ms.isValidStore(getValue().
getType(), AtomicOrdering::not_atomic,
286 getAlignment(), &dataLayout,
emitDiag))
295 build(builder, state, value, ptrs, mask,
296 alignment ? std::optional<int64_t>(alignment) : std::nullopt);
303 void StoreOp::getEffects(
312 if (getVolatile_() || (getOrdering() != AtomicOrdering::not_atomic &&
313 getOrdering() != AtomicOrdering::unordered)) {
321 MemorySpaceAttrInterface ms = getPtr().getType().getMemorySpace();
323 if (!ms.isValidStore(getValue().
getType(), getOrdering(), getAlignment(),
329 {AtomicOrdering::acquire, AtomicOrdering::acq_rel});
333 Value addr,
unsigned alignment,
bool isVolatile,
334 bool isNonTemporal,
bool isInvariantGroup,
335 AtomicOrdering ordering, StringRef syncscope) {
336 build(builder, state, value, addr,
337 alignment ? std::optional<int64_t>(alignment) : std::nullopt,
338 isVolatile, isNonTemporal, isInvariantGroup, ordering,
339 syncscope.empty() ?
nullptr : builder.
getStringAttr(syncscope));
356 LogicalResult PtrAddOp::inferReturnTypes(
364 auto offTy = dyn_cast<ShapedType>(offsetType);
367 inferredReturnTypes.push_back(baseType);
370 auto baseTy = dyn_cast<ShapedType>(baseType);
374 inferredReturnTypes.push_back(offTy.clone(baseType));
379 if (offTy.getShape() != baseTy.getShape()) {
391 inferredReturnTypes.push_back(baseType);
401 if (!isa<ShapedType>(getLhs().
getType()))
406 if (getResult().
getType().getTypeID() != getLhs().
getType().getTypeID()) {
407 return emitError() <<
"expected the result to have the same container "
408 "type as the operands when operands are shaped";
414 ptr::PtrType PtrDiffOp::getPtrType() {
415 Type lhsType = getLhs().getType();
416 if (
auto shapedType = dyn_cast<ShapedType>(lhsType))
417 return cast<ptr::PtrType>(shapedType.getElementType());
418 return cast<ptr::PtrType>(lhsType);
421 Type PtrDiffOp::getIntType() {
422 Type resultType = getResult().getType();
423 if (
auto shapedType = dyn_cast<ShapedType>(resultType))
424 return shapedType.getElementType();
439 ToPtrOp toPtr = *
this;
440 while (toPtr !=
nullptr) {
445 ptr = fromPtr.getPtr();
453 if (isa<PtrType>(getPtr().
getType()))
454 return emitError() <<
"the input value cannot be of type `!ptr.ptr`";
455 if (
getType().getMemorySpace() != getPtr().
getType().getMemorySpace()) {
457 <<
"expected the input and output to have the same memory space";
466 llvm::TypeSize TypeOffsetOp::getTypeSize(std::optional<DataLayout> layout) {
477 #include "mlir/Dialect/Ptr/IR/PtrOpsDialect.cpp.inc"
479 #define GET_ATTRDEF_CLASSES
480 #include "mlir/Dialect/Ptr/IR/PtrOpsAttrs.cpp.inc"
482 #include "mlir/Dialect/Ptr/IR/PtrOpsEnums.cpp.inc"
484 #define GET_TYPEDEF_CLASSES
485 #include "mlir/Dialect/Ptr/IR/PtrOpsTypes.cpp.inc"
487 #define GET_OP_CLASSES
488 #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 Type getElementType(Type type)
Determine the element type of type.
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.
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.
llvm::TypeSize getTypeSize(Type t) const
Returns the size of the given type in the current scope.
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.
Simple wrapper around a void* in order to express generically how to pass in op properties through AP...
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()
Returns a unique instance for the derived effect class.
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.
LogicalResult verify(Operation *op, bool verifyRecursively=true)
Perform (potentially expensive) checks of invariants, used to detect compiler bugs,...
This represents an operation in an abstracted form, suitable for use with the builder APIs.
bool match(Attribute attr)