Это ошибка GCC при использовании опции -falign-loops?

Я играл с этой опцией, чтобы оптимизировать цикл for в нашей встроенной архитектуре (здесь). Однако я заметил, что когда для выравнивания требуется добавить более одной инструкции nop, компилятор генерирует одну nop, за которой следует столько нулей, сколько требуется (0000).

Я подозреваю, что это ошибка в нашем компиляторе, но может ли кто-нибудь подтвердить, что это не ошибка в GCC?

Вот фрагмент кода:

    __asm__ volatile("nop");  
    __asm__ volatile("nop");  

    for (j0=0; j0<N; j0+=4)
    {
        c[j0+ 0] = a[j0+ 0] + b[j0+ 0];
        c[j0+ 1] = a[j0+ 1] + b[j0+ 1];
        c[j0+ 2] = a[j0+ 2] + b[j0+ 2];
        c[j0+ 3] = a[j0+ 3] + b[j0+ 3];
    }

Скомпилируйте с -falign-loops=8 (или любым другим числом, соответствующим вашей архитектуре, которое превышает требуемое минимальное выравнивание). Вы можете добавить или удалить __asm__ строк по мере необходимости, чтобы сгенерировать смещенное тело цикла.


person ysap    schedule 26.03.2012    source источник
comment
Кстати, я бы также избавился от уродливого ручного развертывания цикла и позволил gcc развернуть циклы (что он будет делать по умолчанию с -O3, когда сочтет это целесообразным).   -  person R.. GitHub STOP HELPING ICE    schedule 27.03.2012
comment
@R.. - видимо, в реальном мире все не так. Этот код на самом деле является частью теста, в котором я выполняю сложение векторов. У меня есть две функции: vecadd() с приведенным выше кодом и vecadd_naive(), похожие на ваше предложение. Дело в том, что мне пришлось развернуть вручную 16 раз, чтобы получить оптимальную производительность, где более чем незначительно лучше, чем наивная версия. Это было с -O3 и (возможно, избыточным) -funroll-loops.   -  person ysap    schedule 27.03.2012
comment
@R ..- помните, что эвристика оптимизатора для развертывания циклов основана на несколько произвольном наборе правил (хорошо, по крайней мере, произвольном по отношению к доступным параметрам). Ваши соображения (например, размер кода или использование регистров) могут отличаться и, в конце концов, привести к более быстрому коду. Я думаю, это то, что я вижу разницу.   -  person ysap    schedule 27.03.2012
comment
Возможно, вы сможете добавить #pragma для параметров решения об уровне оптимизации/развертывании перед циклом вместо того, чтобы разворачивать его вручную. Я не решил, лучше это или уродливее, чем разворачивать цикл самостоятельно...   -  person R.. GitHub STOP HELPING ICE    schedule 28.03.2012


Ответы (1)


Используйте gcc -S -o foo.s foo.c для создания выходных данных сборки без ее сборки. Я подозреваю, что вы увидите директиву .balign или .p2align в файле asm. Предполагая, что эта директива предназначена для работы, я думаю, что это ошибка в ассемблере. Также возможно, что вы поместили код в нестандартный раздел (т. е. не .text) намеренно или случайно (например, с неуместным .data или .section в каком-то другом встроенном ассемблере); обычно ассемблер дополняет правильный размер и количество nop инструкций для разделов, содержащих код, и 0 байтов для разделов, содержащих данные.

person R.. GitHub STOP HELPING ICE    schedule 26.03.2012
comment
Действительно, компилятор вставил директиву .balign 8 в нужное место. К сожалению, я уже выяснил, что если не указать явное значение заполнения, ассемблер генерирует ошибочную последовательность. Насколько я понимаю, функция размещена в секции .text. Интересно, есть ли способ указать компилятору использовать значение-заполнитель при использовании -falign-loops=n, например, при использовании .balignw 8,0x01a2? - person ysap; 27.03.2012
comment
В любом случае, это особенность нашей реализации или это ошибка в GAS? - person ysap; 27.03.2012
comment
Это определенно возможно, если вы отредактируете исходный код gcc, чтобы изменить строку, которую он вставляет в выходную сборку для выравнивания на вашей платформе. Или вы можете внести изменения в GAS. Любое изменение может быть принято восходящим потоком, если сопровождающие подтвердят существование проблемы. - person R.. GitHub STOP HELPING ICE; 27.03.2012
comment
О, ну, я думаю, все возможно, когда у вас есть доступ к исходникам... Я надеялся, что есть недокументированная функция (как расширение для параметра с синтаксисом, аналогичным директиве align). - person ysap; 27.03.2012
comment
Насколько я знаю, нет. Если вы не делаете что-то странное с разделами, которые сбивают с толку компилятор/ассемблер, я почти уверен, что это просто ошибка. - person R.. GitHub STOP HELPING ICE; 27.03.2012
comment
Хорошо, вот действительно дешевое решение. Найдите путь, по которому ваш gcc ищет двоичные файлы (вероятно, он находится под /usr/lib/gcc или подобным) и поместите туда сценарий оболочки с именем as. Пусть он пропустит свой ввод через sed, чтобы внести необходимые исправления в выравнивание и запустить настоящий двоичный файл as. - person R.. GitHub STOP HELPING ICE; 27.03.2012
comment
Интересная идея. В один из ближайших дней попробую. - person ysap; 27.03.2012
comment
В ПОРЯДКЕ. Помните, что ассемблер может вводить данные из файла или стандартного ввода. Немного сложнее проанализировать командную строку, чтобы определить, какой аргумент является именем файла для сборки (и одновременно не нарушать другие параметры), поэтому, если вы можете контролировать среду сборки, было бы проще просто убедиться, что gcc всегда вызывается с помощью -pipe, поэтому входные данные для ассемблера поступают на стандартный ввод. Тогда ваш скрипт-оболочка может просто сделать sed sed_expression_here | /real/path/to/as "$@" - person R.. GitHub STOP HELPING ICE; 27.03.2012
comment
Однако я предвижу проблему - как мы можем отличить .alignbw, предназначенный для nop, и .alignbw, предназначенный для нулей (например, для заполнения объектов данных)... - person ysap; 27.03.2012
comment
Если это просто заполнение в объектах данных, какое значение имеет значение? Вся концепция заполнения заключается в том, что оно не должно оказывать никакого влияния на значение. Если это окажется проблемой, вы можете создать более продвинутый сценарий sed с диапазонами адресов на основе директив, которые изменяют раздел. - person R.. GitHub STOP HELPING ICE; 27.03.2012
comment
... не знаю... может быть, т.к. так и должно быть согласно документации GCC?? В противном случае, я думаю, действительно не имеет значения, какое значение заполнения - за исключением того факта, что оно казалось достаточно важным, поэтому в директиву align была добавлена ​​​​опция для явного значения. - person ysap; 27.03.2012
comment
На большинстве арок ассемблер вставляет нулевое заполнение в разделы данных, а для разделов кода он вставляет инструкции NOP оптимального размера для достижения желаемого заполнения с наименьшим количеством кодов операций (это возможно только в архитектурах, где размер кода операции является переменным). - person R.. GitHub STOP HELPING ICE; 27.03.2012