Gcc优化问题:无符号mod与if分支

时间:2018-12-13 18:26:48

标签: gcc compiler-optimization modulo

我有一个经常在实时微控制器程序(ARM Cortex-M)中调用的函数(每秒至少40,000次),并且它基本上将计数器保留在缓冲区长度之内,而不是二的幂。

所以我可以选择以下两个选项之一:

extern uint32_t x;

void increment_MOD(void)
{
    x = (x + 1) % 100;
}

void increment_IF(void)
{
    uint32_t tmp = x + 1;
    if (tmp >= 100)
        tmp = 0;
    x = tmp;
}

除非我错了,否则这两个函数在功能上是等效的,所以:

GCC将其中之一优化为更快的形式(无论哪种形式)是否不正确?

“ if”版本看起来仍然会更快,除非管道/分支错误预测是一个问题(但是ARM Cortex-M cpus没有大型管道AFAIK)。

// it's nice to see that % is implemented
// using multiplication and shifts

increment_MOD:
    ldr r1, .L2
    ldr r3, .L2+4
    ldr r2, [r1]
    add r2, r2, #1
    umull r0, r3, r2, r3
    lsr r3, r3, #5
    add r3, r3, r3, lsl #2
    add r3, r3, r3, lsl #2
    sub r3, r2, r3, lsl #2
    str r3, [r1]
    bx lr
.L2:
   .word x
   .word 1374389535

// this is the IF variant

increment_IF:
    ldr r2, .L6
    ldr r3, [r2]
    add r3, r3, #1
    cmp r3, #99
    movhi r3, #0
    str r3, [r2]
    bx lr
.L6:
    .word x

1 个答案:

答案 0 :(得分:2)

优化无效,因为在输入函数时,x永远不会大于99,因此编译器无法从代码中得知。如果使用x=100输入该函数,则使用if分支increment_IF在函数x=0的出口处,而对于mod变量increment_MOD,您将得到{{1} }。