Я получил приведенный ниже список сборки в результате JIT-компиляции для моей java-программы.
mov 0x14(%rsp),%r10d
inc %r10d
mov 0x1c(%rsp),%r8d
inc %r8d
test %eax,(%r11) ; <--- this instruction
mov (%rsp),%r9
mov 0x40(%rsp),%r14d
mov 0x18(%rsp),%r11d
mov %ebp,%r13d
mov 0x8(%rsp),%rbx
mov 0x20(%rsp),%rbp
mov 0x10(%rsp),%ecx
mov 0x28(%rsp),%rax
movzbl 0x18(%r9),%edi
movslq %r8d,%rsi
cmp 0x30(%rsp),%rsi
jge 0x00007fd3d27c4f17
Насколько я понимаю, инструкция test здесь бесполезна, потому что основная идея теста -
The flags SF, ZF, PF are modified while the result of the AND is discarded.
и здесь мы не используем эти флаги результатов.
Это ошибка JIT или я что-то упускаю? Если да, то где лучше всего сообщить об этом? Спасибо!
FWIW неявно проверяет, содержит ли r11 действительный указатель, и вызывает исключение, если нет. Это намеренно? Не знаю, вне контекста.
Теперь, когда мы знаем ответ, если бы у JVM было больше времени для анализа окружающего кода, она могла бы использовать mov (%r11), %r9d, потому что r9 вот-вот будет написан другой инструкцией. MOV - это такое же количество байтов кода, но это чистая загрузка без мупа ALU. Это небольшая оптимизация, потому что давление порта ALU здесь почти наверняка не проблема, а современные процессоры x86 сохраняют нагрузку микросредой в один uop с инструкцией ALU на большей части конвейера, поэтому это не снижает пропускную способность интерфейса. .
Но требуется дополнительная запись в планировщике до тех пор, пока загрузка не будет готова, чтобы можно было выполнить ALU uop, и 2 записи ROB на Sandybridge и более ранних версиях Intel. IvyBridge и более поздние версии имеют ROB с объединенным доменом, но SnB имеет буфер ReOrder с несвязанным доменом. Источник: Упоминается в строке таблицы 3 в этом документе: публикации.vpw.me/publications/2015_uop_flow_simulation.pd f. См. Понимание влияния lfence на цикл с двумя длинными цепочками зависимостей для увеличения длины
@PeterCordes Это довольно нелогично и странно. Я всегда думал, что микроплавкие мопы будут оставаться слитыми до тех пор, пока не будут отправлены в порт выполнения. Я дважды проверяю руководство Агнера Фога, они также говорят, что муп будет соединен с RS. Они даже говорят на странице 92, что сохранение записи ROB является преимуществом микрослияния, начиная с PM, что вполне разумно. Вы уверены, что ROB является неиспользуемым доменом до IvyBridge?
@liliscent: Зря я сказал SnB и раньше. Я думаю, что в статье говорилось только о SnB, а не о IvB, и не упоминалось pre-SnB. (И не предоставил никакой информации о том, как именно они пришли к такому выводу, поэтому я не доверяю ему на 100%, но в остальном это похоже на хорошую статью.) Да, я думаю, что у семейства P6 есть ROB с объединенным доменом. SnB упростил внутренний формат uop (отсюда снятие ламинирования режимов индексированного адреса), поэтому эксперименты с несвязанным ROB правдоподобны, а затем возврат к ROB с объединенным доменом для IvB после выяснения того, как или просто обнаружив, что это не стоит того компромисс.
@liliscent: Как показал мой ответ на Понимание влияния lfence на цикл с двумя длинными цепочками зависимостей для увеличения длины (сноска 2) с экспериментальными результатами из SKL и Conroe / Merom, семейство P6 имеет RS слитного домена, но Skylake имеет RS с незадействованным доменом, где каждый отправляемый uop принимает отдельный Вход. Хорошо заметный гайд по uarch Агнера Фога ошибается в том, что RS является слитным доменом, когда он описывает это в разделе HSW / BDW. Думаю, я пропустил это и всегда предполагал, что RS - это неиспользуемый домен перед тестированием.
@PeterCordes Я думаю, что вы правы, особенно после прочтения связанного ответа. Должно быть какое-то изменение в SnB. Описание микрослияния в Anger Fog слишком расплывчато для более поздних, они, кажется, просто заявляют, что SnB - SKL точно такие же, как PM, без особых подробностей.
@liliscent: Я думаю, что у Агнера не было столько времени, чтобы посвятить тестирование материалов для HSW / SKL, как раньше. Он проделал большую работу по выяснению uop-cache Sandybridge, но некоторые вещи HSW / SKL, к сожалению, просто неправильно скопированы. И да, он может пропустить изменения, которых никто не ожидал! например Он подсчитал uops, проверяя, как они упаковываются в uop-cache, а не с помощью счетчиков производительности для слитого / нераспределенного домена, поэтому он полностью пропустил ламинирование в семействе SnB и не смог воспроизвести мои результаты на Микро-слияние и режимы адресации




Это должен быть локальный опрос рукопожатия.
Посмотри откуда читается %r11. Если он читается с какого-то смещения на %r15 (локальное хранилище потока), то это парень. См. Пример здесь:
0.31% ↗ ...70: movzbl 0x94(%r9),%r10d
0.19% │ ...78: mov 0x108(%r15),%r11 ; read the thread-local page addr
25.62% │ ...7f: add $0x1,%rbp
35.10% │ ...83: test %eax,(%r11) ; thread-local handshake poll
34.91% │ ...86: test %r10d,%r10d
╰ ...89: je ...70
Это не бесполезно, это вызовет SEGV, как только защитная страница будет помечена как нечитаемая, и это передаст управление обработчику SEGV JVM. Это часть механизма JVM для безопасной точки Java-потоков, например для GC.
UPD: Надеюсь, поподробнее здесь.
Эта инструкция действительно кажется бесполезной.