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

bug and potential fix for using long double with DoNotOptimize and gcc #903

Open
KlausLeppkes opened this issue Nov 21, 2019 · 4 comments
Open
Assignees

Comments

@KlausLeppkes
Copy link

Hi,

1.) I discovered that g++ has a problem with +m inside DoNotOptimize.
As Jakub Jelinek stated in my gcc bugreport, +g works instead of +m (see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92597).
2.) I attached the small example (test.cpp+makefile), which gives wrong values using g++[9.2] with +m.
Also, if you define -DFIX inside the makefile, gcc is working fine. Clang and Intel seem to not having this problem, but are also checked.

For reproduction, g++ is called to compile with +m:
$>make
...
FMA: 0; TYPE: double; ASM Volatile: 1 => y=6.9529e-305
FMA: 1; TYPE: long double; ASM Volatile: 1 => y=-nan
make: *** [makefile:17: diff_gcc] Error 1

If you uncomment the -DFIX inside the CFLAGS, gcc produces the correct numbers.

I don't know if this fixes the problem entirely, but I wanted to let you know that there is a problem and a workaround for gcc.

Cheers,
Klaus

googlebench_bugreport.zip

@dmah42 dmah42 assigned dmah42 and EricWF and unassigned dmah42 Nov 21, 2019
@dmah42
Copy link
Member

dmah42 commented Nov 21, 2019

@KlausLeppkes thanks for the comprehensive bug report!

@EricWF this is your area of the code and you know it best so over to you :)

@KlausLeppkes
Copy link
Author

KlausLeppkes commented Nov 21, 2019

I searched for some doc and found:
"g" : Any register, memory or immediate integer operand is allowed, except for registers that are not general registers." (x86 specified!).
vs.
"m" : A memory operand is allowed, with any kind of address that the machine supports in general.
source: https://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

@EricWF: The helper functions are for x86 anyway, so why not changing m into g everywhere?

@dmah42
Copy link
Member

dmah42 commented May 8, 2021

closed the PR but i'd like to understand if there's something that we need to do here after all.

@MatejKafka
Copy link

GCC maintainers are pretty adamant that this is not a compiler bug, and that the "+m,r" is incorrect. Not that it is documented anywhere, so we're gonna have to take their word for it. :)

The issue is that the in/out operand is internally split into 2 separate operands: __asm__ __volatile__("" : "=m,r"(value) : "m,0"(value) : "memory");. When DoNotOptimize is used to obfuscate a fixed input to a benchmark, this results in value never being initialized:

extern int external_fn(int);
extern int arg;

int fn() {
    arg = 5;
    asm volatile("" : "+m,r"(arg) : : "memory"); // inlined content of `DoNotOptimize`
    return external_fn(arg);
}

The inline asm statement in this snippet is turned into __asm__ __volatile__("" : "=m,r"(arg) : "m,0"(5) : "memory");, which results in gcc placing the constant 5 into memory, passing the address as the input argument and expecting the asm block to store the result into arg, resulting in calling external_fn with an uninitialized argument.

See the following for a repro: https://godbolt.org/z/W7GYMcann

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

No branches or pull requests

4 participants