c++/6546: static const members optimization failure
Nathan Myers
ncm-nospam@cantrip.org
Fri Jun 28 21:31:00 GMT 2002
On Fri, Jun 28, 2002 at 08:42:29AM +0200, Gabriel Dos Reis wrote:
> Nathan Myers <ncm-nospam@cantrip.org> writes:
> | I thought folks on this list should know about this. In short,
> | the "will-not-fix" below means that on gcc-3.1, as in 3.0, and
> | maybe in 3.2 and beyond, in
> |
> | struct foo { static const int bar = 3; };
> | int f(int i) { return std::min(foo::bar, i); }
> |
> | the compiler actually generates code to load the static value
> | for foo::bar from memory each time (twice, in the code above),
> | instead of using the manifest constant 3 in its place.
>
> I don't know why loading twice. But I can understand loading once,
> and I'm not sure I would qualify the behaviour as a bug.
>
> std::min() expect an lvalue, foo::bar is such a thing, therefore its
> the designated object's address is taken; thyen its definition is
> required. Anything after that is optimization, optimization that
> can't change the semantics. Therefore the definition is required.
Please study the case more carefully. The context is an inline
function expanded in a context that doesn't need an lvalue. In
fact, in gcc-2.95, the memory references were optimized away just
fine. The compiler was entirely justified in eliding the memory
references. The result was faster, correct code. This makes it
a regression.
Yes, it is conforming to do the memory reference. That doesn't
make it OK. It just means instead of a conformance regression,
we have a quality-of-implementation regression. Neither is a
good thing. We're supposed to be getting better, not worse.
> | Furthermore, it insists on having a int foo::bar defined
> | someplace, creating a porting difficulty from other compilers
> | that don't.
>
> Well, I think it is assuming the compiler will not require the
> definition that is the non-portable assumption.
It is not assumptions that are at issue. It is the unnecessary
nuisance. It's not hard to concoct cases where the memory address
really is needed (e.g. "return &Foo::bar;"). That's not an excuse
for demanding it where there is no objective reason.
> | As an alternative, casting the value:
> |
> | int g(int i) { return std::min(int(foo::bar), i); }
> |
> | seems to work around the problem.
>
> Indeed, that use doesn't need the address of the object, so the
> compiler is free to apply any relevant optimization.
As noted, the definition of f() doesn't need the address either,
because std::min() is an inline function in our library, and the
entire context is locally visible to the compiler.
Is this regression something we can live with? Certainly, for
a while. But let's not fool ourselves into thinking that it is
something not to be embarrassed about. Other compilers don't
have any trouble optimizing away the memory reference, and we
should expect at least as much of our compiler.
Enough said. When we get AST optimizations (whatever the heck they
are) the regression will be probably be fixed.
Nathan Myers
ncm at cantrip dot org
More information about the Libstdc++
mailing list