diff --git a/mlir/lib/ExecutionEngine/SparseTensorUtils.cpp b/mlir/lib/ExecutionEngine/SparseTensorUtils.cpp --- a/mlir/lib/ExecutionEngine/SparseTensorUtils.cpp +++ b/mlir/lib/ExecutionEngine/SparseTensorUtils.cpp @@ -356,20 +356,24 @@ /// Returns this sparse tensor storage scheme as a new memory-resident /// sparse tensor in coordinate scheme with the given dimension order. SparseTensorCOO *toCOO(const uint64_t *perm) { - // Restore original order of the dimension sizes and allocate coordinate - // scheme with desired new ordering specified in perm. uint64_t rank = getRank(); - std::vector orgsz(rank); - for (uint64_t r = 0; r < rank; r++) - orgsz[rev[r]] = sizes[r]; - SparseTensorCOO *tensor = SparseTensorCOO::newSparseTensorCOO( - rank, orgsz.data(), perm, values.size()); - // Populate coordinate scheme restored from old ordering and changed with - // new ordering. Rather than applying both reorderings during the recursion, - // we compute the combine permutation in advance. + // The permutation of dimensions from this tensor's storage-order to + // the new COO's storage-order. This is just the composition of `rev` + // (to map this tensor's storage-order back to the original/semantic + // order) with `perm` (to map that original order to the new COO's + // storage-order); but we precompute it to avoid needing to compute + // it during the recursion. std::vector reord(rank); - for (uint64_t r = 0; r < rank; r++) - reord[r] = perm[rev[r]]; + // The new coordinate scheme's sizes array. + std::vector permsz(rank); + for (uint64_t r = 0; r < rank; r++) { + uint64_t s = perm[rev[r]]; + assert(s < rank && "Permutation index is out of range"); + reord[r] = s; + permsz[s] = sizes[r]; + } + SparseTensorCOO *tensor = new SparseTensorCOO(permsz, values.size()); + // Populate the coordinate scheme. toCOO(*tensor, reord, 0, 0); assert(tensor->getElements().size() == values.size()); return tensor;