[PATCH 01/20] alpha: use prefetch-with-modify-intent in memset on EV7

Matt Turner <[email protected]>
Newsgroups gmane.comp.lib.glibc.alpha
Message-ID <282b022a12959d4cb81f02aabcfcffad74c4cd06.1786497497.git.mattst88@gmail.com>
The unrolled loop in the ev6 memset issues wh64 two cache lines ahead of
the stores to avoid read-for-ownership on whole-line stores.  That is
tuned for the 21264 (EV6, EV67, EV68) with an external Bcache.  On the
21364 (EV7), with its on-chip memory controller and much longer memory
latency, two lines is far too close: the hint neither overlaps the fill
nor avoids the Mbox replay traps it provokes in the store stream.

Dispatch on IMPLVER (2 for the 21264 family, 3 for the 21364 family) and
give EV7 its own unrolled loop that issues a software prefetch with
modify intent (LDS to F31, a ReadBlkMod that allocates the line
writeable) six cache lines ahead of the stores.  On EV7 this beats wh64
at every distance and, unlike wh64, only reads, so prefetching past the
end of the region is harmless and no overrun guard is needed.  The 21264
code path is unchanged.

Measured on an AlphaServer ES47 (EV7, 1.3GHz), cycles/call:
  size     cold before  cold after     hot before  hot after
  1024            2056        1566 -24%        220        204
  4096           13167       11036 -16%        807        731
  65536         111438       76719 -31%       8495       7729
  262144        423219      285094 -33%     102067      54753 -46%
Mbox replay traps (perf -e r4) were used to identify the wh64 prefetch
distance as the bottleneck.
---
 sysdeps/alpha/alphaev6/memset.S | 51 +++++++++++++++++++++++++++++++++
 1 file changed, 51 insertions(+)

diff --git ./sysdeps/alpha/alphaev6/memset.S ./sysdeps/alpha/alphaev6/memset.S
index 6057274f1a..5c1e307cdf 100644
--- ./sysdeps/alpha/alphaev6/memset.S
+++ ./sysdeps/alpha/alphaev6/memset.S
@@ -103,6 +103,26 @@ $aligned:
 	 * $3	Number quads to write
 	 */
 
+	/*
+	 * Dispatch on the CPU implementation.  The 21264 (EV6, EV67, EV68) uses
+	 * wh64 two cache lines ahead to avoid read-for-ownership on whole-line
+	 * stores.  That distance is far too short for the 21364 (EV7), whose
+	 * on-chip memory controller has a much longer latency: there the hint
+	 * neither overlaps the fill nor avoids Mbox replay traps.  Issuing a
+	 * software prefetch-with-modify-intent (LDS to F31, a ReadBlkMod that
+	 * allocates the line writeable) six lines ahead instead recovers a
+	 * large cold-store win -- about -30% at >=64KB -- and, unlike wh64,
+	 * does not zero the line, so no end-guard against overrun is needed.
+	 * EV7 therefore takes its own unrolled loop.  IMPLVER returns 2 for the
+	 * 21264 family (EV6/67/68) and 3 for the 21364 family (EV7/EV79).
+	 */
+	subq	$3, 16, $4	# E : Only try to unroll if > 128 bytes
+	blt	$4, $loop	# U : too small -- scalar tail loop
+	implver	$2		# E : 2 = 21264 (EV6/67/68), 3 = 21364 (EV7)
+	subq	$2, 3, $2	# E : EV7 -> 0
+
+	beq	$2, $ev7_unroll	# U : EV7 takes the prefetch-modify path
+
 	and	$16, 0x3f, $2	# E : Forward work (only useful for unrolled loop)
 	subq	$3, 16, $4	# E : Only try to unroll if > 128 bytes
 	subq	$2, 0x40, $1	# E : bias counter (aligning stuff 0mod64)
@@ -174,6 +194,37 @@ $do_wh64:
 	nop
 	nop
 	beq	$3, $no_quad	# U : Might have finished already
+	br	$31, $loop	# U : 1..7 trailing quads
+
+	/*
+	 * EV7 (21364): 64-byte unrolled store loop that issues a software
+	 * prefetch-with-modify-intent (LDS to F31) six cache lines (384 bytes)
+	 * ahead of the current block.  No 0mod64 pre-align is needed.  The
+	 * prefetch only reads -- it never writes -- so prefetching past the end
+	 * of the region is harmless (a prefetch that misses the TLB or hits an
+	 * unwriteable page is simply dropped), and no end-guard is required.
+	 * $3 - quads left, $5 - dest (0mod8), $17 - store value, $7 scratch.
+	 */
+	.align 4
+$ev7_unroll:
+	lds	$f31, 6*64($5)	# L : prefetch w/ modify intent, six lines ahead
+	stq	$17, 0($5)	# L :
+	stq	$17, 8($5)	# L :
+	stq	$17, 16($5)	# L :
+	stq	$17, 24($5)	# L :
+	stq	$17, 32($5)	# L :
+	stq	$17, 40($5)	# L :
+	stq	$17, 48($5)	# L :
+	stq	$17, 56($5)	# L :
+
+	subq	$3, 8, $3	# E : decrement quad count
+	addq	$5, 64, $5	# E : advance dest
+	subq	$3, 8, $7	# E : at least 8 more quads?
+	bge	$7, $ev7_unroll	# U :
+
+	beq	$3, $no_quad	# U : exact multiple, done
+	nop
+	nop
 
 	.align 4
 	/*
-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.