@@ -960,7 +960,8 @@ template <int NumOfDims> class PoolSizeCalculator {
960960 // height and width labels in variables.
961961 Value getPoolSize (OpBuilder &b, SmallVectorImpl<Value> &kernelSizeIntValues,
962962 SmallVectorImpl<int64_t > &strideInts,
963- SmallVectorImpl<int64_t > &paddingInts);
963+ SmallVectorImpl<int64_t > &paddingInts,
964+ SmallVectorImpl<int64_t > &dilationInts);
964965
965966private:
966967 int64_t SumPoolTypeDimIndex[NumOfDims];
@@ -994,12 +995,14 @@ PoolSizeCalculator<NumOfDims>::PoolSizeCalculator(
994995template <int NumOfDims>
995996Value PoolSizeCalculator<NumOfDims>::getPoolSize(
996997 OpBuilder &b, SmallVectorImpl<Value> &kernelDimSizes,
997- SmallVectorImpl<int64_t > &strideInts,
998- SmallVectorImpl<int64_t > &paddingInts ) {
998+ SmallVectorImpl<int64_t > &strideInts, SmallVectorImpl< int64_t > &paddingInts,
999+ SmallVectorImpl<int64_t > &dilationInts ) {
9991000 Value poolSize;
10001001
10011002 Value cstZero =
10021003 b.createOrFold <arith::ConstantOp>(location, b.getI64IntegerAttr (0 ));
1004+ Value cstOne =
1005+ b.createOrFold <arith::ConstantOp>(location, b.getI64IntegerAttr (1 ));
10031006
10041007 for (int i = 0 ; i < NumOfDims; ++i) {
10051008 // See the link below for the PyTorch implementation where this is
@@ -1016,25 +1019,60 @@ Value PoolSizeCalculator<NumOfDims>::getPoolSize(
10161019 location, b.getI64IntegerAttr (strideInts[i]));
10171020 Value PadDim = b.createOrFold <arith::ConstantOp>(
10181021 location, b.getI64IntegerAttr (paddingInts[i]));
1022+ Value DilDim = b.createOrFold <arith::ConstantOp>(
1023+ location, b.getI64IntegerAttr (dilationInts[i]));
10191024 Value ODimDDim = b.createOrFold <arith::MulIOp>(location, ODim, DDim);
10201025 Value IDim0 = b.createOrFold <arith::SubIOp>(location, ODimDDim, PadDim);
10211026 Value IDim = castIndexToInt64 (b, location, InputSpatialDimSizes[i]);
1027+
1028+ // Effective window end: IDim0 + (kernel - 1) * dilation + 1
1029+ Value KernelM1 =
1030+ b.createOrFold <arith::SubIOp>(location, kernelDimSizes[i], cstOne);
1031+ Value KernelM1Dil =
1032+ b.createOrFold <arith::MulIOp>(location, KernelM1, DilDim);
1033+ Value EffectiveKernel =
1034+ b.createOrFold <arith::AddIOp>(location, KernelM1Dil, cstOne);
10221035 Value IDim0KDim =
1023- b.createOrFold <arith::AddIOp>(location, IDim0, kernelDimSizes[i] );
1036+ b.createOrFold <arith::AddIOp>(location, IDim0, EffectiveKernel );
10241037 Value IDimPadDim = b.createOrFold <arith::AddIOp>(location, IDim, PadDim);
10251038 Value IDim1 =
10261039 b.createOrFold <arith::MinSIOp>(location, IDim0KDim, IDimPadDim);
10271040
1028- Value IDim0Clamped =
1029- b.createOrFold <arith::MaxSIOp>(location, IDim0, cstZero);
10301041 Value IDim1Clamped = b.createOrFold <arith::MinSIOp>(location, IDim1, IDim);
1031- Value IDim1_IDim0_Clamped =
1032- b.createOrFold <arith::SubIOp>(location, IDim1Clamped, IDim0Clamped);
10331042
1034- Value poolSizeDim =
1035- !isCountIncludePad
1036- ? IDim1_IDim0_Clamped
1037- : b.createOrFold <arith::SubIOp>(location, IDim1, IDim0);
1043+ // Count valid taps using k_min/k_max approach:
1044+ // Tap k is valid when IDim0 + k*dilation is in [0, IDim1Clamped), where
1045+ // IDim1Clamped = min(window end, IDim) is the input extent clamped to the
1046+ // window.
1047+ // k_min = ceil(max(-IDim0, 0) / dilation) -- first valid k
1048+ // k_max_excl = ceil((IDim1Clamped - IDim0) / dilation) -- first k past the
1049+ // end ValidTaps = max(k_max_excl - k_min, 0)
1050+ Value NegIDim0 = b.createOrFold <arith::SubIOp>(location, cstZero, IDim0);
1051+ Value KMinNumer =
1052+ b.createOrFold <arith::MaxSIOp>(location, NegIDim0, cstZero);
1053+ Value KMin =
1054+ b.createOrFold <arith::CeilDivSIOp>(location, KMinNumer, DilDim);
1055+ Value IDim1ClampedMinusIDim0 =
1056+ b.createOrFold <arith::SubIOp>(location, IDim1Clamped, IDim0);
1057+ Value KMaxExcl = b.createOrFold <arith::CeilDivSIOp>(
1058+ location, IDim1ClampedMinusIDim0, DilDim);
1059+ Value KDiff = b.createOrFold <arith::SubIOp>(location, KMaxExcl, KMin);
1060+ Value ValidTaps = b.createOrFold <arith::MaxSIOp>(location, KDiff, cstZero);
1061+
1062+ // For count_include_pad: count every dilated tap position in the full
1063+ // effective window [IDim0, IDim1), including padded positions. Same as
1064+ // ValidTaps but WITHOUT the low-side clamp (padded taps are counted), so
1065+ // it reduces to k_min == 0:
1066+ // FullTaps = max(ceil((IDim1 - IDim0) / dilation), 0)
1067+ // The max(.., 0) keeps this in agreement with ValidTaps on a degenerate
1068+ // empty window (range <= 0 => 0 taps).
1069+ Value FullRange = b.createOrFold <arith::SubIOp>(location, IDim1, IDim0);
1070+ Value FullTapsRaw =
1071+ b.createOrFold <arith::CeilDivSIOp>(location, FullRange, DilDim);
1072+ Value FullTaps =
1073+ b.createOrFold <arith::MaxSIOp>(location, FullTapsRaw, cstZero);
1074+
1075+ Value poolSizeDim = !isCountIncludePad ? ValidTaps : FullTaps;
10381076 if (i == 0 ) {
10391077 poolSize = poolSizeDim;
10401078 } else {
@@ -1060,7 +1098,8 @@ class ConvertAtenAvgPoolOp : public OpConversionPattern<OpTy> {
10601098 static bool
10611099 doesAvgPoolDivisorNeedsClamping (bool ceilMode, bool countIncludePad,
10621100 SmallVectorImpl<int64_t > &strideInts,
1063- SmallVectorImpl<int64_t > &paddingInts);
1101+ SmallVectorImpl<int64_t > &paddingInts,
1102+ SmallVectorImpl<int64_t > &dilationInts);
10641103
10651104 // Creates the average pooling operation value with a clamped
10661105 // divisor. The clamped divisor is the product of kernel
@@ -1073,6 +1112,7 @@ class ConvertAtenAvgPoolOp : public OpConversionPattern<OpTy> {
10731112 SmallVectorImpl<Value> &kernelDimSizes,
10741113 SmallVectorImpl<int64_t > &strideInts,
10751114 SmallVectorImpl<int64_t > &paddingInts,
1115+ SmallVectorImpl<int64_t > &dilationInts,
10761116 SmallVector<AffineMap> &indexingMapsAvg,
10771117 SmallVector<utils::IteratorType> &iteratorTypesAvg);
10781118
@@ -1147,11 +1187,11 @@ LogicalResult ConvertAtenAvgPoolOp<OpTy, PoolingOpTy, Dim>::matchAndRewrite(
11471187 Dim + 2 , utils::IteratorType::parallel);
11481188
11491189 if (doesAvgPoolDivisorNeedsClamping (ceilMode, countIncludePad, strideInts,
1150- paddingInts)) {
1190+ paddingInts, dilationInts )) {
11511191 return createAveragePoolValueWithClampedDivisor (
11521192 ceilMode, countIncludePad, op, adaptor, rewriter, self, sumPool,
11531193 outputTensor, resultType, kernelSizeIntValues, strideInts, paddingInts,
1154- indexingMapsAvg, iteratorTypesAvg);
1194+ dilationInts, indexingMapsAvg, iteratorTypesAvg);
11551195 }
11561196
11571197 return createAveragePoolValueWithRegularDivisor (
@@ -1163,7 +1203,8 @@ template <typename OpTy, typename PoolingOpTy, int Dim>
11631203bool ConvertAtenAvgPoolOp<OpTy, PoolingOpTy, Dim>::
11641204 doesAvgPoolDivisorNeedsClamping (bool ceilMode, bool countIncludePad,
11651205 SmallVectorImpl<int64_t > &strideInts,
1166- SmallVectorImpl<int64_t > &paddingInts) {
1206+ SmallVectorImpl<int64_t > &paddingInts,
1207+ SmallVectorImpl<int64_t > &dilationInts) {
11671208 // Determines whether the average pooling divisor needs to be clamped
11681209 // (i.e., adjusted to exclude padded or out-of-bounds elements).
11691210 //
@@ -1193,8 +1234,11 @@ bool ConvertAtenAvgPoolOp<OpTy, PoolingOpTy, Dim>::
11931234 !llvm::all_of (paddingInts, [](int64_t p) { return p == 0 ; });
11941235 bool allStridesUnitary =
11951236 llvm::all_of (strideInts, [](int64_t s) { return s == 1 ; });
1237+ bool allDilationsUnitary =
1238+ llvm::all_of (dilationInts, [](int64_t d) { return d == 1 ; });
11961239
1197- return (!countIncludePad && hasPadding) || (ceilMode && !allStridesUnitary);
1240+ return (!countIncludePad && hasPadding) || (ceilMode && !allStridesUnitary) ||
1241+ !allDilationsUnitary;
11981242}
11991243
12001244template <typename OpTy, typename PoolingOpTy, int Dim>
@@ -1206,6 +1250,7 @@ LogicalResult ConvertAtenAvgPoolOp<OpTy, PoolingOpTy, Dim>::
12061250 SmallVectorImpl<Value> &kernelDimSizes,
12071251 SmallVectorImpl<int64_t > &strideInts,
12081252 SmallVectorImpl<int64_t > &paddingInts,
1253+ SmallVectorImpl<int64_t > &dilationInts,
12091254 SmallVector<AffineMap> &indexingMapsAvg,
12101255 SmallVector<utils::IteratorType> &iteratorTypesAvg) {
12111256 Location loc = op->getLoc ();
@@ -1241,7 +1286,7 @@ LogicalResult ConvertAtenAvgPoolOp<OpTy, PoolingOpTy, Dim>::
12411286 [&](OpBuilder &b, Location loc, ValueRange args) {
12421287 if (!poolSize) {
12431288 poolSize = poolSizeCalculator.getPoolSize (
1244- b, kernelDimSizes, strideInts, paddingInts);
1289+ b, kernelDimSizes, strideInts, paddingInts, dilationInts );
12451290 }
12461291 Value divisor =
12471292 convertScalarToDtype (b, loc, poolSize, resultElementType);
0 commit comments