summaryrefslogtreecommitdiff
path: root/libavutil/x86/tx_float.asm
Commit message (Collapse)AuthorAge
* x86/tx_float: save a branch during coefficient deinterleavingLynne2022-08-09
| | | | | | | | | | | Directly branch into the special 64-point deinterleave subroutine rather than going through the general deinterleave. 64-point transform timings on Zen 3: Before: 1974 decicycles in av_tx (fft),16776864 runs, 352 skips After: 1956 decicycles in av_tx (fft),16775378 runs, 1838 skips
* x86/tx_float: replace fft_sr_avx with fft_sr_fma3Lynne2022-05-21
| | | | | | | | | | | | When the SLOW_GATHER flag was added to the AVX2 version, this made FMA3-features not enabled on Zen CPUs. As FMA3 adds 6-7% across all platforms that support it, in the interest of saving space, this commit removes the AVX version and replaces it with an FMA3 version. The only CPUs affected are Sandy Bridge and Bulldozer, which have AVX support, but no FMA3 support. In the future, if there's a demand for it, a version of the function duplicated for AVX can be added.
* x86/tx_float: improve temporary register allocation for loadsLynne2022-05-21
| | | | | | | | | | On Zen 3: Before: 1484285 decicycles in av_tx (fft), 131072 runs, 0 skips After: 1415243 decicycles in av_tx (fft), 131072 runs, 0 skips
* Revert "x86/tx_float: remove vgatherdpd usage"Lynne2022-05-21
| | | | | | | | This reverts commit 82a68a8771ca39564f6a74e0f875d6852e7a0c2a. Smarter slow ISA penalties makes gathers still useful. The intention is to use gathers with the final stage of non-ptwo iMDCTs, where they give benefit.
* x86/tx_float: remove vgatherdpd usageLynne2022-05-20
| | | | | | | | | | | | | | | | | | | | Its performance loss ranges from either being just as fast as individual loads (Skylake), a few percent slower (Alderlake), 8% slower (Zen 3), to completely disasterous (older/other CPUs). Sadly, gathers never panned out fast on x86, even with the benefit of time and implementation experience. This also saves a register, as there's no need to fill out an additional register mask. Zen 3 (16384-point transform): Before: 1561050 decicycles in av_tx (fft), 131072 runs, 0 skips After: 1449621 decicycles in av_tx (fft), 131072 runs, 0 skips Alderlake: 2% slower on big transforms (65536), to 1% (131072), to a few percent for smaller sizes.
* libavutil: include assembly with full path from source rootAlexander Kanavin2022-02-08
| | | | | | | | Otherwise nasm writes the full host-specific paths into .o output, which breaks binary reproducibility. Signed-off-by: Alexander Kanavin <alex.kanavin@gmail.com> Signed-off-by: Anton Khirnov <anton@khirnov.net>
* x86/tx_float: avoid redefining macrosLynne2022-02-02
| | | | FFT16_FN was used for fft8 and for fft16 afterwards.
* x86/tx_float: add permute-free FFT versionsLynne2022-01-26
| | | | These are used in the PFA transforms and MDCTs.
* lavu/tx: rewrite internal code as a tree-based codelet constructorLynne2022-01-26
| | | | | | | | | | This commit rewrites the internal transform code into a constructor that stitches transforms (codelets). This allows for transforms to reuse arbitrary parts of other transforms, and allows transforms to be stacked onto one another (such as a full iMDCT using a half-iMDCT which in turn uses an FFT). It also permits for each step to be individually replaced by assembly or a custom implementation (such as an ASIC).
* x86/tx_float: correctly load the transform lengthLynne2021-07-18
| | | | | | | | The field is a standard field, yet we were loading it as if it was a quadword. This worked for forward transforms by chance, but broke when the transform was inverse. checkasm couldn't catch that because we only test forward transforms, which are identical to inverse transforms but with a different revtab.
* x86/tx_float: remove ff_ prefix from external constant tablesJames Almer2021-04-25
| | | | | | | Fixes compilation with some assemblers. Reviewed-by: Lynne Signed-off-by: James Almer <jamrial@gmail.com>
* x86/tx_float: fix forgotten 2-argument mulpsLynne2021-04-24
| | | | Yasm *really* cannot deal with any omitted arguments at all.
* x86/tx_float: use all arguments on vperm2f and vpermilps and reindent commentsLynne2021-04-24
| | | | Apparently even old nasm isn't required to accept incomplete instructions.
* x86/tx_float: Fixes compilation with old yasmJames Almer2021-04-24
| | | | | | | Use three operand format on some instructions, and lea to load effective addresses of tables. Signed-off-by: James Almer <jamrial@gmail.com>
* lavu/x86/tx_float: fix FMA3 implying AVX2 is availableLynne2021-04-24
| | | | It's the other way around - AVX2 implies FMA3 is available.
* lavu/x86: add FFT assemblyLynne2021-04-24
This commit adds a pure x86 assembly SIMD version of the FFT in libavutil/tx. The design of this pure assembly FFT is pretty unconventional. On the lowest level, instead of splitting the complex numbers into real and imaginary parts, we keep complex numbers together but split them in terms of parity. This saves a number of shuffles in each transform, but more importantly, it splits each transform into two independent paths, which we process using separate registers in parallel. This allows us to keep all units saturated and lets us use all available registers to avoid dependencies. Moreover, it allows us to double the granularity of our per-load permutation, skipping many expensive lookups and allowing us to use just 4 loads per register, rather than 8, or in case FMA3 (and by extension, AVX2), use the vgatherdpd instruction, which is at least as fast as 4 separate loads on old hardware, and quite a bit faster on modern CPUs). Higher up, we go for a bottom-up construction of large transforms, foregoing the traditional per-transform call-return recursion chains. Instead, we always start at the bottom-most basis transform (in this case, a 32-point transform), and continue constructing larger and larger transforms until we return to the top-most transform. This way, we only touch the stack 3 times per a complete target transform: once for the 1/2 length transform and two times for the 1/4 length transform. The combination algorithm we use is a standard Split-Radix algorithm, as used in our C code. Although a version with less operations exists (Steven G. Johnson and Matteo Frigo's "A modified split-radix FFT with fewer arithmetic operations", IEEE Trans. Signal Process. 55 (1), 111–119 (2007), which is the one FFTW uses), it only has 2% less operations and requires at least 4x the binary code (due to it needing 4 different paths to do a single transform). That version also has other issues which prevent it from being implemented with SIMD code as efficiently, which makes it lose the marginal gains it offered, and cannot be performed bottom-up, requiring many recursive call-return chains, whose overhead adds up. We go through a lot of effort to minimize load/stores by keeping as much in registers in between construcring transforms. This saves us around 32 cycles, on paper, but in reality a lot more due to load/store aliasing (a load from a memory location cannot be issued while there's a store pending, and there are only so many (2 for Zen 3) load/store units in a CPU). Also, we interleave coefficients during the last stage to save on a store+load per register. Each of the smallest, basis transforms (4, 8 and 16-point in our case) has been extremely optimized. Our 8-point transform is barely 20 instructions in total, beating our old implementation 8-point transform by 1 instruction. Our 2x8-point transform is 23 instructions, beating our old implementation by 6 instruction and needing 50% less cycles. Our 16-point transform's combination code takes slightly more instructions than our old implementation, but makes up for it by requiring a lot less arithmetic operations. Overall, the transform was optimized for the timings of Zen 3, which at the time of writing has the most IPC from all documented CPUs. Shuffles were preferred over arithmetic operations due to their 1/0.5 latency/throughput. On average, this code is 30% faster than our old libavcodec implementation. It's able to trade blows with the previously-untouchable FFTW on small transforms, and due to its tiny size and better prediction, outdoes FFTW on larger transforms by 11% on the largest currently supported size.