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

Matt Turner mattst88@gmail.com
Wed Aug 12 01:19:42 GMT 2026


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



More information about the Libc-alpha mailing list