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();
302 if (!isa<LLVM::LLVMPointerType>(base.
getType()))
303 return rewriter.notifyMatchFailure(op,
"Incompatible pointer type");
306 Value offset = adaptor.getOffset();
309 Type elementType = IntegerType::get(rewriter.getContext(), 8);
312 LLVM::GEPNoWrapFlags flags;
313 switch (op.getFlags()) {
314 case ptr::PtrAddFlags::none:
315 flags = LLVM::GEPNoWrapFlags::none;
317 case ptr::PtrAddFlags::nusw:
318 flags = LLVM::GEPNoWrapFlags::nusw;
320 case ptr::PtrAddFlags::nuw:
321 flags = LLVM::GEPNoWrapFlags::nuw;
323 case ptr::PtrAddFlags::inbounds:
324 flags = LLVM::GEPNoWrapFlags::inbounds;
329 rewriter.replaceOpWithNewOp<LLVM::GEPOp>(op, base.
getType(), elementType,
339ToPtrOpConversion::matchAndRewrite(ptr::ToPtrOp op, OpAdaptor adaptor,
340 ConversionPatternRewriter &rewriter)
const {
342 if (!isa<MemRefType>(op.getPtr().getType()))
343 return rewriter.notifyMatchFailure(op,
"Expected a memref input");
347 op, MemRefDescriptor(adaptor.getPtr()).alignedPtr(rewriter, op.getLoc()));
355LogicalResult TypeOffsetOpConversion::matchAndRewrite(
356 ptr::TypeOffsetOp op, OpAdaptor adaptor,
357 ConversionPatternRewriter &rewriter)
const {
359 Type type = getTypeConverter()->convertType(op.getElementType());
361 return rewriter.notifyMatchFailure(op,
"Couldn't convert the type");
364 Type rTy = getTypeConverter()->convertType(op.getResult().getType());
366 return rewriter.notifyMatchFailure(op,
"Couldn't convert the result type");
372 auto ptrTy = LLVM::LLVMPointerType::get(
getContext());
376 LLVM::GEPOp::create(rewriter, op.getLoc(), ptrTy, type,
377 LLVM::ZeroOp::create(rewriter, op.getLoc(), ptrTy),
378 ArrayRef<LLVM::GEPArg>({LLVM::GEPArg(1)}));
381 rewriter.replaceOpWithNewOp<LLVM::PtrToIntOp>(op, rTy, offset.getRes());
389LogicalResult ConstantOpConversion::matchAndRewrite(
390 ptr::ConstantOp op, OpAdaptor adaptor,
391 ConversionPatternRewriter &rewriter)
const {
392 TypedAttr value = op.getValue();
393 Type resultType = getTypeConverter()->convertType(op.getType());
395 return rewriter.notifyMatchFailure(op,
"Couldn't convert the result type");
397 if (isa<ptr::NullAttr>(value)) {
398 rewriter.replaceOpWithNewOp<LLVM::ZeroOp>(op, resultType);
401 auto addrAttr = dyn_cast<ptr::AddressAttr>(value);
404 return rewriter.notifyMatchFailure(
405 op,
"unsupported value attribute kind: " +
406 value.getAbstractAttribute().getName());
408 Type intType = rewriter.getIntegerType(addrAttr.getValue().getBitWidth());
409 Value intConst = LLVM::ConstantOp::create(rewriter, op.getLoc(), intType,
410 addrAttr.getValue());
411 rewriter.replaceOpWithNewOp<LLVM::IntToPtrOp>(op, resultType, intConst);
421struct PtrToLLVMDialectInterface :
public ConvertToLLVMPatternInterface {
422 PtrToLLVMDialectInterface(Dialect *dialect)
423 : ConvertToLLVMPatternInterface(dialect) {}
425 void loadDependentDialects(MLIRContext *context)
const final {
426 context->loadDialect<LLVM::LLVMDialect>();
431 void populateConvertToLLVMConversionPatterns(
432 ConversionTarget &
target, LLVMTypeConverter &converter,
433 RewritePatternSet &patterns)
const final {
446 converter.addTypeAttributeConversion(
447 [&](PtrLikeTypeInterface type, ptr::GenericSpaceAttr memorySpace)
448 -> TypeConverter::AttributeConversionResult {
449 if (type.getMemorySpace() != memorySpace)
450 return TypeConverter::AttributeConversionResult::na();
451 return IntegerAttr::get(IntegerType::get(type.getContext(), 32), 0);
455 converter.addConversion([&](ptr::PtrType type) ->
Type {
456 std::optional<Attribute> maybeAttr =
457 converter.convertTypeAttribute(type, type.getMemorySpace());
459 maybeAttr ? dyn_cast_or_null<IntegerAttr>(*maybeAttr) : IntegerAttr();
462 return LLVM::LLVMPointerType::get(type.getContext(),
463 memSpace.getValue().getSExtValue());
467 converter.addConversion([&](ptr::PtrMetadataType type) ->
Type {
468 auto mTy = dyn_cast<MemRefType>(type.getType());
471 FailureOr<LLVM::LLVMStructType> res =
473 return failed(res) ?
Type() : res.value();
477 patterns.
add<FromPtrOpConversion, GetMetadataOpConversion, PtrAddOpConversion,
478 ToPtrOpConversion, TypeOffsetOpConversion, ConstantOpConversion>(
484 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.