Как заставить GCC не использовать SSE-инструкции с выравниванием для операндов в стеке?
При использовании компилятора GCC 5.1.0 (32bits Windows, компилятор TDM GCC) для компиляции dll-библиотеки при включенных SSE-оптимизациях происходит ошибка SEGFAULT (обращение к 0xffffffff). Выяснил, что ошибка связана с инструкциями типа:
movaps %xmm0,0x50(%esp)
movaps %xmm0,-0x10(%ebp)
Т.к. при этом параметры стека, и следовательно esp, ebp не выровнены по границе 16 байт (вероятно при вызове из основного модуля), то происходит ошибка. Нужно было бы использовать movups для невыровненных данных. Как этого можно достичь? В чем может быть проблема? Есть ли какие-то настройки для использования только movups вместо movaps; возможно есть и другие инструкции, обращающиеся к невыровненным данным. Включение SSE-оптимизаций при линковке основного модуля не дало эффектов.
Армянское Радио, UB, безусловно, исключать не стоит, но пока по описанию вопроса видно что автор на верном пути рассуждений.
При загрузке регистров его память не выровнена. Это может быть последствием работы с четырехмерным вектором четырехбайтовых целых, для которого не был использован alignas. Выравнивание у такого вектора будет на 4Б.
User700 , показывай код. Определение типа этого вектора, информацию после компиляции - размер и выравнивание объекта вектора. Покажи участок кода, который транслируется в сбойную последовательность инструкций.
Но при этом, если знает что edx не выровнено, то использует movups. Возможно при компоновке dll он выравнивает стек на параграф, если есть SSE-инструкции. А вообще, кажется не выравнивает его в каждом случае при компоновке dll:
Как я понял, он просто пытается сохранять в стеке xmm-регистры.
Если тебе нужна точность понимания, то movapsделает наоборот. Она загружает значения из памяти в векторный регистр.
Что будет если использоватьalignas при объявлении объекта вектора на стеке?
Условия бывают разные и я не исключаю что в твоем коде этот вектор нельзя выровнять на 16 как тип тем же alignas, поэтому пробуй выровнять конкретный объект на стеке.
Здесь синтаксис ассемблера выдал дебаггер / IDE как AT&T и операнды наоборот. Какой объект там сохраняется я не знаю точно, вполне возможно что несколько полей структуры, или просто набор параметров, подготовленных для следующих вызовов, с учетом инлайнинга трудно понять. Библиотека не моя, исходный код её около 2 Мб, а специальных типов для SSE там нет, только обычные массивы / циклы сложения / умножения и т.д., которые могут оптимизироваться при включении соотв. флагов. Иначе -- заметно притормаживает.
Если просто запатчить все эти инструкции в dll, то будут аналогичные ошибки уже при умножениях.
Компилятора (не линковщика?). Да, смотрю в сторону этого и атрибута __attribute__((force_align_arg_pointer)) у функций и методов. Пока примел это для компиляции основного модуля. Атрибут force_align_arg_pointer помогает, но не совсем: когда происходит событие по нажатию кнопки из FLTK-окна (это окно тоже все в рамках dll-библиотеки делается и обрабатывается), то появляется опять невыровненность. FLTK статически линкуется к dll-кам библиотеки при ее компиляции, а в нем самом вроде бы SSE не включен; а в обработчике нет выравнивания. Вероятно mstackrealign нужно ставить при компиляции библиотеки, т.к. основной модуль считает, что это ему нигде не нужно.