diamond rax - регистр о 64 битах, только не MMX, а обычный. Введен в рамках архитектуры AMD Athlon64. Вернее их 15 как расширение обычных GPR 32-битных регистров: RAX, RBX, RCX, RDX, RBP, RSI, RDI, RSP, R8-R15.
if (a == 1 && b == 3 && c == 4) если переменные размером байт, можно заменить на if( (a << 16 | b<<8 | c) == 0x010304 ) здесь достаточно одного регистра. хотя именно с такими цифрами можно и как-нибудь чисто арифметическую проверку делать.
Полезно было бы следующее: Если бы инструкции setXX обнуляли старшие 24 бита регистра, или, ещё лучше, в случае выполнения условия, устанавливали регистр в -1. Инструкция subi (обратное вычитание) Инструкция subs (беззнаковое вычитание с сатурацией - если результат получается меньше 0, вернуть 0) Инструкция abs (абсолютное значение) Инструкции sqrt (Целочисленный корень) и pow2 (квадрат) Инструкция gcd (НОД) Инструкция log10 (десятиный логарифм) Инструкции uinc, usub (принимает указатель на символ в UTF8 и увеличивает указатель так, чтобы он указывал на следующий символ) Инструкции MMX: mmsel mmA,mmB (Search & Expand Left - найти самый правый байт (слово, двойное слово) mmA, равный соответствующему байту mmB, и распространить его на все байты левее, mmser (Search & Expand Right), mmscl (Search & Copy Left - то же самое, но байтам левее найденного присваивается значение соответствующих байтов mmB), mmscr (Search & Copy Right)
S_T_A_S_ То есть так: mov edx, [a] shl edx, 16 mov ebx, or edx, [c] lea ebx, [edx + ebx * 8] cmp ebx, 0x10304h Или по мнению компилятора: mov ecx,dword ptr [a] shl ecx,10h mov edx,dword ptr shl edx,8 or ecx,edx or ecx,dword ptr [c] cmp ecx,10304h И того 7 комманд, вместо 4, плюс требуется воображение компилятора и свободные регистры. Я к чему этот тред начал - в ближайшем будущем ожидается качественное развитие процессорных архитектур, и одним таким улучшеним будет комбинирование привычных нам CISC/RISC с FPGA (перепрограммируемых логических матриц), которые позволят серьезно поднять вычислительные возможности компьютеров. Поэтому потребуются специалисты умеющие свободно проектировать как программный, так и программно-аппаратный код. Воспринимать критически конечно эту идею можно, но подавлять свою фантазию консерватизмом не стоит.
Я не зря уточнил, что размер - байт: Код (Text): movzx eax, byte [a] shl eax, 16 mov ah, [b] mov al, [c] cmp eax, 0x010304 MS C++ Compiler 13.10.3077 сделал так: Код (Text): xor eax, eax mov ah, [a] mov al, [b] movzx ecx, [c] shl eax, 8 or eax, ecx cmp eax, 10304
Не заметил, но твой код череват пенальти, поэтому будет не быстрее, а скорее даже медленее того что с cmpm. И компилятор тоже не догался до него: Код (Text): <font color="green] char a = rand (); char b = a + rand () & 3; char c = a - b; if( (a << 16 | b<<8 | c) == 0x010304 ) movsx edx,byte ptr [a] shl edx,10h movsx eax,byte ptr [b] shl eax,8 or edx,eax movsx ecx,byte ptr [c] or edx,ecx cmp edx,10304h </font><!--color--> Плюс опять же - один регистр испорчен. -------------------------------------------------- Еще команды - выбор экстремумов: imax r*, r*/m* (* = 8, 16, 32) imin r*, r*/m* (* = 8, 16, 32)
твой код с ошибкой - movzx нужно использовать. хотя на данных числах ошибка не проявится. по поводу пенальти в моём коде, он понятно, только вот cmpm тоже обладает зависимостью по данным, поэтому для случая когда важна скорость нужно несколько регистров использовать.
S_T_A_S_ С зависимостью думаю можно справиться аппаратно - например если теневых регистров для eflags будет штук 3, то инструкции jxx будут срабатывать лишь при полном совпадении флагов во всех этих регистрах. Таким образом - 3 cmpm будут выполняться за три тика и ( с последней инструкцией cmpm будет следовать маскировка регистров), а jхх за 1-2 (branch). Код (Text): Для инструкций: cmpm [a], 1 cmpm [b], 3 cmpm [c], 4 Алгоритм (три тика): eflgs [0] = cmp [a], 1 ;; Load, Alu eflgs [1] = cmp [b], 3 ;; Load, Alu eflgs [2] = cmp [c], 4 ;; Load, Alu eflgs = eflgs [0] & eflgs [1] & eflgs [2] ;; Alu ;; Инструкция cmp также устанавливает все теневые регистры в 0FFFFFFFFh.
alpet улучшения: 1) все все флаги должны генериться в регистр для избавления от зависимостей. А то раз уж есть теневые регистры, для избежания пенальти и на них транзисторв потрачены - лучше их добавить к адресуемым регистрам. А то многие приведенные здесь инструкции относятся к убиранию разного рода пенальти, которые вобщем-то не нужны - убирать надо сами пенальти. 2) стековый фпу - зло. фпу должен прямо адресоваться, как xmm 3) теневые регистры GPR (ROB) перевести в просто адресуемые и разрешение зависимостей перенести на компилятор, хотя тут спорно, потому что ревизии ядер сейчас выходят часто, а у них разные тайминги для разрешения зависимостей и компиляторы могут не поспеть. 4) простая однотипная кодировка, а не как с ebp, esp Такие архитектуры есть - вот на них и надо переходить и дорабатывать. Хотя все это мало реально - совместимость необходимая штука. PS: ждем PS3 на котором будет линукс =)
semen 1) На счет флагов: как сие реализовать с учетом, что с трех конвееров считываются макропы (RISC-86 MacroOps) и распределяются по исполнительным устройствам. Все пенальти связанные с зависимостями данных разрешить аппаратно не удаться - приведенный мной код лишь частный случай. Другое дело FPGA, там пространство аппаратных алгоритмов - можно самому организовывать ИУ и эксплуатировать их по максимуму. В честь этого кстати можно сразу обозначить набор 16 программируемых инструкций. Программирование их может осуществляться через MSR. 3) Если развести эти регистры на управляемые процессор будет слишком медленно выполнять обычный x86 код.
alpet 1) не понял в чем проблема - cmp r1, r2, r3 <= флаги сюда; прыгаем: jxx rx <= откуда флаги брать, ry\imm <= куда прыгаем; соответственно можно избежать зависимостей сторя флаги в разные регистры, а когда нет зависимостей - высок параллелелизм. Просто в х86 сделали уловки для разрешения ложных зависимостей - теневые регистры как ты их назвал. И архитектуры используюшие данный метод есть. 3) ну да. на это и не расчитано - это только при полном переходе на другую архитектуру с условием фиксации задержек чтобы реализовать эффективный компилятор и не менять его каждый день разводя 10 вариантов одного кода для достижения производительности на данном железе, как вобщем-то уже есть на x86 из-за разных наборов инструкций и 2х разных архитектур у AMD\Intel.
semen 1) Получается для сравнения 3 пар аргументов надо создавать свердлинную инструкцию (6 операндов), причем могущую воспринимать динамическое количество операндов. Это плохой подход. 3) Вот как раз о создании новых архитектур можно создать другой тред. В таком случае почему сразу не развивать Itanium 2, это ведь как раз EPIC архитектура - 64 GRPs и 256 регистров данных, все на поверхности.
alpet 1) Опять я ничего не понял. Где сравнивается 3 пары??? Сравниваются 2 числа в 2х регистрах, как обычно, результат вычитания не записывает никуда, как обычно, но флаги попадают не в eflags, а в произвольный GPR регистр. Если регистров 8, то 3 поля по 3 бита, если 16, то 3 поля по 4 бита - где сверхдлинная инструкция? С одним из аргументов в памяти можно для простоты не поддерживать. Любая архитегтура, где это реализовано от этого только выигрывала. 3) если остаемся в х86 - то да, делать этого ни в коем случае нельзя, согласен.
semen Блин, не воспринял правильно . Другое дело, что с выносом наружу интеграции флагов по сравнению опять же с аппаратным решением, зависимость данных будет усугубляться дополнительной коммандой и порчей регистров. Пример: cmpx [a], 1, eax cmpx , 3, ebx cmpx [c], 4, ecx and3 eax, ebx, ecx ;; вот такую еще надо будет ввести команду
alpet ну да =) но если бесполезные теперь теневые регистры флагов преобразовать в GPR то баланс восстановится =) короче не расчитывал я что остаемся в х86, ты об этом нигде явно не указал до моего поста, хотя с 16 GPR в x86_64 уже неплохо будет, но все равно вносить в x86 новые наборы команд прыжков jxx rx, ry\imm слишком тяжело для процессора (наверно), надо изначально только на них расчитывать (тоже самое с FPU).
semen 1. Они не бесполезные, иначе бы их не ввели. Просто надо понимать - основное достоинство архитектуры x86 в сегодняшних ее реализациях - быстрое выполнение массы уже существующего кода. Если ее этого лишить, она просто никому будет не нужна. 2. Касательно условных переходов - любая оптимизация касается прежде всего развития эффективности работы устройств предсказания перехода. А вот с использованием префиксов условного выполнения можно вообще было бы отказаться (но нельзя ) от Jcc инструкций: je xxxx = oneq jmp xxxx/call xxxx jc xxxx = oncr jmp xxxx/call xxxx Вобщем гибкость повыше чем у простого перехода.
alpet 1. Они полезны, для разрешения зависимостей, а когда мы увеличиваем число GPR, как в большинстве риск архитектур, и распараллеливаем програмно, они бесполезны и как правило снижается число стадий процессора, связаных с ROB. Например, в ROB`е первых пней 40 слотов - фактически неуправляемые регистры. А не лучше ли нам самим решить что хранить в этих регистрах? Регистровая память она дорогая, еще никому не мешала. Как я уже говорил, я не имел ввиду что остаемся в х86 - его можно пытаться эффективно рекомпилировать, под никс\линукс вообще проблемы несовместимости кода почти нет - все в сорсах, М$ вроде всерьез (не дай бог) собралась на свой MISL переходить. 2. Тут тоже не согласен, одно дело реализовать min\max, другое дело кондиционное выполнение - в микроопах, скорее всего, эффективная реализация все равно выльется в тоже самое, что и прыжок через инструкцию. Тут будет таже байда с неверно предсказанным псевдо-ветвлением итд, так что если и будет быстрее, то разве что из-за разгрузки кэша кода(кэшу трасс скорее пофигу), хотя в коде с большим количеством ветвлений, недостатка в показателе скорости кэша не наблюдается, так что единственный плюс - в размере кода и если остаемся в х86, усложнять проц из-за этого сомнительно. Кстати вот продолжение цикла статей про P4 на фцентре, на сей раз про trace cache если кто не читал =) http://www.fcenter.ru/online.shtml?articles/hardware/processors/13736 Хотя все из этих статей желательно самому проверять...
semen 1. Ладно можно считать это за улучшение, которое нежизнеспособно в рыночных условиях, да и изобретено достаточно давно. Замечу что рынок процессоров в большей степени зависим от софтверной индустрии, и надеятся что миллионы программ кто-то возьмется рекомпилировать ради очевидно сомнительных преимуществ (к примеру на Itanium и Power4 такого ажиотажа нет). Ктому же с опкодами ожидается еще большая неразбериха - фактически формат машинной команды при введении такого количества регистров можно считать изменившимся очень серьезно, и тогда возникает вопрос - что остается от x86? 2. В микропах все будет хорошо, особенно когда префиксы сочетаются с не переходными инструкциями. Здесь конечно с зависимостью тоже будут некоторые проблемы, только неправильно предсказанный переход будет в этом случае подменяться неправильным предвычислением. Другое дело что столь серьезного пенальти это вызывать не будет - процессору потребуется пересчитать с места ошибки только зависимый код, а не весь как это получается в следствии jump missprediction. Замечу еще что прыжок через инструкцию - две инструкции, а это явно хуже в плане эксплуатации конвейеров. И вообще нападать на эту идею считаю бессмыслицей, поскольку она уже частично реализована в архитектуре Itanium, и вполне себя оправдывает.