4

I am integrating the PoissonRecon code available here into my own mesh manipulation code, but I've been unable to compile the integrated code in x64 because of an "illegal instruction" error in every bit-shift instruction in the Poisson code's octree generation.

I'm using Visual Studio 2015 and my issue occurs only when compiled in x64 and only when in release mode (i.e., it works in x86 debug and release as well as x64 debug).

As an example of one of the bitshift instructions, the following is defined at the top of Octree.inl:

template< class NodeData > const int OctNode< NodeData >::DepthShift=5;
template< class NodeData > const int OctNode< NodeData >::OffsetShift = ( sizeof(long long)*8 - DepthShift ) / 3;
template< class NodeData > const int OctNode< NodeData >::DepthMask=(1<<DepthShift)-1; // This variable is correct
template< class NodeData > const int OctNode< NodeData >::OffsetMask=(1<<OffsetShift)-1; // This variable is also correct
template< class NodeData > const int OctNode< NodeData >::OffsetShift1=DepthShift;
template< class NodeData > const int OctNode< NodeData >::OffsetShift2=OffsetShift1+OffsetShift;
template< class NodeData > const int OctNode< NodeData >::OffsetShift3=OffsetShift2+OffsetShift;

And these variables are used in the following function:

template< class NodeData >
inline unsigned long long OctNode< NodeData >::Index( int depth , const int offset[3] )
{
    unsigned long long idx=0;
    idx |= ( ( (unsigned long long)(depth    ) ) & DepthMask  );
    idx |= ( ( (unsigned long long)(offset[0]) ) & OffsetMask ) << OffsetShift1;
    idx |= ( ( (unsigned long long)(offset[1]) ) & OffsetMask ) << OffsetShift2;
    idx |= ( ( (unsigned long long)(offset[2]) ) & OffsetMask ) << OffsetShift3;
    return idx;
}

This function breaks at the line

idx |= ( ( (unsigned long long)(offset[0]) ) & OffsetMask ) << OffsetShift1;

which I've split down further and found that the issue is the bit-shift itself, i.e. (var)<<OffsetShift1; but this causes an "illegal instruction" error.

Note that OffsetShift1 is simply "5", so this is equivalent to (var)<<5; which does work as expected.

A possible workaround is to simply #define all of these variables at the top (which does fix the issue), but this does not solve other bit-shift issues such as the following:

void _startAndWidth( const TreeOctNode* node , Point3D< Real >& start , Real& width ) const
    {
        LocalDepth d ; LocalOffset off;
        _localDepthAndOffset( node , d , off );
        if (d >= 0) width = Real(1.0 / (1 << d));
        else width = Real( 1.0 * (1<<(-d)) );
        for( int dd=0 ; dd<DIMENSION ; dd++ ) start[dd] = Real( off[dd] ) * width;
    }

I've tried to static_cast<long long> everything, but it's not an overflow issue. Even stranger, if I break before a bit-shift (while in release mode) and then highlight the operation, the debugger tells me the correct result (for example, d = 5 in _startAndWidth, so 1 << d returns 32 in the debugger) but actually stepping over the operation causes an "illegal instruction" error.

Since the program works correctly in debug mode, I've tried removing all optimizations in release mode, but I still get the same error. The only workaround I've found is to replace all bit-shift operations with pow() instead, and while that works, it seems a bit ridiculous.

4

1 回答 1

3

事实证明,重构代码附带的 .sln 文件是用 AVX2 设置的,我的机器不支持它。

Configuration Properties >> C/C++ >> Code Generation“启用增强指令集”设置为 AVX 解决了该问题。

汇编代码现在显示“SHL”而不是“SHLX”,因此“非法指令”是实际的 SHLX 命令不可用,而不是进入 SHLX 的参数有问题。

于 2017-02-15T18:28:34.757 回答