Huhu,
auf der Arbeit stecken wir seit einem Jahr bei Visual C++ 2015 fest, weil das Produkt kaputtgeht, wenn wir auf 2017 aktualisieren.
Ich habe das Problem auf folgende Situation eingegrenzt:
struct Matrix {
__m128 a;
__m128 b;
__m128 c;
__m128 d;
};
…
return { // Matrix
{ fa, fb, fc, fd }, // alles floats
{ fe, ff, fg, fh },
{ fi, fj, fk, fl },
{ fm, fn, fo, fp }
};
Diese Initialisierungsliste funktionierte mit Visual C++ 2015 richtig, aber mit Visual C++ 2017 wird der zweite Vektor falsch initialisiert. Wenn ich statt einer Initialisierungsliste vier Mal _mm_set_ps() nutze, funktioniert der Code wieder.
Bevor ich einen Bug melde: Ist das undefined behavior? __m128 ist definiert als
union __m128 {
float m128_f32[4];
unsigned __int64 m128_u64[2];
…
};
Meines Wissens nach müsste die Initializer List für das erste Member gelten, also die vier floats. Oder gibt es da einen Fallstrick, dass meine zweite Initializer List auf die 64-Bit-Integer bezogen werden kann? (Dann kann ich mir aber nicht erklären, warum der dritte und vierte Vektor wieder richtig initialisiert werden.)
[Visual C++] Initializer List für __m128 erlaubt?
- xq
- Establishment
- Beiträge: 1590
- Registriert: 07.10.2012, 14:56
- Alter Benutzername: MasterQ32
- Echter Name: Felix Queißner
- Wohnort: Stuttgart & Region
- Kontaktdaten:
Re: [Visual C++] Initializer List für __m128 erlaubt?
Also ein Blick in die Doku sagt:
Das klingt für mich so, als solltest du das auch nicht initializerlist initialisierienSie sollten auf die __m128-Felder nicht direkt zugreifen. Sie können diese Typen jedoch im Debugger finden. Eine Variable vom Typ __m128 wird den XMM[0-7]-Registern zugeordnet.
War mal MasterQ32, findet den Namen aber mittlerweile ziemlich albern…
Programmiert viel in Zig und nervt Leute damit.
Programmiert viel in Zig und nervt Leute damit.
- Krishty
- Establishment
- Beiträge: 8316
- Registriert: 26.02.2009, 11:18
- Benutzertext: state is the enemy
- Kontaktdaten:
Re: [Visual C++] Initializer List für __m128 erlaubt?
Mit dem Zitat hast du recht. Ich möchte das nicht einfach so beiseite wischen, aber meinem Eindruck nach ist es veraltet:
- damit gäbe es keine Möglichkeit, constexpr __m128 zu initialisieren
- der Compiler erzeugt seit 2015 bei direktem Zugriff auf die Member oft besseren Code als mit Intrinsics (in vorherigen Compiler-Versionen war es umgekehrt), was darauf schließen lässt, dass sie diese Richtung langfristig anstreben
- dann hätte es mit VS 2015 auch nicht funktionieren sollen
- die Umstände (extrem abhängig vom Registerdruck; verschwindet bei deaktivierter Optimierung oder bei Inlining; zerstört nur zwei Werte statt alle vier) lassen es immer mehr wie einen Optimizer-Bug aussehen