Now that memref supports arbitrary element types, add support for memref of memref and make sure it is properly converted to the LLVM dialect. The type support itself avoids adding the interface to the memref type itself similarly to other built-in types. This allows the shape, and therefore byte size, of the memref descriptor to remain a lowering aspect that is easier to customize and evolve as opposed to sanctifying it in the data layout specification for the memref type itself. Factor out the code previously in a testing pass to live in a dedicated data layout analysis and use that analysis in the conversion to compute the allocation size for memref of memref. Other conversions will be ported separately. Depends On D103827 Reviewed By: rriddle Differential Revision: https://reviews.llvm.org/D103828
52 lines
1.8 KiB
C++
52 lines
1.8 KiB
C++
//===- DataLayoutAnalysis.cpp ---------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "mlir/Analysis/DataLayoutAnalysis.h"
|
|
#include "mlir/IR/BuiltinOps.h"
|
|
#include "mlir/IR/Operation.h"
|
|
#include "mlir/Interfaces/DataLayoutInterfaces.h"
|
|
|
|
using namespace mlir;
|
|
|
|
DataLayoutAnalysis::DataLayoutAnalysis(Operation *root)
|
|
: defaultLayout(std::make_unique<DataLayout>(DataLayoutOpInterface())) {
|
|
// Construct a DataLayout if possible from the op.
|
|
auto computeLayout = [this](Operation *op) {
|
|
if (auto iface = dyn_cast<DataLayoutOpInterface>(op))
|
|
layouts[op] = std::make_unique<DataLayout>(iface);
|
|
if (auto module = dyn_cast<ModuleOp>(op))
|
|
layouts[op] = std::make_unique<DataLayout>(module);
|
|
};
|
|
|
|
// Compute layouts for both ancestors and descendants.
|
|
root->walk(computeLayout);
|
|
for (Operation *ancestor = root->getParentOp(); ancestor != nullptr;
|
|
ancestor = ancestor->getParentOp()) {
|
|
computeLayout(ancestor);
|
|
}
|
|
}
|
|
|
|
const DataLayout &DataLayoutAnalysis::getAbove(Operation *operation) const {
|
|
for (Operation *ancestor = operation->getParentOp(); ancestor != nullptr;
|
|
ancestor = ancestor->getParentOp()) {
|
|
auto it = layouts.find(ancestor);
|
|
if (it != layouts.end())
|
|
return *it->getSecond();
|
|
}
|
|
|
|
// Fallback to the default layout.
|
|
return *defaultLayout;
|
|
}
|
|
|
|
const DataLayout &DataLayoutAnalysis::getAtOrAbove(Operation *operation) const {
|
|
auto it = layouts.find(operation);
|
|
if (it != layouts.end())
|
|
return *it->getSecond();
|
|
return getAbove(operation);
|
|
}
|