On 5/10/2016 5:24 AM, Andrew Haley wrote:
On 09/05/16 22:40, Tom Udale wrote:
My confusion is whether or not the memory cobberer prevents movement of
statements in addition to flushing any values that may be in registers
before the compiler_barrier() line. i.e. it is unclear if there is any
control over what statements the memory being flushed is attached to (if
this makes any sense).
Memory barriers only prevent code which accesses memory from being
moved.
It's not going to be easy to do what you're asking for in the
presence of optimization. GCC orders instruction generation by
dependency. I'd simply put all the code you want to time into a
separate function in a separate compilation unit and do this:
start = starttime(); foo(); end = endtime();
Alteratively, it might be possible to define asm inputs and outputs
so that your asm barriers depend on the statements you're trying
to measure.
I may have stumbled onto an idiom for this and I was wondering if there
were any obvious stumbling blocks.
I speculated that doing something like this:
extern int volatile alwaysTrue;
void foo()
{
int time;
int ct;
ct=CNT;
if(alwaysTrue)
{
// do a bunch of stuff I want timed.
}
time=CNT-ct;
}
might disable the movement of code that was breaking my timings. It
seems to indeed.
My next thought was how to get the same effect without the overhead of
the if();
This appears to work:
void foo()
{
int time;
int ct;
ct=CNT;
__asm__ volatile goto(""::::begin,end);
begin:
// do a bunch of stuff I want timed.
end:
time=CNT-ct;
}
The idea being that the compiler does not know if the asm code will jump
to "begin" or "end" and therefore cannot move things around those labels.
Does this look like a fool-proof approach or am I just getting lucky?
My main fear is that the optimizer will look at the empty assembly ""
block and say "wait a minute, nothing is happening in there, how can it
possibly jump"?
All the best,
Tom