|
|
Subscribe / Log in / New account

Looking forward to GCC 7

By Jonathan Corbet
April 5, 2017
The GNU Compiler Collection (GCC) project produces a major release on an approximately annual schedule, often in April. The next major release, GCC 7, is currently in stage 4, otherwise known as "regression and documentation mode". As of mid-March, the project was still hoping for a mid-April release date. Whether that date holds or slips, the set of GCC 7 features is well known at this point. What follows is a shameless cribbing of the high points from the GCC 7 changes document.

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.


to post comments

repent ye coders, for the End is nigh!

Posted Apr 6, 2017 6:31 UTC (Thu) by alison (subscriber, #63752) [Link] (3 responses)

"There is an option to get those suggestions in machine-parsable form, enabling a suitably intelligent development environment to make fixes automatically." Uh-oh, what's going to pay for my beer?

repent ye coders, for the End is nigh!

Posted Apr 6, 2017 10:50 UTC (Thu) by epa (subscriber, #39769) [Link] (2 responses)

I'd like it if some of the relatively high-level optimizations, such as the new loop splitting, could feed back suggestions to higher levels. So your development environment could prompt you (if you like) to split a loop in two, or hoist a constant out of a loop, or do some assignment later because it can be proven it's not needed yet. Some of these are already provided by IDEs, but the compiler has better and deeper knowledge.

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.

repent ye coders, for the End is nigh!

Posted Apr 7, 2017 18:49 UTC (Fri) by guus (subscriber, #41608) [Link]

These kinds of optimizations are extremely helpful when using macros/templates/generics. Those tend to expand into suboptimal source code, but with the help of optimizations like these they perform well.

repent ye coders, for the End is nigh!

Posted Apr 8, 2017 8:18 UTC (Sat) by dvdeug (guest, #10998) [Link]

In many cases, optimizations could depend on which platform you're running on or which options you're compiling with. One of the highest dreams of a highly-optimizing compiler is inlining something and using the information from the context to hoist constants, split loops and delete now-dead code.

Looking forward to GCC 7

Posted Apr 6, 2017 17:42 UTC (Thu) by alvieboy (guest, #51617) [Link] (2 responses)

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

Posted Apr 6, 2017 19:43 UTC (Thu) by zlynx (guest, #2285) [Link] (1 responses)

Uh, code hasn't been executed in the order it's written for 20 years or more. Optimizing compilers have been moving code all over the place and CPUs don't even run instructions in the order they arrive. Depending on what's happening in cache, the CPU may not even run the instructions in the same order each time.

Looking forward to GCC 7

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...

Looking forward to GCC 7

Posted Apr 6, 2017 17:44 UTC (Thu) by lonely_bear (subscriber, #2726) [Link]

One big change from GCC 6 also is the removal of the gcl Java front end.

Looking forward to GCC 7

Posted Apr 7, 2017 7:52 UTC (Fri) by ncm (guest, #165) [Link] (6 responses)

I would like for it to stop inserting another instruction between a test and the branch it controls. That keeps the two instructions from being fused into one micro-op, thereby both slowing loops and adding micro-op cache pressure. (I would not be surprised to find the latter is the larger effect.)

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.

Looking forward to GCC 7

Posted Apr 7, 2017 15:49 UTC (Fri) by zlynx (guest, #2285) [Link] (5 responses)

That should be a tune option. I know that on some CPUs the "test" operation takes multiple cycles and you can issue other instructions while the test completes. On those, test+branch is a waste of time.

Looking forward to GCC 7

Posted Apr 7, 2017 21:37 UTC (Fri) by ncm (guest, #165) [Link] (4 responses)

When I last looked, the policy was that, by default, the compiler should generate code that runs correctly on the widest variety of released hardware (i.e. the smallest common instruction set), but is tuned for the latest, fastest chips. This makes sense, in that users who are most interested in performance have the newest hardware, and anybody who wants better performance actually gets it by buying the new hardware and running the program as built with the newest compiler. I don't think that policy changed.

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.

Looking forward to GCC 7

Posted Apr 7, 2017 22:30 UTC (Fri) by excors (subscriber, #95769) [Link] (1 responses)

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

Posted Apr 8, 2017 3:18 UTC (Sat) by ncm (guest, #165) [Link]

That is an unusually large source file by any standard.

Looking forward to GCC 7

Posted Apr 10, 2017 11:39 UTC (Mon) by joib (subscriber, #8541) [Link] (1 responses)

The default policy is to do no optimization at all. However, these days most Linux distros AFAIK use something like "-O2 -g -mtune=generic" as their default CFLAGS, which should roughly accomplish what you say.

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.

Looking forward to GCC 7

Posted Apr 10, 2017 12:55 UTC (Mon) by pabs (subscriber, #43278) [Link]

GCC should also enable some of the hardening flags by default. It is pretty silly that every distro has to do that manually.

Looking forward to GCC 7

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:

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.

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:

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();

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.

Looking forward to GCC 7

Posted Apr 7, 2017 18:52 UTC (Fri) by guus (subscriber, #41608) [Link]

This is excellent news for people who make use of the for-case paradigm ;)

Looking forward to GCC 7

Posted Apr 8, 2017 20:48 UTC (Sat) by lsl (subscriber, #86508) [Link] (5 responses)

> the (removed in C++17) register keyword

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...

Looking forward to GCC 7

Posted Apr 13, 2017 8:30 UTC (Thu) by gowen (guest, #23914) [Link] (4 responses)

If you want your "register" code to still compile, specify a -std=c++11 or something that predates C++17. How hard is that?

Looking forward to GCC 7

Posted Apr 14, 2017 17:17 UTC (Fri) by lsl (subscriber, #86508) [Link] (3 responses)

Depending on the build system, it can be a bit annoying to specify per-source-file CXXFLAGS. Possibly more annoying than just removing the "register" specifiers.

My point is that it's rude to break backwards compatibility. Doubly so when you do it for dubious gain.

Looking forward to GCC 7

Posted Apr 17, 2017 0:10 UTC (Mon) by zlynx (guest, #2285) [Link] (2 responses)

If you aren't specifying a standard when you compile, you are taking whatever the default happens to be. If it breaks you get all the pieces.

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.

Looking forward to GCC 7

Posted Apr 17, 2017 12:49 UTC (Mon) by mathstuf (subscriber, #69389) [Link]

Standard flags don't make sense as per-source, but if you have an optional backend which is only used in one file, limiting the -D flag to just that file can help minimize errant use of the flag and reduce the number of files to recompile when toggling the feature.

Looking forward to GCC 7

Posted Apr 18, 2017 20:01 UTC (Tue) by lsl (subscriber, #86508) [Link]

> And why would you want per source file CXXFLAGS? You'd set the -std=c++11 for all compile steps, not just some files.

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).


Copyright © 2017, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds