【问题标题】:Gcc optimization question: unsigned mod vs if branchGcc优化问题:unsigned mod vs if branch
【发布时间】:2018-12-13 18:26:47
【问题描述】:

我有一个在实时微控制器程序 (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

【问题讨论】:

  • 理论上这将是一个有效的 as-if 规则优化,但我不希望编译器实现它。
  • 请注意,您可以使用自己的GCC plugin 将自己的优化传递添加到 GCC。但这需要付出很多努力。

标签: gcc compiler-optimization modulo


【解决方案1】:

优化无效,因为编译器无法从代码中知道x 在输入函数时永远不会>99。如果函数是用x=100 输入的,那么在函数increment_IF 的出口用if 分支x=0,而对于mod 变体increment_MOD,你会得到x=1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-05
    • 2017-06-16
    • 2011-04-08
    • 1970-01-01
    • 2011-01-30
    • 1970-01-01
    相关资源
    最近更新 更多