[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