我正在审查我的程序中 if 条件的用法,在那里,我有以下几行:
if(count > 4) count = 4;
将上述 if 条件语句编写为以下非分支语句是不是一个好主意?
count = 4*(count> 4) + count*(count<= 4);
我还有以下片段:
for (j=0, i=0; j<NCARD_PER_SUIT && i<CARDS_PER_PLAYER+CARDS_ON_BOARD; ++j) {
if (card_cfg.hearts & cfg_mask[j]) {
player_hand[i].card.face = j;
player_hand[i++].card.suit = HEART;
}
if (card_cfg.spades & cfg_mask[j]) {
player_hand[i].card.face = j;
player_hand[i++].card.suit = SPADE;
}
if (card_cfg.clubs & cfg_mask[j]) {
player_hand[i].card.face = j;
player_hand[i++].card.suit = CLUB;
}
if (card_cfg.diamonds & cfg_mask[j]) {
player_hand[i].card.face = j;
player_hand[i++].card.suit = DIAMOND;
}
}
并想知道是否有良好的(非分支)方式来编写上述任何建议?
编辑:基于下面的一些反馈,我比较了装配说明(使用MSVS2015 for Windows 10)并获得了以下内容:
; 718 : count = 4*(count> 4) + count*(count<= 4);
xor ebx, ebx
cmp edx, 4
setle bl
xor ecx, ecx
imul ebx, edx
cmp edx, 4
mov edx, 4
cmovg ecx, edx
add ebx, ecx
如果恢复到if语句,我得到以下内容,其中没有跳转指令和指令总数2/3与上述相比:
; 718 : if( count >4) count = 4;
mov eax, DWORD PTR _i$6$[ebp]
cmp edx, edi
mov ebx, DWORD PTR _player$GSCopy$1$[ebp]
cmovg edx, edi
mov edi, DWORD PTR _count$1$[ebp]
mov DWORD PTR _count$4$[ebp], edx
编辑#2:根据以下评论中的提示,我继续创建
union
typedef union {
struct cfg {
unsigned short hearts;
unsigned short spades;
unsigned short clubs;
unsigned short diamonds;
} suit;
unsigned long long allsuits;
} card_cfg_t;
在这个联盟的帮助下,我能够重写第二段OP,如下所示,如果我为64位机器构建并花费更多时间,这似乎可以节省很多(在我的情况下为20%)额外的40%)如果我为32位机器构建它:
for (j=0, i=0; j<NCARD_PER_SUIT && i<CARDS_PER_PLAYER+CARDS_ON_BOARD; ++j) {
for (int k=0; k<4; ++k) {
present = (int)((card_cfg.allsuits & (cfg_mask[j] << 16*k)) != 0);
player_hand[i].card.face = j*present;
player_hand[i].card.suit = k;
i = i + present;
}
}
答案 0 :(得分:1)
那些微观优化并没有太多意义,但你想要比较(你会看到你和我之间的区别 - 开启优化 - 编译器真的很好):
int count;
void foo()
{
count = 4*(count> 4) + count*(count <= 4);
}
void foo1()
{
count = count > 4 ? 4 : count;
}
void foo4()
{
if(count> 4) count = 4;
}
foo:
mov edx, DWORD PTR count[rip]
xor ecx, ecx
cmp edx, 4
setle al
setg cl
movzx eax, al
imul eax, edx
lea eax, [rax+rcx*4]
mov DWORD PTR count[rip], eax
ret
foo1:
cmp DWORD PTR count[rip], 4
mov eax, 4
cmovle eax, DWORD PTR count[rip]
mov DWORD PTR count[rip], eax
ret
foo4:
cmp DWORD PTR count[rip], 4
jle .L6
mov DWORD PTR count[rip], 4
.L6:
rep ret
答案 1 :(得分:1)
第二个循环的答案必须是:
pushcards(player, popcards(dealer));