38 votes

Pourquoi cette variable inutilisée n’est-elle pas optimisée?

J'ai joué un peu avec Godbolt de CompilerExplorer. Je voulais voir comment certaines optimisations sont. Mon minimales de travail exemple:

#include <vector>

int foo() {
    std::vector<int> v {1, 2, 3, 4, 5};
    return v[4];
}

L'assembleur généré (par clang 5.0.0, -O2 -std=c++14):

foo(): # @foo()
  push rax
  mov edi, 20
  call operator new(unsigned long)
  mov rdi, rax
  call operator delete(void*)
  mov eax, 5
  pop rcx
  ret

Comme on peut le voir, clang connaît la réponse, mais fait beaucoup de choses avant de retourner. Il semble à mon que même le vecteur est créé, à cause de "l'opérateur new/delete".

Quelqu'un peut-il m'expliquer ce qui se passe ici et pourquoi il n'est pas juste de retour?

Le code généré par GCC (pas de copié ici) semble de construire le vecteur explicitement. Personne ne sait GCC n'est pas capable d'en déduire le résultat?

29voto

Vittorio Romeo Points 2559

std::vector<T> est assez compliqué de classe qui implique l'allocation dynamique. Alors qu' clang++ est parfois en mesure d'éluder les allocations de tas, il est assez difficile d'optimisation et vous ne devriez pas compter sur elle. Exemple:

int foo() {
    int* p = new int{5};
    return *p;
}
foo():                                # @foo()
        mov     eax, 5
        ret

Comme un exemple, en utilisant std::array<T> (ce qui ne veut pas allouer dynamiquement des) produit entièrement inline code:

#include <array>

int foo() {
    std::array v{1, 2, 3, 4, 5};
    return v[4];
}
foo():                                # @foo()
        mov     eax, 5
        ret

Comme Marc Glisse observée dans les autres répondre à des commentaires, c'est ce que dit la Norme dans [expr.nouveau] #10:

Une mise en œuvre est permis d'omettre un appel à une remplaçable global allocation de fonction ([nouveau.supprimer.unique], [nouveau.supprimer.tableau]). Quand il le fait, le stockage est fourni par la mise en œuvre ou prévues par l'extension de l'allocation d'une nouvelle expression. La mise en œuvre peut s'étendre à l'allocation d'une nouvelle expression de e1 pour fournir un stockage pour une nouvelle expression e2 si ce qui suit est vrai ont l'allocation n'est pas étendue: [...]

7voto

MSalters Points 74024

Comme le notent les commentaires, operator new peut être remplacé. Cela peut arriver dans n'importe quelle unité de traduction. Optimiser un programme pour le cas où il n'est pas remplacé nécessite donc une analyse complète du programme. Et si elle est remplacée, vous devez l' appeler bien sûr.

Que ce soit par défaut operator new est un appel d' E / S de bibliothèque non spécifié. C'est important, car les appels d'E / S de bibliothèque sont observables et ne peuvent donc pas être optimisés.

4voto

T.C. Points 22510

N3664's changement de [expr.nouveau], cité dans une réponse et un commentaire, permet nouvelle expression des à ne pas appeler un remplaçable par l'affectation globale de la fonction. Mais vector alloue de la mémoire à l'aide de std::allocator<T>::allocate, qui demande ::operator new directement, et non par l'intermédiaire d'une nouvelle expression. De sorte qu'une autorisation spéciale ne s'applique pas, et en général les compilateurs ne peuvent pas éluder ces appels directs à l' ::operator new.

Tout espoir n'est pas perdu, cependant, pour std::allocator<T>::allocates'spécification a ceci à dire:

Remarques: le stockage est obtenu en appelant ​::​operator new, mais il n'est pas précisé quand et à quelle fréquence cette fonction est appelée.

Fort de cette autorisation, la libc++s' std::allocator usages spéciaux clang built-ins pour indiquer au compilateur que l'élision est autorisée. Avec -stdlib=libc++, clang compile le code en bas à

foo():                                # @foo()
        mov     eax, 5
        ret

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X