GCC Vector-Extensions: misterioeser Segfault



  • Hiho!
    Ich spiel grad ein wenig mit der GCC Vector-Extensions. Ich verwende den GCC 4.2.1 unter Windows. Ich hab eine Klasse fuer 3D-Vektoren, die zur Zeit so ausschaut:

    #define USE_GCC_VECTORISATION (defined(__SSE__) && 1)
    
    class Vector3D
    {
    	public:
    		/*
    		 * ... die ueblichen Operatoren
    		 */
    
    	private:
    		#if USE_GCC_VECTORISATION
    			typedef float v4sf __attribute__ (( vector_size(4 * sizeof(float)) ));
    			typedef int v4si __attribute__ (( vector_size(4 * sizeof(int)) ));
    			union
    			{
    				float v[4];
    				v4sf vec;
    			};
    			Vector3D(const v4sf& v);
    		#else
    			float v[3];
    		#endif
    };
    

    Ohne die Vector-Extensions funktioniert mein Programm problemlos. MIT Vektorisierung hingegen erhalte ich prompt beim ersten Aufruf einen Segfault (ich glaub das ist die erste Vector3D-Funktion, die im ganzen Programm aufgerufen wird):

    inline const Vector3D operator-(const Vector3D& lhs, const Vector3D& rhs)
    {
    #if USE_GCC_VECTORISATION
    	return Vector3D(lhs.vec - rhs.vec);
    #else
    	Vector3D retval(lhs);
    	retval -= rhs;
    	return retval;
    #endif
    }
    

    Oder genauer gesagt:

    Frame function: operator-(Vector3D const&, Vector3D const&) (src/Vector3D.cpp:138)
    Frame address : 0x0022FA60
    --------------------------------------------------------------------------------
    0x4f07d0	push   %ebp
    0x4f07d1	mov    %esp,%ebp
    0x4f07d3	push   %ebx
    0x4f07d4	sub    $0x1c,%esp
    0x4f07d7	mov    0x8(%ebp),%ebx
    0x4f07da	mov    %ebx,%edx
    0x4f07dc	mov    0xc(%ebp),%eax
    0x4f07df	movaps (%eax),%xmm1  ; <<<<----- hier passiert der Segfault
    0x4f07e2	mov    0x10(%ebp),%eax
    0x4f07e5	movaps (%eax),%xmm0
    0x4f07e8	movaps %xmm1,%xmm2
    0x4f07eb	subps  %xmm0,%xmm2
    0x4f07ee	movaps %xmm2,%xmm0
    0x4f07f1	movaps %xmm0,0xffffffe8(%ebp)
    0x4f07f5	lea    0xffffffe8(%ebp),%eax
    0x4f07f8	mov    %eax,0x4(%esp)
    0x4f07fc	mov    %edx,(%esp)
    0x4f07ff	call   0x46cefc <Vector3D::Vector3D(float __vector const&)>
    0x4f0804	mov    %ebx,%eax
    0x4f0806	add    $0x1c,%esp
    0x4f0809	pop    %ebx
    0x4f080a	pop    %ebp
    0x4f080b	ret    $0x4
    

    Wenn ich mir die Werte der einzelnen Komponenten von rhs/lhs im Debugger anschaue, schaut soweit eigentlich alles vollkommen normal aus. EAX enthaelt zu dem Zeitpunkt genau die Adresse von lhs (Ich verstehe zwar nur ein paar Brocken ASM, aber der generierte Code schaut auch nicht fehlerhaft aus).

    Wenn ich die Klasse allerdings ausserhalb meines Projektes verwende (also z. B. versuche, einen minimalen Testcase zusammenzustellen), funktioniert komischerweise alles einwandfrei. z. B. funktioniert folgendes absolut fehlerfrei (und gibt den richtigen Wert aus):

    #include "Vector3D.h"
    int main ( int argc, char** argv )
    {
    	// dies ist ziemlich genau das, was im Original-Quelltext beim segfault getan wird:
    	Vector3D a(-4, -3, 10);
    	Vector3D b(-4, 5, 10);
    	Vector3D c = a - b;
    
    	std::cout << c << std::endl;
    
    	return 0;
    }
    

    Hat irgendwer eine Ahnung, wo der Fehler stecken koennte?

    EDIT: ich meinte natuerlich Vector-Extensions, nicht Auto-Vectorisation



  • Disclaimer: Ich kenne mich mit SSE und Auto-Vec nicht so gut aus. Aber ich versuch es mal

    1. Bei SSE müssen die Daten 16 byte aligned sein. Kümmert sich vector_size darum? (Kenne nur als Attribute altivec(...) für PPCs AltiVec)

    2. Musste man MMX/SSE nicht mit einem Befehl erst initialisieren? Schau vielleicht mal ob dafür Code generiert wird (obwohl das dürfte eher ein SIGFPE oder so geben)

    im Zweifelsfall solltest du dich mal an die GCC Leute wenden (zB #gcc auf OFTC oder per Mailingliste).



  • rüdiger schrieb:

    im Zweifelsfall solltest du dich mal an die GCC Leute wenden (zB #gcc auf OFTC oder per Mailingliste).

    Mailingliste.. vielleicht. Aber #gcc?! Nein!! Der Channel ist nur für die Entwicklung... :p

    (War da ja schon ab und zu mit diversen G++-Bugs. :D)



  • rüdiger schrieb:

    1. Bei SSE müssen die Daten 16 byte aligned sein. Kümmert sich vector_size darum? (Kenne nur als Attribute altivec(...) für PPCs AltiVec)

    Davon gehe ich aus, zumindest wurde in allen Beispielen, die ich bisher zu Auto-Vectorisation gefunden hab, nie eine eigene Align-Anweisung verwendet.

    2. Musste man MMX/SSE nicht mit einem Befehl erst initialisieren? Schau vielleicht mal ob dafür Code generiert wird (obwohl das dürfte eher ein SIGFPE oder so geben)

    Glaub ich nicht, sonst muesste das 2te Beispiel auch nicht funktionieren.

    im Zweifelsfall solltest du dich mal an die GCC Leute wenden (zB #gcc auf OFTC oder per Mailingliste).

    OFTC?
    Jedenfalls wollt ich erstmal hier nachfragen, nicht dass ich am Ende nur was ganz Triviales vergessen hab 😉


Anmelden zum Antworten