[PATCH 08/20] alpha: fold null and difference tests in strcmp aligned loop

Adhemerval Zanella Netto adhemerval.zanella@linaro.org
Wed Aug 12 20:53:56 GMT 2026



On 11/08/26 22:19, Matt Turner wrote:
> The co-aligned main loop tested for a difference (xor; bne) and for the
> terminating null (cmpbge; beq) with two separate branches per quadword.
> On EV6/EV7 the loop is issue-bound and right at the one-branch-per-cycle
> limit, so the second branch is a bottleneck.
> 
> Combine the two into a single syndrome -- "or" of the difference bits and
> the null mask -- so one branch closes the loop and the difference test for
> the first word moves out into the head.  The loop still loads the next
> word only after the current one tests clean (a zero syndrome implies no
> null, so the string continues and the next word is mapped), so it never
> reads past the terminating null onto an unmapped page.
> 
> bench-strcmp on EV7 (21364): co-aligned compares ~6-9% faster across
> lengths that stay in L1, neutral once memory-bound; the mutually
> misaligned path is unchanged.  Passes string/test-strcmp.

The alpha strcmp.S is another potential candidate to be removed, the
generic implementation contains all the optimizations bits (word aligned
loops, word unaligned loop, and mismatch/EOS tails) and will use all
the require alpha instruction to speed them up.

> ---
>  sysdeps/alpha/strcmp.S | 24 +++++++++++++++++-------
>  1 file changed, 17 insertions(+), 7 deletions(-)
> 
> diff --git ./sysdeps/alpha/strcmp.S ./sysdeps/alpha/strcmp.S
> index c7f092d1b7..6454b7aab0 100644
> --- ./sysdeps/alpha/strcmp.S
> +++ ./sysdeps/alpha/strcmp.S
> @@ -53,22 +53,32 @@ $aligned:
>  	ornot	t0, t3, t0	# .. e1 :
>  	cmpbge	zero, t1, t7	# e0    : bits set iff null found
>  	bne	t7, $eos	# e1 (zdb)
> +	xor	t0, t1, t2	# e0    : difference in the first word?
> +	bne	t2, $wordcmp	# .. e1 (zdb)
> +
> +	/* Aligned compare main loop.  Fold the difference test (xor) and the
> +	   null test (cmpbge) into a single syndrome with "or", so one branch
> +	   per quadword closes the loop instead of two.  Each load is gated by
> +	   the previous word being clean -- a zero syndrome means no null, so
> +	   the string continues and the next word is mapped -- hence we never
> +	   read past the terminating null onto an unmapped page.
>  
> -	/* Aligned compare main loop.
>  	   On entry to this basic block:
>  	   t0 == an s1 word.
> -	   t1 == an s2 word not containing a null.  */
> +	   t1 == an s2 word, equal to t0 and not containing a null.  */
>  
>  $a_loop:
> -	xor	t0, t1, t2	# e0	:
> -	bne	t2, $wordcmp	# .. e1 (zdb)
>  	ldq_u	t1, 8(a1)	# e0    :
>  	ldq_u	t0, 8(a0)	# .. e1 :
>  	addq	a1, 8, a1	# e0    :
>  	addq	a0, 8, a0	# .. e1 :
> -	cmpbge	zero, t1, t7	# e0    :
> -	beq	t7, $a_loop	# .. e1 (zdb)
> -	br	$eos		# e1    :
> +	xor	t0, t1, t2	# e0    : bytes that differ
> +	cmpbge	zero, t1, t7	# .. e1 : bits set iff null found
> +	or	t2, t7, t8	# e0    : syndrome = difference | null
> +	beq	t8, $a_loop	# .. e1 (zdb) : clean word, keep going
> +
> +	bne	t7, $eos	# e0    : null present (handles diff-before-null)
> +	br	$wordcmp	# .. e1 : a pure difference, no null
>  
>  	/* The two strings are not co-aligned.  Align s1 and cope.  */
>  



More information about the Libc-alpha mailing list