Оптимизация компилятора, заставляющая программу работать медленнее

У меня есть следующий фрагмент кода, который я написал в C. Его довольно просто, поскольку он просто правильный бит-сдвиги x для каждого цикла for.

int main() {
   int x = 1;
   for (int i = 0; i > -2; i++) {
      x >> 2;
   }
}

Теперь странная вещь, которая происходит, заключается в том, что когда я просто компилирую ее без каких-либо оптимизаций или оптимизации первого уровня (-O), она работает просто отлично (я синхронизирую исполняемый файл и его 1.4s с -O и 5.4s без каких-либо оптимизаций.

Теперь, когда я добавляю переключатель -O2 или -O3 для компиляции и времени в результате исполняемого файла, он не останавливается (я тестировал до 60s).

Любые идеи о том, что может быть причиной этого?

Ответ 1

Оптимизированный цикл создает бесконечный цикл, который является результатом вас в зависимости от переполнения целых чисел . Поднятое целочисленное переполнение - это поведение undefined в C и от этого не должно зависеть. Он может не только запутать разработчиков, но также может быть оптимизирован компилятором.

Сборка (без оптимизации): gcc -std=c99 -S -O0 main.c

_main:
LFB2:
    pushq   %rbp
LCFI0:
    movq    %rsp, %rbp
LCFI1:
    movl    $1, -4(%rbp)
    movl    $0, -8(%rbp)
    jmp L2
L3:
    incl    -8(%rbp)
L2:
    cmpl    $-2, -8(%rbp)
    jg  L3
    movl    $0, %eax
    leave
    ret


Сборка (оптимизированный уровень 3): gcc -std = c99 -S -O3 main.c

_main:
LFB2:
    pushq   %rbp
LCFI0:
    movq    %rsp, %rbp
LCFI1:
L2:
    jmp L2  #<- infinite loop

Ответ 2

Вы получите окончательный ответ, посмотрев на созданный двоичный файл (используя objdump или что-то еще).

Но, как отмечали другие, это, вероятно, потому, что вы полагаетесь на поведение undefined. Одно из возможных объяснений заключается в том, что компилятор может предположить, что i никогда не будет меньше -2, и поэтому полностью устранит условие и преобразует его в бесконечный цикл.

Кроме того, ваш код не имеет видимых побочных эффектов, поэтому компилятор также может оптимизировать всю программу до нуля, если ей нравится.