[PATCH 05/20] alpha: document ev6 memcpy design constraints

Matt Turner <[email protected]>
Newsgroups gmane.comp.lib.glibc.alpha
Message-ID <a71e399fc7c4a85bb44f7561525748995c1ee558.1786497497.git.mattst88@gmail.com>
Record two non-obvious decisions in memcpy.S so the next reader
does not spend the effort a second time.

No source prefetch on EV6: adding a read prefetch on the source
measured a net loss on an EV68CB -- it gave back a third of the wh64
gain on cold copies and cost 15% at 64KB hot.  The loop is
memory-latency-bound with loads already spread across the trip; an
extra reference only competes for the 21264's 8-entry MAF.

Misaligned path not unrolled: unrolling four quads to a trip cuts 38%
of instructions but gains only 1.4% in cycles, with IPC falling from
0.37 to 0.23.  The path stalls on the serial ldq_u -> extql/extqh ->
bis chain that produces each quad; feeding it more instructions per
trip does not shorten that chain.

Comment only, no change to generated code.
---
 sysdeps/alpha/alphaev6/memcpy.S | 38 +++++++++++++++++++++++++++------
 1 file changed, 31 insertions(+), 7 deletions(-)

diff --git ./sysdeps/alpha/alphaev6/memcpy.S ./sysdeps/alpha/alphaev6/memcpy.S
index cf5c97c1de..89324be23a 100644
--- ./sysdeps/alpha/alphaev6/memcpy.S
+++ ./sysdeps/alpha/alphaev6/memcpy.S
@@ -96,13 +96,23 @@ $do_unroll:
 	 * gain past two lines is under 1%, while the stretch at the end of the
 	 * region that has to fall back to hinting the current block grows and
 	 * makes short copies slower.  memset, which has no load stream to hide
-	 * behind, needs four.  wh64 is far too
-	 * longer latency: there wh64 neither overlaps the fill nor avoids the
-	 * Mbox replay traps it provokes in the store stream.  EV7 takes its own
-	 * unrolled loop that software-prefetches both streams several lines
-	 * ahead -- the source with a plain read prefetch (LDL to R31) and the
-	 * destination with a prefetch-with-modify-intent (LDS to F31, a
-	 * ReadBlkMod that allocates the line writeable).  Both are reads only,
+	 * behind, needs four.
+	 *
+	 * The source stream deliberately has no prefetch of its own.  The CWG
+	 * asks for one per stream, but adding a read prefetch here measured a
+	 * net loss on an EV68CB -- it gave back a third of the wh64 gain on cold
+	 * copies and cost 15% at 64KB hot.  The loads of this loop are already
+	 * spread across the trip, so the memory-level parallelism a prefetch
+	 * would add is present anyway, and the extra reference only competes for
+	 * the 21264's 8-entry MAF with the demand misses that need it.
+	 *
+	 * wh64 is far too short a hint for the 21364 (EV7), whose on-chip memory
+	 * controller has a much longer latency: there wh64 neither overlaps the
+	 * fill nor avoids the Mbox replay traps it provokes in the store stream.
+	 * EV7 takes its own unrolled loop that software-prefetches both streams
+	 * several lines ahead -- the source with a plain read prefetch (LDL to
+	 * R31) and the destination with a prefetch-with-modify-intent (LDS to
+	 * F31, a ReadBlkMod that allocates the line writeable).  Both are reads only,
 	 * so prefetching past the end of the region is harmless and no overrun
 	 * guard is needed.  IMPLVER returns 2 for the 21264 family and 3 for
 	 * the 21364 family.
@@ -289,6 +299,20 @@ $dest_0mod8:
 	ldq_u	$3, 0($17)		# L : seed (rotating load) of 8 bytes
 	nop				# E :
 
+	/*
+	 * This loop moves a quadword a trip, about 1.4 instructions per byte
+	 * against 0.46 for the aligned loop above, and a mismatched-alignment
+	 * copy costs 1.84 cycles a byte on an EV68CB where an aligned one costs
+	 * 1.13.  The instruction count is not what makes it slow, so unrolling
+	 * it does not help: a four-quad-per-trip version cut instructions by
+	 * 38% and bought 1.4%, with IPC falling from 0.37 to 0.23.  Both paths
+	 * take the same Bcache misses -- the data moved is identical -- and
+	 * this one takes fewer replay traps than the aligned loop, so it is
+	 * neither memory-bound nor issue-bound.  It is stalled on the serial
+	 * ldq_u -> extql/extqh -> bis chain that produces each stored quad.
+	 * Making it faster means breaking that dependence, not feeding it more
+	 * instructions per trip.
+	 */
 $mis_quad:
 	ldq_u	$16, 8($17)		# L : Fetch next 8
 	extql	$3, $17, $3		# U : masking
-- 
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.