Вопрос оптимизации Gcc: неподписанный мод против ветки if - PullRequest
0 голосов
/ 13 декабря 2018

У меня есть функция, которая очень часто вызывается в программе микроконтроллера в реальном времени (ARM Cortex-M) (по крайней мере, 40000 раз в секунду), и она в основном держит счетчик внутри длины буфера, который не являетсястепень двух.

Таким образом, у меня может быть один из этих двух вариантов:

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 нет больших конвейеров 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 голосов
/ 15 декабря 2018

Оптимизация недопустима, так как компилятор не может узнать из кода, учитывая, что x никогда не> 99 при входе в функцию.Если функция введена с помощью x=100, то при выходе из функции increment_IF с веткой if x=0, а для варианта мода increment_MOD вы получите x=1.

...