Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions mlir/include/mlir/Dialect/Ptr/IR/PtrAttrDefs.td
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define PTR_ATTRDEFS

include "mlir/Dialect/Ptr/IR/PtrDialect.td"
include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td"
include "mlir/IR/AttrTypeBase.td"

// All of the attributes will extend this class.
Expand All @@ -20,6 +21,38 @@ class Ptr_Attr<string name, string attrMnemonic,
let mnemonic = attrMnemonic;
}

//===----------------------------------------------------------------------===//
// IAddressSpaceAttr
//===----------------------------------------------------------------------===//

def Ptr_IAddressSpaceAttr :
Ptr_Attr<"IAddressSpace", "int_space", [
DeclareAttrInterfaceMethods<MemorySpaceAttrInterface>
]> {
let summary = "Int memory space";
let description = [{
The `int_as` attribute defines a memory space attribute with the following
properties:
- Load and store operations are always valid, regardless of the type.
- Atomic operations are always valid, regardless of the type.
- Cast operations are valid between pointers with `int_space` memory space,
or between non-scalable `vector` of pointers with `int_space` memory space.

The default address spaces is 0.

Example:

```mlir
// Default address space: 0.
#ptr.int_space
// Address space 3.
#ptr.int_space<3>
```
}];
let parameters = (ins DefaultValuedParameter<"int64_t", "0">:$value);
let assemblyFormat = "(`<` $value^ `>`)?";
}

//===----------------------------------------------------------------------===//
// SpecAttr
//===----------------------------------------------------------------------===//
Expand Down
2 changes: 2 additions & 0 deletions mlir/include/mlir/Dialect/Ptr/IR/PtrAttrs.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

#include "mlir/IR/OpImplementation.h"

#include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.h"

#define GET_ATTRDEF_CLASSES
#include "mlir/Dialect/Ptr/IR/PtrOpsAttrs.h.inc"

Expand Down
11 changes: 11 additions & 0 deletions mlir/include/mlir/Dialect/Ptr/IR/PtrEnums.td
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,15 @@ def AtomicOrdering : I64EnumAttr<
let cppNamespace = "::mlir::ptr";
}

//===----------------------------------------------------------------------===//
// Ptr add flags enum attr.
//===----------------------------------------------------------------------===//

def Ptr_PtrAddFlags : I32EnumAttr<"PtrAddFlags", "Pointer add flags", [
I32EnumAttrCase<"none", 0>, I32EnumAttrCase<"nusw", 1>,
I32EnumAttrCase<"nuw", 2>, I32EnumAttrCase<"inbounds", 3>
]> {
let cppNamespace = "::mlir::ptr";
}

#endif // PTR_ENUMS
2 changes: 2 additions & 0 deletions mlir/include/mlir/Dialect/Ptr/IR/PtrOps.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
#include "mlir/Dialect/Ptr/IR/PtrDialect.h"
#include "mlir/Dialect/Ptr/IR/PtrTypes.h"
#include "mlir/IR/OpDefinition.h"
#include "mlir/Interfaces/SideEffectInterfaces.h"
#include "mlir/Interfaces/ViewLikeInterface.h"

#define GET_OP_CLASSES
#include "mlir/Dialect/Ptr/IR/PtrOps.h.inc"
Expand Down
71 changes: 71 additions & 0 deletions mlir/include/mlir/Dialect/Ptr/IR/PtrOps.td
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,78 @@

include "mlir/Dialect/Ptr/IR/PtrDialect.td"
include "mlir/Dialect/Ptr/IR/PtrAttrDefs.td"
include "mlir/Dialect/Ptr/IR/PtrEnums.td"
include "mlir/Dialect/Ptr/IR/MemorySpaceInterfaces.td"
include "mlir/Interfaces/SideEffectInterfaces.td"
include "mlir/Interfaces/ViewLikeInterface.td"
include "mlir/IR/OpAsmInterface.td"

//===----------------------------------------------------------------------===//
// PtrAddOp
//===----------------------------------------------------------------------===//

def Ptr_PtrAddOp : Pointer_Op<"ptradd", [
Pure, AllTypesMatch<["base", "result"]>,
DeclareOpInterfaceMethods<ViewLikeOpInterface>
]> {
let summary = "Pointer add operation";
let description = [{
The `ptradd` operation adds an integer offset to a pointer to produce a new
pointer. The input and output pointer types are always the same.

Example:

```mlir
%x_off = ptr.ptradd %x, %off : !ptr.ptr<0>, i32
%x_off0 = ptr.ptradd nusw %x, %off : !ptr.ptr<0>, i32
```
}];

let arguments = (ins
Ptr_PtrType:$base,
AnySignlessIntegerOrIndex:$offset,
DefaultValuedAttr<Ptr_PtrAddFlags,
"::mlir::ptr::PtrAddFlags::none">:$flags);
let results = (outs Ptr_PtrType:$result);
let assemblyFormat = [{
($flags^)? $base `,` $offset attr-dict `:` type($base) `,` type($offset)
}];
let hasFolder = 1;
}

//===----------------------------------------------------------------------===//
// TypeOffsetOp
//===----------------------------------------------------------------------===//

def Ptr_TypeOffsetOp : Pointer_Op<"type_offset", [ConstantLike, Pure]> {
let summary = "Type offset operation";
let description = [{
The `type_offset` operation produces an int or index-typed SSA value
equal to a target-specific constant representing the offset of a single
element of the given type.

Example:

```mlir
%0 = ptr.type_offset f32 : index
%1 = ptr.type_offset memref<12 x f64> : i32
```
}];

let arguments = (ins TypeAttr:$element_type);
let results = (outs AnySignlessIntegerOrIndex:$result);
let builders = [
OpBuilder<(ins "TypeAttr":$element_type)>
];
let assemblyFormat = [{
$element_type attr-dict `:` type($result)
}];
let extraClassDeclaration = [{
/// Returns the type offset according to `maybeLayout`. If `maybeLayout` is
/// `nullopt` the nearest layout the op will be used for the computation.
llvm::TypeSize getTypeSize(std::optional<DataLayout> layout = std::nullopt);
}];
let hasFolder = 1;
}

#endif // PTR_OPS
1 change: 1 addition & 0 deletions mlir/lib/Dialect/Ptr/IR/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,5 @@ add_mlir_dialect_library(
MLIRIR
MLIRDataLayoutInterfaces
MLIRMemorySlotInterfaces
MLIRViewLikeInterface
)
46 changes: 46 additions & 0 deletions mlir/lib/Dialect/Ptr/IR/PtrAttrs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,59 @@
//===----------------------------------------------------------------------===//

#include "mlir/Dialect/Ptr/IR/PtrAttrs.h"
#include "mlir/IR/BuiltinTypes.h"
#include "llvm/ADT/TypeSwitch.h"

using namespace mlir;
using namespace mlir::ptr;

constexpr const static unsigned kBitsInByte = 8;

//===----------------------------------------------------------------------===//
// IAddressSpaceAttr
//===----------------------------------------------------------------------===//

LogicalResult IAddressSpaceAttr::isValidLoad(
Type type, ptr::AtomicOrdering ordering, IntegerAttr alignment,
function_ref<InFlightDiagnostic()> emitError) const {
return success();
}

LogicalResult IAddressSpaceAttr::isValidStore(
Type type, ptr::AtomicOrdering ordering, IntegerAttr alignment,
function_ref<InFlightDiagnostic()> emitError) const {
return success();
}

LogicalResult IAddressSpaceAttr::isValidAtomicOp(
ptr::AtomicBinOp op, Type type, ptr::AtomicOrdering ordering,
IntegerAttr alignment, function_ref<InFlightDiagnostic()> emitError) const {
return success();
}

LogicalResult IAddressSpaceAttr::isValidAtomicXchg(
Type type, ptr::AtomicOrdering successOrdering,
ptr::AtomicOrdering failureOrdering, IntegerAttr alignment,
function_ref<InFlightDiagnostic()> emitError) const {
return success();
}

LogicalResult IAddressSpaceAttr::isValidAddrSpaceCast(
Type tgt, Type src, function_ref<InFlightDiagnostic()> emitError) const {
// TODO: update this method once the `addrspace_cast` op is added to the
// dialect.
assert(false && "unimplemented, see TODO in the source.");
return failure();
}

LogicalResult IAddressSpaceAttr::isValidPtrIntCast(
Type intLikeTy, Type ptrLikeTy,
function_ref<InFlightDiagnostic()> emitError) const {
// TODO: update this method once the int-cast ops are added to the dialect.
assert(false && "unimplemented, see TODO in the source.");
return failure();
}

//===----------------------------------------------------------------------===//
// SpecAttr
//===----------------------------------------------------------------------===//
Expand Down
33 changes: 33 additions & 0 deletions mlir/lib/Dialect/Ptr/IR/PtrDialect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@

#include "mlir/Dialect/Ptr/IR/PtrOps.h"
#include "mlir/IR/DialectImplementation.h"
#include "mlir/IR/Matchers.h"
#include "mlir/IR/PatternMatch.h"
#include "mlir/Interfaces/DataLayoutInterfaces.h"
#include "mlir/Transforms/InliningUtils.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/TypeSwitch.h"
Expand All @@ -39,6 +41,37 @@ void PtrDialect::initialize() {
>();
}

//===----------------------------------------------------------------------===//
// PtrAddOp
//===----------------------------------------------------------------------===//

/// Fold the op to the base ptr when the offset is 0.
OpFoldResult PtrAddOp::fold(FoldAdaptor adaptor) {
Attribute attr = adaptor.getOffset();
if (!attr)
return nullptr;
if (llvm::APInt value; m_ConstantInt(&value).match(attr) && value.isZero())
return getBase();
return nullptr;
}

Value PtrAddOp::getViewSource() { return getBase(); }

//===----------------------------------------------------------------------===//
// TypeOffsetOp
//===----------------------------------------------------------------------===//

OpFoldResult TypeOffsetOp::fold(FoldAdaptor adaptor) {
return TypeAttr::get(getElementType());
}

llvm::TypeSize TypeOffsetOp::getTypeSize(std::optional<DataLayout> layout) {
if (layout)
return layout->getTypeSize(getElementType());
DataLayout dl = DataLayout::closest(*this);
return dl.getTypeSize(getElementType());
}

//===----------------------------------------------------------------------===//
// Pointer API.
//===----------------------------------------------------------------------===//
Expand Down
33 changes: 33 additions & 0 deletions mlir/test/Dialect/Ptr/canonicalize.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// RUN: mlir-opt --canonicalize %s | FileCheck %s

/// Check `ptradd` and `type_offset` canonicalizer patterns.

// CHECK-LABEL: @ops0
func.func @ops0(%ptr: !ptr.ptr<#ptr.int_space<3>>, %c: i1) -> !ptr.ptr<#ptr.int_space<3>> {
// CHECK: (%[[PTR_0:.*]]: !ptr.ptr<#ptr.int_space<3>>,
// CHECK: %[[F32_OFF:.*]] = ptr.type_offset f32 : index
// CHECK: %[[PTR_1:.*]] = ptr.ptradd %[[PTR_0]], %[[F32_OFF]] : <#ptr.int_space<3>>, index
// CHECK: %[[PTR_2:.*]] = ptr.ptradd %[[PTR_1]], %[[F32_OFF]] : <#ptr.int_space<3>>, index
// CHECK: %[[PTR_3:.*]] = scf.if %{{.*}} -> (!ptr.ptr<#ptr.int_space<3>>) {
// CHECK: %[[PTR_4:.*]] = ptr.ptradd %[[PTR_2]], %[[F32_OFF]] : <#ptr.int_space<3>>, index
// CHECK: scf.yield %[[PTR_4]] : !ptr.ptr<#ptr.int_space<3>>
// CHECK: } else {
// CHECK: scf.yield %[[PTR_0]] : !ptr.ptr<#ptr.int_space<3>>
// CHECK: }
// CHECK: return %[[PTR_3]] : !ptr.ptr<#ptr.int_space<3>>
// CHECK: }
%off0 = ptr.type_offset f32 : index
%res0 = ptr.ptradd %ptr, %off0 : !ptr.ptr<#ptr.int_space<3>>, index
%off1 = ptr.type_offset f32 : index
%res1 = ptr.ptradd %res0, %off1 : !ptr.ptr<#ptr.int_space<3>>, index
%res3 = scf.if %c -> !ptr.ptr<#ptr.int_space<3>> {
%off2 = ptr.type_offset f32 : index
%res2 = ptr.ptradd %res1, %off2 : !ptr.ptr<#ptr.int_space<3>>, index
scf.yield %res2 : !ptr.ptr<#ptr.int_space<3>>
} else {
scf.yield %ptr : !ptr.ptr<#ptr.int_space<3>>
}
%off3 = index.constant 0
%res4 = ptr.ptradd %res3, %off3 : !ptr.ptr<#ptr.int_space<3>>, index
return %res4 : !ptr.ptr<#ptr.int_space<3>>
}
15 changes: 15 additions & 0 deletions mlir/test/Dialect/Ptr/ops.mlir
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// RUN: mlir-opt %s --verify-roundtrip | FileCheck %s

/// Check op assembly.
func.func @ops0(%ptr: !ptr.ptr<#ptr.int_space>) -> !ptr.ptr<#ptr.int_space> {
// CHECK-LABEL: @ops0
// CHECK: ptr.type_offset f32 : index
// CHECK-NEXT: ptr.ptradd %{{.*}}, %{{.*}} : <#ptr.int_space>, index
%off = ptr.type_offset f32 : index
%res = ptr.ptradd %ptr, %off : !ptr.ptr<#ptr.int_space>, index
%res0 = ptr.ptradd none %ptr, %off : !ptr.ptr<#ptr.int_space>, index
%res1 = ptr.ptradd nusw %ptr, %off : !ptr.ptr<#ptr.int_space>, index
%res2 = ptr.ptradd nuw %ptr, %off : !ptr.ptr<#ptr.int_space>, index
%res3 = ptr.ptradd inbounds %ptr, %off : !ptr.ptr<#ptr.int_space>, index
return %res : !ptr.ptr<#ptr.int_space>
}
Loading