hexagon: use DMA for contiguous dim1 CONCAT (#29404)

* hexagon: use DMA for contiguous dim1 CONCAT

Assisted-by: OpenCode

* hexagon: update CONCAT DMA for DMA64

Assisted-by: OpenCode
This commit is contained in:
kurquhar
2026-09-24 19:03:41 -07:00
committed by GitHub
parent 84e76d8a23
commit ed319febb1
+59
View File
@@ -247,6 +247,61 @@ static void concat_generic(unsigned int nth, unsigned int ith, void * data) {
}
}
static bool concat_dim1_contiguous_dma(struct htp_ops_context * octx, int dim, uint32_t type_size) {
const struct htp_tensor * src0 = octx->src[0];
const struct htp_tensor * src1 = octx->src[1];
const struct htp_tensor * dst = octx->dst;
if (dim != 1 || octx->ctx->mdev.count > 1 ||
(dst->type != HTP_TYPE_F32 && dst->type != HTP_TYPE_F16 && dst->type != HTP_TYPE_I32) ||
src0->type != dst->type || src1->type != dst->type ||
src0->ne[0] != dst->ne[0] || src1->ne[0] != dst->ne[0] ||
src0->ne[2] != dst->ne[2] || src1->ne[2] != dst->ne[2] ||
src0->ne[3] != dst->ne[3] || src1->ne[3] != dst->ne[3] ||
dst->ne[1] != src0->ne[1] + src1->ne[1] ||
!htp_tensor_is_contiguous(src0, type_size) ||
!htp_tensor_is_contiguous(src1, type_size) ||
!htp_tensor_is_contiguous(dst, type_size)) {
return false;
}
const uint32_t src0_row_size = src0->ne[0] * type_size;
const uint32_t src1_row_size = src1->ne[0] * type_size;
// v75+ dma_queue_push() writes a 2D descriptor directly and does not split overflow.
#if __HVX_ARCH__ >= 75
if (src0_row_size > 0xffffffu || src1_row_size > 0xffffffu ||
src0->nb[1] > 0xffffffu || src1->nb[1] > 0xffffffu || dst->nb[1] > 0xffffffu ||
src0->ne[1] > UINT16_MAX || src1->ne[1] > UINT16_MAX) {
return false;
}
#endif
dma_queue * q = octx->ctx->dma[0];
for (uint32_t i3 = 0; i3 < dst->ne[3]; ++i3) {
for (uint32_t i2 = 0; i2 < dst->ne[2]; ++i2) {
dma_addr_t dst_addr = dst->data + i3 * dst->nb[3] + i2 * dst->nb[2];
dma_addr_t src0_addr = src0->data + i3 * src0->nb[3] + i2 * src0->nb[2];
dma_addr_t src1_addr = src1->data + i3 * src1->nb[3] + i2 * src1->nb[2];
if (!dma_queue_push(q, dma_make_data(dst_addr, src0_addr), dst->nb[1], src0->nb[1], src0_row_size, src0->ne[1])) {
dma_queue_flush(q);
dma_queue_push(q, dma_make_data(dst_addr, src0_addr), dst->nb[1], src0->nb[1], src0_row_size, src0->ne[1]);
}
dst_addr += src0->ne[1] * dst->nb[1];
if (!dma_queue_push(q, dma_make_data(dst_addr, src1_addr), dst->nb[1], src1->nb[1], src1_row_size, src1->ne[1])) {
dma_queue_flush(q);
dma_queue_push(q, dma_make_data(dst_addr, src1_addr), dst->nb[1], src1->nb[1], src1_row_size, src1->ne[1]);
}
}
}
dma_queue_flush(q);
return true;
}
int op_concat(struct htp_ops_context * octx) {
const struct htp_tensor * src0 = octx->src[0];
const struct htp_tensor * src1 = octx->src[1];
@@ -258,6 +313,10 @@ int op_concat(struct htp_ops_context * octx) {
bool is_src1_transposed = (src1->nb[0] > src1->nb[1]);
bool is_src0_transposed = (src0->nb[0] > src0->nb[1]);
if (concat_dim1_contiguous_dma(octx, dim, type_size)) {
return HTP_STATUS_OK;
}
uint32_t n_threads = octx->n_threads;
struct htp_concat_context cctx;
cctx.octx = octx;