second temp commit: i will soft-reset and recommit after next changes
Validate Operations / validate-operations (push) Has been cancelled
Validate Operations / validate-operations (push) Has been cancelled
This commit is contained in:
@@ -14,10 +14,11 @@
|
||||
#include "src/Accelerators/PIM/Common/IR/LoopUtils.hpp"
|
||||
#include "src/Accelerators/PIM/Common/IR/TensorSliceUtils.hpp"
|
||||
#include "src/Accelerators/PIM/Common/Support/Diagnostics.hpp"
|
||||
#include "src/Accelerators/PIM/Compiler/PimCompilerOptions.hpp"
|
||||
#include "src/Accelerators/PIM/Conversion/ONNXToSpatial/Common/BiasAddUtils.hpp"
|
||||
#include "src/Accelerators/PIM/Conversion/ONNXToSpatial/Common/Common.hpp"
|
||||
#include "src/Accelerators/PIM/Conversion/ONNXToSpatial/Common/MatrixProductLowering.hpp"
|
||||
#include "src/Accelerators/PIM/Conversion/ONNXToSpatial/Common/RowStripLayoutUtils.hpp"
|
||||
#include "src/Accelerators/PIM/Conversion/ONNXToSpatial/Patterns/Math/Gemm.hpp"
|
||||
#include "src/Accelerators/PIM/Conversion/ONNXToSpatial/CompileTime.hpp"
|
||||
#include "src/Accelerators/PIM/Conversion/ONNXToSpatial/PlanLowering.hpp"
|
||||
#include "src/Accelerators/PIM/Conversion/ONNXToSpatial/Patterns/Math/ConvGeometry.hpp"
|
||||
@@ -30,11 +31,14 @@ namespace onnx_mlir {
|
||||
namespace {
|
||||
|
||||
struct ConvToGemm : OpConversionPattern<ONNXConvOp> {
|
||||
using OpConversionPattern::OpConversionPattern;
|
||||
explicit ConvToGemm(MLIRContext* ctx, const spatial::SpatialTargetInfo& target)
|
||||
: OpConversionPattern<ONNXConvOp>(ctx), target(target) {}
|
||||
|
||||
LogicalResult matchAndRewrite(ONNXConvOp convOp,
|
||||
ONNXConvOpAdaptor convOpAdaptor,
|
||||
ConversionPatternRewriter& rewriter) const override;
|
||||
|
||||
const spatial::SpatialTargetInfo& target;
|
||||
};
|
||||
|
||||
struct PreparedConvInput {
|
||||
@@ -43,45 +47,21 @@ struct PreparedConvInput {
|
||||
};
|
||||
|
||||
static Value createZeroGemmBias(RankedTensorType gemmResultType, PatternRewriter& rewriter);
|
||||
static StringRef stringifyConvLoweringStrategy(PimConvLoweringType strategy) {
|
||||
static StringRef stringifyConvLoweringStrategy(spatial::ConvLoweringStrategy strategy) {
|
||||
switch (strategy) {
|
||||
case PimConvLoweringAuto: return "auto";
|
||||
case PimConvLoweringLegacy: return "legacy";
|
||||
case PimConvLoweringDepthwise: return "depthwise";
|
||||
case PimConvLoweringPackedIm2Col: return "packed-im2col";
|
||||
case PimConvLoweringStreamedPatch: return "streamed-patch";
|
||||
case PimConvLoweringStreamedPacked: return "streamed-packed";
|
||||
case PimConvLoweringOutputChannelTiled: return "output-channel-tiled";
|
||||
case PimConvLoweringInputKTiled: return "input-k-tiled";
|
||||
case PimConvLoweringTiled2D: return "tiled-2d";
|
||||
case spatial::ConvLoweringStrategy::Auto: return "auto";
|
||||
case spatial::ConvLoweringStrategy::Legacy: return "legacy";
|
||||
case spatial::ConvLoweringStrategy::Depthwise: return "depthwise";
|
||||
case spatial::ConvLoweringStrategy::PackedIm2Col: return "packed-im2col";
|
||||
case spatial::ConvLoweringStrategy::StreamedPatch: return "streamed-patch";
|
||||
case spatial::ConvLoweringStrategy::StreamedPacked: return "streamed-packed";
|
||||
case spatial::ConvLoweringStrategy::OutputChannelTiled: return "output-channel-tiled";
|
||||
case spatial::ConvLoweringStrategy::InputKTiled: return "input-k-tiled";
|
||||
case spatial::ConvLoweringStrategy::Tiled2D: return "tiled-2d";
|
||||
}
|
||||
llvm_unreachable("unknown conv lowering strategy");
|
||||
}
|
||||
|
||||
static PimConvLoweringType chooseConvLoweringStrategy(const ConvGeometry& geo,
|
||||
PimConvLoweringType requested) {
|
||||
if (requested != PimConvLoweringAuto)
|
||||
return requested;
|
||||
|
||||
// Transform-based convolution is intentionally not selected for this ISA:
|
||||
// it would require explicit transform sequences and staging traffic on top of
|
||||
// the same crossbar MVM primitive, which is not attractive here.
|
||||
if (geo.isDepthwise)
|
||||
return PimConvLoweringDepthwise;
|
||||
if (geo.k <= geo.xbarSize && geo.c <= geo.xbarSize && geo.pack >= 2 && geo.im2colElements <= pimConvIm2colMaxElements)
|
||||
return PimConvLoweringPackedIm2Col;
|
||||
if (geo.k <= geo.xbarSize && geo.c <= geo.xbarSize && geo.pack >= 2 && geo.im2colElements > pimConvIm2colMaxElements)
|
||||
return PimConvLoweringStreamedPacked;
|
||||
if (geo.k <= geo.xbarSize && geo.c <= geo.xbarSize)
|
||||
return PimConvLoweringStreamedPatch;
|
||||
if (geo.k <= geo.xbarSize && geo.c > geo.xbarSize)
|
||||
return PimConvLoweringOutputChannelTiled;
|
||||
if (geo.k > geo.xbarSize && geo.c <= geo.xbarSize)
|
||||
return PimConvLoweringLegacy;
|
||||
return PimConvLoweringTiled2D;
|
||||
}
|
||||
|
||||
|
||||
static Value expandBiasIfNeeded(Value bias, PatternRewriter& rewriter, Location loc) {
|
||||
auto biasType = cast<RankedTensorType>(bias.getType());
|
||||
if (biasType.getRank() != 1)
|
||||
@@ -194,7 +174,11 @@ static Value createCollectedConvOutput(ValueRange gemmRows,
|
||||
int64_t packFactor,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc);
|
||||
static FailureOr<ConvLoweringState> analyzeConvLoweringState(ONNXConvOp convOp, Value x, Value w, Value b);
|
||||
static FailureOr<ConvLoweringState> analyzeConvLoweringState(ONNXConvOp convOp,
|
||||
Value x,
|
||||
Value w,
|
||||
Value b,
|
||||
const spatial::SpatialTargetInfo& target);
|
||||
|
||||
namespace depthwise {
|
||||
|
||||
@@ -215,10 +199,10 @@ static std::optional<Tiling> computeTiling(int64_t batchSize,
|
||||
int64_t wHeight,
|
||||
int64_t wWidth,
|
||||
int64_t outHeight,
|
||||
int64_t outWidth) {
|
||||
int64_t outWidth,
|
||||
int64_t xbarDim) {
|
||||
const int64_t kernelElements = wHeight * wWidth;
|
||||
const int64_t outputMultiplier = numChannelsOut / numChannelsIn;
|
||||
const int64_t xbarDim = static_cast<int64_t>(crossbarSize.getValue());
|
||||
if (kernelElements <= 0 || outputMultiplier <= 0 || kernelElements > xbarDim || outputMultiplier > xbarDim)
|
||||
return std::nullopt;
|
||||
|
||||
@@ -249,8 +233,9 @@ static Value buildPackedWeights(DenseElementsAttr wDenseAttr,
|
||||
const Tiling& tiling,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc,
|
||||
int64_t xbarDim,
|
||||
int64_t paddedInputRows = -1) {
|
||||
const int64_t paddedOutputChannels = static_cast<int64_t>(crossbarSize.getValue());
|
||||
const int64_t paddedOutputChannels = xbarDim;
|
||||
const int64_t packedInputRows = paddedInputRows > 0 ? paddedInputRows : tiling.tileInputRows;
|
||||
auto packedWeightType = RankedTensorType::get(
|
||||
{tiling.numChannelTiles, packedInputRows, paddedOutputChannels}, wType.getElementType());
|
||||
@@ -396,7 +381,7 @@ static Value createWeightTile(Value packedWeights,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc) {
|
||||
SmallVector<OpFoldResult> offsets {channelTileIndex, rewriter.getIndexAttr(0), rewriter.getIndexAttr(0)};
|
||||
const int64_t paddedOutputChannels = static_cast<int64_t>(crossbarSize.getValue());
|
||||
const int64_t paddedOutputChannels = packedWeightType.getDimSize(2);
|
||||
SmallVector<OpFoldResult> sizes {rewriter.getIndexAttr(1),
|
||||
rewriter.getIndexAttr(tiling.tileInputRows),
|
||||
rewriter.getIndexAttr(paddedOutputChannels)};
|
||||
@@ -528,7 +513,8 @@ static bool canUseStructuredRewrite(const ConvLoweringState& state) {
|
||||
state.wHeight,
|
||||
state.wWidth,
|
||||
state.outHeight,
|
||||
state.outWidth);
|
||||
state.outWidth,
|
||||
state.targetInfo().matrixShape.rows);
|
||||
if (!tiling)
|
||||
return false;
|
||||
|
||||
@@ -559,7 +545,8 @@ rewriteConv(Operation* convOp, const ConvLoweringState& state, PatternRewriter&
|
||||
state.wType.getDimSize(2),
|
||||
state.wType.getDimSize(3),
|
||||
state.outType.getDimSize(2),
|
||||
state.outType.getDimSize(3));
|
||||
state.outType.getDimSize(3),
|
||||
state.targetInfo().matrixShape.rows);
|
||||
if (!tiling) {
|
||||
convOp->emitOpError("failed to derive a structured depthwise tiling that fits Spatial weighted VMM lowering");
|
||||
return failure();
|
||||
@@ -579,9 +566,10 @@ rewriteConv(Operation* convOp, const ConvLoweringState& state, PatternRewriter&
|
||||
paddedInputType.getDimSize(3),
|
||||
paddedInputType.getDimSize(1)},
|
||||
paddedInputType.getElementType());
|
||||
Value channelLastInput = ONNXTransposeOp::create(
|
||||
rewriter, loc, channelLastInputType, paddedInput, rewriter.getI64ArrayAttr({0, 2, 3, 1}));
|
||||
Value packedWeights = buildPackedWeights(wDenseAttr, state.wType, *tiling, rewriter, loc);
|
||||
Value channelLastInput = createLinalgTranspose(
|
||||
paddedInput, channelLastInputType, {0, 2, 3, 1}, rewriter, loc);
|
||||
Value packedWeights = buildPackedWeights(
|
||||
wDenseAttr, state.wType, *tiling, rewriter, loc, state.targetInfo().matrixShape.rows);
|
||||
|
||||
Value expandedBias;
|
||||
SmallVector<Value> batchInputs {channelLastInput};
|
||||
@@ -600,7 +588,7 @@ rewriteConv(Operation* convOp, const ConvLoweringState& state, PatternRewriter&
|
||||
RankedTensorType::get({tiling->totalPatches, state.outType.getDimSize(1)}, state.outType.getElementType());
|
||||
auto rowTileType = RankedTensorType::get({1, tiling->tileOutputChannels}, state.outType.getElementType());
|
||||
auto paddedRowTileType = RankedTensorType::get(
|
||||
{1, static_cast<int64_t>(crossbarSize.getValue())}, state.outType.getElementType());
|
||||
{1, static_cast<int64_t>(state.targetInfo().matrixShape.rows)}, state.outType.getElementType());
|
||||
auto piecesType = spatial::getGraphBatchPhysicalResultType(
|
||||
tiling->totalPatches * tiling->numChannelTiles, rowTileType);
|
||||
auto inputTileType =
|
||||
@@ -826,8 +814,7 @@ static Value createWeightMatrix(
|
||||
});
|
||||
if (!transpose)
|
||||
return flattened;
|
||||
return ONNXTransposeOp::create(rewriter, loc, plan.wTransType, flattened, rewriter.getI64ArrayAttr({1, 0}))
|
||||
.getResult();
|
||||
return createLinalgTranspose(flattened, plan.wTransType, {1, 0}, rewriter, loc);
|
||||
};
|
||||
|
||||
if (isCompileTimeComputable(weights))
|
||||
@@ -963,17 +950,17 @@ static FailureOr<Value> rewriteInputKTiledConv(const ConvLoweringState& state,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc) {
|
||||
PreparedConvInput preparedInput = prepareInputForIm2Col(state, rewriter, loc);
|
||||
ConvGeometry geo = buildConvGeometry(state);
|
||||
ConvGeometry geo = buildConvGeometry(state, state.targetInfo());
|
||||
const int64_t xbarDim = geo.xbarSize;
|
||||
const int64_t numKSlices = ceilIntegerDivide(geo.k, xbarDim);
|
||||
const int64_t paddedK = numKSlices * xbarDim;
|
||||
const uint64_t maxLanesPerBatch =
|
||||
std::max<uint64_t>(1,
|
||||
static_cast<uint64_t>(crossbarCountInCore.getValue())
|
||||
static_cast<uint64_t>(state.targetInfo().matrixUnitsPerProcessor)
|
||||
/ static_cast<uint64_t>(std::max<int64_t>(1, numKSlices * 4)));
|
||||
const uint64_t rowChunkWidth = std::max<uint64_t>(
|
||||
1,
|
||||
std::min<uint64_t>({chooseStreamChunkPositions(geo, /*packFactor=*/1),
|
||||
std::min<uint64_t>({chooseStreamChunkPositions(geo, /*packFactor=*/1, state.targetInfo()),
|
||||
maxLanesPerBatch,
|
||||
static_cast<uint64_t>(state.outWidth)}));
|
||||
const auto elementType = state.outType.getElementType();
|
||||
@@ -1227,7 +1214,7 @@ buildConvGemmPlan(const ConvLoweringState& state,
|
||||
const int64_t wMaxDim = std::max(plan.patchSize, state.numChannelsOut);
|
||||
plan.maxParallelPixels = forcedPackFactor
|
||||
? *forcedPackFactor
|
||||
: std::max<int64_t>(1, static_cast<int64_t>(crossbarSize.getValue()) / wMaxDim);
|
||||
: std::max<int64_t>(1, static_cast<int64_t>(state.targetInfo().matrixShape.rows) / wMaxDim);
|
||||
plan.effectiveMaxParallelPixels =
|
||||
(canPackWeightsAsConstants && canPackBiasAsConstants) ? plan.maxParallelPixels : 1;
|
||||
plan.packedNumRows = ceilIntegerDivide(plan.chunkNumPatches, plan.effectiveMaxParallelPixels);
|
||||
@@ -1251,7 +1238,8 @@ static Value createIm2colRows(const ConvLoweringState& state,
|
||||
const ConvGemmPlan& plan,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc) {
|
||||
if (plan.gemmInputRowsType.getDimSize(1) > crossbarSize.getValue()) {
|
||||
if (plan.gemmInputRowsType.getDimSize(1)
|
||||
> static_cast<int64_t>(state.targetInfo().matrixShape.rows)) {
|
||||
assert(plan.effectiveMaxParallelPixels == 1 && "multi-crossbar im2col rows cannot pack pixels");
|
||||
auto compute = createSpatCompute<1>(
|
||||
rewriter, loc, TypeRange {plan.gemmInputRowsType}, {}, preparedInput.value, [&](Value input) {
|
||||
@@ -1419,15 +1407,15 @@ static Value maybeUnpackChunkRows(Value gemmRows,
|
||||
return unpackCompute.getResult(0);
|
||||
}
|
||||
|
||||
static Value createStreamedConvRows(const ConvLoweringState& state,
|
||||
const PreparedConvInput& preparedInput,
|
||||
Value weightMatrix,
|
||||
Value biasMatrix,
|
||||
DenseElementsAttr wDenseAttr,
|
||||
DenseElementsAttr biasDenseAttr,
|
||||
int64_t forcedPackFactor,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc) {
|
||||
static FailureOr<Value> createStreamedConvRows(const ConvLoweringState& state,
|
||||
const PreparedConvInput& preparedInput,
|
||||
Value weightMatrix,
|
||||
Value biasMatrix,
|
||||
DenseElementsAttr wDenseAttr,
|
||||
DenseElementsAttr biasDenseAttr,
|
||||
int64_t forcedPackFactor,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc) {
|
||||
const int64_t totalPatches = state.batchSize * state.outHeight * state.outWidth;
|
||||
ConvGemmPlan plan = buildConvGemmPlan(state, static_cast<bool>(wDenseAttr),
|
||||
!state.hasBias || static_cast<bool>(biasDenseAttr), 0, totalPatches, forcedPackFactor);
|
||||
@@ -1435,14 +1423,18 @@ static Value createStreamedConvRows(const ConvLoweringState& state,
|
||||
Value packedWeights = buildPackedWeights(wDenseAttr, weightMatrix, state, plan, rewriter, loc);
|
||||
Value gemmBias = state.hasBias ? state.b : createZeroGemmBias(plan.gemmOutputRowsType, rewriter);
|
||||
Value packedBias = buildPackedBias(gemmBias, biasMatrix, biasDenseAttr, state, plan, rewriter, loc);
|
||||
Value gemmRows = ONNXGemmOp::create(rewriter, loc, plan.gemmOutputRowsType, inputRows,
|
||||
packedWeights, packedBias, APFloat(1.0f), APFloat(1.0f), 0, !wDenseAttr).getY();
|
||||
return maybeUnpackChunkRows(gemmRows, plan, rewriter, loc);
|
||||
FailureOr<Value> gemmRows = lowerGemmToSpatial(
|
||||
state.diagnosticAnchor, inputRows, packedWeights, packedBias,
|
||||
plan.gemmOutputRowsType, /*transA=*/false, /*transB=*/!wDenseAttr,
|
||||
/*alpha=*/1.0f, /*beta=*/1.0f, state.targetInfo(), rewriter, loc);
|
||||
if (failed(gemmRows))
|
||||
return failure();
|
||||
return maybeUnpackChunkRows(*gemmRows, plan, rewriter, loc);
|
||||
}
|
||||
|
||||
static Value rewritePackedIm2ColConv(const ConvLoweringState& state,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc) {
|
||||
static FailureOr<Value> rewritePackedIm2ColConv(const ConvLoweringState& state,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc) {
|
||||
auto wDenseAttr = getHostConstDenseElementsAttr(state.w);
|
||||
PreparedConvInput preparedInput = prepareInputForIm2Col(state, rewriter, loc);
|
||||
Value biasMatrix;
|
||||
@@ -1466,19 +1458,14 @@ static Value rewritePackedIm2ColConv(const ConvLoweringState& state,
|
||||
gemmBias = state.b;
|
||||
Value gemmC = buildPackedBias(gemmBias, biasMatrix, biasDenseAttr, state, plan, rewriter, loc);
|
||||
|
||||
Value gemmRows = ONNXGemmOp::create(rewriter,
|
||||
loc,
|
||||
plan.gemmOutputRowsType,
|
||||
gemmInputRows,
|
||||
gemmB,
|
||||
gemmC,
|
||||
APFloat(1.0f),
|
||||
APFloat(1.0f),
|
||||
/*transA=*/0,
|
||||
/*transB=*/!wDenseAttr)
|
||||
.getY();
|
||||
FailureOr<Value> gemmRows = lowerGemmToSpatial(
|
||||
state.diagnosticAnchor, gemmInputRows, gemmB, gemmC,
|
||||
plan.gemmOutputRowsType, /*transA=*/false, /*transB=*/!wDenseAttr,
|
||||
/*alpha=*/1.0f, /*beta=*/1.0f, state.targetInfo(), rewriter, loc);
|
||||
if (failed(gemmRows))
|
||||
return failure();
|
||||
|
||||
return createCollectedConvOutput(ValueRange {gemmRows},
|
||||
return createCollectedConvOutput(ValueRange {*gemmRows},
|
||||
state.outType,
|
||||
plan.gemmOutType,
|
||||
plan.nhwcType,
|
||||
@@ -1490,10 +1477,10 @@ static Value rewritePackedIm2ColConv(const ConvLoweringState& state,
|
||||
loc);
|
||||
}
|
||||
|
||||
static Value rewriteStreamedConv(const ConvLoweringState& state,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc,
|
||||
int64_t forcedPackFactor) {
|
||||
static FailureOr<Value> rewriteStreamedConv(const ConvLoweringState& state,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc,
|
||||
int64_t forcedPackFactor) {
|
||||
auto wDenseAttr = getHostConstDenseElementsAttr(state.w);
|
||||
PreparedConvInput preparedInput = prepareInputForIm2Col(state, rewriter, loc);
|
||||
Value biasMatrix;
|
||||
@@ -1506,20 +1493,22 @@ static Value rewriteStreamedConv(const ConvLoweringState& state,
|
||||
ConvGemmPlan seedPlan = buildConvGemmPlan(
|
||||
state, static_cast<bool>(wDenseAttr), !state.hasBias || static_cast<bool>(biasDenseAttr), 0, 1, forcedPackFactor);
|
||||
Value weightMatrix = createWeightMatrix(state.w, seedPlan, static_cast<bool>(wDenseAttr), rewriter, loc);
|
||||
Value collectedRows = createStreamedConvRows(state,
|
||||
preparedInput,
|
||||
weightMatrix,
|
||||
biasMatrix,
|
||||
wDenseAttr,
|
||||
biasDenseAttr,
|
||||
forcedPackFactor,
|
||||
rewriter,
|
||||
loc);
|
||||
auto gemmOutType = cast<RankedTensorType>(collectedRows.getType());
|
||||
FailureOr<Value> collectedRows = createStreamedConvRows(state,
|
||||
preparedInput,
|
||||
weightMatrix,
|
||||
biasMatrix,
|
||||
wDenseAttr,
|
||||
biasDenseAttr,
|
||||
forcedPackFactor,
|
||||
rewriter,
|
||||
loc);
|
||||
if (failed(collectedRows))
|
||||
return failure();
|
||||
auto gemmOutType = cast<RankedTensorType>(collectedRows->getType());
|
||||
auto nhwcType = RankedTensorType::get({state.batchSize, state.outHeight, state.outWidth, state.numChannelsOut},
|
||||
state.outType.getElementType());
|
||||
return createCollectedConvOutput(
|
||||
ValueRange {collectedRows}, state.outType, gemmOutType, nhwcType, state.outType, gemmOutType.getDimSize(0),
|
||||
ValueRange {*collectedRows}, state.outType, gemmOutType, nhwcType, state.outType, gemmOutType.getDimSize(0),
|
||||
state.numChannelsOut, /*packFactor=*/1, rewriter, loc);
|
||||
}
|
||||
|
||||
@@ -1534,12 +1523,12 @@ static Value createZeroGemmBias(RankedTensorType gemmResultType, PatternRewriter
|
||||
static bool rowStripOutputTileFitsOneCore(const ConvGeometry& geometry) {
|
||||
return ceilIntegerDivide(geometry.k, geometry.xbarSize)
|
||||
* ceilIntegerDivide(geometry.c, geometry.xbarSize)
|
||||
<= static_cast<int64_t>(crossbarCountInCore.getValue());
|
||||
<= geometry.matrixUnitsPerProcessor;
|
||||
}
|
||||
|
||||
static bool rowStripOutputChannelTileFitsOneCore(const ConvGeometry& geometry) {
|
||||
return ceilIntegerDivide(geometry.k, geometry.xbarSize)
|
||||
<= static_cast<int64_t>(crossbarCountInCore.getValue());
|
||||
<= geometry.matrixUnitsPerProcessor;
|
||||
}
|
||||
|
||||
static int64_t chooseRowStripPixelPackFactor(const ConvLoweringState& state, int64_t xbarDim) {
|
||||
@@ -1581,7 +1570,7 @@ static bool canConsumePixelMajorRowStripFragments(const ConvLoweringState& state
|
||||
failureReason = "non_constant_weight";
|
||||
return false;
|
||||
}
|
||||
if (!rowStripOutputChannelTileFitsOneCore(buildConvGeometry(state))) {
|
||||
if (!rowStripOutputChannelTileFitsOneCore(buildConvGeometry(state, state.targetInfo()))) {
|
||||
failureReason = "output_channel_tile_does_not_fit_one_core";
|
||||
return false;
|
||||
}
|
||||
@@ -1790,8 +1779,7 @@ static Value extractDenseConvWindowRow(Value denseInput,
|
||||
rewriter.getIndexAttr(state.xWidth)};
|
||||
Value nchw = tensor::ExtractSliceOp::create(
|
||||
rewriter, loc, nchwType, denseInput, offsets, sizes, getUnitStrides(rewriter, 4));
|
||||
return ONNXTransposeOp::create(
|
||||
rewriter, loc, fragmentType, nchw, rewriter.getI64ArrayAttr({0, 2, 3, 1}));
|
||||
return createLinalgTranspose(nchw, fragmentType, {0, 2, 3, 1}, rewriter, loc);
|
||||
}
|
||||
|
||||
static Value createRowStripWindowMaskTable(const ConvLoweringState& state, PatternRewriter& rewriter) {
|
||||
@@ -2429,7 +2417,7 @@ static FailureOr<Value> createOutputChannelTiledRowStripConvOutput(const ConvLow
|
||||
|
||||
static FailureOr<Value>
|
||||
createRowStripConvOutputFromDenseInput(const ConvLoweringState& state, PatternRewriter& rewriter, Location loc) {
|
||||
ConvGeometry geometry = buildConvGeometry(state);
|
||||
ConvGeometry geometry = buildConvGeometry(state, state.targetInfo());
|
||||
if (state.group != 1 || state.batchSize != 1 || !rowStripOutputChannelTileFitsOneCore(geometry))
|
||||
return failure();
|
||||
|
||||
@@ -2481,7 +2469,7 @@ static FailureOr<Value> createConvOutputFromPixelMajorRowStripFragments(Value ro
|
||||
if (!canConsumePixelMajorRowStripFragments(state, failureReason))
|
||||
return failure();
|
||||
|
||||
ConvGeometry geometry = buildConvGeometry(state);
|
||||
ConvGeometry geometry = buildConvGeometry(state, state.targetInfo());
|
||||
const int64_t xbarDim = geometry.xbarSize;
|
||||
const int64_t basePatchSize = state.numChannelsIn * state.wHeight * state.wWidth;
|
||||
const int64_t baseNumKSlices = ceilIntegerDivide(basePatchSize, xbarDim);
|
||||
@@ -2521,7 +2509,7 @@ static FailureOr<Value> createPointwiseOutputFromRowStripFragments(Value rowStri
|
||||
Location loc) {
|
||||
FailureOr<RowStripPhysicalValue> input = describeRowStripPhysicalValue(rowStripStorage, state.xType);
|
||||
if (failed(input)) return failure();
|
||||
ConvGeometry geometry = buildConvGeometry(state);
|
||||
ConvGeometry geometry = buildConvGeometry(state, state.targetInfo());
|
||||
const int64_t xbarDim = geometry.xbarSize;
|
||||
const int64_t inputFragmentChannels = input->fragmentType.getDimSize(3);
|
||||
if (inputFragmentChannels % xbarDim != 0 || state.numChannelsIn % xbarDim != 0)
|
||||
@@ -2621,8 +2609,10 @@ static bool canConsumeDepthwiseRowStrip(const ConvLoweringState& state) {
|
||||
state.wHeight,
|
||||
state.wWidth,
|
||||
state.outHeight,
|
||||
state.outWidth);
|
||||
return tiling && tiling->numChannelTiles <= static_cast<int64_t>(crossbarCountInCore.getValue());
|
||||
state.outWidth,
|
||||
state.targetInfo().matrixShape.rows);
|
||||
return tiling && tiling->numChannelTiles
|
||||
<= static_cast<int64_t>(state.targetInfo().matrixUnitsPerProcessor);
|
||||
}
|
||||
|
||||
static Value insertDepthwiseInputSegment(Value inputWindow,
|
||||
@@ -2726,16 +2716,23 @@ static FailureOr<Value> createDepthwiseOutputFromRowStripFragments(Value rowStri
|
||||
state.wHeight,
|
||||
state.wWidth,
|
||||
state.outHeight,
|
||||
state.outWidth);
|
||||
state.outWidth,
|
||||
state.targetInfo().matrixShape.rows);
|
||||
auto weight = getHostConstDenseElementsAttr(state.w);
|
||||
if (!tiling || !weight)
|
||||
return failure();
|
||||
|
||||
Value packedWeights = depthwise::buildPackedWeights(
|
||||
weight, state.wType, *tiling, rewriter, loc, static_cast<int64_t>(crossbarSize.getValue()));
|
||||
weight,
|
||||
state.wType,
|
||||
*tiling,
|
||||
rewriter,
|
||||
loc,
|
||||
static_cast<int64_t>(state.targetInfo().matrixShape.rows),
|
||||
static_cast<int64_t>(state.targetInfo().matrixShape.rows));
|
||||
Value bias = state.hasBias ? expandBiasIfNeeded(state.b, rewriter, loc) : Value();
|
||||
auto paddedOutputType = RankedTensorType::get(
|
||||
{1, static_cast<int64_t>(crossbarSize.getValue())}, state.outType.getElementType());
|
||||
{1, static_cast<int64_t>(state.targetInfo().matrixShape.rows)}, state.outType.getElementType());
|
||||
auto outputTileType = RankedTensorType::get(
|
||||
{1, tiling->tileOutputChannels}, state.outType.getElementType());
|
||||
auto outputPixelType = RankedTensorType::get(
|
||||
@@ -2759,7 +2756,7 @@ static FailureOr<Value> createDepthwiseOutputFromRowStripFragments(Value rowStri
|
||||
Value c0 = getOrCreateIndexConstant(rewriter, anchor, 0);
|
||||
Value c1 = getOrCreateIndexConstant(rewriter, anchor, 1);
|
||||
Value cOutWidth = getOrCreateIndexConstant(rewriter, anchor, state.outWidth);
|
||||
const int64_t xbarDim = static_cast<int64_t>(crossbarSize.getValue());
|
||||
const int64_t xbarDim = static_cast<int64_t>(state.targetInfo().matrixShape.rows);
|
||||
auto paddedInputScratchType = RankedTensorType::get(
|
||||
{tiling->numChannelTiles, 1, 1, xbarDim}, state.xType.getElementType(), state.xType.getEncoding());
|
||||
auto tileScratchType = RankedTensorType::get(
|
||||
@@ -2773,7 +2770,8 @@ static FailureOr<Value> createDepthwiseOutputFromRowStripFragments(Value rowStri
|
||||
SmallVector<Value> biasTiles;
|
||||
SmallVector<Value> tileIndices;
|
||||
SmallVector<OpFoldResult> weightTileSizes {
|
||||
rewriter.getIndexAttr(1), rewriter.getIndexAttr(xbarDim), rewriter.getIndexAttr(xbarDim)};
|
||||
rewriter.getIndexAttr(1), rewriter.getIndexAttr(xbarDim),
|
||||
rewriter.getIndexAttr(xbarDim)};
|
||||
for (int64_t tile = 0; tile < tiling->numChannelTiles; ++tile) {
|
||||
Value tileIndex = getOrCreateIndexConstant(rewriter, anchor, tile);
|
||||
tileIndices.push_back(tileIndex);
|
||||
@@ -2861,10 +2859,10 @@ static FailureOr<Value> createDepthwiseOutputFromRowStripFragments(Value rowStri
|
||||
|
||||
static FailureOr<Value> createConvOutputFromRowStripInput(const ConvLoweringState& state,
|
||||
Value rowStripInput,
|
||||
PimConvLoweringType strategy,
|
||||
spatial::ConvLoweringStrategy strategy,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc) {
|
||||
if (strategy == PimConvLoweringDepthwise)
|
||||
if (strategy == spatial::ConvLoweringStrategy::Depthwise)
|
||||
return createDepthwiseOutputFromRowStripFragments(rowStripInput, state, rewriter, loc);
|
||||
if (state.xHeight == 1 && state.xWidth == 1 && state.wHeight == 1 && state.wWidth == 1)
|
||||
return createPointwiseOutputFromRowStripFragments(rowStripInput, state, rewriter, loc);
|
||||
@@ -2905,17 +2903,23 @@ static Value createCollectedConvOutput(ValueRange gemmRows,
|
||||
{0, 1, 2},
|
||||
{3}
|
||||
});
|
||||
Value nchwOut = ONNXTransposeOp::create(rewriter, loc, outType, nhwcOut, rewriter.getI64ArrayAttr({0, 3, 1, 2}));
|
||||
Value nchwOut = createLinalgTranspose(nhwcOut, outType, {0, 3, 1, 2}, rewriter, loc);
|
||||
spatial::SpatYieldOp::create(rewriter, loc, nchwOut);
|
||||
});
|
||||
return collectComputeOp.getResult(0);
|
||||
}
|
||||
|
||||
static FailureOr<ConvLoweringState> analyzeConvLoweringState(ONNXConvOp convOp, Value x, Value w, Value b) {
|
||||
static FailureOr<ConvLoweringState> analyzeConvLoweringState(ONNXConvOp convOp,
|
||||
Value x,
|
||||
Value w,
|
||||
Value b,
|
||||
const spatial::SpatialTargetInfo& target) {
|
||||
ConvLoweringState state;
|
||||
state.diagnosticAnchor = convOp.getOperation();
|
||||
state.x = x;
|
||||
state.w = w;
|
||||
state.b = b;
|
||||
state.target = ⌖
|
||||
state.xType = cast<RankedTensorType>(state.x.getType());
|
||||
state.wType = cast<RankedTensorType>(state.w.getType());
|
||||
state.outType = cast<RankedTensorType>(convOp.getY().getType());
|
||||
@@ -3019,6 +3023,7 @@ static FailureOr<ConvLoweringState> analyzeConvLoweringState(ONNXConvOp convOp,
|
||||
state.padWidthBegin = getI64Attr(*padsAttr, 1);
|
||||
state.padHeightEnd = getI64Attr(*padsAttr, 2);
|
||||
state.padWidthEnd = getI64Attr(*padsAttr, 3);
|
||||
classifyConvProblem(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -3043,6 +3048,7 @@ static FailureOr<ConvLoweringState> analyzeConvLoweringState(ONNXConvOp convOp,
|
||||
state.padWidthEnd = totalPadW / 2;
|
||||
state.padWidthBegin = totalPadW - state.padWidthEnd;
|
||||
}
|
||||
classifyConvProblem(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -3051,18 +3057,25 @@ static FailureOr<ConvLoweringState> analyzeConvLoweringState(ONNXConvOp convOp,
|
||||
return failure();
|
||||
}
|
||||
|
||||
classifyConvProblem(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
static FailureOr<ConvLoweringState> analyzeConvLoweringState(ONNXConvOp convOp, ONNXConvOpAdaptor convOpAdaptor) {
|
||||
return analyzeConvLoweringState(convOp, convOpAdaptor.getX(), convOpAdaptor.getW(), convOpAdaptor.getB());
|
||||
static FailureOr<ConvLoweringState> analyzeConvLoweringState(ONNXConvOp convOp,
|
||||
ONNXConvOpAdaptor convOpAdaptor,
|
||||
const spatial::SpatialTargetInfo& target) {
|
||||
return analyzeConvLoweringState(
|
||||
convOp, convOpAdaptor.getX(), convOpAdaptor.getW(), convOpAdaptor.getB(), target);
|
||||
}
|
||||
|
||||
static FailureOr<ConvLoweringState> analyzeConvLoweringState(spatial::SpatConv2DPlanOp planOp) {
|
||||
static FailureOr<ConvLoweringState> analyzeConvLoweringState(
|
||||
spatial::SpatConv2DPlanOp planOp, const spatial::SpatialTargetInfo& target) {
|
||||
ConvLoweringState state;
|
||||
state.diagnosticAnchor = planOp.getOperation();
|
||||
state.x = planOp.getInput();
|
||||
state.w = planOp.getWeight();
|
||||
state.b = planOp.getBias() ? planOp.getBias() : Value();
|
||||
state.target = ⌖
|
||||
state.xType = dyn_cast<RankedTensorType>(state.x.getType());
|
||||
state.wType = dyn_cast<RankedTensorType>(state.w.getType());
|
||||
state.outType = dyn_cast<RankedTensorType>(planOp.getOutput().getType());
|
||||
@@ -3111,79 +3124,56 @@ static FailureOr<ConvLoweringState> analyzeConvLoweringState(spatial::SpatConv2D
|
||||
state.strideWidth = strides[1];
|
||||
state.dilationHeight = dilations[0];
|
||||
state.dilationWidth = dilations[1];
|
||||
classifyConvProblem(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
static FailureOr<PimConvLoweringType> resolveRequestedConvLoweringStrategy(Operation* op) {
|
||||
if (!useExperimentalConvImpl)
|
||||
return pimConvLowering.getValue();
|
||||
static FailureOr<spatial::ConvLoweringStrategy>
|
||||
resolveRequestedConvLoweringStrategy(Operation* op, const spatial::SpatialTargetInfo& target) {
|
||||
if (!target.useExperimentalConvImplementation)
|
||||
return target.convLoweringStrategy;
|
||||
|
||||
if (pimConvLowering != PimConvLoweringAuto && pimConvLowering != PimConvLoweringPackedIm2Col) {
|
||||
if (target.convLoweringStrategy != spatial::ConvLoweringStrategy::Auto
|
||||
&& target.convLoweringStrategy != spatial::ConvLoweringStrategy::PackedIm2Col) {
|
||||
op->emitOpError() << "--use-experimental-conv-impl conflicts with --pim-conv-lowering="
|
||||
<< stringifyConvLoweringStrategy(pimConvLowering);
|
||||
<< stringifyConvLoweringStrategy(target.convLoweringStrategy);
|
||||
return failure();
|
||||
}
|
||||
return PimConvLoweringPackedIm2Col;
|
||||
return spatial::ConvLoweringStrategy::PackedIm2Col;
|
||||
}
|
||||
|
||||
static LogicalResult verifyForcedConvLoweringStrategy(Operation* op,
|
||||
const ConvGeometry& geo,
|
||||
PimConvLoweringType strategy) {
|
||||
switch (strategy) {
|
||||
case PimConvLoweringAuto:
|
||||
case PimConvLoweringLegacy:
|
||||
return success();
|
||||
case PimConvLoweringDepthwise:
|
||||
if (geo.isDepthwise)
|
||||
return success();
|
||||
return op->emitOpError("forced depthwise Conv lowering requires a depthwise convolution");
|
||||
case PimConvLoweringPackedIm2Col:
|
||||
if (geo.k <= geo.xbarSize && geo.c <= geo.xbarSize && geo.pack >= 2 && geo.im2colElements <= pimConvIm2colMaxElements)
|
||||
return success();
|
||||
return op->emitOpError("forced packed-im2col Conv lowering requires K/C to fit, pack >= 2, and im2col within budget");
|
||||
case PimConvLoweringStreamedPatch:
|
||||
if (geo.k <= geo.xbarSize && geo.c <= geo.xbarSize)
|
||||
return success();
|
||||
return op->emitOpError("forced streamed-patch Conv lowering requires K and C to each fit one crossbar");
|
||||
case PimConvLoweringStreamedPacked:
|
||||
if (geo.k <= geo.xbarSize && geo.c <= geo.xbarSize && geo.pack >= 2)
|
||||
return success();
|
||||
return op->emitOpError("forced streamed-packed Conv lowering requires K/C to fit and pack >= 2");
|
||||
case PimConvLoweringOutputChannelTiled:
|
||||
if (geo.k <= geo.xbarSize && geo.c > geo.xbarSize)
|
||||
return success();
|
||||
return op->emitOpError("forced output-channel-tiled Conv lowering requires K <= X and C > X");
|
||||
case PimConvLoweringInputKTiled:
|
||||
if (geo.k > geo.xbarSize && geo.c <= geo.xbarSize)
|
||||
return success();
|
||||
return op->emitOpError("forced input-k-tiled Conv lowering requires K > X and C <= X");
|
||||
case PimConvLoweringTiled2D:
|
||||
if (geo.k > geo.xbarSize && geo.c > geo.xbarSize)
|
||||
return success();
|
||||
return op->emitOpError("forced tiled-2d Conv lowering requires K > X and C > X");
|
||||
}
|
||||
llvm_unreachable("unknown conv lowering strategy");
|
||||
}
|
||||
|
||||
static FailureOr<PimConvLoweringType> selectConvLoweringStrategy(Operation* op,
|
||||
const ConvLoweringState& state) {
|
||||
FailureOr<PimConvLoweringType> requested = resolveRequestedConvLoweringStrategy(op);
|
||||
static FailureOr<ConvPlan> selectConvLoweringPlan(
|
||||
Operation* op, const ConvLoweringState& state) {
|
||||
FailureOr<spatial::ConvLoweringStrategy> requested =
|
||||
resolveRequestedConvLoweringStrategy(op, state.targetInfo());
|
||||
if (failed(requested))
|
||||
return failure();
|
||||
|
||||
ConvGeometry geometry = buildConvGeometry(state);
|
||||
PimConvLoweringType strategy = chooseConvLoweringStrategy(geometry, *requested);
|
||||
if (strategy == PimConvLoweringDepthwise && !depthwise::canUseStructuredRewrite(state)
|
||||
&& *requested == PimConvLoweringAuto)
|
||||
strategy = PimConvLoweringLegacy;
|
||||
if (failed(verifyForcedConvLoweringStrategy(op, geometry, strategy)))
|
||||
if (*requested == spatial::ConvLoweringStrategy::Auto) {
|
||||
for (const ConvPlan& candidate : buildConvPlanCandidates(state, state.targetInfo())) {
|
||||
if (candidate.strategy == spatial::ConvLoweringStrategy::Depthwise
|
||||
&& !depthwise::canUseStructuredRewrite(state)) {
|
||||
continue;
|
||||
}
|
||||
return candidate;
|
||||
}
|
||||
op->emitOpError("has no applicable Conv lowering candidate for the injected Spatial target");
|
||||
return failure();
|
||||
return strategy;
|
||||
}
|
||||
|
||||
FailureOr<ConvPlan> candidate = makeConvPlan(state, *requested, state.targetInfo());
|
||||
if (failed(candidate)) {
|
||||
op->emitOpError() << "forced Conv lowering `"
|
||||
<< stringifyConvLoweringStrategy(*requested)
|
||||
<< "` is not applicable to this Conv problem";
|
||||
return failure();
|
||||
}
|
||||
return *candidate;
|
||||
}
|
||||
|
||||
static FailureOr<Value> lowerDenseSelectedConvPlan(Operation* op,
|
||||
const ConvLoweringState& state,
|
||||
PimConvLoweringType strategy,
|
||||
spatial::ConvLoweringStrategy strategy,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc);
|
||||
|
||||
@@ -3196,18 +3186,18 @@ static ConvLoweringState makeGroupedConvLoweringState(const ConvLoweringState& p
|
||||
static FailureOr<Value> buildConvValueForStrategy(Operation* op,
|
||||
Location loc,
|
||||
const ConvLoweringState& state,
|
||||
PimConvLoweringType strategy,
|
||||
spatial::ConvLoweringStrategy strategy,
|
||||
PatternRewriter& rewriter);
|
||||
|
||||
static FailureOr<Value> buildGroupedConvValue(Operation* op,
|
||||
Location loc,
|
||||
const ConvLoweringState& state,
|
||||
PimConvLoweringType strategy,
|
||||
spatial::ConvLoweringStrategy strategy,
|
||||
PatternRewriter& rewriter);
|
||||
|
||||
static FailureOr<Value> lowerGroupedSelectedConvPlan(Operation* op,
|
||||
const ConvLoweringState& state,
|
||||
PimConvLoweringType strategy,
|
||||
spatial::ConvLoweringStrategy strategy,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc) {
|
||||
return buildGroupedConvValue(op, loc, state, strategy, rewriter);
|
||||
@@ -3215,7 +3205,7 @@ static FailureOr<Value> lowerGroupedSelectedConvPlan(Operation* op,
|
||||
|
||||
static FailureOr<Value> lowerDenseSelectedConvPlan(Operation* op,
|
||||
const ConvLoweringState& state,
|
||||
PimConvLoweringType strategy,
|
||||
spatial::ConvLoweringStrategy strategy,
|
||||
PatternRewriter& rewriter,
|
||||
Location loc) {
|
||||
return buildConvValueForStrategy(op, loc, state, strategy, rewriter);
|
||||
@@ -3224,29 +3214,29 @@ static FailureOr<Value> lowerDenseSelectedConvPlan(Operation* op,
|
||||
static FailureOr<Value> buildConvValueForStrategy(Operation* op,
|
||||
Location loc,
|
||||
const ConvLoweringState& state,
|
||||
PimConvLoweringType strategy,
|
||||
spatial::ConvLoweringStrategy strategy,
|
||||
PatternRewriter& rewriter) {
|
||||
const ConvGeometry geo = buildConvGeometry(state);
|
||||
const ConvGeometry geo = buildConvGeometry(state, state.targetInfo());
|
||||
switch (strategy) {
|
||||
case PimConvLoweringDepthwise: {
|
||||
case spatial::ConvLoweringStrategy::Depthwise: {
|
||||
return depthwise::rewriteConv(op, state, rewriter, loc);
|
||||
}
|
||||
case PimConvLoweringLegacy:
|
||||
case PimConvLoweringPackedIm2Col: {
|
||||
case spatial::ConvLoweringStrategy::Legacy:
|
||||
case spatial::ConvLoweringStrategy::PackedIm2Col: {
|
||||
return standard::rewritePackedIm2ColConv(state, rewriter, loc);
|
||||
}
|
||||
case PimConvLoweringStreamedPatch:
|
||||
case PimConvLoweringOutputChannelTiled:
|
||||
case PimConvLoweringTiled2D: {
|
||||
case spatial::ConvLoweringStrategy::StreamedPatch:
|
||||
case spatial::ConvLoweringStrategy::OutputChannelTiled:
|
||||
case spatial::ConvLoweringStrategy::Tiled2D: {
|
||||
return standard::rewriteStreamedConv(state, rewriter, loc, /*forcedPackFactor=*/1);
|
||||
}
|
||||
case PimConvLoweringInputKTiled: {
|
||||
case spatial::ConvLoweringStrategy::InputKTiled: {
|
||||
return standard::rewriteInputKTiledConv(state, rewriter, loc);
|
||||
}
|
||||
case PimConvLoweringStreamedPacked: {
|
||||
case spatial::ConvLoweringStrategy::StreamedPacked: {
|
||||
return standard::rewriteStreamedConv(state, rewriter, loc, geo.pack);
|
||||
}
|
||||
case PimConvLoweringAuto:
|
||||
case spatial::ConvLoweringStrategy::Auto:
|
||||
break;
|
||||
}
|
||||
op->emitOpError("unexpected auto strategy at Conv lowering dispatch");
|
||||
@@ -3282,13 +3272,14 @@ static ConvLoweringState makeGroupedConvLoweringState(
|
||||
state.numChannelsInPerGroup = state.numChannelsIn;
|
||||
state.numChannelsOutPerGroup = state.numChannelsOut;
|
||||
state.hasBias = static_cast<bool>(groupB);
|
||||
classifyConvProblem(state);
|
||||
return state;
|
||||
}
|
||||
|
||||
static FailureOr<Value> buildGroupedConvValue(Operation* op,
|
||||
Location loc,
|
||||
const ConvLoweringState& state,
|
||||
PimConvLoweringType strategy,
|
||||
spatial::ConvLoweringStrategy strategy,
|
||||
PatternRewriter& rewriter) {
|
||||
SmallVector<Value> xSlices = sliceTensor(state.x, /*axis=*/1, state.numChannelsInPerGroup, rewriter, loc);
|
||||
SmallVector<Value> wSlices = sliceTensor(state.w, /*axis=*/0, state.numChannelsOutPerGroup, rewriter, loc);
|
||||
@@ -3344,7 +3335,7 @@ static FailureOr<Value> buildGroupedConvValue(Operation* op,
|
||||
LogicalResult ConvToGemm::matchAndRewrite(ONNXConvOp convOp,
|
||||
ONNXConvOpAdaptor convOpAdaptor,
|
||||
ConversionPatternRewriter& rewriter) const {
|
||||
FailureOr<ConvLoweringState> state = analyzeConvLoweringState(convOp, convOpAdaptor);
|
||||
FailureOr<ConvLoweringState> state = analyzeConvLoweringState(convOp, convOpAdaptor, target);
|
||||
if (failed(state))
|
||||
return failure();
|
||||
SmallVector<int64_t> pads {
|
||||
@@ -3362,15 +3353,20 @@ LogicalResult ConvToGemm::matchAndRewrite(ONNXConvOp convOp,
|
||||
rewriter.getDenseI64ArrayAttr(strides),
|
||||
rewriter.getDenseI64ArrayAttr(dilations),
|
||||
rewriter.getI64IntegerAttr(state->group),
|
||||
rewriter.getStringAttr("nchw"));
|
||||
spatial::getNCHWLayout(rewriter.getContext()));
|
||||
rewriter.replaceOp(convOp, convPlan.getResult());
|
||||
return success();
|
||||
}
|
||||
|
||||
void populateConvPatterns(RewritePatternSet& patterns, MLIRContext* ctx) { patterns.insert<ConvToGemm>(ctx); }
|
||||
void populateConvPatterns(RewritePatternSet& patterns,
|
||||
MLIRContext* ctx,
|
||||
const spatial::SpatialTargetInfo& target) {
|
||||
patterns.insert<ConvToGemm>(ctx, target);
|
||||
}
|
||||
|
||||
LogicalResult canLowerConvPlanToRowStrip(spatial::SpatConv2DPlanOp planOp) {
|
||||
FailureOr<ConvLoweringState> state = analyzeConvLoweringState(planOp);
|
||||
LogicalResult canLowerConvPlanToRowStrip(spatial::SpatConv2DPlanOp planOp,
|
||||
const spatial::SpatialTargetInfo& target) {
|
||||
FailureOr<ConvLoweringState> state = analyzeConvLoweringState(planOp, target);
|
||||
if (failed(state))
|
||||
return failure();
|
||||
|
||||
@@ -3383,38 +3379,41 @@ LogicalResult canLowerConvPlanToRowStrip(spatial::SpatConv2DPlanOp planOp) {
|
||||
if (state->hasBias && !isSupportedBiasAddValue(state->b, state->outType))
|
||||
return failure();
|
||||
|
||||
ConvGeometry geometry = buildConvGeometry(*state);
|
||||
ConvGeometry geometry = buildConvGeometry(*state, state->targetInfo());
|
||||
if (!rowStripOutputChannelTileFitsOneCore(geometry))
|
||||
return failure();
|
||||
FailureOr<PimConvLoweringType> strategy = selectConvLoweringStrategy(planOp.getOperation(), *state);
|
||||
if (failed(strategy))
|
||||
FailureOr<ConvPlan> plan =
|
||||
selectConvLoweringPlan(planOp.getOperation(), *state);
|
||||
if (failed(plan))
|
||||
return failure();
|
||||
|
||||
switch (*strategy) {
|
||||
case PimConvLoweringLegacy:
|
||||
case PimConvLoweringDepthwise:
|
||||
case PimConvLoweringPackedIm2Col:
|
||||
case PimConvLoweringStreamedPatch:
|
||||
case PimConvLoweringOutputChannelTiled:
|
||||
case PimConvLoweringTiled2D:
|
||||
case PimConvLoweringStreamedPacked:
|
||||
switch (plan->strategy) {
|
||||
case spatial::ConvLoweringStrategy::Legacy:
|
||||
case spatial::ConvLoweringStrategy::Depthwise:
|
||||
case spatial::ConvLoweringStrategy::PackedIm2Col:
|
||||
case spatial::ConvLoweringStrategy::StreamedPatch:
|
||||
case spatial::ConvLoweringStrategy::OutputChannelTiled:
|
||||
case spatial::ConvLoweringStrategy::Tiled2D:
|
||||
case spatial::ConvLoweringStrategy::StreamedPacked:
|
||||
return success();
|
||||
case PimConvLoweringAuto:
|
||||
case PimConvLoweringInputKTiled:
|
||||
case spatial::ConvLoweringStrategy::Auto:
|
||||
case spatial::ConvLoweringStrategy::InputKTiled:
|
||||
return failure();
|
||||
}
|
||||
llvm_unreachable("unknown conv lowering strategy");
|
||||
}
|
||||
|
||||
LogicalResult canConsumeAndProduceRowStrip(spatial::SpatConv2DPlanOp planOp) {
|
||||
FailureOr<ConvLoweringState> state = analyzeConvLoweringState(planOp);
|
||||
LogicalResult canConsumeAndProduceRowStrip(spatial::SpatConv2DPlanOp planOp,
|
||||
const spatial::SpatialTargetInfo& target) {
|
||||
FailureOr<ConvLoweringState> state = analyzeConvLoweringState(planOp, target);
|
||||
if (failed(state))
|
||||
return failure();
|
||||
|
||||
FailureOr<PimConvLoweringType> strategy = selectConvLoweringStrategy(planOp.getOperation(), *state);
|
||||
if (failed(strategy))
|
||||
FailureOr<ConvPlan> plan =
|
||||
selectConvLoweringPlan(planOp.getOperation(), *state);
|
||||
if (failed(plan))
|
||||
return failure();
|
||||
if (*strategy == PimConvLoweringDepthwise)
|
||||
if (plan->strategy == spatial::ConvLoweringStrategy::Depthwise)
|
||||
return canConsumeDepthwiseRowStrip(*state) ? success() : failure();
|
||||
StringRef failureReason;
|
||||
return canConsumePixelMajorRowStripFragments(*state, failureReason) ? success() : failure();
|
||||
@@ -3424,23 +3423,25 @@ FailureOr<Value>
|
||||
lowerSelectedConv2DPlan(spatial::SpatConv2DPlanOp planOp,
|
||||
std::optional<Value> rowStripInput,
|
||||
bool emitRowStripLayout,
|
||||
const spatial::SpatialTargetInfo& target,
|
||||
PatternRewriter& rewriter) {
|
||||
FailureOr<ConvLoweringState> state = analyzeConvLoweringState(planOp);
|
||||
FailureOr<ConvLoweringState> state = analyzeConvLoweringState(planOp, target);
|
||||
if (failed(state))
|
||||
return failure();
|
||||
|
||||
FailureOr<PimConvLoweringType> strategy = selectConvLoweringStrategy(planOp.getOperation(), *state);
|
||||
if (failed(strategy))
|
||||
FailureOr<ConvPlan> plan =
|
||||
selectConvLoweringPlan(planOp.getOperation(), *state);
|
||||
if (failed(plan))
|
||||
return failure();
|
||||
|
||||
if (emitRowStripLayout) {
|
||||
if (rowStripInput) {
|
||||
if (failed(canConsumeAndProduceRowStrip(planOp)))
|
||||
if (failed(canConsumeAndProduceRowStrip(planOp, target)))
|
||||
return planOp.emitOpError("selected row-strip input/output layout is not supported for this Conv plan"), failure();
|
||||
return createConvOutputFromRowStripInput(
|
||||
*state, *rowStripInput, *strategy, rewriter, planOp.getLoc());
|
||||
*state, *rowStripInput, plan->strategy, rewriter, planOp.getLoc());
|
||||
}
|
||||
if (failed(canLowerConvPlanToRowStrip(planOp)))
|
||||
if (failed(canLowerConvPlanToRowStrip(planOp, target)))
|
||||
return planOp.emitOpError("selected row-strip layout is not supported for this Conv plan"), failure();
|
||||
FailureOr<Value> rowStripStorage = createRowStripConvOutputFromDenseInput(*state, rewriter, planOp.getLoc());
|
||||
if (failed(rowStripStorage))
|
||||
@@ -3448,11 +3449,11 @@ lowerSelectedConv2DPlan(spatial::SpatConv2DPlanOp planOp,
|
||||
return *rowStripStorage;
|
||||
}
|
||||
|
||||
if (*strategy == PimConvLoweringDepthwise)
|
||||
return lowerDenseSelectedConvPlan(planOp.getOperation(), *state, *strategy, rewriter, planOp.getLoc());
|
||||
if (plan->strategy == spatial::ConvLoweringStrategy::Depthwise)
|
||||
return lowerDenseSelectedConvPlan(planOp.getOperation(), *state, plan->strategy, rewriter, planOp.getLoc());
|
||||
if (state->group != 1)
|
||||
return lowerGroupedSelectedConvPlan(planOp.getOperation(), *state, *strategy, rewriter, planOp.getLoc());
|
||||
return lowerDenseSelectedConvPlan(planOp.getOperation(), *state, *strategy, rewriter, planOp.getLoc());
|
||||
return lowerGroupedSelectedConvPlan(planOp.getOperation(), *state, plan->strategy, rewriter, planOp.getLoc());
|
||||
return lowerDenseSelectedConvPlan(planOp.getOperation(), *state, plan->strategy, rewriter, planOp.getLoc());
|
||||
}
|
||||
|
||||
} // namespace onnx_mlir
|
||||
|
||||
Reference in New Issue
Block a user