Optimization in hash chain comparison for 64 bit

Arrays were compared 32 bits at a time, it is now done 64 bits at a time.
Overall encoding speed-up is only of 0.2% on @skal's small PNG corpus.
It is of 3% on my initial 1.3 Mp desktop screenshot image.

Change-Id: I1acb32b437397a7bf3dcffbecbcd4b06d29c05e1
This commit is contained in:
Vincent Rabaud 2015-12-01 13:01:57 +01:00
parent 829bd14145
commit a141178255

View File

@ -56,12 +56,12 @@ static int DistanceToPlaneCode(int xsize, int dist) {
return dist + 120; return dist + 120;
} }
// TODO(vikasa): Evaluate loading (and comparing) 32/64 bits for the inner while
// loop.
static WEBP_INLINE int FindMatchLength(const uint32_t* const array1, static WEBP_INLINE int FindMatchLength(const uint32_t* const array1,
const uint32_t* const array2, const uint32_t* const array2,
int best_len_match, int best_len_match,
int max_limit) { int max_limit) {
#if !defined(__x86_64__)
// TODO(vrabaud): Compare on other architectures.
int match_len = 0; int match_len = 0;
// Before 'expensive' linear match, check if the two arrays match at the // Before 'expensive' linear match, check if the two arrays match at the
// current best length index. // current best length index.
@ -70,6 +70,32 @@ static WEBP_INLINE int FindMatchLength(const uint32_t* const array1,
++match_len; ++match_len;
} }
return match_len; return match_len;
#else
const uint32_t* array1_32 = array1;
const uint32_t* array2_32 = array2;
// max value is aligned to (uint64_t*) array1
const uint32_t* const array1_32_max = array1 + (max_limit & ~1);
// Before 'expensive' linear match, check if the two arrays match at the
// current best length index.
if (array1[best_len_match] != array2[best_len_match]) return 0;
// TODO(vrabaud): add __predict_true on bound checking?
while (array1_32 < array1_32_max) {
if (*(uint64_t*)array1_32 == *(uint64_t*)array2_32) {
array1_32 += 2;
array2_32 += 2;
} else {
// if the uint32_t pointed to are the same, then the following ones have
// to be different
return (array1_32 - array1) + (*array1_32 == *array2_32);
}
}
// Deal with the potential last uint32_t.
if ((max_limit & 1) && (*array1_32 != *array2_32)) return max_limit - 1;
return max_limit;
#endif
} }
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------