Maison > développement back-end > C++ > Pourquoi l'optimisation du compilateur interrompt-elle cette fonction d'échange 64 bits ?

Pourquoi l'optimisation du compilateur interrompt-elle cette fonction d'échange 64 bits ?

DDD
Libérer: 2024-11-28 08:34:12
original
529 Les gens l'ont consulté

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

Pourquoi l'optimisation dégrade cette fonction

Lors d'une conférence universitaire sur les spécialités de programmation, un professeur a présenté une fonction qui a dérouté les étudiants :

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

    return tmp;
}
Copier après la connexion

Au départ, la fonction fonctionnait sans problème, mais après avoir activé des niveaux d'optimisation élevés, elle est devenue inerte. La raison derrière ce comportement réside dans le concept de règles d'alias strictes.

Violation d'alias stricte

Le code fourni viole des règles d'alias strictes, qui dictent que les objets ne doivent être accessible via des types de pointeurs compatibles. Dans ce cas, les pointeurs u32 et u64 pointent vers une mémoire potentiellement superposée, mais le compilateur suppose qu'ils représentent des objets distincts. Cette hypothèse lui permet d'optimiser les affectations à la variable temporaire tmp, rendant la fonction inefficace.

Pourquoi l'optimisation se produit

Le compilateur est autorisé à optimiser le code en fonction d'hypothèses sur le comportement du pointeur. Puisque u32 et u64 sont de types différents, le compilateur suppose qu'ils ne pointent pas vers la même mémoire et que les modifications apportées via les pointeurs u32 n'affecteront pas la valeur de tmp. Cette optimisation conduit au comportement observé.

Solutions pour préserver le comportement des fonctions

Pour éviter que le code ne soit optimisé, les types de pointeurs doivent correspondre aux types de données consultés. Une approche consiste à utiliser une union pour accéder directement aux bits :

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);
}
Copier après la connexion

En utilisant une union, nous nous assurons que les pointeurs et les types de données sont compatibles, empêchant le compilateur d'optimiser les modifications prévues.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal