将零位位移位正常工作? [英] Will bit-shift by zero bits work correctly?

查看:140
本文介绍了将零位位移位正常工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

说我有这样的功能:

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.

这篇关于将零位位移位正常工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆