This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Giving hints to the compiler/optimizer (#pragma hint ...)


On 06/26/2018 05:31 AM, U.Mutlu wrote:
Martin Sebor wrote on 06/26/2018 05:16 AM:
When the reference passed to f() is bound to an object that's
defined const GCC could assume that the call to f() doesn't
change it and emit better code but, unfortunately, it does not.
As a result, even though GCC could avoid the test below, it
emits it.

   void g (void)
   {
     const std::vector<int> v;

     int n = v.size ();

     f (v);

     if (v.size () != n)
       __builtin_abort ();
   }

GCC does eliminate such tests in the simple cases when v is
a fundamental type like int, but not when it's a struct (even
a trivial one containing just an int).

Hmm. if that is really true then I would be negatively surprised.
I just tested it with the the latest g++ (v9) and it gives a compile
error
if one tries to modify the vector inside f().
And that is the expected behaviour, so I wonder which compiler &
version you
mean?

Ok, you mean this:
  if (v.size () != n)
    __builtin_abort ();

But the compliler cannot know that size() returns a vector-internal
value,
ie. it could also be an external value, therefore it can't optimize it
away, IMO.

Jonathan already made it clear earlier that GCC can determine
that the return value of vector::size() doesn't change between
successive calls to the function because it's is trivially
inline and doesn't modify any data, and therefore can
eliminate all but the first call.

For a reduced test case showing the missing optimization see
bug 86318.

Ok, I see, with a deep-analysis the compiler/optimizer can determine
whether the member func, here size() const, is returning
a non-changing value, that is
 a) either an object-intern variable
    (in this case regardless of the constness of the object itself
    as a whole as it was passed to f() as a const reference,
    so v can't change in f() and therefore between the two v.size()
calls)),
 b) a true const variable or value (intern or extern), or
 c) a calculated value (intern or extern) that is always the same,
then the said optimization afterwards can indeed be made, yes, true.

It's all about the quality/depthness of the analysis.
But in the general case (ie. any func), the _calculated_ return value
cases are IMO the hardest to analyse correctly.

Therefore, I think the power-user can and should help the
compiler/optimizer
with some new function attributes/hints (and maybe also variable
attributes/hints), to keep the gcc guesswork and the codebase light,
and still be flexible and powerful.

Attributes const and pure exist to provide hints about these
properties of out-of-line functions.  Inline functions are
more or less transparent to the compiler: it sees their
definitions (almost) as if they were expanded like macros
within their callers.  There is no need to provide similar
hints for expressions -- their effects are fully known to
the compiler.  There is also no need for hints of this sort
for variables: their properties are fully described by their
declarations in standard C (and mostly also C++).  Declaring
a variable that doesn't change const lets the compiler take
advantage of its immutability for optimization (unfortunately,
few programmers appreciate this benefit of constness, and as
we saw, GCC itself doesn't yet take full advantage of it).
Declaring a pointer both const and restrict guarantees that
the pointed to object itself doesn't change during
the pointer's lifetime (if the object is accessed by
the restrict-qualified pointer). (GCC doesn't yet take
advantage of this feature.)

Beyond these static properties, the __builtin_unreachable()
intrinsic can be used to assert various aspects of program
state (e.g.,
if (v.size() != n) __builtin_unreachable ();)

Martin


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]