Seite 1 von 1

[Visual C++] Initializer List für __m128 erlaubt?

Verfasst: 12.03.2018, 15:56
von Krishty
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.)

Re: [Visual C++] Initializer List für __m128 erlaubt?

Verfasst: 12.03.2018, 16:05
von xq
Also ein Blick in die Doku sagt:
Sie 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.
Das klingt für mich so, als solltest du das auch nicht initializerlist initialisierien

Re: [Visual C++] Initializer List für __m128 erlaubt?

Verfasst: 12.03.2018, 22:25
von Krishty
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
Ich habe es nun einfach trotzdem gemeldet und warte auf die Reaktion der Schöpfer.