Search code examples
cperformanceavr-gcc

avr-gcc: loop with >= faster than > check


There is something I don't understand with my code. I'm working with avr-gcc and optimizing my code for speed. I've read about loops, counting down and post/pre (de)crements, comparison with 0 and discovered something odd.

This code runs in 47s:

UInt8 ret, i;
i = UJ_THREAD_QUANTUM;
do {
    ret = ujThreadPrvInstr(h, t);
    if (ret == UJ_ERR_RETRY_LATER) {
        // do not bother with the rest of time quantum if we're already stuck
        ret = UJ_ERR_NONE;      
        break;
    }
    died = (t->pc == UJ_PC_DONE);
    if (died) {
        break;
    }
    if (ret != UJ_ERR_NONE) {
        break;
    }
} while(--i);

This code in 43s:

for (i = UJ_THREAD_QUANTUM; i >= 0; --i) {
    ret = ujThreadPrvInstr(h, t);
    if (ret == UJ_ERR_RETRY_LATER) {
        // do not bother with the rest of time quantum if we're already stuck
        ret = UJ_ERR_NONE;
        break;
    }
    died = (t->pc == UJ_PC_DONE);
    if (died) {
        break;
    }
    if (ret != UJ_ERR_NONE) {
        break;
    }
}

This code in 47s again:

for (i = UJ_THREAD_QUANTUM+1; i > 0; --i) {
    ret = ujThreadPrvInstr(h, t);
    if (ret == UJ_ERR_RETRY_LATER) {
        // do not bother with the rest of time quantum if we're already stuck
        ret = UJ_ERR_NONE;      
        break;
    }
    died = (t->pc == UJ_PC_DONE);
    if (died) {
        break;
    }
    if (ret != UJ_ERR_NONE) {
        break;
    }
}

Thinking that I perhaps misunderstood some internal workings, I varied the value of UJ_THREAD_QUANTUM (which is 10 by default) and post/predecrement counters but eventually discovered that it appears that whether I use >= 0 or > 0 is the deciding factor.

Can anybody explain why this is?


Solution

  • UInt8 ret, i;
    

    means i >= 0 is always true. But i > 0 has to be evaluated.