-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathncopy_7.76(loop_6).ys
152 lines (133 loc) · 4.87 KB
/
ncopy_7.76(loop_6).ys
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# Author:李一凡 [email protected]
# 优化思路1:将原来的“先把常数移到寄存器中再做运算”的方法改成使用iaddq实现,减少冗余;(13.70)
# 优化思路2:将Always Taken的分支预测方法改成BTFNT, 提高预测准确性。不过由于现在程序中分支并不多,所以这条方法没有很大改进;(13.63)
# 优化点:Y86-64处理器默认寄存器存储的是0,所以一开始的那个异或是没必要的;(13.56)
# 优化点:在mrmovq和rmmovq之间插入无关痛痒的%rdi+=8,因为后一个mov在前一个访存之后才能接收到数据转发,而这造成了一个阶段的暂停。把第一遍改漏的subq也换成iaddq;(11.56)
# 优化点:每次对len减一的时候总是andq判断一下再跳转,实际上跳转之前只要没有其他运算就可以了;(10.56)
# 优化思路3:按len-=2展开循环。一开始先把len-2,判断有没有资格进入设计出来的Loop_double。每次从Loop_double出来都要先-2,判断有没有再次进入Loop_double的资格。
# 每次发现没有进入的资格就直接跳到Once 里面。由于%rdx比2小但是每次只是减去2,所以这个部分会判断%rdx是0(直接返回到Done)还是1(按照Once中的语句再ncopy一次);(8.73)
# 优化思路4:按len-=3展开循环。与思路3类似,只是在最后跳出的判断出有差异。我选择先把由于小于3而不能进入下一次Loop_trible的%rdx先加上2,这样原来的0是负的,1是equal,2是正的。然后跳转到各自的处理模块中即可;(8.12)
# 优化思路5:按len-=4展开循环。与上述过程类似,在第一个mrmov的地方利用bubble多复制一个,之后滚雪球。最后判断余数的时候,先加上3,再看大于或小于。等于只用执行一次。如果执行3次,先把最后一个复制过去,剩下两个与复制两次的用同一片代码,便于之后展开规模更大时不超字节限制;(7.90)
# 优化思路6:按len-=6展开循环。处理余数的时候没什么技巧,只是加了一些数然后分成-1,0和从1开始的正数。如果不能完全分开就减一些数,仍然把他们分成-1,0,,一些正数......
# 目前ncopy.yo的字节数637, 最后处理余数的环节出现了不少bubble;(7.76)
#
#/* $begin ncopy-ys */
##################################################################
# ncopy.ys - Copy a src block of len words to dst.
# Return the number of positive words (>0) contained in src.
#
# Include your name and ID here.
#
# Describe how and why you modified the baseline code.
#
##################################################################
# Do not modify this portion
# Function prologue.
# %rdi = src, %rsi = dst, %rdx = len
ncopy:
##################################################################
# You can modify this portion
# Loop header
# xorq %rax,%rax # count = 0;
iaddq $-6, %rdx
jl Last
Loop_six:
mrmovq (%rdi), %r10 # read val from src...
mrmovq 8(%rdi), %r11 # Destory this bubble.
rmmovq %r10, (%rsi) # ...and store it to dst
andq %r10, %r10 # val <= 0?
jle L1 # if so, goto L1 (Across iaddq):
iaddq $1, %rax # irmovq $1, %r10
# addq %r10, %rax # count++
L1:
mrmovq 16(%rdi), %r10
rmmovq %r11, 8(%rsi)
andq %r11, %r11
jle L2
iaddq $1, %rax
L2:
mrmovq 24(%rdi), %r11
rmmovq %r10, 16(%rsi)
andq %r10, %r10
jle L3
iaddq $1, %rax
L3:
mrmovq 32(%rdi), %r10
rmmovq %r11, 24(%rsi)
andq %r11, %r11
jle L4
iaddq $1, %rax
L4:
mrmovq 40(%rdi), %r11
rmmovq %r10, 32(%rsi)
andq %r10, %r10
jle L5
iaddq $1, %rax
L5:
rmmovq %r11, 40(%rsi)
andq %r11, %r11
jle L6
iaddq $1, %rax
L6:
iaddq $48, %rdi # src += 6
iaddq $48, %rsi # dst += 6
iaddq $-6, %rdx
jge Loop_six # if %rdx >= 6, goto Loop again:
Last:
iaddq $5, %rdx
jl Done
jg Judge_remain # 对应着原来的2,3,4,5.
mrmovq (%rdi), %r10
rmmovq %r10, (%rsi)
andq %r10, %r10
jle Done
iaddq $1, %rax
ret
Judge_remain:
iaddq $-2, %rdx
je Loop_three
jl Loop_twice
jg Judge_four_five
Judge_four_five:
iaddq $-1, %rdx
je Loop_four
Loop_five:
mrmovq 32(%rdi), %r10
rmmovq %r10, 32(%rsi)
andq %r10, %r10
jle Loop_four
iaddq $1, %rax
Loop_four:
mrmovq 24(%rdi), %r10
rmmovq %r10, 24(%rsi)
andq %r10, %r10
jle Loop_three
iaddq $1, %rax
Loop_three:
mrmovq 16(%rdi), %r10
rmmovq %r10, 16(%rsi)
andq %r10, %r10
jle Loop_twice
iaddq $1, %rax
Loop_twice:
mrmovq (%rdi), %r10
mrmovq 8(%rdi), %r11 # Destory the bubble.
rmmovq %r10, (%rsi)
andq %r10, %r10
jle Second
iaddq $1, %rax
Second:
rmmovq %r11, 8(%rsi)
andq %r11, %r11
jle Done
iaddq $1, %rax
ret
##################################################################
# Do not modify the following section of code
# Function epilogue.
Done:
ret
##################################################################
# Keep the following label at the end of your function (AND MAKE SURE THERE IS A BLANKE LINE IN THE END!!!)
End:
#/* $end ncopy-ys */