We have new option in clang (https://github.com/llvm/llvm-project/pull/124834)
to mark globals to be allocated in non-large sections. We can mark all globals
that are referenced from hardcoded assembly (which implicitly references globals
assuming they are in non-large sections) with this attribute to avoid running
into problems when dav1d is built with -mcmodel=medium with clang.
'-fvisibility=hidden' only applies to definitions, not declarations,
so the compiler has to be conservative about how references to global
data symbols are performed.
Explicitly specifying the visibility allows for better code generation.
We use the 'noinline' attribute in order to reduce code size, but that
doesn't prevent gcc from cloning the function, which is something that
goes against the purpose of preventing inlining in the first place.
Adding the 'noclone' attribute reduces the (stripped) binary size by
around 45 kB on x86-64.
Add buffer pools for miscellaneous smaller buffers that are
repeatedly being freed and reallocated.
Also improve dav1d_ref_create() by consolidating two separate
memory allocations into a single one.
This only supports 10 bpc, not 12 bpc, as the sum and tmp buffers can
be int16_t for 10 bpc, but need to be int32_t for 12 bpc.
Make actual templates out of the functions in looprestoration_tmpl.S,
and add box3/5_h to looprestoration16.S.
Extend dav1d_sgr_calc_abX_neon with a mandatory bitdepth_max parameter
(which is passed even in 8bpc mode), add a define to bitdepth.h for
passing such a parameter in all modes. This makes this function
a few instructions slower in 8bpc mode than it was before (overall impact
seems to be around 1% of the total runtime of SGR), but allows using the
same actual function instantiation for all modes, saving a bit of code
size.
Examples of checkasm runtimes:
Cortex A53 A72 A73
selfguided_3x3_10bpc_neon: 516755.8 389412.7 349058.7
selfguided_5x5_10bpc_neon: 380699.9 293486.6 254591.6
selfguided_mix_10bpc_neon: 878142.3 667495.9 587844.6
Corresponding 8 bpc numbers for comparison:
selfguided_3x3_8bpc_neon: 491058.1 361473.4 347705.9
selfguided_5x5_8bpc_neon: 352655.0 266423.7 248192.2
selfguided_mix_8bpc_neon: 826094.1 612372.2 581943.1
We specify most strides in bytes, but since C defines offsets
in multiples of sizeof(type) we use the PXSTRIDE() macro to
downshift the strides by one in high-bit depth templated files.
This however means that the compiler is required to mask away
the least significant bit, because it could in theory be non-zero.
Avoid that by telling the compiler (when compiled in release mode)
that the lsb is in fact guaranteed to always be zero.
CFI will SIGILL when calling a function pointer obtained through
dlsym(), regardless of whether or not the signature is correct.
See https://bugs.llvm.org/show_bug.cgi?id=44500
__assume() doesn't work correctly in clang-cl versions prior to 7.0.0
which causes bogus warnings regarding use of uninitialized variables
to be printed. Avoid that by using __builtin_unreachable() instead.
When compiling in release mode, instead of just deleting assertions,
use them to give hints to the compiler. This allows for slightly
better code generation in some cases.
For the cdef_filter tests, one could also extend the buffer to
contain 16*11 pixels, to simplify printing it as one rectangular
section.
Extend the common hex_dump function to allow dumping to an arbitrary
FILE* pointer, to reuse it for printing the source pixel buffer in
case of errors.
A symbol starting with two leading underscores is reserved for
the compiler/standard library implementation.
Also remove the trailing two double underscores for consistency
and symmetry.
Decreases runtime of decoding first 1000 frames of Chimera (1080p, 8bit)
from 12.227 to 12.075s (average of 6 runs) after changing decode.c, and
further down to 12.027s (1.67%) with the changes to recon_tmpl.c included.
After the changes to lf_mask.c, it goes down to 11.842s.
For arm/arm64, there's no need to align any buffer to 32 bytes
as the assembly doesn't need it and doesn't benefit from it.
This would be much more elegant if defined like this:
#define MAX_ALIGN 16
#define ALIGN(align) __attribute__((aligned(MIN(align, MAX_ALIGN))))
This works for GCC and Clang, but the MSVC alignment __declspec
needs a literal alignment value, it can't handle an expression.
__builtin_ctz:
Returns the number of trailing 0-bits in x, starting at the least significant
bit position. If x is 0, the result is undefined.
_BitScanForward:
Search the mask data from least significant bit (LSB) to the most significant
bit (MSB) for a set bit (1). If a set bit is found, the bit position of the
first set bit found is returned in the first parameter. If no set bit is found,
0 is returned; otherwise, 1 is returned.
__builtin_clz:
Returns the number of leading 0-bits in x, starting at the most significant
bit position. If x is 0, the result is undefined.
_BitScanReverse:
Search the mask data from most significant bit (MSB) to least significant bit
(LSB) for a set bit (1). Returns Nonzero if Index was set, or 0 if no set bits
were found. Index is loaded with the bit position of the first set bit (1) found.