@@ -448,7 +448,7 @@ std::optional<Value> convertScatterNdOp(PatternRewriter &rewriter,
448448 auto indicesType = dyn_cast<RankedTensorType>(indicesValue.getType ());
449449 auto fillValuesType = dyn_cast<RankedTensorType>(fillValues.getType ());
450450
451- if (!resultType || !paramsType || !indicesType)
451+ if (!resultType || !paramsType || !indicesType || !fillValuesType )
452452 return std::nullopt ;
453453
454454 // N: number of batches
@@ -522,7 +522,7 @@ std::optional<Value> convertScatterNdOp(PatternRewriter &rewriter,
522522 // !torch.vtensor<[1,4],si64>
523523 // Detail algorithm visualization:
524524
525- int N = 1 , W = 1 , K = 1 , fillK = 1 , C = 1 , ND = 1 ;
525+ int N = 1 , W = 1 , K = 1 , C = 1 , ND = 1 ;
526526
527527 int paramsRank = paramsType.getShape ().size (); // 2
528528 int indicesRank = indicesType.getShape ().size (); // 2
@@ -553,11 +553,18 @@ std::optional<Value> convertScatterNdOp(PatternRewriter &rewriter,
553553 // input(chould be scatter) C = product(params.shape[ND:] ND = 2, paramsRank,
554554 // C = 1
555555 for (int i = ND ; i < paramsRank; i++) {
556- C *= paramsType.getShape ()[i];
556+ int64_t dim = paramsType.getShape ()[i];
557+ if (dim < 0 ) {
558+ (void )rewriter.notifyMatchFailure (
559+ op, " scatter channel dimensions must be static" );
560+ return std::nullopt ;
561+ }
562+ C *= dim;
557563 }
558564
559565 // int N = 1, W = 3, K = 4, fillk = 3, C = 1, ND = 2;
560566 SmallVector<int64_t , 3 > tosaInputValuesShape ({N, K, C}); // {1,4,1}
567+ SmallVector<int64_t , 3 > tosaFillValuesShape ({N, W, C}); // {1,3,1}
561568 SmallVector<int64_t , 2 > tosaIndicesShape ({N, W}); // {1,3}
562569 SmallVector<int64_t , 2 > indicesMatrixShape ({W, ND }); // {3,2}
563570 SmallVector<int64_t , 2 > indicesMatrixReducesumShape ({W, 1 }); // {3,1}
@@ -569,18 +576,26 @@ std::optional<Value> convertScatterNdOp(PatternRewriter &rewriter,
569576 // 2. !torch.vtensor<[],si64>
570577 // reshape(1) tile(3) reshape(1,3) reshape(1,3,1)
571578 // [] -> [0] -> [0,0,0] -> [[0,0,0]] -> [[[0], [0], [0]]]
572- // reshape to [1] and then tile to same number of indicesValue.shape[0],
573- // [1,1,1]
574- if (fillValuesType.getRank () == 0 ) {
579+ // reshape to [1] and then tile to W * C update values.
580+ if (fillValuesType.getRank () == 0 && C == 0 ) {
581+ auto emptyFillValues = getZerosLikeTensor (
582+ rewriter, op,
583+ GetTypeFromTensorShape (tosaFillValuesShape,
584+ fillValuesType.getElementType ()));
585+ if (!emptyFillValues)
586+ return std::nullopt ;
587+ fillValues = *emptyFillValues;
588+ fillValuesType = dyn_cast<RankedTensorType>(fillValues.getType ());
589+ } else if (fillValuesType.getRank () == 0 ) {
575590 // [] -> [0]
576- SmallVector<int64_t , 1 > oneShape ({1 }); // {3, 1}
591+ SmallVector<int64_t , 1 > oneShape ({1 }); // {1}
577592 auto tosaFillValuesOneReshapeOp = tosa::CreateOpAndInfer<tosa::ReshapeOp>(
578593 rewriter, op->getLoc (),
579594 GetTypeFromTensorShape (oneShape, fillValuesType.getElementType ()),
580595 fillValues, tosa::getTosaConstShape (rewriter, op->getLoc (), oneShape));
581596
582597 // [0] -> [0,0,0]
583- SmallVector<int64_t , 1 > tileShape ({W}); // {3}
598+ SmallVector<int64_t , 1 > tileShape ({W * C }); // {3}
584599 auto tileOpMultiples =
585600 tosa::getTosaConstShape (rewriter, op->getLoc (), tileShape);
586601 auto tosaFillValuesTileOp = tosa::CreateOpAndInfer<tosa::TileOp>(
@@ -589,7 +604,7 @@ std::optional<Value> convertScatterNdOp(PatternRewriter &rewriter,
589604 tosaFillValuesOneReshapeOp.getResult (), tileOpMultiples);
590605
591606 // [0,0,0] -> [[0,0,0]]
592- SmallVector<int64_t , 2 > newTosaFillValuesShape ({N, W}); // {1,3}
607+ SmallVector<int64_t , 2 > newTosaFillValuesShape ({N, W * C }); // {1,3}
593608 auto newTosaFillValuesReshapeOp = tosa::CreateOpAndInfer<tosa::ReshapeOp>(
594609 rewriter, op->getLoc (),
595610 GetTypeFromTensorShape (newTosaFillValuesShape,
@@ -601,12 +616,18 @@ std::optional<Value> convertScatterNdOp(PatternRewriter &rewriter,
601616 fillValuesType = dyn_cast<RankedTensorType>(fillValues.getType ());
602617 }
603618
604- // fillK: range of each index, total number of fillInput(could be scatter)
605- // after flattened k = 1*1*3 = 3
606- for (int i = 0 ; i < ND ; i++) {
607- fillK *= fillValuesType.getShape ()[i];
619+ // TOSA scatter update values are shaped [N, W, C], where W is the
620+ // number of flattened scatter indices.
621+ int64_t fillNumElements = 1 ;
622+ for (int64_t dim : fillValuesType.getShape ()) {
623+ fillNumElements *= dim;
624+ }
625+ if (fillNumElements != W * C) {
626+ (void )rewriter.notifyMatchFailure (
627+ op, " scatter update element count must match flattened indices and "
628+ " channels" );
629+ return std::nullopt ;
608630 }
609- SmallVector<int64_t , 3 > tosaFillValuesShape ({N, fillK, C}); // {1,3,1}
610631
611632 // Reshape/Flatten fillValues to 3d tensor
612633 // [[0,0,0]] -> [[[0], [0], [0]]]
0 commit comments