Когато оптимизирате за процесори на Intel, винаги поставяйте инструкцията за задаване на флаг точно преди инструкцията за условно прескачане (ако е една от простите, изброени в таблицата по-долу), така че те да могат да се слеят макроси в една uop в декодерите.
Правенето на това не е значително по-лошо за по-стари процесори, които не извършват макросливане. Поставянето на настройката на флага по-рано може да съкрати наказанието за неправилно предвиждане на клона с едно за такива процесори, но изпълнението извън реда означава, че преместването на dec
няколко инструкции по-рано няма да има реална разлика. Вижте също Избягвайте спирането на конвейера, като изчислявате условно рано. За да направите наистина разлика, вие правите неща като разгръщане на цикъла и/или разклоняване на нещо, което може да се изчисли по-просто, в идеалния случай без зависимост от бавен вход, така че OoO exec може да има разклонението вече разрешено, докато работи върху по-стари итерации на тялото на цикъла. т.е. деп-веригата на брояча на цикъла може да работи преди основната работа.
Нямам бенчмаркове, но не мисля, че малкият недостатък на все по-редките процесори оправдава пропускането на предимството на пропускателната способност на предния край (декодиране и проблем) за процесори, които правят синтез. Общата пропускателна способност на uop често може да бъде тясно място.
AMD Bulldozer/Piledriver/Steamroller може да слее test/cmp
с който и да е jcc
, но само test/cmp
, не и други ALU инструкции. Така че определено се сравнява с клонове. Все още е ценно за процесорите на Intel да поставят други неща с разклонения, ако могат да се свържат с макро предпазител на sandybridge-family.
От ръководството за микроарки на Agner Fog, таблица 9.2 (за Sandybridge / Ivybridge):
First | can pair with these | cannot pair with
instruction | (and the inverse) |
---------------------------------------------
cmp |jz, jc, jb, ja, jl, jg| js, jp, jo
add, sub |jz, jc, jb, ja, jl, jg| js, jp, jo
adc, sbb |none |
inc, dec |jz, jl, jg | jc, jb, ja, js, jp, jo
test | all |
and | all |
or, xor, not, neg | none |
shift, rotate | none |
Table 9.2. Instruction fusion
Така че основно inc/dec
може да се слее макрос с jcc
, стига условието да зависи само от битове, които са модифицирани от inc/dec
.
(В противен случай те не се обединяват с макроси и получавате вмъкнат допълнителен uop за обединяване на флаговете (като когато четете eax
след запис на al
). Или при по-стари процесори частичните флагове спират.)
Core2 / Nehalem бяха по-ограничени по отношение на възможностите за макросливане (само за CMP/TEST с по-ограничени JCC комбинации), а Core2 изобщо не можеше да слее макроси в 64-битов режим.
Прочетете и ръководствата за оптимизиране на asm и C на Agner Fog, ако още не сте го направили. Те са пълни с основни знания.
person
Peter Cordes
schedule
03.08.2015
dec
не се препоръчва, защото причинява спиране на актуализирането на частични флагове. - person Jester   schedule 02.08.2015dec
иadd
? В такъв случай можете ли да не използватеjcxz
? (Не можете да направите условен скок, който не зависи от инструкцията, която създава условието). - person davmac   schedule 02.08.2015lea 4(%esi),%esi
за добавяне и това не засяга флаговете, така че можете да вмъкнетеsubl $1, %ecx
по-нагоре. Както казва @davmac, не можете да се отървете от зависимостта, освен ако не използвате инструкциятаloop
, която отново не се препоръчва. - person Jester   schedule 02.08.2015jcxz
, освен ако това не ви позволява да избегнете инструкцияtest
илиcmp
. При процесорите на Intel това е инструкция 2-uop. (По-малко голяма работа, когато кодът е в uop кеша, в противен случай може да забави декодирането, защото може да се обработва само от комплексния декодер.) - person Peter Cordes   schedule 03.08.2015dec
е добре, когато макро-слива със следния клон (на процесори на Intel.) Процесорите на AMD също така избягват задръствания с частични флагове, като третират отделни битове от флаговете като независими. (Въпреки това не съм сравнявал AMD или корпуса без сливане на макроси на Intel.) - person Peter Cordes   schedule 03.08.2015