Heim >Backend-Entwicklung >C++ >Warum unterbricht die Compiler-Optimierung diese 64-Bit-Swap-Funktion?

Warum unterbricht die Compiler-Optimierung diese 64-Bit-Swap-Funktion?

DDD
DDDOriginal
2024-11-28 08:34:12530Durchsuche

Why Does Compiler Optimization Break This 64-bit Swap Function?

Warum Optimierung diese Funktion beeinträchtigt

In einer Universitätsvorlesung über Programmierspezialitäten stellte ein Dozent eine Funktion vor, die Studenten verblüffte:

inline u64 Swap_64(u64 x)
{
    u64 tmp;
    (*(u32*)&tmp)       = Swap_32(*(((u32*)&x)+1));
    (*(((u32*)&tmp)+1)) = Swap_32(*(u32*) &x);

    return tmp;
}

Anfangs funktionierte die Funktion reibungslos, aber nach der Aktivierung hoher Optimierungsstufen wurde sie inaktiv. Der Grund für dieses Verhalten liegt im Konzept der strengen Aliasing-Regeln.

Strenge Aliasing-Verletzung

Der bereitgestellte Code verstößt gegen strenge Aliasing-Regeln, die vorschreiben, dass nur Objekte zulässig sind Der Zugriff erfolgt über kompatible Zeigertypen. In diesem Fall verweisen die u32- und u64-Zeiger auf möglicherweise überlappenden Speicher, der Compiler geht jedoch davon aus, dass sie unterschiedliche Objekte darstellen. Diese Annahme ermöglicht es ihm, Zuweisungen an die temporäre Variable tmp zu optimieren, wodurch die Funktion unwirksam wird.

Warum die Optimierung stattfindet

Der Compiler darf Code basierend auf Annahmen optimieren über Zeigerverhalten. Da u32 und u64 unterschiedliche Typen sind, geht der Compiler davon aus, dass sie nicht auf denselben Speicher verweisen und dass die über die u32-Zeiger vorgenommenen Änderungen keinen Einfluss auf den Wert von tmp haben. Diese Optimierung führt zum beobachteten Verhalten.

Lösungen zur Erhaltung des Funktionsverhaltens

Um zu verhindern, dass der Code herausoptimiert wird, sollten die Zeigertypen mit den Datentypen übereinstimmen, auf die zugegriffen wird. Ein Ansatz besteht darin, eine Union zu verwenden, um direkt auf die Bits zuzugreifen:

typedef union
{
  uint32_t u32;
  uint16_t u16[2];
} U32;

uint32_t swap_words(uint32_t arg)
{
  U32 in;
  uint16_t lo;
  uint16_t hi;

  in.u32    = arg;
  hi        = in.u16[0];
  lo        = in.u16[1];
  in.u16[0] = lo;
  in.u16[1] = hi;

  return (in.u32);
}

Durch die Verwendung einer Union stellen wir sicher, dass die Zeiger und Datentypen kompatibel sind, und verhindern so, dass der Compiler die beabsichtigten Änderungen herausoptimiert.

Das obige ist der detaillierte Inhalt vonWarum unterbricht die Compiler-Optimierung diese 64-Bit-Swap-Funktion?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn