问题描述
说我有这样的功能:
inline int shift( int what, int bitCount )
{
return what >> bitCount;
}
它会从不同的站点,每次位计数
将为非负位在 INT 。我特别关注具有呼叫
位计数
等于零 - 它会正常工作,然后
It will be called from different sites each time
bitCount
will be non-negative and within the number of bits in int
. I'm particularly concerned about call with bitCount
equal to zero - will it work correctly then?
也有一个机会,一个编译器看到函数的整个code编译其呼叫站点将减少
位计数
通话等于零无时-OP?
Also is there a chance that a compiler seeing the whole code of the function when compiling its call site will reduce calls with
bitCount
equal to zero to a no-op?
推荐答案
是某些的至少有一个C ++编译器会认清形势时(0在编译时是已知的),并使其无操作:
It is certain that at least one C++ compiler will recognize the situation (when the 0 is known at compile time) and make it a no-op:
源代码
inline int shift( int what, int bitcount)
{
return what >> bitcount ;
}
int f() {
return shift(42,0);
}
编译器开关
icpc -S -O3 -mssse3 -fp-model fast=2 bitsh.C
英特尔C ++ 11.0组装
# -- Begin _Z1fv
# mark_begin;
.align 16,0x90
.globl _Z1fv
_Z1fv:
..B1.1: # Preds ..B1.0
movl $42, %eax #7.10
ret #7.10
.align 16,0x90
# LOE
# mark_end;
.type _Z1fv,@function
.size _Z1fv,.-_Z1fv
.data
# -- End _Z1fv
.data
.section .note.GNU-stack, ""
# End
正如你可以看到..B1.1,英特尔编译回移(42,0),以回归42。
As you can see at ..B1.1, Intel compiles "return shift(42,0)" to "return 42."
11英特尔也为中精选这两种形式的转变:
Intel 11 also culls the shift for these two variations:
int g() {
int a = 5;
int b = 5;
return shift(42,a-b);
}
int h(int k) {
return shift(42,k*0);
}
有关的情况下,当移值是在编译时不可知...
For the case when the shift value is unknowable at compile time ...
int egad(int m, int n) {
return shift(42,m-n);
}
...无法避免换档...
... the shift cannot be avoided ...
# -- Begin _Z4egadii
# mark_begin;
.align 16,0x90
.globl _Z4egadii
_Z4egadii:
# parameter 1: 4 + %esp
# parameter 2: 8 + %esp
..B1.1: # Preds ..B1.0
movl 4(%esp), %ecx #20.5
subl 8(%esp), %ecx #21.21
movl $42, %eax #21.10
shrl %cl, %eax #21.10
ret #21.10
.align 16,0x90
# LOE
# mark_end;
...但至少它的内联,所以没有调用的开销。
... but at least it's inlined so there's no call overhead.
奖励大会:波动是昂贵的。源...
Bonus assembly: volatile is expensive. The source ...
int g() {
int a = 5;
volatile int b = 5;
return shift(42,a-b);
}
...而不是一个空操作,编译成...
... instead of a no-op, compiles to ...
..B3.1: # Preds ..B3.0
pushl %esi #10.9
movl $5, (%esp) #12.18
movl (%esp), %ecx #13.21
negl %ecx #13.21
addl $5, %ecx #13.21
movl $42, %eax #13.10
shrl %cl, %eax #13.10
popl %ecx #13.10
ret #13.10
.align 16,0x90
# LOE
# mark_end;
...因此,如果你的机器在那里你值推栈上,当你弹出他们,也可能是不一样的工作,这错过了优化可能是最少你的烦恼。
... so if you're working on a machine where values you push on the stack might not be the same when you pop them, well, this missed optimization is likely the least of your troubles.
这篇关于将零位位移位正常工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!