2004年作成
インライン展開時のスタックポインタ処理
-O2でコンパイルするとinline定義されたものはinline展開します。
展開するにもかかわらずスタックポインタ操作の処理がそのまま残っています。
inline の場合は元になる関数の部分で全てを済ませればいいのですから、全て無駄なコードになっています。
1 _start::
2 ila $7,66051
3 stqd $17,-48($sp)
4 lqa $4,Test1In+16
:
39 stqd $lr,16($sp) # リターンレジスタも積む必要無し
38 a $7,$5,$4
39 stqd $sp,-112($sp) # スタックポインタのセーブ処理
40 sfh $6,$11,$6
41 lnop
42 ah $2,$2,$14
43 lqd $15,0($7)
44 ila $4,q4x4+16
45 lnop
46 sfi $8,$8,-15
47 shufb $10,$2,$6,$10
48 ai $sp,$sp,-112 # スタック拡張
49 shufb $2,$2,$6,$17
50 lqx $16,$5,$4
51 ila $4,66051
52 ai $sp,$sp,112 # スタック戻し
53 shufb $8,$8,$8,$4
54 sfh $4,$10,$2
レジスタ割り当て
callerレジスタの使用方法で無駄な箇所があります。
:
3 stqd $17,-48($sp) # $17 store:
4 lqa $4,Test1In+16
5 lqa $17,.LC0 # $17 def
6 lqa $2,Test1In
:
13 lqa $5,mod_six+20
14 shufb $6,$2,$4,$17 # $17 use
15 shufb $2,$2,$4,$10
:
22 ah $6,$6,$2
23 stqd $16,-32($sp) # $16 store
24 stqd $15,-16($sp)
:
49 shufb $2,$2,$6,$17 #
50 lqx $16,$5,$4 # $16 def
51 ila $4,66051
52 ai $sp,$sp,112
53 shufb $8,$8,$8,$4
54 sfh $4,$10,$2
55 lqd $17,-48($sp) # $17 reload
56 ah $2,$2,$10
:
74 mpya $5,$9,$15,$5
75 mpya $6,$2,$16,$6 # $16 use
76 mpyhha $4,$9,$15
77 lqd $15,-16($sp)
78 mpyhha $7,$2,$16 # $16 use
79 lqd $16,-32($sp) # $16 reload
$16と$17が実際は一つのレジスタにまとめることができます。
$17 は 3-55, $16 は 23-79 でライブレンジが重なっているように見えますが、store-reload の部分が重なっているので、これは同一レジスタに割り当てることが可能です。
定数
同じ定数を別のレジスタに割り当てている部分があります。
同じレジスタを使用することによって、レジスタのスピル処理を減らすことができます。
下記の例はMEのものです。定数515に関して一つのレジスタにまとめることが出来ます。
1 SubSampleFi4x4:
2 nop $127
3 stqd $42,-448($sp)
4 il $42,-1152
5 stqd $15,-16($sp)
6 stqd $16,-32($sp)
7 stqd $17,-48($sp)
8 stqd $18,-64($sp)
9 stqd $19,-80($sp)
10 stqd $20,-96($sp)
11 stqd $21,-112($sp)
12 stqd $22,-128($sp)
13 stqd $23,-144($sp)
14 stqd $24,-160($sp)
15 stqd $25,-176($sp)
16 ilh $25,515
17 stqd $26,-192($sp)
18 # iprefetch
19 lnop
20 stqd $27,-208($sp)
21 stqd $28,-224($sp)
22 stqd $29,-240($sp)
23 ilh $29,515
24 stqd $30,-256($sp)
25 stqd $31,-272($sp)
26 stqd $32,-288($sp)
27 nop $127
28 stqd $33,-304($sp)
29 ilh $33,515
無駄なレジスタを使用してしまうのは上記の2と同じ問題です。
inline展開を多用しますと、どうしても使用するレジスタ数が増えます。
無駄なレジスタ使用が 1 つあるとスタックへのロード・セーブでパイプラインの P1 が二つ埋まってしまいます。
無駄なnop
下記のトレース結果はme実行時のものです。
85,86にnopがありますが、これは無駄ではないでしょうか。
ただ、nop を削るとスケジュールが崩れる場合があるので、どういう準拠によってnop が挿入されるかわかりません。
89-92 で処理が空いているのは 87 で $26 の準備をしているのが間に合っていないためです。
80 で $10 の設定処理をしている部分と交換すれば、この無駄なサイクルを削ることが出来ます。
D Cycle 80: PC:00178 [P0:il $9,0x0000] PC:0017c [P1:lqa $10,0x015c0]
S Cycle 81: PC:00180 [P1:stqd $0,0x001($1)]
S Cycle 82: PC:00184 [P1:stqd $1,0x3f2($1)]
S Cycle 83: PC:00188 [P0:ai $1,$1,0x320] PC:0018c [P1:lnop ]
S Cycle 84: PC:00190 [P0:il $8,0x0000] PC:00194 [P1:hbra 0x01c,0x0068]
N Cycle 85: PC:00198 [P1:lnop ]
N Cycle 86: PC:0019c [P0:nopi ,0x00007f]
D Cycle 87: PC:001a0 [P0:ila $20,0x01600] PC:001a4 [P1:lqa $26,0x02000]
S Cycle 88: PC:001a8 [P1:lqa $25,0x02010]
R Cycle 89:
R Cycle 90:
R Cycle 91:
R Cycle 92:
S Cycle 93: PC:001ac [P0:mpyh $24,$9,$26]
0 件のコメント:
コメントを投稿