MLIR  17.0.0git
AllocLikeConversion.h
Go to the documentation of this file.
1 //===- AllocLikeConversion.h - Convert allocation ops to LLVM ---*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef MLIR_CONVERSION_MEMREFTOLLVM_ALLOCLIKECONVERSION_H
10 #define MLIR_CONVERSION_MEMREFTOLLVM_ALLOCLIKECONVERSION_H
11 
13 
14 namespace mlir {
15 
16 /// Lowering for memory allocation ops.
21 
22  explicit AllocationOpLLVMLowering(StringRef opName,
23  LLVMTypeConverter &converter)
24  : ConvertToLLVMPattern(opName, &converter.getContext(), converter) {}
25 
26 protected:
27  /// Computes the aligned value for 'input' as follows:
28  /// bumped = input + alignement - 1
29  /// aligned = bumped - bumped % alignment
31  Value input, Value alignment);
32 
33  static MemRefType getMemRefResultType(Operation *op) {
34  return op->getResult(0).getType().cast<MemRefType>();
35  }
36 
37  /// Computes the alignment for the given memory allocation op.
38  template <typename OpType>
40  OpType op) const {
41  MemRefType memRefType = op.getType();
42  Value alignment;
43  if (auto alignmentAttr = op.getAlignment()) {
44  alignment = createIndexConstant(rewriter, loc, *alignmentAttr);
45  } else if (!memRefType.getElementType().isSignlessIntOrIndexOrFloat()) {
46  // In the case where no alignment is specified, we may want to override
47  // `malloc's` behavior. `malloc` typically aligns at the size of the
48  // biggest scalar on a target HW. For non-scalars, use the natural
49  // alignment of the LLVM type given by the LLVM DataLayout.
50  alignment = getSizeInBytes(loc, memRefType.getElementType(), rewriter);
51  }
52  return alignment;
53  }
54 
55  /// Computes the alignment for aligned_alloc used to allocate the buffer for
56  /// the memory allocation op.
57  ///
58  /// Aligned_alloc requires the allocation size to be a power of two, and the
59  /// allocation size to be a multiple of the alignment.
60  template <typename OpType>
62  Location loc, OpType op,
63  const DataLayout *defaultLayout) const {
64  if (std::optional<uint64_t> alignment = op.getAlignment())
65  return *alignment;
66 
67  // Whenever we don't have alignment set, we will use an alignment
68  // consistent with the element type; since the allocation size has to be a
69  // power of two, we will bump to the next power of two if it isn't.
70  unsigned eltSizeBytes =
71  getMemRefEltSizeInBytes(op.getType(), op, defaultLayout);
72  return std::max(kMinAlignedAllocAlignment,
73  llvm::PowerOf2Ceil(eltSizeBytes));
74  }
75 
76  /// Allocates a memory buffer using an allocation method that doesn't
77  /// guarantee alignment. Returns the pointer and its aligned value.
78  std::tuple<Value, Value>
80  Value sizeBytes, Operation *op,
81  Value alignment) const;
82 
83  /// Allocates a memory buffer using an aligned allocation method.
85  Location loc, Value sizeBytes, Operation *op,
86  const DataLayout *defaultLayout,
87  int64_t alignment) const;
88 
89 private:
90  /// Computes the byte size for the MemRef element type.
91  unsigned getMemRefEltSizeInBytes(MemRefType memRefType, Operation *op,
92  const DataLayout *defaultLayout) const;
93 
94  /// Returns true if the memref size in bytes is known to be a multiple of
95  /// factor.
96  bool isMemRefSizeMultipleOf(MemRefType type, uint64_t factor, Operation *op,
97  const DataLayout *defaultLayout) const;
98 
99  /// The minimum alignment to use with aligned_alloc (has to be a power of 2).
100  static constexpr uint64_t kMinAlignedAllocAlignment = 16UL;
101 };
102 
103 /// Lowering for AllocOp and AllocaOp.
105  explicit AllocLikeOpLLVMLowering(StringRef opName,
106  LLVMTypeConverter &converter)
107  : AllocationOpLLVMLowering(opName, converter) {}
108 
109 protected:
110  /// Allocates the underlying buffer. Returns the allocated pointer and the
111  /// aligned pointer.
112  virtual std::tuple<Value, Value>
114  Value sizeBytes, Operation *op) const = 0;
115 
116 private:
117  // An `alloc` is converted into a definition of a memref descriptor value and
118  // a call to `malloc` to allocate the underlying data buffer. The memref
119  // descriptor is of the LLVM structure type where:
120  // 1. the first element is a pointer to the allocated (typed) data buffer,
121  // 2. the second element is a pointer to the (typed) payload, aligned to the
122  // specified alignment,
123  // 3. the remaining elements serve to store all the sizes and strides of the
124  // memref using LLVM-converted `index` type.
125  //
126  // Alignment is performed by allocating `alignment` more bytes than
127  // requested and shifting the aligned pointer relative to the allocated
128  // memory. Note: `alignment - <minimum malloc alignment>` would actually be
129  // sufficient. If alignment is unspecified, the two pointers are equal.
130 
131  // An `alloca` is converted into a definition of a memref descriptor value and
132  // an llvm.alloca to allocate the underlying data buffer.
134  matchAndRewrite(Operation *op, ArrayRef<Value> operands,
135  ConversionPatternRewriter &rewriter) const override;
136 };
137 
138 } // namespace mlir
139 
140 #endif // MLIR_CONVERSION_MEMREFTOLLVM_ALLOCLIKECONVERSION_H
static Value max(ImplicitLocOpBuilder &builder, Value value, Value bound)
This class implements a pattern rewriter for use with ConversionPatterns.
Base class for operation conversions targeting the LLVM IR dialect.
Definition: Pattern.h:37
Type getIndexType() const
Gets the MLIR type wrapping the LLVM integer type whose bit width is defined by the used type convert...
Definition: Pattern.cpp:37
Value getSizeInBytes(Location loc, Type type, ConversionPatternRewriter &rewriter) const
Computes the size of type in bytes.
Definition: Pattern.cpp:167
Value createIndexConstant(ConversionPatternRewriter &builder, Location loc, uint64_t value) const
Create an LLVM dialect operation defining the given index constant.
Definition: Pattern.cpp:63
Type getVoidPtrType() const
Get the MLIR type wrapping the LLVM i8* type.
Definition: Pattern.cpp:50
The main mechanism for performing data layout queries.
Conversion from types to the LLVM IR dialect.
Definition: TypeConverter.h:30
This class defines the main interface for locations in MLIR and acts as a non-nullable wrapper around...
Definition: Location.h:63
Operation is the basic unit of execution within MLIR.
Definition: Operation.h:75
OpResult getResult(unsigned idx)
Get the 'idx'th result of this operation.
Definition: Operation.h:368
MLIRContext * getContext() const
Return the MLIRContext used to create this pattern.
Definition: PatternMatch.h:133
U cast() const
Definition: Types.h:321
This class represents an instance of an SSA value in the MLIR system, representing a computable value...
Definition: Value.h:93
Type getType() const
Return the type of this value.
Definition: Value.h:122
Include the generated interface declarations.
Lowering for AllocOp and AllocaOp.
virtual std::tuple< Value, Value > allocateBuffer(ConversionPatternRewriter &rewriter, Location loc, Value sizeBytes, Operation *op) const =0
Allocates the underlying buffer.
AllocLikeOpLLVMLowering(StringRef opName, LLVMTypeConverter &converter)
Lowering for memory allocation ops.
static Value createAligned(ConversionPatternRewriter &rewriter, Location loc, Value input, Value alignment)
Computes the aligned value for 'input' as follows: bumped = input + alignement - 1 aligned = bumped -...
int64_t alignedAllocationGetAlignment(ConversionPatternRewriter &rewriter, Location loc, OpType op, const DataLayout *defaultLayout) const
Computes the alignment for aligned_alloc used to allocate the buffer for the memory allocation op.
Value getAlignment(ConversionPatternRewriter &rewriter, Location loc, OpType op) const
Computes the alignment for the given memory allocation op.
Value allocateBufferAutoAlign(ConversionPatternRewriter &rewriter, Location loc, Value sizeBytes, Operation *op, const DataLayout *defaultLayout, int64_t alignment) const
Allocates a memory buffer using an aligned allocation method.
static MemRefType getMemRefResultType(Operation *op)
std::tuple< Value, Value > allocateBufferManuallyAlign(ConversionPatternRewriter &rewriter, Location loc, Value sizeBytes, Operation *op, Value alignment) const
Allocates a memory buffer using an allocation method that doesn't guarantee alignment.
Value createIndexConstant(ConversionPatternRewriter &builder, Location loc, uint64_t value) const
Create an LLVM dialect operation defining the given index constant.
Definition: Pattern.cpp:63
AllocationOpLLVMLowering(StringRef opName, LLVMTypeConverter &converter)
This class represents an efficient way to signal success or failure.
Definition: LogicalResult.h:26