Last active
February 14, 2016 02:31
-
-
Save TABETA/9dddd84d84ec49dcf9a6 to your computer and use it in GitHub Desktop.
switch文のケースに使われているリテラル値で最適化はしてくれるのか? ref: http://qiita.com/abedominal/items/5f4eb9750737aff76efe
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//maskの右辺値はコンパイル時に決められるから計算コスト不要であることを期待 | |
class Select0 | |
{ | |
public: | |
bool operator()(int bitPos, uint32_t dword) | |
{ | |
uint32_t mask = 0; | |
switch (bitPos) | |
{ | |
case 1: mask = 1<<0; break; | |
case 2: mask = 1<<1; break; | |
case 3: mask = 1<<2; break; | |
case 4: mask = 1<<3; break; | |
case 5: mask = 1<<4; break; | |
case 6: mask = 1<<5; break; | |
case 7: mask = 1<<6; break; | |
case 8: mask = 1<<7; break; | |
default: return false; | |
} | |
return (dword & mask) != 0; | |
} | |
}; | |
//Select0の派生。Select0が最適化されていたらこれと同じ速度になるはず。 | |
class Select00 | |
{ | |
public: | |
bool operator()(int bitPos, uint32_t dword) | |
{ | |
switch (bitPos) | |
{ | |
case 1: return (dword & (1 << 0)) != 0; | |
case 2: return (dword & (1 << 1)) != 0; | |
case 3: return (dword & (1 << 2)) != 0; | |
case 4: return (dword & (1 << 3)) != 0; | |
case 5: return (dword & (1 << 4)) != 0; | |
case 6: return (dword & (1 << 5)) != 0; | |
case 7: return (dword & (1 << 6)) != 0; | |
case 8: return (dword & (1 << 7)) != 0; | |
default: return false; | |
} | |
} | |
}; | |
//Select0の派生。Select0が最適化されていたらこれと同じ速度になるはず。 | |
class Select01 | |
{ | |
public: | |
bool operator()(int bitPos, uint32_t dword) | |
{ | |
switch (bitPos) | |
{ | |
case 1: return (dword & (1 )) != 0; | |
case 2: return (dword & (2 )) != 0; | |
case 3: return (dword & (4 )) != 0; | |
case 4: return (dword & (8 )) != 0; | |
case 5: return (dword & (16 )) != 0; | |
case 6: return (dword & (32 )) != 0; | |
case 7: return (dword & (64 )) != 0; | |
case 8: return (dword & (128)) != 0; | |
default: return false; | |
} | |
} | |
}; | |
//最適化が賢ければSelect0はこう書いても同じになるはず。 | |
class Select1 | |
{ | |
public: | |
bool operator()(int bitPos, uint32_t dword) | |
{ | |
switch (bitPos) | |
{ | |
case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: | |
{ | |
const uint32_t mask = 1 << (bitPos - 1); | |
return (dword & mask) != 0; | |
} | |
default: return false; | |
} | |
} | |
}; | |
//if文で普通に処理するパターン | |
class Select2 | |
{ | |
public: | |
bool operator()(int bitPos, uint32_t dword) | |
{ | |
if (bitPos < 1 || 8 < bitPos) | |
{ | |
return false; | |
} | |
return ((dword >> (bitPos - 1)) & 1) == 1; | |
} | |
}; | |
//if文で範囲外をはじいてからテーブル処理するパターン。テーブル内のシフト演算はコンパイル時に確定するはず。 | |
class Select30 | |
{ | |
public: | |
bool operator()(int bitPos, uint32_t dword) | |
{ | |
if (bitPos < 1 || 8 < bitPos) | |
{ | |
return false; | |
} | |
static const uint32_t mask[] = { 0, 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7}; | |
return (dword & mask[bitPos]) != 0; | |
} | |
}; | |
//Select30の亜種。範囲外はすべて0番目の配列で処理 | |
class Select31 | |
{ | |
public: | |
bool operator()(int bitPos, uint32_t dword) | |
{ | |
static const uint32_t mask[] = { 0, 1, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 }; | |
return (dword & mask[8<bitPos ? 0 : bitPos]) != 0; | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include "Timer.hpp" | |
template<typename T> | |
class Measure | |
{ | |
static const uint64_t rep = 100000000; | |
int count_; | |
public: | |
Measure() :count_() | |
{} | |
int count() | |
{ | |
return count_; | |
} | |
double execute(uint32_t dword) | |
{ | |
Timer<TimerType::HighAccuracy> timer; | |
for (uint64_t i = 0; i < rep; ++i) | |
{ | |
if (T()(i % 8 + 1, dword)) | |
{ | |
++count_; | |
} | |
} | |
return timer.elapsed(); | |
} | |
}; | |
#include <iomanip> | |
#define measure(n,dw) \ | |
{ \ | |
Measure<Select##n> a; \ | |
volatile double r = a.execute(dw); \ | |
int c = a.count(); \ | |
cout << #n":\t" << /*fixed << setprecision(6) << */ r << ", " << c << endl; \ | |
} | |
//setprecisionをつけるとなぜかSelect2が遅くなる | |
int main(int argv, char* argc[]) | |
{ | |
static const int testNum = 2; | |
//最適化効いたらいやなので標準入力から32という数値を放り込む | |
uint32_t in; | |
cin >> in; | |
volatile uint32_t dw = in; | |
measure(0, dw); | |
measure(00, dw); | |
measure(01, dw); | |
measure(1, dw); | |
measure(2, dw); | |
measure(30, dw); | |
measure(31, dw); | |
return 0; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
0: 0.276666, 12500000 | |
00: 0.216566, 12500000 | |
01: 0.213629, 12500000 | |
1: 0.143589, 12500000 | |
2: 0.113139, 12500000 | |
30: 0.115278, 12500000 | |
31: 0.144108, 12500000 | |
続行するには何かキーを押してください . . . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
0: 0.276666, 12500000 | |
00: 0.216566, 12500000 | |
01: 0.213629, 12500000 | |
1: 0.143589, 12500000 | |
2: 0.113139, 12500000 | |
30: 0.115278, 12500000 | |
31: 0.144108, 12500000 | |
続行するには何かキーを押してください . . . |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$LL4@execute: | |
mov eax, ecx | |
and eax, 7 | |
cmp eax, 7 | |
ja SHORT $LN3@execute | |
jmp DWORD PTR $LN45@execute[eax*4] | |
$LN23@execute: | |
mov al, bl | |
and eax, -255 ; ffffff01H | |
jmp SHORT $LN24@execute | |
$LN22@execute: | |
mov eax, ebx | |
shr eax, 1 | |
jmp SHORT $LN40@execute | |
$LN21@execute: | |
mov eax, ebx | |
shr eax, 2 | |
jmp SHORT $LN40@execute | |
$LN20@execute: | |
mov eax, ebx | |
shr eax, 3 | |
jmp SHORT $LN40@execute | |
$LN19@execute: | |
mov eax, ebx | |
shr eax, 4 | |
jmp SHORT $LN40@execute | |
$LN18@execute: | |
mov eax, ebx | |
shr eax, 5 | |
jmp SHORT $LN40@execute | |
$LN17@execute: | |
mov eax, ebx | |
shr eax, 6 | |
jmp SHORT $LN40@execute | |
$LN16@execute: | |
mov eax, ebx | |
shr eax, 7 | |
$LN40@execute: | |
and al, 1 | |
$LN24@execute: | |
test al, al | |
je SHORT $LN3@execute; Line 23 | |
inc DWORD PTR [edi] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
_TEXT SEGMENT | |
_dword$ = 8 ; size = 4 | |
$T1 = 12 ; size = 4 | |
??RSelect1@@QAE_NHI@Z PROC ; Select1::operator(), COMDAT | |
push ebp | |
mov ebp, esp | |
cmp DWORD PTR $T1[ebp], 8 | |
jle SHORT $LN2@operator | |
xor al, al | |
pop ebp | |
ret 8 | |
$LN2@operator: | |
dec ecx | |
mov eax, 1 | |
shl eax, cl | |
and eax, DWORD PTR _dword$[ebp] | |
neg eax | |
sbb eax, eax | |
neg eax | |
pop ebp | |
ret 8 | |
??RSelect1@@QAE_NHI@Z ENDP ; Select1::operator() | |
_TEXT ENDS |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
cmp ecx, 7 | |
ja SHORT $LN3@execute | |
mov eax, ebx | |
shr eax, cl | |
and al, 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment