GCC: conflicting optimizations - c++

Due to long build times, I haven't been able to sufficiently narrow down the culprit leading to internal compiler error: Segmentation fault (I have managed to rule out LTO, though). Present in GCC versions 4.8.2, 4.8.3, and 4.9.1, rather than a bug I'm suspecting a conflict between the remaining various optimization strategies:
Generic: most likely unrelated, here for completeness
-pipe
-march=native
-O3
-msse2
-mfpmath=sse
-ffast-math
Graphite: loop optimization with regard to memory access
-floop-interchange
-floop-strip-mine
-floop-block
Graphite: not really sure
-fgraphite-identity
ISL: loop optimizations with regard to memory access and automatic parallelism
-floop-nest-optimize
Graphite: loop optimization with regard to automatic parallelism
-floop-parallelize-all
-ftree-parallelize-loops=2
Sets of options seem to share significant functional overlap. If this has likely been leading to the segmentation fault during compilation, which options should I preserve and which should I cull in order to maximize performance?

Finally narrowed the segfault down to the -ffast-math and -floop-parallelize-all options, exclusively. This issue is identical to [4.8/4.9 Regression] [graphite] Segmentation fault with -Ofast -floop-paralle..., and should be fixed upstream. Since the fix was pushed Jun 29, while gcc 4.9.1 was released Jul 16 it was branched in Apr, it is not included in the 4.8.3 and 4.9.1 releases.

Related

Meaning of this=<optimized out> in GDB

I understand the general concept of using optimization flags like -O2 and ending up having had things optimized out, makes sense. But what does it mean for the 'this' function parameter in a gdb frame to be optimized out? Does it mean the use of an Object was determined to be entirely pointless, and that it, and the following function call was elided from existence? Is it indicative of a function having been inlined? Is it indicative of the function call having been elided?
How would I go about investigating further? This occurs with both -O0 and -Og.
If it makes any difference, this is with an ARM process. I'm doing remote debugging using GNU gdbserver (GDB) 7.12.1.20170417-git and 'gdb-multiarch' GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1.
But what does it mean for the 'this' function parameter in a gdb frame to be optimized out?
It means that GDB doesn't have sufficient debug info to understand the current value of this.
It could happen for two reasons:
the compiler failed to emit relevant debug info
the info is there, but GDB failed to understand it
GCC used to do (1) a lot with -O2 and higher optimization levels, but that has been significantly improved around 2015-2016. I have never seen <optimized out> with GCC at -O0.
Clang still does (1) with -O2 and above on x86_64 in 2022, but again I've never seen it do that at -O0.
How would I go about investigating further?
You can run readelf --debug-dump ./a.out and see what info is present in the binary. Beware -- there is a lot of info, and making sense of it requires understanding of what's supposed to be there.
Or you could file a bugzilla issue with exact compiler and debugger versions and compilation command, attach a small binary, and hope that someone will look.
But first make sure you still get this behavior from the latest released version of GCC and GDB (or the current tip-of-trunk versions if you can build them).

Memory Sanitizer

I am playing around with Memory Sanitizer with Clang 3.7.0 on Ubuntu 14.04. The following code does work perfectly:
#include <cstdio>
int main() {
double ans;
printf("Hello World: %f\n", ans);
return 0;
}
when compiled with
clang++ -g -O1 -fsanitize=memory -fsanitize-memory-track-origins=2 -fomit-frame-pointer sanitize.cpp -o sanitize
I was expecting an error. Doesn't Memory Sanitizer catch the fact that ans was not initialized?
Thanks for your help.
From the clang santitizer documentation it is clear that it only deals with unitialized memory reads from dynamically allocated memory. Automatic memory is not part of sanitizer checks.
Valgrind memcheck could be an option to detect the uninitialized stack values.
Valgrind documentation:
For uninitialised values originating from a heap block, Memcheck shows where the block was allocated. For uninitialised values originating from a stack allocation, Memcheck can tell you which function allocated the value, but no more than that -- typically it shows you the source location of the opening brace of the function. So you should carefully check that all of the function's local variables are initialised properly.
Reference:
http://valgrind.org/docs/manual/mc-manual.html
You don't need any Sanitizer to catch this error. The compiler can figure out this error in compile time (sanitizers and valgrind work at run time). In fact, all of GCC Clang and ICC will all give a warning for this code if you switch on the warnings. This particular warning is controlled with -Wuninitialized flag. In general, it is a good practice to always use high warning level. I would recommend the following combination of warning flags, especially while learning the language:
-Wall -Wextra -pedantic
If you get some false positives, only after rigorously checking that they are really false, you can disable specific warnings. There is no reason not to use warning flags. Some projects even use -Werror flag, turning all the warnings into errors.

This pointer is 0xfffffffc, potential causes?

I'm compiling the Crypto++ library at -O3. According to Undefined Behavior Sanitizer (UBsan) and Address Sanitizer (Asan), its OK. The program runs fine at -O2 (and -O3 on many platforms).
Its also OK according to Valgrind under -O2. At -O3, Valgrind dies with "Your program just tried to execute an instruction that Valgrind does not understand". I'm fairly certain that's because of SSE4 instructions and vectorizations at -O3.
However, I'm catching a crash on some platforms with -O3. This particular machine is Fedora 22 i686, and its has GCC 5.2.1. The frame in question shows this=0xfffffffc:
Program received signal SIGSEGV, Segmentation fault.
0x0807be29 in CryptoPP::DL_GroupParameters_IntegerBased::GetEncodedElementSize
(this=0xfffffffc, reversible=0x1) at gfpcrypt.h:55
55 unsigned int GetEncodedElementSize(bool reversible) const {return GetModulus().ByteCount();}
The best I can tell, there's nothing located around that address:
(gdb) info shared
From To Syms Read Shared Object Library
0xb7fdd860 0xb7ff6b30 Yes (*) /lib/ld-linux.so.2
0xb7eb63d0 0xb7f7a344 Yes (*) /lib/libstdc++.so.6
0xb7e005f0 0xb7e32bd8 Yes (*) /lib/libm.so.6
0xb7951060 0xb7980cc4 Yes (*) /lib/libubsan.so.0
0xb7932090 0xb7948001 Yes (*) /lib/libgcc_s.so.1
0xb7916840 0xb79238d1 Yes (*) /lib/libpthread.so.0
0xb775d3f0 0xb78a0b6b Yes (*) /lib/libc.so.6
0xb7741a90 0xb7742a31 Yes (*) /lib/libdl.so.2
I've seen this=0x00000000 if a static class object declared in one translation unit is used in another translation unit before initialization is complete. But I don't recall seeing 0xfffffffc in the past.
What are some potential reasons for this=0xfffffffc? Or how can I troubleshoot it further?
If you have a 32 bits machine 0xfffffffc is ((int*)nullptr)-1. So perhaps you are taking the previous element of a nil pointer (e.g. wrongly using some reverse iterator, etc etc...)
Use the bt or backtrace command of gdb to understand what has happened. I guess that the trouble is in the caller (or its caller, etc...)
Try also some other compiler (e.g. some older version of GCC and several versions of Clang/LLVM....). You could have some undefined behavior that your other tools did not detect as such. You need to understand if the bug is inside Crypto++ (or perhaps, but very unlikely, it is inside GCC itself; then report a bug on GCC bugzilla....). If you suspect the compiler, pass -S -fverbose-asm -fdump-tree-all -O3 to g++ to understand what GCC is doing.... (this will dump hundreds of files, including the generated .s assembler code).
Ask also on crypto++ lists; perhaps report the bug on Crypto++ bug tracker. Test with other versions or snapshot of that library
BTW, I'm not sure that -fsanitize=undefined or -fsanitize=address should be used with -O3; I guess that they are more suitable with -O0 -g or -Og -g

gcc detecting "subindex out of bound" error

Surprisingly I found gcc can find this error when it compiles C. I simplified the code which still triggers the warning. I post the question for making clear the details of the techniques it uses. Below is my code of file a.c
int main(){
int a[1]={0};
return(a[1]);
}
My gcc version is gcc (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3. When using gcc a.c -Wall, there is no warning; when using gcc -O1 a.c -Wall, there is a warning:
warning: ‘a[1]’ is used uninitialized in this function [-Wuninitialized]
and when using gcc -O2 a.c -Wall (or -O3), there is another warning:
warning: array subscript is above array bounds [-Warray-bounds]
The most surprising thing is that, when I give a[1] a value, then none of the above compiling options gives any warning. There is no warning even when I change the index to a huge number (of course the compiled file offends the operating system and will be kicked out),
int main(){
int a[1]={0};
a[2147483648]=0;
return(a[2147483648]);
}
I think the above phenomenon is more of a function than a bug. I hope someone help me figure out what happens, and/or why the compiler is designed so. Many thanks!
Accessing memory past the end of the array results in undefined behaviour.
gcc is nice enough to go out of its way to detect, and warn you about, some of these errors. However, it is under no obligation to do so, and certainly cannot be expected to catch all such errors.
The compiler is not required to provide diagnostic for this kind of error, but gcc is often able to help; notice that these warnings often arise in part as a byproduct of the static analysis passes done for optimization purposes, which means that, as you noticed, such warnings often depend from the specified optimization level.

max number of allowable warnings while compiling

Is it possible to 'tell' compiler that if total number of warnings (while compiling a C++ program) are more than say 10 then stop compiling further, and emit an error?
Or is it possible to hack a compiler like clang to provide this functionality.
GCC has two options together would achieve this, from gnu online docs:
-Werror
Make all warnings into errors.
-fmax-errors=n
Limits the maximum number of error messages to n, at which point GCC bails out rather than attempting to continue processing the source
code.
This would make a build with any warnings fail though, the options just define when to stop parsing.
I haven't seen this kind of feature in gcc or clang. You can certainly try to patch it into either of them, both are open source. There is also -Werror (accepted by both compilers) which simply treats warnings as errors.
How about using -Werror to make warnings into errors and -fmax-errors=n to set the limit.
(Also, perhaps making your code completely warning free would be a good thing).