Что особенного в gcc в цикле, который повторяется 999 раз? - PullRequest
0 голосов
/ 02 марта 2019

Фон

Использование gcc 7.2 Я обнаружил, что вывод компилятора изменяется, когда цикл повторяется 999 раз.

В частности, эта программа ( ссылка на проводник компилятора с использованием gcc 7.2 ):

int f()
{
    int i=0x7fffffff-998;
    while (i+1>i)
        i++;
    return i;
}

компилируется (используя -O3 -fwrapv) в:

f():
  mov eax, 2147483647
  ret

, но если я изменяю 998 на 999, вместо этого он компилируется в:

f():
  xor eax, eax
  movdqa xmm0, XMMWORD PTR .LC0[rip]
  movdqa xmm2, XMMWORD PTR .LC1[rip]
  jmp .L2
.L3:
  movdqa xmm0, xmm1
.L2:
  movdqa xmm1, xmm0
  add eax, 1
  cmp eax, 250
  paddd xmm1, xmm2
  jne .L3
  pshufd xmm0, xmm0, 255
  movd eax, xmm0
  ret
.LC0:
  .long 2147482648
  .long 2147482649
  .long 2147482650
  .long 2147482651
.LC1:
  .long 4
  .long 4
  .long 4
  .long 4

Вопрос

Почему меняется выход, и есть ли переключатель для управления порогом изменения поведения?

Примечание

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

1 Ответ

0 голосов
/ 02 марта 2019

Это в основном результат произвольной константы в источниках GCC.

GCC имеет внутренний параметр, который контролирует, сколько раз цикл предварительно развернут во время оптимизации:

/* The maximum number of iterations of a loop the brute force algorithm
   for analysis of # of iterations of the loop tries to evaluate.  */
DEFPARAM(PARAM_MAX_ITERATIONS_TO_TRACK,
        "max-iterations-to-track",
        "Bound on the number of iterations the brute force #"
        " of iterations analysis algorithm evaluates.",
        1000, 0, 0)

Это используется для анализа циклов, если GCC не имеет специальной логики для выполнения какого-либо алгебраического преобразования для получения счетчика итераций.

Если вы измените этот параметр на другое значение, переключение с результата на другое будетслучиться с другой магической ценностью.С вашим исходным значением 998 я получаю это:

$ gcc -O3 -fwrapv -S -o- --param max-iterations-to-track=997 t.c | grep jl
    jl  .L3
$ gcc -O3 -fwrapv -S -o- --param max-iterations-to-track=998 t.c | grep jl
    jl  .L3
$ gcc -O3 -fwrapv -S -o- --param max-iterations-to-track=999 t.c | grep jl
$ gcc -O3 -fwrapv -S -o- --param max-iterations-to-track=1000 t.c | grep jl

Эти параметры являются внутренней деталью реализации и могут изменить значение в любое время или полностью исчезнуть.

(Версия компилятора Iused, основанный на GCC 6.3, не использует эти векторные инструкции для неоптимизированного случая, но представляет собой последовательность с условным скачком jl, и точка отсечения немного отличается, предположительно из-за других оптимизаций.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...