Qt, GCC, SSE и выравнивание стека

Я пытаюсь создать программу, скомпилированную с помощью GCC и использующую встроенные функции Qt и SSE. Кажется, что когда Qt вызывает одну из моих функций, выравнивание стека не сохраняется. Вот краткий пример, чтобы проиллюстрировать, что я имею в виду:

#include <cstdio>
#include <emmintrin.h>
#include <QtGui/QApplication.h>
#include <QtGui/QWidget.h>


class Widget: public QWidget {
public:
    void paintEvent(QPaintEvent *) {
        __m128 a;
        printf("a: 0x%08x\n", ((void *) &a));
    }
};


int main(int argc, char** argv)
{
    QApplication application(argc, argv);
    Widget w;
    w.paintEvent(NULL); // Called from here, my function behaves correctly
    w.show();
    w.update();
    // Qt will call Widget::paintEvent and my __m128 will not be
    // aligned on 16 bytes as it should
    application.processEvents();

    return 0;
}

Вот результат:

a: 0x0023ff40 // OK, that's aligned on 16 bytes
a: 0x0023d14c // Not aligned!

Конфигурация:

  • Intel Core2
  • WinXP, SP3
  • GCC 4.4 (Mingw включен в Qt SDK 2010.01)

Я попытался скомпилировать пример программы с теми же параметрами, что и в make-файле Qt:

-O2 -Wall -frtti -fexceptions -mthreads

, варианты ссылок:

-enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -Wl,-s -mthreads

Теперь не знаю, в каких направлениях искать. Любые подсказки будут оценены. Спасибо!

Фабьен


person Fabien    schedule 05.03.2010    source источник


Ответы (2)


Вы можете использовать опцию -mstackrealign, чтобы сделать это без добавления атрибутов в исходный код:

-mstackrealign Выровнять стек при входе. На Intel x86 параметр -mstackrealign будет генерировать альтернативный пролог и эпилог, которые при необходимости перестраивают стек времени выполнения. Это поддерживает смешивание устаревших кодов, которые сохраняют выровненный по 4 байта стек, с современными кодами, которые сохраняют 16-байтовый стек для совместимости с SSE. См. также атрибут force_align_arg_pointer, применимый к отдельным функциям.

(из документов GCC)

person Community    schedule 06.03.2010
comment
Спасибо! Согласно eigen.tuxfamily.org/dox/WrongStackAlignment.html, кажется, что лучше для производительности использовать атрибут force_align_arg_pointer. Использование -mincoming-stack-boundary=2 может быть другим решением (в Windows), так что GCC знает, что он действительно должен проявлять особую осторожность, чтобы соблюдать выравнивание 16 байтов. - person Fabien; 08.03.2010

__attribute__((force_align_arg_pointer)) void paintEvent(QPaintEvent *);

заставил это работать! У кого-нибудь есть лучшее решение?

person Fabien    schedule 05.03.2010
comment
Что произойдет, если вы попытаетесь добавить -mms-bitfields к флагам компилятора? - person Mihai Limbășan; 05.03.2010