Это эквивалентно foo(int numFruits, long quadSize)
.Ну, может быть int quadSize
, если ваш y86 ABI имеет 64-битный int
.Все обычные x86-64 ABI имеют 32-битный int
, а Windows x64 даже имеет 32-битный long
.
Вы также пометили этот x86.x86-64 может переместить 8
в 64-битный регистр с помощью 5-байтовой инструкции, например mov $8, %r13d
: 1 байт кода операции + imm32.(На самом деле 6 байтов, включая префикс REX).Вам нужно mov r64, imm64
только для констант, которые не помещаются в 32-битные значения с нулевым или расширенным знаком.Запись 32-битного регистра начинается с нуля до полного 64-битного регистра.Вы можете даже настроить постоянную настройку игры в гольф за счет скорости.Как push $imm8
/ pop %r13
в 3 байта (фактически 4 для префикса REX).При оптимизации размера кода вы хотите избежать r8..r15.https://codegolf.stackexchange.com/questions/132981/tips-for-golfing-in-x86-x64-machine-code/132985#132985.
Я понятия не имею, имеет ли y86 эффективные кодировки машинного кода для малых констант.
Не существует каких-либо физических процессоров y86, о которых я знаю.Есть эмуляторы, но я не уверен, есть ли вообще какие-либо виртуальные конструкции (например, verilog) аппаратного обеспечения y86, которые можно было бы смоделировать в симуляторе с точностью до цикла.
Так что любой разговор о "сохранении циклов"натяжка для y86. Реальные x86-64 процессоры являются конвейерными суперскалярными с неупорядоченным выполнением и часто не являются узкими местами при выборке кода.Особенно в современных процессорах с кешем UOP.В зависимости от цикла, дополнительные инструкции mov-немедленного из критического пути могут не замедлять работу. https://agner.org/optimize/, и видеть ссылки на производительность в x86 wiki .
Но да, вам, как правило, следует поднимать постоянную настройку из циклов.
Если ваш "цикл" является рекурсивным, вы не можете легко оптимизировать его в обычный цикл без дорогостоящего call
/ret
, вы, безусловно, можете сделать функцию-обертку для публичного использования, и она может превратиться в частную функцию, которая эффективно использует пользовательское соглашение о вызовах (которое предполагает, что %r13 = 8
).
.globl foo
foo:
irmovq $8, %r13
# .p2align 4 # optional 16-byte alignment for the recursion entry point
# fall through
.Lprivate_foo:
# only reachable with r13=8
# blah blah using r13=8
call .Lprivate_foo
# blah blah still assuming r13=8
call .Lprivate_foo
# more stuff
ret # the final return
Ничегоеще можно позвонить private_foo
;это локальный ярлык (.Lxxx
), видимый только из этого источника.Таким образом, тело .Lprivate_foo
может предполагать, что R13 = 8.
Если r13
является регистром, сохраняющим вызов, в вашем соглашении о вызовах y86 (как это происходит в x86-64 System V), тогда либо выберитерегистр с отложенным вызовом, такой как r11, или с функцией общедоступной оболочки call private_foo
, чтобы он мог восстановить r13
вызывающего перед возвратом.Использование регистра, который функциям обычно разрешено блокировать, приводит к тому, что это почти нулевые дополнительные издержки вместо введения дополнительного уровня call / ret.
Но это работает, только если вы не вызываете какие-либо другие неизвестные функции изнутриваша рекурсивная функция, в противном случае вы должны предположить, что они перекрыли R11.
Оптимизация рекурсии в цикле имеет большое преимущество, и компиляторы делают это всякий раз, когда это возможно.(В двойной рекурсивной функции, такой как обход дерева, они часто превращают 2-й рекурсивный вызов в ветвь цикла, но все же фактически выполняют рекурсию для нехвостовой рекурсии.)
Если выпросто используя 8
в качестве коэффициента масштабирования, я беспокоюсь, что вы используете умножение.Гораздо эффективнее использовать сдвиг на 3. Или (поскольку вы пометили этот x86, а также y86), возможно, используйте режим адресации с масштабированным индексом.Но если это для увеличения указателя, то реальный x86 будет использовать немедленное добавление.Как и add $8, %rsi
, используется кодировка add r/m64, imm8
, в которой для константы используется только 1 байт (знак расширен до 64 бит).
Но эквивалент x86 будет векторной константой SIMDили константы с плавающей запятой, потому что их нет.И в этом случае да, вы хотите установить константу в регистре вне цикла.