One of the micro-optimizations I am about to merge from TCB
involves disregarding V_MAY_DEF/V_MUST_DEF operands for read-only
globals.
So, if a symbol is marked read-only and the operand scanner
requests a V_MAY_DEF or V_MUST_DEF operand for it, we replace it
with a VUSE.
This works fine, except that I was having comparison errors with
SPEC2000's eon. I tracked it down to the C++ FE emitting an
assignment instruction for a global const variable. What follows
is speculation, I have no idea how the FE really works:
The source code declares
const double ggPi = 3.14159265358979323846;
double const divPi = 1 / ggPi;
And since divPi is initialized to an expression, I guess it needs
to compute it at runtime, so it emits an initialization function:
void __static_initialization_and_destruction_0(int, int) (__initialize_p,
__priority)
{
...
if (D.55019)
{
ggPi.319 = ggPi;
D.55021 = 1.0e+0 / ggPi.319;
divPi = D.55021;
}
...
}
So, we now have an assignment for divPi in the IL stream. This
throws a monkey wrench into my micro-optimization because it
shouldn't really have ignored that V_MUST_DEF (we end up removing
the assignment).
I also wouldn't want the FE to mark divPi writeable, as we would
now consider it call-clobbered. Is this analysis correct? Will
other FEs need to do things like this? If so, then I'll just get
rid of this transformation. We are already ignoring read-only
symbols at call sites and there are new analysis for trimming
clobbering lists even further down the pipe.
Thanks. Diego.