From patchwork Sat Aug 13 20:48:30 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Swinney, Jonathan" X-Patchwork-Id: 37257 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:3d0d:b0:8d:a68e:8a0e with SMTP id y13csp511676pzi; Sat, 13 Aug 2022 13:48:45 -0700 (PDT) X-Google-Smtp-Source: AA6agR6qoyxp3+IbZ3eQkSz9ox5DumDKKUr6UnWCuOllzvtmgBi8/1n6KxaJiglpao1F4kkOzlmu X-Received: by 2002:a17:907:2856:b0:730:df57:1249 with SMTP id el22-20020a170907285600b00730df571249mr6346799ejc.536.1660423725360; Sat, 13 Aug 2022 13:48:45 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1660423725; cv=none; d=google.com; s=arc-20160816; b=f6htsOzwpyQNg2FNNpQccF0Bufxvw+e1NXPeJhpK0MzMVgKEGSyC1A57xxz+7NldFX +cn1zUJ5/1WMqUXlaHBrGzmqiqm2J/mBKpVPaur6+68yIc4O6vYha6nq/52cJ3KYEZCe MdaA2jACZROOxaUmfNpRZbKH4uRrDHszaS01G0S0CdY3RinQCT+A9VY5xAuT1VMJTKfr 0oZGxRYR+GslJ2Bw+2FSeCO+OgEcJhQHXaJ20da2hhslC/OWIWq3frmkFrzkUqox88pK JlN6Gx/dBA2L7C4xB+B/DH5KyXW7m3/z9i+JJ5Ar+eAYdMes2SX0wTMVVkJgbl64mrYi OFWQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:content-language :accept-language:message-id:date:thread-index:thread-topic:to:from :dkim-signature:delivered-to; bh=6twrSwqiTkx9pBD8MFedb+wfz/+8kdAgny0IcYIm/8E=; b=LWRJObAItSM/OJzg93/xwkVrVJx4P/AxLubCbaL9UQ/6Vt7zFA7VCKxNWXOf7LOFPv zeFRLqmzgvpAaojFgNnQHtbDZjduKxuJztraFfd2fCa3H1HxzsuO5EVJ0t7z1nKHYVgN 09VVduqWffmj8eZhEUg96XoyajoTZGhxvhFqLLA2i7X6HWf+AdM15h5jwRxDbxDjnaa1 nPmffrlwxbwZOEko6QwZEbdQLzbwpehhlzRCu2eMSfjjbSQAl3LKTiH/WVtlalyrapgp v1WZc6msozCusVwjqrN8EFjofJ11mPdk830edlDJTT69Rl0yQelyfa8k1mZkEi3SR+SR /u7A== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@amazon.com header.s=amazon201209 header.b="iRbDS/1Y"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id b8-20020a056402350800b0043d99f453f1si4967739edd.64.2022.08.13.13.48.44; Sat, 13 Aug 2022 13:48:45 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@amazon.com header.s=amazon201209 header.b="iRbDS/1Y"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=amazon.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 24D0768B7EB; Sat, 13 Aug 2022 23:48:41 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from smtp-fw-2101.amazon.com (smtp-fw-2101.amazon.com [72.21.196.25]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id D152F689CDD for ; Sat, 13 Aug 2022 23:48:33 +0300 (EEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1660423719; x=1691959719; h=from:to:cc:subject:date:message-id: content-transfer-encoding:mime-version; bh=rbh0uWXX9qQZoYaJ6DODIroYh8s1v7h8FmDg7Ie++No=; b=iRbDS/1YY91p6XI0zyQ899BkynDxLHtRbFr2kSHd54m0F4sDV5tdNM4D GJJcbLWoX0mpQbSVcGTBvdMx7ALUaBuKwCWlSL88UlKpfDb89ac90905g eWP02WaFSqc7LGH7X4T6Zna5SGMfDr5laSy7xdlReye9nqUZUcv1ZcNjt I=; X-IronPort-AV: E=Sophos;i="5.93,236,1654560000"; d="scan'208";a="229332797" Received: from iad12-co-svc-p1-lb1-vlan3.amazon.com (HELO email-inbound-relay-iad-1d-9a235a16.us-east-1.amazon.com) ([10.43.8.6]) by smtp-border-fw-2101.iad2.amazon.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 13 Aug 2022 20:48:32 +0000 Received: from EX13MTAUWB001.ant.amazon.com (iad12-ws-svc-p26-lb9-vlan3.iad.amazon.com [10.40.163.38]) by email-inbound-relay-iad-1d-9a235a16.us-east-1.amazon.com (Postfix) with ESMTPS id 9182E80178; Sat, 13 Aug 2022 20:48:31 +0000 (UTC) Received: from EX19D007UWB003.ant.amazon.com (10.13.138.28) by EX13MTAUWB001.ant.amazon.com (10.43.161.207) with Microsoft SMTP Server (TLS) id 15.0.1497.38; Sat, 13 Aug 2022 20:48:31 +0000 Received: from EX19D007UWB001.ant.amazon.com (10.13.138.75) by EX19D007UWB003.ant.amazon.com (10.13.138.28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.1118.12; Sat, 13 Aug 2022 20:48:31 +0000 Received: from EX19D007UWB001.ant.amazon.com ([fe80::bcaa:e18f:a569:3851]) by EX19D007UWB001.ant.amazon.com ([fe80::bcaa:e18f:a569:3851%6]) with mapi id 15.02.1118.012; Sat, 13 Aug 2022 20:48:30 +0000 From: "Swinney, Jonathan" To: "ffmpeg-devel@ffmpeg.org" Thread-Topic: [PATCH v2] libswscale/aarch64: add another hscale specialization Thread-Index: AdivVfuprMUaDubfQly0vkUQmQMG0Q== Date: Sat, 13 Aug 2022 20:48:30 +0000 Message-ID: <2e1354629afd457fbdf0b13f17e3ce93@amazon.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.43.162.134] MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH v2] libswscale/aarch64: add another hscale specialization X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Cc: =?utf-8?q?Martin_Storsj=C3=B6?= , Hubert Mazur Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 4WtL8+CyPQ7q This specialization handles the case where filtersize is 4 mod 8, e.g. 12, 20, etc. Aarch64 was previously using the c function for this case. This implementation speeds up that case significantly. hscale_8_to_15__fs_12_dstW_512_c: 6234.1 hscale_8_to_15__fs_12_dstW_512_neon: 1505.6 Signed-off-by: Jonathan Swinney --- libswscale/aarch64/hscale.S | 107 +++++++++++++++++++++++++++++++++++ libswscale/aarch64/swscale.c | 18 +++--- 2 files changed, 117 insertions(+), 8 deletions(-) diff --git a/libswscale/aarch64/hscale.S b/libswscale/aarch64/hscale.S index b7b21b7a0f..a16d3dca42 100644 --- a/libswscale/aarch64/hscale.S +++ b/libswscale/aarch64/hscale.S @@ -91,6 +91,113 @@ function ff_hscale8to15_X8_neon, export=1 ret endfunc +function ff_hscale8to15_X4_neon, export=1 +// x0 SwsContext *c (not used) +// x1 int16_t *dst +// w2 int dstW +// x3 const uint8_t *src +// x4 const int16_t *filter +// x5 const int32_t *filterPos +// w6 int filterSize + +// This function for filter sizes that are 4 mod 8. In other words, anything that's 0 mod 4 but not +// 0 mod 8. It also assumes that dstW is 0 mod 4. + + lsl w7, w6, #1 // w7 = filterSize * 2 +1: + ldp w8, w9, [x5] // filterPos[idx + 0], [idx + 1] + ldp w10, w11, [x5, #8] // filterPos[idx + 2], [idx + 3] + + movi v16.2d, #0 // initialize accumulator for idx + 0 + movi v17.2d, #0 // initialize accumulator for idx + 1 + movi v18.2d, #0 // initialize accumulator for idx + 2 + movi v19.2d, #0 // initialize accumulator for idx + 3 + + mov x12, x4 // filter pointer for idx + 0 + add x13, x4, x7 // filter pointer for idx + 1 + add x8, x3, w8, uxtw // srcp + filterPos[idx + 0] + add x9, x3, w9, uxtw // srcp + filterPos[idx + 1] + + add x14, x13, x7 // filter pointer for idx + 2 + add x10, x3, w10, uxtw // srcp + filterPos[idx + 2] + add x11, x3, w11, uxtw // srcp + filterPos[idx + 3] + + mov w0, w6 // copy filterSize to a temp register, w0 + add x5, x5, #16 // advance the filterPos pointer + add x15, x14, x7 // filter pointer for idx + 3 + mov x16, xzr // temp register for offsetting filter pointers + +2: + // This section loops over 8-wide chunks of filter size + ldr d4, [x8], #8 // load 8 bytes from srcp for idx + 0 + ldr q0, [x12, x16] // load 8 values, 16 bytes from filter for idx + 0 + + ldr d5, [x9], #8 // load 8 bytes from srcp for idx + 1 + ldr q1, [x13, x16] // load 8 values, 16 bytes from filter for idx + 1 + + uxtl v4.8h, v4.8b // unsigned extend long for idx + 0 + uxtl v5.8h, v5.8b // unsigned extend long for idx + 1 + + ldr d6, [x10], #8 // load 8 bytes from srcp for idx + 2 + ldr q2, [x14, x16] // load 8 values, 16 bytes from filter for idx + 2 + + smlal v16.4s, v0.4h, v4.4h // val += src[srcPos + j + 0..3] * filter[fs * i + j + 0..3], idx + 0 + smlal v17.4s, v1.4h, v5.4h // val += src[srcPos + j + 0..3] * filter[fs * i + j + 0..3], idx + 1 + + ldr d7, [x11], #8 // load 8 bytes from srcp for idx + 3 + ldr q3, [x15, x16] // load 8 values, 16 bytes from filter for idx + 3 + + sub w0, w0, #8 // decrement the remaining filterSize counter + smlal2 v16.4s, v0.8h, v4.8h // val += src[srcPos + j + 4..7] * filter[fs * i + j + 4..7], idx + 0 + smlal2 v17.4s, v1.8h, v5.8h // val += src[srcPos + j + 4..7] * filter[fs * i + j + 4..7], idx + 1 + uxtl v6.8h, v6.8b // unsigned extend long for idx + 2 + uxtl v7.8h, v7.8b // unsigned extend long for idx + 3 + smlal v18.4s, v2.4h, v6.4h // val += src[srcPos + j + 0..3] * filter[fs * i + j + 0..3], idx + 2 + smlal v19.4s, v3.4h, v7.4h // val += src[srcPos + j + 0..3] * filter[fs * i + j + 0..3], idx + 3 + + cmp w0, #8 // are there at least 8 more elements in filter to consume? + add x16, x16, #16 // advance the offsetting register for filter values + + smlal2 v18.4s, v2.8h, v6.8h // val += src[srcPos + j + 4..7] * filter[fs * i + j + 4..7], idx + 2 + smlal2 v19.4s, v3.8h, v7.8h // val += src[srcPos + j + 4..7] * filter[fs * i + j + 4..7], idx + 3 + + b.ge 2b // branch back to inner loop + + // complete the remaining 4 filter elements + sub x17, x7, #8 // calculate the offset of the filter pointer for the remaining 4 elements + + ldr s4, [x8] // load 4 bytes from srcp for idx + 0 + ldr d0, [x12, x17] // load 4 values, 8 bytes from filter for idx + 0 + ldr s5, [x9] // load 4 bytes from srcp for idx + 1 + ldr d1, [x13, x17] // load 4 values, 8 bytes from filter for idx + 1 + + uxtl v4.8h, v4.8b // unsigned extend long for idx + 0 + uxtl v5.8h, v5.8b // unsigned extend long for idx + 1 + + ldr s6, [x10] // load 4 bytes from srcp for idx + 2 + ldr d2, [x14, x17] // load 4 values, 8 bytes from filter for idx + 2 + smlal v16.4s, v0.4h, v4.4h // val += src[srcPos + j + 0..3] * filter[fs * i + j + 0..3], idx + 0 + smlal v17.4s, v1.4h, v5.4h // val += src[srcPos + j + 0..3] * filter[fs * i + j + 0..3], idx + 1 + ldr s7, [x11] // load 4 bytes from srcp for idx + 3 + ldr d3, [x15, x17] // load 4 values, 8 bytes from filter for idx + 3 + + uxtl v6.8h, v6.8b // unsigned extend long for idx + 2 + uxtl v7.8h, v7.8b // unsigned extend long for idx + 3 + addp v16.4s, v16.4s, v17.4s // horizontal pair adding for idx 0,1 + smlal v18.4s, v2.4h, v6.4h // val += src[srcPos + j + 0..3] * filter[fs * i + j + 0..3], idx + 2 + smlal v19.4s, v3.4h, v7.4h // val += src[srcPos + j + 0..3] * filter[fs * i + j + 0..3], idx + 3 + + addp v18.4s, v18.4s, v19.4s // horizontal pair adding for idx 2,3 + addp v16.4s, v16.4s, v18.4s // final horizontal pair adding producing one vector with results for idx = 0..3 + + subs w2, w2, #4 // dstW -= 4 + sqshrn v0.4h, v16.4s, #7 // shift and clip the 2x16-bit final values + st1 {v0.4h}, [x1], #8 // write to destination idx 0..3 + add x4, x4, x7, lsl #2 // filter += (filterSize*2) * 4 + b.gt 1b // loop until end of line + ret +endfunc + function ff_hscale8to15_4_neon, export=1 // x0 SwsContext *c (not used) // x1 int16_t *dst diff --git a/libswscale/aarch64/swscale.c b/libswscale/aarch64/swscale.c index ab28be4da6..a19ee64159 100644 --- a/libswscale/aarch64/swscale.c +++ b/libswscale/aarch64/swscale.c @@ -32,7 +32,8 @@ void ff_hscale ## from_bpc ## to ## to_bpc ## _ ## filter_n ## _ ## opt( \ SCALE_FUNC(filter_n, 8, 15, opt); #define ALL_SCALE_FUNCS(opt) \ SCALE_FUNCS(4, opt); \ - SCALE_FUNCS(X8, opt) + SCALE_FUNCS(X8, opt); \ + SCALE_FUNCS(X4, opt) ALL_SCALE_FUNCS(neon); @@ -47,13 +48,14 @@ void ff_yuv2planeX_8_neon(const int16_t *filter, int filterSize, } \ } while (0) -#define ASSIGN_SCALE_FUNC(hscalefn, filtersize, opt) \ - switch (filtersize) { \ - case 4: ASSIGN_SCALE_FUNC2(hscalefn, 4, opt); break; \ - default: if (filtersize % 8 == 0) \ - ASSIGN_SCALE_FUNC2(hscalefn, X8, opt); \ - break; \ - } +#define ASSIGN_SCALE_FUNC(hscalefn, filtersize, opt) do { \ + if (filtersize == 4) \ + ASSIGN_SCALE_FUNC2(hscalefn, 4, opt); \ + else if (filtersize % 8 == 0) \ + ASSIGN_SCALE_FUNC2(hscalefn, X8, opt); \ + else if (filtersize % 4 == 0 && filtersize % 8 != 0) \ + ASSIGN_SCALE_FUNC2(hscalefn, X4, opt); \ +} while (0) av_cold void ff_sws_init_swscale_aarch64(SwsContext *c) {