21static bool isScalarLikeType(
Type type) {
29 if (!varName.empty()) {
30 auto varNameAttr = acc::VarNameAttr::get(builder.
getContext(), varName);
36struct MemRefPointerLikeModel
37 :
public PointerLikeType::ExternalModel<MemRefPointerLikeModel<T>, T> {
39 return cast<T>(pointer).getElementType();
42 mlir::acc::VariableTypeCategory
45 if (
auto mappableTy = dyn_cast<MappableType>(varType)) {
46 return mappableTy.getTypeCategory(varPtr);
48 auto memrefTy = cast<T>(pointer);
49 if (!memrefTy.hasRank()) {
52 return mlir::acc::VariableTypeCategory::uncategorized;
55 if (memrefTy.getRank() == 0) {
56 if (isScalarLikeType(memrefTy.getElementType())) {
57 return mlir::acc::VariableTypeCategory::scalar;
61 return mlir::acc::VariableTypeCategory::uncategorized;
65 assert(memrefTy.getRank() > 0 &&
"rank expected to be positive");
66 return mlir::acc::VariableTypeCategory::array;
69 mlir::Value genAllocate(Type pointer, OpBuilder &builder, Location loc,
70 StringRef varName, Type varType, Value originalVar,
71 bool &needsFree)
const {
72 auto memrefTy = cast<MemRefType>(pointer);
76 if (memrefTy.hasStaticShape()) {
78 auto allocaOp = memref::AllocaOp::create(builder, loc, memrefTy);
79 attachVarNameAttr(allocaOp, builder, varName);
80 return allocaOp.getResult();
85 if (originalVar && originalVar.
getType() == memrefTy &&
87 SmallVector<Value> dynamicSizes;
88 for (int64_t i = 0; i < memrefTy.getRank(); ++i) {
89 if (memrefTy.isDynamicDim(i)) {
93 memref::DimOp::create(builder, loc, originalVar, indexValue);
94 dynamicSizes.push_back(dimSize);
101 memref::AllocOp::create(builder, loc, memrefTy, dynamicSizes);
102 attachVarNameAttr(allocOp, builder, varName);
103 return allocOp.getResult();
110 bool genFree(Type pointer, OpBuilder &builder, Location loc,
112 Type varType)
const {
115 Value valueToInspect = allocRes ? allocRes : memrefValue;
118 Value currentValue = valueToInspect;
119 Operation *originalAlloc =
nullptr;
123 while (currentValue) {
126 if (isa<memref::AllocOp, memref::AllocaOp>(definingOp)) {
127 originalAlloc = definingOp;
132 if (
auto castOp = dyn_cast<memref::CastOp>(definingOp)) {
133 currentValue = castOp.getSource();
138 if (
auto reinterpretCastOp =
139 dyn_cast<memref::ReinterpretCastOp>(definingOp)) {
140 currentValue = reinterpretCastOp.getSource();
152 if (isa<memref::AllocaOp>(originalAlloc)) {
156 if (isa<memref::AllocOp>(originalAlloc)) {
158 memref::DeallocOp::create(builder, loc, memrefValue);
167 bool genCopy(Type pointer, OpBuilder &builder, Location loc,
171 auto destMemref = dyn_cast_if_present<TypedValue<MemRefType>>(destination);
172 auto srcMemref = dyn_cast_if_present<TypedValue<MemRefType>>(source);
178 if (destMemref && srcMemref &&
179 destMemref.getType().getElementType() ==
180 srcMemref.getType().getElementType() &&
181 destMemref.getType().getShape() == srcMemref.getType().getShape()) {
182 memref::CopyOp::create(builder, loc, srcMemref, destMemref);
189 mlir::Value
genLoad(Type pointer, OpBuilder &builder, Location loc,
191 Type valueType)
const {
196 auto memrefValue = dyn_cast_if_present<TypedValue<MemRefType>>(srcPtr);
200 auto memrefTy = memrefValue.
getType();
203 if (memrefTy.getRank() != 0)
206 return memref::LoadOp::create(builder, loc, memrefValue,
ValueRange{});
209 bool genStore(Type pointer, OpBuilder &builder, Location loc,
215 auto memrefValue = dyn_cast_if_present<TypedValue<MemRefType>>(destPtr);
219 auto memrefTy = memrefValue.getType();
222 if (memrefTy.getRank() != 0)
225 memref::StoreOp::create(builder, loc, valueToStore, memrefValue);
229 Value
genCast(Type, OpBuilder &builder, Location loc, Value value,
230 Type resultType)
const {
231 if (value.
getType() == resultType)
234 if (isa<BaseMemRefType>(value.
getType()) &&
235 isa<BaseMemRefType>(resultType)) {
238 return memref::CastOp::create(builder, loc, resultType, value);
239 if (memref::MemorySpaceCastOp::areCastCompatible(
241 return memref::MemorySpaceCastOp::create(builder, loc, resultType,
248 if (
auto resPtrLike = dyn_cast<PointerLikeType>(resultType))
249 if (!isa<BaseMemRefType>(resPtrLike))
250 if (Value v = resPtrLike.genCast(builder, loc, value, resultType))
252 if (
auto valPtrLike = dyn_cast<PointerLikeType>(value.
getType()))
253 if (!isa<BaseMemRefType>(valPtrLike))
254 if (Value v = valPtrLike.genCast(builder, loc, value, resultType))
260 bool isDeviceAccessible(Type pointer, Value var)
const {
261 auto memrefTy = cast<T>(pointer);
262 Attribute memSpace = memrefTy.getMemorySpace();
263 return isa_and_nonnull<gpu::AddressSpaceAttr>(memSpace);
266 MemRefType getAsMemRefType(Type pointer, ModuleOp module)
const {
268 return dyn_cast<MemRefType>(pointer);
272struct MemrefAddressOfGlobalModel
273 :
public AddressOfGlobalOpInterface::ExternalModel<
274 MemrefAddressOfGlobalModel, memref::GetGlobalOp> {
275 SymbolRefAttr getSymbol(Operation *op)
const {
276 auto getGlobalOp = cast<memref::GetGlobalOp>(op);
277 return getGlobalOp.getNameAttr();
281struct MemrefGlobalVariableModel
282 :
public GlobalVariableOpInterface::ExternalModel<MemrefGlobalVariableModel,
284 bool isConstant(Operation *op)
const {
285 auto globalOp = cast<memref::GlobalOp>(op);
286 return globalOp.getConstant();
289 bool hasInitializer(Operation *op)
const {
290 auto globalOp = cast<memref::GlobalOp>(op);
291 return globalOp.getInitialValue().has_value();
294 Region *getInitRegion(Operation *op)
const {
299 bool isDeviceAccessible(Operation *op)
const {
300 auto globalOp = cast<memref::GlobalOp>(op);
301 Attribute memSpace = globalOp.getType().getMemorySpace();
302 return isa_and_nonnull<gpu::AddressSpaceAttr>(memSpace);
305 bool isInDeviceMemory(Operation *op)
const {
309 return isDeviceAccessible(op);
312 bool isCompilerGenerated(Operation *op)
const {
return false; }
322 MemRefType::attachInterface<MemRefPointerLikeModel<MemRefType>>(*ctx);
323 UnrankedMemRefType::attachInterface<
324 MemRefPointerLikeModel<UnrankedMemRefType>>(*ctx);
325 memref::GetGlobalOp::attachInterface<MemrefAddressOfGlobalModel>(*ctx);
326 memref::GlobalOp::attachInterface<MemrefGlobalVariableModel>(*ctx);
static Type getElementType(Type type, ArrayRef< int32_t > indices, function_ref< InFlightDiagnostic(StringRef)> emitErrorFn)
Walks the given type hierarchy with the given indices, potentially down to component granularity,...
static void genStore(OpBuilder &builder, Location loc, Value val, Value mem, Value idx)
Generates a store with proper index typing and proper value.
static Value genLoad(OpBuilder &builder, Location loc, Value mem, Value idx)
Generates a load with proper index typing.
MLIRContext * getContext() const
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.
MLIRContext is the top-level object for a collection of MLIR operations.
T * getOrLoadDialect()
Get (or create) a dialect for the given derived dialect type.
This class helps build Operations.
Operation is the basic unit of execution within MLIR.
void setDiscardableAttr(StringAttr name, Attribute value)
Set a discardable attribute by name.
Instances of the Type class are uniqued, have an immutable identifier and an optional mutable compone...
bool isIntOrIndexOrFloat() const
Return true if this is an integer (of any signedness), index, or float type.
Type getType() const
Return the type of this value.
Operation * getDefiningOp() const
If this value is the result of an operation, return the operation that defines it.
static ConstantIndexOp create(OpBuilder &builder, Location location, int64_t value)
void registerMemRefInterfaces(DialectRegistry ®istry)
Register OpenACC interfaces for MemRef IR.
static constexpr StringLiteral getVarNameAttrName()
Value genCast(OpBuilder &builder, Location loc, Value value, Type dstTy)
Add type casting between arith and index types when needed.
Include the generated interface declarations.
std::conditional_t< std::is_same_v< Ty, mlir::Type >, mlir::Value, detail::TypedValue< Ty > > TypedValue
If Ty is mlir::Type this will select Value instead of having a wrapper around it.