On Thursday, 28 February 2013 at 14:31:08 UTC, Steven Schveighoffer wrote:
On Thu, 28 Feb 2013 06:23:45 -0500, deadalnix

I have to say I agree with deadalnix.

you have essentially in lexer.c:

outer:
while(1)
{
   switch(r.front)
   {
      case 0:
        break outer;
      ...
   }
}

whereas a range where empty is defined as r.front == 0:

while(!r.empty)  // inlined to r.front != 0
{
   switch(r.front) // why would another load occur here?
   {
      // no need to check for 0, already done
      ...
   }
}

If this doesn't translate to the same code, I don't know why not[SNIP].

-Steve

The difference is that by doing "!r.empty" first, you are actually executing "r.front == 0" each and every time, before doing the rest of the checks proper.

Doing it the other way around however, the only time you actually check the sentinel value is once you've reached the actual sentinel value, or you've run out of values "of interest": EG not actually on every element.

You are basically re-ordering the tests to speed up the usual case.

//----

This is kind of the same logic as in C++'s "operator=": It is recommended to always check for self assignment. However, most quality implementations will *not* execute this check, instead being extra careful about instruction ordering.

While the rare self-assignement case becomes more expensive, the common assignment becomes cheaper. That's where the win is.

Reply via email to