|
最適化オプション"エイリアスを使わないと仮定する"の意味を熟考すべし |
|
|
VC++には(それ以外のコンパイラにもきっと)、"エイリアスを使わないと仮定する"(/Ow,/Oa)という最適化オプションが用意されています。 |
|
|
List1 |
|
ソース |
void MemClear(int *pSize,char *pBuffer)
{
for(int i=0; i<*pSize; i++ ){
pBuffer[i] = 0;
}
}
|
出力 |
void MemClear(int *pSize,char *pBuffer)
{
mov ecx, pSize
xor eax, eax
cmp DWORD PTR [ecx], eax
jle SHORT LABEL2
LABEL1 // ループ戻り先(このラベルは次のmovの下でいい気がする…)
mov edx,pBuffer // クリアするバッファを取得
and BYTE PTR [eax+edx],0 // 1バイトクリア
inc eax // カウンタをインクリメント
cmp eax, DWORD PTR [ecx] // クリアサイズとカウンタを比較して
jl SHORT LABEL1 // まだ途中ならLABEL1に戻って繰り返す
LABEL2
ret
}
|
|
このコードは一見してわかるように、指定された領域のメモリをクリアする関数です。 |
|
|
List2 |
|
ソース |
// "エイリアスを使わないと仮定する"を有効
#pragma optimize ( "a", on )
void MemClear(int *pSize,char *pBuffer)
{
for(int i=0; i<*pSize; i++ ){
pBuffer[i] = 0;
}
}
#pragma optimize ( "", on ) // 元に戻す
|
出力 |
void MemClear(int *pSize,char *pBuffer)
{
mov eax, pSize
mov ecx, DWORD PTR [eax]
test ecx, ecx
jle SHORT LABEL1
mov edx, ecx
push edi
mov edi, pBuffer
xor eax, eax
shr ecx, 2 // クリアサイズ(の1/4。32BITで処理する為)
rep stosd // 一気にクリア
mov ecx, edx
and ecx, 3 // クリアサイズ(の4で割った余り)
rep stosb // 一気にクリア
pop edi
LABEL1
ret
}
|
|
リスト1と比べると、繰り返し処理(条件分岐)も無くなっており、見るからに早そうです。 |
|
|
List3 |
|
|
ソース |
void MemClear(int *pSize,char *pBuffer)
{
int nSize = *pSize; // サイズをローカル変数にコピー
for(int i=0; i<nSize; i++ ){
pBuffer[i] = 0;
}
}
|
出力 |
(リスト2と同じコードなので割愛) |
|
最初にクリアサイズ(*pSize)をローカル変数にコピーして、そのローカル変数がforを抜ける条件であると書くことで、 |
|
|
前のページ メンバ変数の並びを考慮すべし |
コンテンツのトップ |
次のページ try 〜 throw 〜 catch の乱用を避けるべし |




