Why does returning an element of copied Matrix3d ​​lead to incorrect output when using Clang 3.9?

Compiling the following example with -O2 in Clang 3.9 will return the returned garbage ( 1.9038e+185 ) when called in main :

Code

 double reproFunction(const Eigen::Matrix3d& R_in) { const Eigen::Matrix3d R = R_in; Eigen::Matrix3d Q = R.cwiseAbs(); if(R(1,2) < 2) { Eigen::Vector3d n{0, 1, R(1, 2)}; double s2 = R(1,2); s2 /= n.norm(); } return R(1, 2); } int main() { Eigen::Matrix3d R; R = Eigen::Matrix3d::Zero(3,3); // This fails - reproFunction(R) returns 0 R(1, 2) = 0.7; double R12 = reproFunction(R); bool are_they_equal = (R12 == R(1,2)); std::cout << "R12 == R(1,2): " << are_they_equal << std::endl; std::cout << "R12: " << R12 << std::endl; std::cout << "R(1, 2): " << R(1, 2) << std::endl; } 

Output

 R12 == R(1,2): 0 R12: 1.9036e+185 R(1, 2): 0.7 

reproFunction , initializes R (which is const) to the destination of R_in . It returns R(1, 2) . Between assignment and return, reproFunction uses R in several operations, but none of them can change R When deleting any of these operations, the result of reproFunction returns the correct value.

This behavior does not appear in any of the following cases:

  • The program is compiled using Clang 3.5, Clang 4.0 or g ++ - 5.4.
  • Optimization level -O1 or lower
  • Instead of Eigen 3.3.3, Eigen 3.2.10 is used

Now the question is: Is this behavior due to an error that I missed in the above code, an error in Eigen 3.3.3, or an error in Clang 3.9?

An example of self-contained playback can be found at https://github.com/avalenzu/eigen-clang-weirdness .

+5
source share
1 answer

I could reproduce this with clang 3.9, but not with clang 3.8. I divided the question on the Eigen side into this commit from 2016-05-24 21:54 :

Error 256: allow vectorization with unbalanced loads / storages. This applies to all architectures and all sizes. This new behavior can be disabled by setting EIGEN_UNALIGNED_VECTORIZE = 0

This commit allows vectorized operations with low data.

I still think this is a bug in clang, but you can get around it by compiling with

 -D EIGEN_UNALIGNED_VECTORIZE=0 

In addition, Eigen can be “fixed” by automatically disabling this feature if clang 3.9 is detected as a compiler.

+4
source

Source: https://habr.com/ru/post/1270504/


All Articles