Looking forward to GCC 7
Compilers live or die by their optimizers, so it is unsurprising that GCC
has, as usual, seen some optimization work. Some of these, like the new
store merging feature ("merges constant stores to adjacent memory
locations into fewer, wider, stores
") are the sort of thing that can
strike fear into kernel developers but should yield better performance in
general. A new code-hoisting option reorganizes functions by finding the
code that will be
executed in all paths through the function and moving it to the beginning,
yielding both size and speed improvements.
Another optimization, called "loop splitting", kicks in if a loop contains
a conditional test where the condition itself will not change while the
loop executes. The compiler may split it into two separate loops, one for
each case, moving the test and the jump out of the loop body.
The AddressSanitizer mechanism is now able to detect uses of variables after they go out of scope. Usually this problem results from taking a pointer to a variable, then dereferencing the pointer after exiting the block where that variable was in scope. LLVM has had this ability for a while, but the GCC implementation is claimed to be better by virtue of better handling of complex cases involving goto, as well as the ability to handle C++ temporaries.
Warnings are one area where GCC is said to fall short of LLVM, so one would expect improvements in that area. The C compiler, in particular, has a number of new warnings. For example, -Wimplicit-fallthrough will warn about switch-statement cases that fall through into the following case. This warning can be suppressed with a special attribute declaration — or a comment like "/* falls through */". There are warnings for if-else constructs with identical code in both branches, memset() calls where the size argument matches the number of elements in the array but not the size of the array, use of the (removed in C++17) register keyword, and more.
While GCC 6 was able to perform a certain amount of spell-checking on structure field names, GCC 7 expands that feature to function, macro, type, and enum names, and is now able to offer suggestions on how to fix the problem. There is an option to get those suggestions in machine-parsable form, enabling a suitably intelligent development environment to make fixes automatically. Format-string warnings now highlight the specific part of the string that is being complained about and offer fixes as well.
There are some additional warnings for situations that could create buffer overflows, including one for code that passes a huge size to a memory-allocation function. The compiler can now calculate the size of the output string in many sprintf() calls and warn if that destination array might be overrun. Similarly, possible truncation in snprintf() calls will generate a warning. A number of possible overflows in memcpy() and strcpy() calls can be detected at compile time as well.
The C++ compiler now has experimental support for the entire C++17 draft standard; a long list of new language features was added to achieve that support. Fortran has better DO-loop optimization and partial OpenMP 4.5 support. Ada code can now run without the need for an executable stack — a somewhat overdue security improvement. There is Go 1.8 support. On the other hand, the Java front end has been removed because there was nobody to maintain it.
Support for the Fuchsia operating system has been added in GCC 7.
Finally, there is now an internal unit-testing API for GCC, and a beginning suite of tests has been added. Parsing of internal-representation dumps has been added, allowing the creation of tests for specific optimization techniques. And, of course, this release will include the usual collection of bug fixes and smaller improvements.
LLVM may be the cool kid on the
compiler block at the moment, but the GCC developers are not sitting
still. GCC 7 will be another full-featured release from this project,
which saw the 30th anniversary of the first beta release in March.
Few projects have been so important to our community for so long, and GCC
clearly is not done yet.
Posted Apr 6, 2017 6:31 UTC (Thu)
by alison (subscriber, #63752)
[Link] (3 responses)
Posted Apr 6, 2017 10:50 UTC (Thu)
by epa (subscriber, #39769)
[Link] (2 responses)
Indeed, there is a case for saying that certain optimizations shouldn't be performed by the compiler at all but it should just create suggestions for how the source code could be transformed. That would pacify grumpy kernel developers who don't like the latest loophole the compiler makers have found in the C standard.
Posted Apr 7, 2017 18:49 UTC (Fri)
by guus (subscriber, #41608)
[Link]
Posted Apr 8, 2017 8:18 UTC (Sat)
by dvdeug (guest, #10998)
[Link]
Posted Apr 6, 2017 17:42 UTC (Thu)
by alvieboy (guest, #51617)
[Link] (2 responses)
Posted Apr 6, 2017 19:43 UTC (Thu)
by zlynx (guest, #2285)
[Link] (1 responses)
Posted Apr 7, 2017 10:42 UTC (Fri)
by jzbiciak (guest, #5246)
[Link]
Indeed. This particular optimization sounds like they've extended partial redundancy elimination further. GCC's had PRE for awhile...
Posted Apr 6, 2017 17:44 UTC (Thu)
by lonely_bear (subscriber, #2726)
[Link]
Posted Apr 7, 2017 7:52 UTC (Fri)
by ncm (guest, #165)
[Link] (6 responses)
Under ideal (but not uncommon) circumstances, modern chips can run two tests and two branches in one cycle, even with indexed sequential address mode operations involved.
Posted Apr 7, 2017 15:49 UTC (Fri)
by zlynx (guest, #2285)
[Link] (5 responses)
Posted Apr 7, 2017 21:37 UTC (Fri)
by ncm (guest, #165)
[Link] (4 responses)
So, inserting instructions between the test and the branch pessimizes current hardware, by default, in exchange for possibly less-bad performance on very old, slow hardware that (manifestly) nobody cares about enough to upgrade. It seems more likely to me that nobody on the project has reviewed the particular choice to insert the instructions, in light of current developments. In fact, when I last checked (in 6.1, I think), telling gcc to tune for Haswell did not make it emit fusible test-and-branch sequences.
But I would be interested to learn about a change in the policy, if any, and what motivated it.
Posted Apr 7, 2017 22:30 UTC (Fri)
by excors (subscriber, #95769)
[Link] (1 responses)
Posted Apr 8, 2017 3:18 UTC (Sat)
by ncm (guest, #165)
[Link]
Posted Apr 10, 2017 11:39 UTC (Mon)
by joib (subscriber, #8541)
[Link] (1 responses)
One could argue that by default GCC should a) do some optimizations b) generate debug symbols, and though I agree with that sentiment, it's another topic.
If GCC missed the opportunity for macro-op fusion with -mtune=generic, that sounds like a missed optimization bug.
Posted Apr 10, 2017 12:55 UTC (Mon)
by pabs (subscriber, #43278)
[Link]
Posted Apr 7, 2017 10:25 UTC (Fri)
by jzbiciak (guest, #5246)
[Link] (1 responses)
If I understood correctly, the loop splitting in GCC 7 is more general than described above. The exact quote from the changes page: What I understand that to mean is that it splits loops that have a condition that changes from true to false (or vice versa) at some point in the middle of the loop into two loops: One for the true case, and one for the false case. That is, there's a conditional whose truth value changes once somewhere in the iteration sequence, rather than zero times. There's an example in an old post from Michael Matz on the GCC development mailing list:
That's actually rather nice. I've written a number of loops where the first few iterations or last few iterations are "special" for some reason. This optimization peels the special iterations out so the compiler doesn't need to test for when we've entered the "special" zone every iteration.
Posted Apr 7, 2017 18:52 UTC (Fri)
by guus (subscriber, #41608)
[Link]
Posted Apr 8, 2017 20:48 UTC (Sat)
by lsl (subscriber, #86508)
[Link] (5 responses)
The C++ committee just can't stop with these small-gain but nonetheless breaking changes to the language. The rationale[1] seems especially weak this time: "it's unnecessary und we might be able to repurpose it for something else. Or we might not, as it's also used by a popular GCC extension."
Different from auto though, the register keyword is still present in lots of working C++ programs, most of it probably originating from older C codebases and copy-pasted as utility functions into another program. Much worse, it is also emitted by gperf, yacc implementations and likely others *today*.
[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n...
Posted Apr 13, 2017 8:30 UTC (Thu)
by gowen (guest, #23914)
[Link] (4 responses)
Posted Apr 14, 2017 17:17 UTC (Fri)
by lsl (subscriber, #86508)
[Link] (3 responses)
My point is that it's rude to break backwards compatibility. Doubly so when you do it for dubious gain.
Posted Apr 17, 2017 0:10 UTC (Mon)
by zlynx (guest, #2285)
[Link] (2 responses)
You really should be specifying the standard level to the compiler. Anything else results in rude surprises, like when I had to go back and remove a bunch of C++14 code from a project at work to make it compile on older C++11 systems. If the standard had been set, that C++14 code wouldn't have been accepted in the first place.
And why would you want per source file CXXFLAGS? You'd set the -std=c++11 for all compile steps, not just some files.
Posted Apr 17, 2017 12:49 UTC (Mon)
by mathstuf (subscriber, #69389)
[Link]
Posted Apr 18, 2017 20:01 UTC (Tue)
by lsl (subscriber, #86508)
[Link]
The C++ program I occasionally work on (which is only used internally, so we don't have to worry about supporting older compilers) is built with -std=gnu++1[y4] and if there's a benefit to be had, it can be moved to (the GNU variant of) C++17. Sadly, that now also involves the patching of register-emitting code generators. Or maybe not, hoping that GCC won't implement this for GNU C++.
Anyway, pointless breakages like this hinder the adoption of new standards. Until recently, the C++ committee generally seemed pretty thorough in avoiding such gratuitous changes (as are most stewards of mature languages, lest they end up with a Python 3).
repent ye coders, for the End is nigh!
repent ye coders, for the End is nigh!
repent ye coders, for the End is nigh!
repent ye coders, for the End is nigh!
A new code-hoisting option reorganizes functions by finding the code that will be executed in all paths through the function and moving it to the beginning,
I'm afraid now. Most developers assume code is executed as it is laid out (I know it's a programmer fault due to lack of barriers, but most just test their code based on whether it works, and don't care about barriers at all).
Has anyone more info on how this is supposed to work ? Most important part is how this option decides whether to move the code or not.
Alvie
Looking forward to GCC 7
Looking forward to GCC 7
Looking forward to GCC 7
Looking forward to GCC 7
Looking forward to GCC 7
Looking forward to GCC 7
Looking forward to GCC 7
GCC does seem to have code for macro fusion like that, added in GCC 4.9.0, so it probably ought to work.
Looking forward to GCC 7
Looking forward to GCC 7
Looking forward to GCC 7
Looking forward to GCC 7
Looking forward to GCC 7
It splits certain loops if they contain a condition that is always true on one side of the iteration space and always false on the other into two loops where each of the new two loops iterates just on one of the sides of the iteration space and the condition does not need to be checked inside of the loop.
i.e. such situations:
for (i = beg; i < end; i++)
if (i < p)
dothis();
else
dothat();
this is transformed into roughly:
for (i = beg; i < p; i++)
dothis();
for (; i < end; i++)
dothat();
This is excellent news for people who make use of the for-case paradigm ;)
Looking forward to GCC 7
Looking forward to GCC 7
Looking forward to GCC 7
Looking forward to GCC 7
Looking forward to GCC 7
Looking forward to GCC 7
Looking forward to GCC 7
