任务
修改ncopy.ys和pipe-full.hcl以尽可能的提高ncopy.ys的运行速度
思路
pipe-full.hcl:
- 实现iaddq指令(家庭作业4.54)
- 实现加载转发(家庭作业4.57)
ncopy.ys:
- 使用循环展开(第5.8节),由于代码长度限制,最终使用十路循环展开
- 使用区间判断处理循环展开之后的余数,并利用技巧减少跳转指令
- 利用总是选择分支策略的特性控制分支优先级,决定优先级的有两个因素:一是区间越大(发生的概率越大)的分支优先级越大;二是余数越小优先级越大,因为每个长度的成绩是CPE(cycles per element),而综合成绩又是每个长度成绩的平均值
- 寄存器默认为零,因此删除xorq %rax, %rax指令不会造成错误
由于采用了十路循环展开,因此余数为[0, 9],由于跳转指令可以为jl,je,jg,因此区间判断的搜索树为一个三叉搜索树,选择3和7进行判断是综合考虑统计因素和余数优先级的结果
代码
##################################################################
# You can modify this portion# Loop header# ten-way loop unrollingiaddq $-10, %rdx # len - 10 < 0?jl L0R9
Loop1:mrmovq (%rdi), %r8 # val = *srcrmmovq %r8, (%rsi) # *dst = valandq %r8, %r8 # val <= 0?jle Loop2 # if so, goto Loop2iaddq $1, %rax # count++
Loop2:mrmovq 0x8(%rdi), %r8rmmovq %r8, 0x8(%rsi)andq %r8, %r8jle Loop3iaddq $1, %rax
Loop3:mrmovq 0x10(%rdi), %r8rmmovq %r8, 0x10(%rsi)andq %r8, %r8jle Loop4iaddq $1, %rax
Loop4:mrmovq 0x18(%rdi), %r8rmmovq %r8, 0x18(%rsi)andq %r8, %r8jle Loop5iaddq $1, %rax
Loop5:mrmovq 0x20(%rdi), %r8rmmovq %r8, 0x20(%rsi)andq %r8, %r8jle Loop6iaddq $1, %rax
Loop6:mrmovq 0x28(%rdi), %r8rmmovq %r8, 0x28(%rsi)andq %r8, %r8jle Loop7iaddq $1, %rax
Loop7:mrmovq 0x30(%rdi), %r8rmmovq %r8, 0x30(%rsi)andq %r8, %r8jle Loop8iaddq $1, %rax
Loop8:mrmovq 0x38(%rdi), %r8rmmovq %r8, 0x38(%rsi)andq %r8, %r8jle Loop9iaddq $1, %rax
Loop9:mrmovq 0x40(%rdi), %r8rmmovq %r8, 0x40(%rsi)andq %r8, %r8jle Loop10iaddq $1, %rax
Loop10:mrmovq 0x48(%rdi), %r8rmmovq %r8, 0x48(%rsi)andq %r8, %r8jle Stepiaddq $1, %rax
Step:iaddq $0x50, %rdiiaddq $0x50, %rsiiaddq $-10, %rdxjge Loop1# applying range checks to remainders
L0R9:iaddq $7,%rdx # Test 3 (len + 10 - 3)jl L0R2 # len < 3jg L4R9 # len > 3je Rem3 # len == 3
L0R2:iaddq $2,%rdx # Test 1 (len + 3 - 1)je Rem1 # len == 1jg Rem2 # len == 2ret # len == 0
L4R6:iaddq $2,%rdx # Test 5 (len + 7 - 5)jl Rem4 # len == 4je Rem5 # len == 5jmp Rem6 # len == 6
L4R9:iaddq $-4,%rdx # Test 7 (len + 3 - 7)jl L4R6 # len < 7je Rem7 # len == 7
L8R9:iaddq $-1,%rdx # Test 8 (len + 7 - 8)je Rem8 # len == 8# dealing with remainders
Rem9:mrmovq 0x40(%rdi), %r8rmmovq %r8, 0x40(%rsi)andq %r8, %r8jle Rem8iaddq $1, %rax
Rem8:mrmovq 0x38(%rdi), %r8rmmovq %r8, 0x38(%rsi)andq %r8, %r8jle Rem7iaddq $1, %rax
Rem7:mrmovq 0x30(%rdi), %r8rmmovq %r8, 0x30(%rsi)andq %r8, %r8jle Rem6iaddq $1, %rax
Rem6:mrmovq 0x28(%rdi), %r8rmmovq %r8, 0x28(%rsi)andq %r8, %r8jle Rem5iaddq $1, %rax
Rem5:mrmovq 0x20(%rdi), %r8rmmovq %r8, 0x20(%rsi)andq %r8, %r8jle Rem4iaddq $1, %rax
Rem4:mrmovq 0x18(%rdi), %r8rmmovq %r8, 0x18(%rsi)andq %r8, %r8jle Rem3iaddq $1, %rax
Rem3:mrmovq 0x10(%rdi), %r8rmmovq %r8, 0x10(%rsi)andq %r8, %r8jle Rem2iaddq $1, %rax
Rem2:mrmovq 0x8(%rdi), %r8rmmovq %r8, 0x8(%rsi)andq %r8, %r8jle Rem1iaddq $1, %rax
Rem1:mrmovq (%rdi), %r8rmmovq %r8, (%rsi)andq %r8, %r8jle Doneiaddq $1, %rax##################################################################
# Do not modify the following section of code
# Function epilogue.
Done:ret
##################################################################
# Keep the following label at the end of your function
End:
#/* $end ncopy-ys */