Оптимизация сборки MIPS

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

funct: add  $v0, $zero, 0
       add  $t0, $zero, 0
Loop:  slt  $t1, $t0, $a0
       beq  $t1, $zero, Exit
       add  $v0, $v0, $t0
       addi $t0, $t0, 1
       j    Loop
Exit:  jr   $ra

Я знаю, что это эквивалентно простому циклу while. Однако я не понимаю, как преобразовать это в цикл do-while, чтобы сократить выполнение программы.


person zzzOp    schedule 29.04.2016    source источник


Ответы (2)


Это похоже на домашнее задание, поэтому я попытаюсь указать вам правильное направление, не кормя вас ответом с ложки.

Вместо того, чтобы задавать условный переход вопросом «мы закончили», подумайте, что вы могли бы сделать, если бы условное выражение было перевернуто на «должны ли мы продолжать».

person Community    schedule 29.04.2016

Если цикл может потребоваться запустить 0 раз, поместите условную ветвь вне цикла, чтобы проверить этот случай.

Вы также можете поместить некоторые инструкции для настройки (или фактически выполнить некоторые из них) для первой итерации вне цикла. Еще одна хитрость заключается в том, чтобы прыгнуть в середину цикла вместо того, чтобы попасть в первую инструкцию. Я не уверен, есть ли название для этой техники. (Википедия определяет конвейерную обработку программного обеспечения как нечто более сложное, что увеличивает размер кода, а не просто чередует последовательность операций. инструкции внутри цикла, настраивая код снаружи, чтобы он соответствовал.)

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


Если вы действительно хотите уменьшить количество выполняемых инструкций, вы можете просто посчитать и устранить цикл. $t0 = 0 .. $a-1, и вы добавляете это к $v0 на каждой итерации. Таким образом, цикл - это просто сумма (0.. $a-1). Существует формула в закрытой форме для суммы (0..n): n * (n+1) / 2.

Обратите внимание, что вы можете пропустить итерацию $t0 = 0 при преобразовании вашего цикла (если вы решите ее сохранить), поскольку 0 является аддитивной идентичностью.

person Peter Cordes    schedule 29.04.2016
comment
Мой ответ на тему Почему циклы всегда компилируются в стиль do...while (прыжок с хвоста)? более подробно описывает ту же концепцию. . Также попробуйте обратиться к компилятору. (На реальном MIPS со слотами задержки ветвления вам нужно будет заполнить слоты задержки. Это может быть сложно, когда петля действительно крошечная, но OTOH не так много разных возможностей для рассмотрения... Пока вы не начнете рассматривать отслаивание некоторые из первой и/или последней итерации, чтобы вы могли вращать цикл, чтобы условие перехода было внизу, даже если это не самая естественная форма для логики цикла.) - person Peter Cordes; 04.01.2021