Почему компилятор поместил инструкцию после инструкции «j» MIPS, которая возвращается из функции? - PullRequest
2 голосов
/ 02 декабря 2019

Я смотрю на вывод некоторых компиляторов для платформы MIPS и пытаюсь понять, как функция возвращает и что допустимо.

Вот простой пример:

int two_x_squared(int x)
{
    return 2*x*x;
}

Если я скомпилируйте его с помощью Compiler Explorer Понятно

two_x_squared(int):
        sll     $2,$4,1
        mult    $2,$4
        mflo    $2
        j       $31
        nop

ОК, ничего страшного, я думаю, j $31 переходит на обратный адрес, и nop может быть чем-тотребуется для защиты от спекулятивного выполнения в конвейере.

Но затем я компилирую с XC32 в -O2 и получаю

two_x_squared:
    mul $4,$4,$4
    j   $31
    sll $2,$4,1

Итак ... строка после j $31 получаетвыполнено после прыжка?!

1 Ответ

6 голосов
/ 02 декабря 2019

Это называется интервал задержки ветвления . Да, ветвь фактически выполняет одну инструкцию позже, чем вы ожидаете, и компилятор должен заполнить слот задержки чем-то полезным - перемещая что-то логически выполненное до перехода в этот слот, или перемещая что-то, что произойдет после веткив этот слот.

Это было введено в исходную архитектуру MIPS (а также HP PA RISC и др.), чтобы помочь с конвейерными процессорами, поскольку им приходится сливать и заполнять конвейер на занятых ветвях, что приводит к потере инструкцийциклов.

Эта функция была удалена в более поздних процессорах MIPS, а также в следующих аппаратных средствах RISC V с открытым исходным кодом. Более современное оборудование использует другие подходы для уменьшения потерь времени, связанных с повторным заполнением конвейера, включая прогнозирование ветвлений, некоторые нестандартные исполнения, предположение, выполнение ветвей ранее в конвейере.

...