How undefined are __builtin_ctz(0) or __builtin_clz(0)?

岁酱吖の 提交于 2019-11-30 03:11:50

Unfortunately, even x86-64 implementations can differ - from Intel's instruction set reference,BSF and BSR, with a source operand value of (0), leaves the destination undefined, and sets the ZF (zero flag). So the behaviour may not be consistent between micro-architectures or, say, AMD and Intel. (I believe AMD leaves the destination unmodified.)

The newer LZCNT and TZCNT instructions are not ubiquitous. Both are present only as of the Haswell architecture (for Intel).

The reason the value is undefined is that it allows the compiler to use processor instructions for which the result is undefined, when those instructions are the fastest way to get an answer.

But it's important to understand that not only are the results undefined; they are undeterministic. It's valid, given Intel's instruction reference, for the instruction to return the low 7 bits of the current time, for example.

And here's where it gets interesting/dangerous: the compiler writer can take advantage of this situation, to produce smaller code. Consider this non-template-specialization version of your code:

using std::numeric_limits;
template<class T>
constexpr auto ctz(T x) {
  return ctznz(0) == numeric_limits<T>::digits || x != 0
       ? ctznz(x) : numeric_limits<T>::digits;
}

This works well on a processor/compiler that have decided to return #bits for ctznz(0). But un a processor/compiler that decide to return pseudo-random values, the compiler may decide "I'm allowed to return whatever I want for ctznz(0), and the code is smaller if I return #bits, so I will". Then the code ends up calling ctznz all the time, even though it produces the wrong answer.

To put it another way: the compiler's undefined results are not guaranteed to be undefined in the same way that the running program's undefined results are.

There really is no way around this. If you must use __builtin_clz, with a source operand that might be zero, you have to add the check, all the time.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!