Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Possibly incorrect code generated with GCC 7+ with -O2 #696

Closed
VaderY opened this issue Nov 8, 2017 · 2 comments
Closed

Possibly incorrect code generated with GCC 7+ with -O2 #696

VaderY opened this issue Nov 8, 2017 · 2 comments
Labels

Comments

@VaderY
Copy link

VaderY commented Nov 8, 2017

Hey,

GLM 0.9.8.5 with GCC 7.0+ if -O2, -O3 or -Ofast flag is used results in incorrect code generation. Seams like a read / write reordering issue, however I am not an expert on the topic.

Used compiler: MinGW720_x64_posix_seh_rev0
With only -O0 or -O1 the bug is not present.

I tried to isolate the bug as much as I can (see below). No multi-threading involved.
I am unable to isolate the problem any further, as soon as I try to replace the glm::mat4 class with a simplified version the problem disappears.

Bug is also present on:

  • MinGW710_x64_posix_seh
  • MinGW710_x64_posix_seh_rev2

However seams like it is NOT present on:

  • MinGW540_x64_posix_seh
  • MinGW620_x64_posix_seh_rev1

The problem is reading from the same matrix twice in a row yields different values. More importantly the first value read (a) is incorrect however after applying a memory barrier the correct values is read (b).

#include <iostream>
#include <glm/mat4x4.hpp>

void foo(glm::mat4& mat) {
	glm::mat4 trans{
		1, 0, 0, 0,
		0, 1, 0, 0,
		0, 0, 1, 0,
		1, 0, 0, 1};
	mat *= trans;

	float a = mat[3][0]; // a = 0 however it should be 1

	asm volatile ("" : : : "memory"); // or just use anything that can "serve" as a memory barrier
	// like: std::cout << std::endl; In the real scenario there was irrelevant code here.

	float b = mat[3][0]; // b = 1

	std::cout << a << b << std::endl; // In my case prints 01 consistently
}

int main() {
	glm::mat4 x{
		1, 0, 0, 0,
		0, 1, 0, 0,
		0, 0, 1, 0,
		0, 0, 0, 1};
	foo(x);

	return 0;
}

@Groovounet
Copy link
Member

float a = mat[3][0]; // a = 0 however it should be 1

Actually it should be 0. mat[3] third column and [0] first row.

You would get 1 for mat[0][0], mat[4][1], mat[2][2], mat[3][3].

Thanks,
Christophe

@VaderY
Copy link
Author

VaderY commented Nov 22, 2017

Please note that the trans matrix is given in its transposed form (The 16 arg ctor transposes).
https://github.com/g-truc/glm/blob/master/glm/detail/type_mat4x4.inl#L47

Matlab:

X = [1, 0, 0, 0;
     0, 1, 0, 0;
     0, 0, 1, 0;
     0, 0, 0, 1]
T = [1, 0, 0, 1;
     0, 1, 0, 0;
     0, 0, 1, 0;
     0, 0, 0, 1]
X * T
ans =
     1     0     0  >> 1 <<
     0     1     0     0
     0     0     1     0
     0     0     0     1

But the issue is not wrong multiplication, but wrong code generation with certain compilers / optimization levels.
The problem is variable a and b are not equal.

It is most likely a GCC bug and not yours. But I could not file a GCC issue as I could not exclude your library from the repo.

(I reserve the right to be wrong)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants