21#include "llvm/Support/LogicalResult.h"
33 matchAndRewrite(ptr::FromPtrOp op, OpAdaptor adaptor,
34 ConversionPatternRewriter &rewriter)
const override;
40struct GetMetadataOpConversion
44 matchAndRewrite(ptr::GetMetadataOp op, OpAdaptor adaptor,
45 ConversionPatternRewriter &rewriter)
const override;
54 matchAndRewrite(ptr::PtrAddOp op, OpAdaptor adaptor,
55 ConversionPatternRewriter &rewriter)
const override;
64 matchAndRewrite(ptr::ToPtrOp op, OpAdaptor adaptor,
65 ConversionPatternRewriter &rewriter)
const override;
71struct TypeOffsetOpConversion
75 matchAndRewrite(ptr::TypeOffsetOp op, OpAdaptor adaptor,
76 ConversionPatternRewriter &rewriter)
const override;
85 matchAndRewrite(ptr::ConstantOp op, OpAdaptor adaptor,
86 ConversionPatternRewriter &rewriter)
const override;
95static FailureOr<LLVM::LLVMStructType>
101 if (failed(addressSpace))
105 auto ptrType = LLVM::LLVMPointerType::get(context, *addressSpace);
110 if (failed(type.getStridesAndOffset(strides, offset)))
126 elements.push_back(ptrType);
129 if (offset == ShapedType::kDynamic)
130 elements.push_back(indexType);
134 if (dim == ShapedType::kDynamic)
135 elements.push_back(indexType);
139 for (
int64_t stride : strides) {
140 if (stride == ShapedType::kDynamic)
141 elements.push_back(indexType);
143 return LLVM::LLVMStructType::getLiteral(context, elements);
150LogicalResult FromPtrOpConversion::matchAndRewrite(
151 ptr::FromPtrOp op, OpAdaptor adaptor,
152 ConversionPatternRewriter &rewriter)
const {
154 auto mTy = dyn_cast<MemRefType>(op.getResult().getType());
156 return rewriter.notifyMatchFailure(op,
"Expected memref result type");
158 if (!op.getMetadata() && op.getType().hasPtrMetadata()) {
159 return rewriter.notifyMatchFailure(
160 op,
"Can convert only memrefs with metadata");
164 Type descriptorTy = getTypeConverter()->convertType(mTy);
166 return rewriter.notifyMatchFailure(op,
"Failed to convert result type");
169 SmallVector<int64_t> strides;
171 if (
failed(mTy.getStridesAndOffset(strides, offset))) {
172 return rewriter.notifyMatchFailure(op,
173 "Failed to get the strides and offset");
175 ArrayRef<int64_t> shape = mTy.getShape();
178 Location loc = op.getLoc();
179 auto desc = MemRefDescriptor::poison(rewriter, loc, descriptorTy);
182 desc.setAllocatedPtr(
184 LLVM::ExtractValueOp::create(rewriter, loc, adaptor.getMetadata(), 0));
185 desc.setAlignedPtr(rewriter, loc, adaptor.getPtr());
188 unsigned fieldIdx = 1;
191 if (offset == ShapedType::kDynamic) {
192 Value offsetValue = LLVM::ExtractValueOp::create(
193 rewriter, loc, adaptor.getMetadata(), fieldIdx++);
194 desc.setOffset(rewriter, loc, offsetValue);
196 desc.setConstantOffset(rewriter, loc, offset);
200 for (
auto [i, dim] : llvm::enumerate(shape)) {
201 if (dim == ShapedType::kDynamic) {
202 Value sizeValue = LLVM::ExtractValueOp::create(
203 rewriter, loc, adaptor.getMetadata(), fieldIdx++);
204 desc.setSize(rewriter, loc, i, sizeValue);
206 desc.setConstantSize(rewriter, loc, i, dim);
211 for (
auto [i, stride] : llvm::enumerate(strides)) {
212 if (stride == ShapedType::kDynamic) {
213 Value strideValue = LLVM::ExtractValueOp::create(
214 rewriter, loc, adaptor.getMetadata(), fieldIdx++);
215 desc.setStride(rewriter, loc, i, strideValue);
217 desc.setConstantStride(rewriter, loc, i, stride);
221 rewriter.replaceOp(op,
static_cast<Value
>(desc));
229LogicalResult GetMetadataOpConversion::matchAndRewrite(
230 ptr::GetMetadataOp op, OpAdaptor adaptor,
231 ConversionPatternRewriter &rewriter)
const {
232 auto mTy = dyn_cast<MemRefType>(op.getPtr().getType());
234 return rewriter.notifyMatchFailure(op,
"Only memref metadata is supported");
237 FailureOr<LLVM::LLVMStructType> mdTy =
240 return rewriter.notifyMatchFailure(op,
241 "Failed to create the metadata type");
245 MemRefDescriptor descriptor(adaptor.getPtr());
248 SmallVector<int64_t> strides;
250 if (
failed(mTy.getStridesAndOffset(strides, offset))) {
251 return rewriter.notifyMatchFailure(op,
252 "Failed to get the strides and offset");
254 ArrayRef<int64_t> shape = mTy.getShape();
257 Location loc = op.getLoc();
258 Value sV = LLVM::UndefOp::create(rewriter, loc, *mdTy);
261 SmallVector<int64_t> pos{0};
262 sV = LLVM::InsertValueOp::create(rewriter, loc, sV,
263 descriptor.allocatedPtr(rewriter, loc), pos);
266 unsigned fieldIdx = 1;
269 if (offset == ShapedType::kDynamic) {
270 sV = LLVM::InsertValueOp::create(
271 rewriter, loc, sV, descriptor.offset(rewriter, loc), fieldIdx++);
275 for (
auto [i, dim] : llvm::enumerate(shape)) {
276 if (dim != ShapedType::kDynamic)
278 sV = LLVM::InsertValueOp::create(
279 rewriter, loc, sV, descriptor.size(rewriter, loc, i), fieldIdx++);
283 for (
auto [i, stride] : llvm::enumerate(strides)) {
284 if (stride != ShapedType::kDynamic)
286 sV = LLVM::InsertValueOp::create(
287 rewriter, loc, sV, descriptor.stride(rewriter, loc, i), fieldIdx++);
289 rewriter.replaceOp(op, sV);
298PtrAddOpConversion::matchAndRewrite(ptr::PtrAddOp op, OpAdaptor adaptor,
299 ConversionPatternRewriter &rewriter)
const {
301 Value base = adaptor.getBase();
303 return rewriter.notifyMatchFailure(op,
"Incompatible pointer type");
306 Type resultType = getTypeConverter()->convertType(op.getType());
309 return rewriter.notifyMatchFailure(op,
"Incompatible result type");
312 Value offset = adaptor.getOffset();
315 Type elementType = IntegerType::get(rewriter.getContext(), 8);
318 LLVM::GEPNoWrapFlags flags;
319 switch (op.getFlags()) {
320 case ptr::PtrAddFlags::none:
321 flags = LLVM::GEPNoWrapFlags::none;
323 case ptr::PtrAddFlags::nusw:
324 flags = LLVM::GEPNoWrapFlags::nusw;
326 case ptr::PtrAddFlags::nuw:
327 flags = LLVM::GEPNoWrapFlags::nuw;
329 case ptr::PtrAddFlags::inbounds:
330 flags = LLVM::GEPNoWrapFlags::inbounds;
335 rewriter.replaceOpWithNewOp<LLVM::GEPOp>(op, resultType, elementType, base,
345ToPtrOpConversion::matchAndRewrite(ptr::ToPtrOp op, OpAdaptor adaptor,
346 ConversionPatternRewriter &rewriter)
const {
348 if (!isa<MemRefType>(op.getPtr().getType()))
349 return rewriter.notifyMatchFailure(op,
"Expected a memref input");
353 op, MemRefDescriptor(adaptor.getPtr()).alignedPtr(rewriter, op.getLoc()));
361LogicalResult TypeOffsetOpConversion::matchAndRewrite(
362 ptr::TypeOffsetOp op, OpAdaptor adaptor,
363 ConversionPatternRewriter &rewriter)
const {
365 Type type = getTypeConverter()->convertType(op.getElementType());
367 return rewriter.notifyMatchFailure(op,
"Couldn't convert the type");
370 Type rTy = getTypeConverter()->convertType(op.getResult().getType());
372 return rewriter.notifyMatchFailure(op,
"Couldn't convert the result type");
378 auto ptrTy = LLVM::LLVMPointerType::get(
getContext());
382 LLVM::GEPOp::create(rewriter, op.getLoc(), ptrTy, type,
383 LLVM::ZeroOp::create(rewriter, op.getLoc(), ptrTy),
384 ArrayRef<LLVM::GEPArg>({LLVM::GEPArg(1)}));
387 rewriter.replaceOpWithNewOp<LLVM::PtrToIntOp>(op, rTy, offset.getRes());
395LogicalResult ConstantOpConversion::matchAndRewrite(
396 ptr::ConstantOp op, OpAdaptor adaptor,
397 ConversionPatternRewriter &rewriter)
const {
398 TypedAttr value = op.getValue();
399 Type resultType = getTypeConverter()->convertType(op.getType());
401 return rewriter.notifyMatchFailure(op,
"Couldn't convert the result type");
403 if (isa<ptr::NullAttr>(value)) {
404 rewriter.replaceOpWithNewOp<LLVM::ZeroOp>(op, resultType);
407 auto addrAttr = dyn_cast<ptr::AddressAttr>(value);
410 return rewriter.notifyMatchFailure(
411 op,
"unsupported value attribute kind: " +
412 value.getAbstractAttribute().getName());
414 Type intType = rewriter.getIntegerType(addrAttr.getValue().getBitWidth());
415 Value intConst = LLVM::ConstantOp::create(rewriter, op.getLoc(), intType,
416 addrAttr.getValue());
417 rewriter.replaceOpWithNewOp<LLVM::IntToPtrOp>(op, resultType, intConst);
427struct PtrToLLVMDialectInterface :
public ConvertToLLVMPatternInterface {
428 PtrToLLVMDialectInterface(Dialect *dialect)
429 : ConvertToLLVMPatternInterface(dialect) {}
431 void loadDependentDialects(MLIRContext *context)
const final {
432 context->loadDialect<LLVM::LLVMDialect>();
437 void populateConvertToLLVMConversionPatterns(
438 ConversionTarget &
target, LLVMTypeConverter &converter,
439 RewritePatternSet &patterns)
const final {
452 converter.addTypeAttributeConversion(
453 [&](PtrLikeTypeInterface type, ptr::GenericSpaceAttr memorySpace)
454 -> TypeConverter::AttributeConversionResult {
455 if (type.getMemorySpace() != memorySpace)
456 return TypeConverter::AttributeConversionResult::na();
457 return IntegerAttr::get(IntegerType::get(type.getContext(), 32), 0);
461 converter.addConversion([&](ptr::PtrType type) ->
Type {
462 std::optional<Attribute> maybeAttr =
463 converter.convertTypeAttribute(type, type.getMemorySpace());
465 maybeAttr ? dyn_cast_or_null<IntegerAttr>(*maybeAttr) : IntegerAttr();
468 return LLVM::LLVMPointerType::get(type.getContext(),
469 memSpace.getValue().getSExtValue());
473 converter.addConversion([&](ptr::PtrMetadataType type) ->
Type {
474 auto mTy = dyn_cast<MemRefType>(type.getType());
477 FailureOr<LLVM::LLVMStructType> res =
479 return failed(res) ?
Type() : res.value();
483 patterns.
add<FromPtrOpConversion, GetMetadataOpConversion, PtrAddOpConversion,
484 ToPtrOpConversion, TypeOffsetOpConversion, ConstantOpConversion>(
490 dialect->addInterfaces<PtrToLLVMDialectInterface>();
static FailureOr< LLVM::LLVMStructType > createMemRefMetadataType(MemRefType type, const LLVMTypeConverter &typeConverter)
Utility class for operation conversions targeting the LLVM dialect that match exactly one source oper...
ConvertOpToLLVMPattern(const LLVMTypeConverter &typeConverter, PatternBenefit benefit=1)
The DialectRegistry maps a dialect namespace to a constructor for the matching dialect.
bool addExtension(TypeID extensionID, std::unique_ptr< DialectExtensionBase > extension)
Add the given extension to the registry.
Conversion from types to the LLVM IR dialect.
FailureOr< unsigned > getMemRefAddressSpace(BaseMemRefType type) const
Return the LLVM address space corresponding to the memory space of the memref type type or failure if...
Type getIndexType() const
Gets the LLVM representation of the index type.
MLIRContext is the top-level object for a collection of MLIR operations.
RewritePatternSet & add(ConstructorArg &&arg, ConstructorArgs &&...args)
Add an instance of each of the pattern types 'Ts' to the pattern list with the given arguments.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
Type getType() const
Return the type of this value.
void populatePtrToLLVMConversionPatterns(LLVMTypeConverter &converter, RewritePatternSet &patterns)
Populate the convert to LLVM patterns for the ptr dialect.
void registerConvertPtrToLLVMInterface(DialectRegistry ®istry)
Register the convert to LLVM interface for the ptr dialect.
Include the generated interface declarations.
Type getElementTypeOrSelf(Type type)
Return the element type or return the type itself.