Как стать автором
Обновить

Комментарии 33

А почему в статье Intel для ассемблера используется синтаксис AT&T? :)
Наверное, потому что gcc по умолчанию использует в асм листингах синтаксис AT&T
Не совсем так. Правильнее сказать, что компилятор GNU транслирует С/С++ код в код asm для GNU AS (as из пакета GNU binutils), который (как, собственно, и все UNIX-ассемблеры) по историческим причинам и устоявшейся традиции используют AT&T синтаксис.
gcc по умолчанию использует в асм листингах синтаксис AT&T

Не по умолчанию же, а всегда. Инструкции текстом в исходном коде записаны.
Нет, можно выбирать между AT&T и Intel. Ключевое слово ".intel_syntax". Так же, можно попросить генерировать ассемблерный выхлоп в нужном варианте. Но лично мне AT&T нравится больше.
Подтверждаю. Достаточно подать GCC "-masm=intel". В целом дело вкуса. Когда работаешь с «X86 Software Developers Manual» проще понимать Intel asm. Для остальной работы мне тоже больше по вкусу AT&T.
Согласен про мануал. Иногда обратный порядок параметров рвет мозг и ты откровенно не понимаешь почему eax нельзя записать в константу 1 :)
Особенно весело становится, когда инструкции имеют три операнда, а сама операция некоммутативна, и приходится мучительно пытаться удержать в голове, каков их порядок: src1, src2, dst или dst, src1, src2; а может dst, src2, src1?

Ах, да. В мнемониках команд в нотации Intel есть один ньюанс — для некоторых векторных команд порядок операндов соответствует AT&T, а для некоторых нет.
-masm=intel

Клёво. Спасибо, не знал.
Можно я ещё задам вопрос не совсем по теме поста, но о gcc (задавал уже здесь: toster.ru/q/139313 ): какими сторонними источниками информации пользуются люди, чтобы научиться менять backend gcc? gccint и код самого gcc не в счёт.
А кроме сорцов и GCC Internals нет более подробных источников информации. Только если отдельные статьи и презентации, поясняющие некоторые моменты.

Новые инструкции относительно просто добавить в machine description по аналогии с другими, а вот для автогенерации уже придётся хорошо изучить сорцы.
нет более подробных источников информации

Да, у меня сложилось подобное впечатление. Мне эта ситуация кажется просто невероятной: gcc — это ж центральный инструмент GNU, визитная карточка проекта, практически.
Ну есть еще такой неявный источник как комментарии maintainer-ов при submit-е патча. По сути лишь они детально разбираются во всех уголках GCC. Почти всегда они открыты для помощи.
А что именно вам кажется неверноятным, собственно?

gccint довольно подробно описывает части из которых состоит GCC, а как всё устроено внутри — написано в исходниках.

То же самое — с ядром Linux'а и прочими другими проектами. Разработчикам же не нужно сертификацию по ISO 9001 получать и за документацию им отдельно никто не платит, так откуда она возьмётся?

Её, в общем, вполне достаточно, для того, чтобы разобраться в проекте если вы понимаете C так же хорошо, как английский.
Вот я как знал, что речь зайдёт о линуксе. Смотрите, про внутреннее устройство линукса есть гора книжек, я вот тут собрал список самых на мой взгляд толковых: toster.ru/q/137069#answer_392065
Написано в них не только *как* устроено, но часто ещё и *почему* именно так, какие есть альтернативы и что лучше использовать в своём коде в разных ситуациях. И авторы этих книжек в большинстве своём отнюдь не ведущие разработчики ядра.

для того, чтобы разобраться в проекте если вы понимаете C так же хорошо, как английский

… и у вас много свободного времени, чтобы по коду составить себе большую картину. Чтобы потом не просто выбирать между двумя плохими вариантами найденными в качестве примера, а понимать, чем и когда можно воспользоваться.
Написано в них не только *как* устроено, но часто ещё и *почему* именно так, какие есть альтернативы и что лучше использовать в своём коде в разных ситуациях.
И всё равно всё это — зачастую неправда, так как там описываются заведомо устаревшие подходы.

Для GCC тоже есть подобный список. Да, он поменьше, чем для ядра, ну так и сам проект поменьше.

Чтобы потом не просто выбирать между двумя плохими вариантами найденными в качестве примера, а понимать, чем и когда можно воспользоваться.
Вы сами-то пробовали? Всё равно не получится. Сделайте как-нибудь, потом поговорите с maintainer'ами, они вам объяснят как вы налажали и попросят всё переделать. И в Linux'е и в GCC.

Или вы думаете, то все сотни разработчиков Столлман обучал лично, под покровом ночи?
И всё равно всё это — зачастую неправда

Весомый аргумент.

там описываются заведомо устаревшие подходы

Вы, мне кажется, не понимаете, что такое «большая картина».

Для GCC тоже есть подобный список.

Ага, только там в основном книжки о фронт-эндах и доки по процессорам. Мой вопрос был о бек-энде. Единственную релевантную книжку, что написал Hans-Peter Nilsson, я видел, но она по сути — рассказ «как я провёл лето» «как я портировал компилятор». Мне бы хотелось увидеть книжку «как портировать компилятор».

Вы сами-то пробовали?

Пробовал, и в линуксе и в gcc, и в других проектах.

Сделайте как-нибудь, потом поговорите с maintainer'ами

Этот подход мне понятен, но он не кажется мне самым эффективным, особенно при начальном погружении в проект.

думаете, то все сотни разработчиков Столлман обучал лично

Думаю, что большинство из них работало в командах, в которых присутствовал локальный gcc эксперт, что позволяло им учиться немного более эффективно.
Вы, мне кажется, не понимаете, что такое «большая картина».
Нет, не понимаю. О какой-такой «большой картине» вы собрались говорить применительно к компиляторам? Компилятор — это вам не ядро, где есть десятки разнородных компонент. Его задача на самом высоком уровне «очень проста» — преобразовать один текст в другой. Ну и как же, блин, нам это сделать? Ах, да: взять bison, lex, написать парсер, сконвертировать вот это вот всё в некоторое количество древовидных структур, дальше их маленько покрутить, потом выплюнуть результат обратно в текстовый файл. Всё.

Структуры (GENRIC, GIMPLE, RTL) — описаны, последовательность их пребразований — описана тоже, какую-такую «большую картину» вы хотите увидеть ещё?

Или вы хотите, чтобы вам объяснили как SSA устроен? Ну так это в других книжках описывается (хотя бы даже в Wikipedia можете на список литературы посмотреть). Начинается всё, понятно, с Мучника ну и далее есть куча других книг, статей и прочего.

Мне бы хотелось увидеть книжку «как портировать компилятор».
А смысл? Новые архитектуры не так часто появляются, а процесс портирования меняется всё время. Вы тут много книжек привели для Linux'а — хоть в одной описано подробно как портировать ядро куда-нибудь? Очень частная, довольно редко требуемая задача, да ещё и каждый раз со своей спецификой. Можно написать книгу, где описать как портировать на новую архитектуру какой-нибудь GCC 4.4.4, но смысла в ней будет… не так много.
Или вы хотите, чтобы вам объяснили

Если вы хотите объяснить, то вот, например, один из вопросов:
в прологах и эпилогах некоторые инструкции манипулирующие стекпойнтером или фреймпойнтером помечаются следующим образом: RTX_FRAME_RELATED_P (insn) = 1. Зачем? Почему не все? Что будет, если их так не помечать?
Всё, что связано с DWARF'ом поляжет нафиг (а это отладчик и zero-cost exceptions). Кроме того, если их не помечать, то peepholeы могут переставить местами инструкции, которые переставлять нельзя. Про RTX_FRAME_RELATED_P, как и про многое другое, написано в gccint.
Хорошо. А о том как работают zero-cost exceptions и как ещё DWARF-информация используется компилятором где можно почитать?

А вот ещё: что такое unspec и unspec_volatile? Да, я могу прочитать чт о них написано в gccint, но яснее от этого не становится.
По исключениям я не спец. Ян Тейлор немного писал по их поводу: тут и тут. В комментариях там ещё есть ссылки.

А что вас по unspec'ам-то неясно? Вы хотите понять чем отличается unspec от unspec_volatile или просто — что такое unspec? unspec — это просто машинно зависимая операция. Любая. Вот не сложение, не вычитание, а нечто-такое-очень-странное.

Хороший пример — это, например, инструкции fnstsw и sahf. UNSPEC_FNSTSW описывает выгрузку флагов 80x87 в AX, UNSPEC_SAHF описывает загрузку из AH в младший байт регистра флагов. Вместе — эта пара инструкций представляет типичную последовательность операций при работе с плавучкой: что-то сравнили/посчитали, перегрузили данные из регистра флагов в AX, а потом и в обычный регистр флагов, сделали переход. Их можно как угодно двигать, можно даже результат выгрузить в память — всё равно всё будет хорошо.

А вот UNSPECV_CMPXCHG так двигать не рекомендуется: что будет если у вас будет цикл, который пытается работать с атомиками, а оптимизатор не зная про семантику cmpxchg вынесет эту операцию из цикла? Ничего хорошего, я вас уверяю.

Или UNSPECV_CLD: он меняет режим работы процессора и если оптимизатор, скажем, решит вынести MOVS из цикла а UNSPECV_CLD оставит в цикле… опять-таки ничего хорошего не будет.

Дальше — тут же возникает хак: так как вызывать cld много раз смысла, в общем-то, не имеет а из-за статуса «volatile» двигать их тоже нельзя, то чтобы избежать лишней работы GCC просто смотрит — нужен ли в функции CLD или нет. Если нужен — вставляет UNSPECV_CLD в пролог (где он вызывается даже в том случае если потом никакие MOVSы не используются). Подобных хаков в GCC довольно много и далеко не все из них описаны, это правда.
Большое спасибо.
Оптимизации эт конечно хорошо.
Но зачем отдаваться на произвол компилятора если в gcc 5.0 (да и в clang тоже) есть встроеннная поддержка cilk plus? Который как раз для таких вещей и заточен.

P.S. Кстати, я так и не понял предложение N3409 по добавлению в С++ стандарт cilk'a завернули, или как http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3409.pdf?
Cilk Plus как и OMP 4.0 сами по себе не могут векторизовать код — нужна поддержа внутри компилятора.
Даже при установке «pragma (omp) simd» перед циклом разные компиляторы будут вести себя по разному. Векторизовать код можно оптимально, а можно и не очень. Именно для того чтобы векторизовать оптимально и развиваются техники векторизации. Данная статья описывает улучшения техники векторизации в GCC для x86. Cilk Plus и OMP 4.0 помогут указать где эти улучшения конкретно применять.
Видел демо, кажется Intel'a, там софтверно рендеренные кубики крутились (чёрно-белые).

Сначала их рендерили в одном потоке, потом векторизировали, потом векторизировали + по потокам раскидывали. Векторизация дала 4х прирост, векторизация + «потокизирование» 20х.

Код показывали в Visual Studio, и помойму какой то плагин там к ней стоял. И вроде как ради демонстрации этого плагина все демо и затевали. :)

Не могу найти теперь.

Не встречали такого? :)
О! Вот они кубики https://www.youtube.com/watch?v=orV5ambLLvQ#t=48

Только не кубики, а шарики. Но все равно — черно-белые!

И таки cilk plus плагин к Visual Studio.
По поводу принятия в стандарт — дело это долгое. Думаю, что процесс идет, но пока не завершен.
Спасибо за статью. Очень интересно, что там сделали для ускорения PIC в 32-битном коде. Буквально недавно тут поднималось обсуждение этой темы. Жду продолжения с нетерпением!
Кстати, насчет векторных оптимизация и cilk'a.

А чего он тут http://goo.gl/t26bbf
c[:] = a[:]+b[:];

не завекторизировал?
Ошибка. Должны поправить к релизу 5.0.
Конечно не скромный вопрос. Но…
А у вас векторизирует? (как я понял у вас есть собранная версия gcc 5.0 под рукой)

А то у меня складывается впечетление что синтаксис массивов [:] (аля векторизация) по назначению использует только Intel Compiler…
Есть. Сейчас не векторизует. Есть патч, чтобы векторизовал. Проблема известная и фикс скорее всего будет в 5.0.
Так как проблема локально в Cilk Plus части, то скорее всего будет и бекпорт в 4.9.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий