Sortie de GNU Compiler Collection 9.1

Posté par . Édité par Davy Defaud, Benoît Sibaud, Florent Zara, Xavier Claude, Julien Jorge et ZeroHeure. Modéré par Julien Jorge. Licence CC by-sa.
Tags :
53
7
mai
2019
GNU

La nouvelle version de la collection de compilateurs GNU est sortie le 3 mai 2019.

Plus qu’à son habitude, elle apporte de très nombreuses améliorations. Une partie d’icelles a été motivée par la récente décision des développeurs de Firefox d’utiliser le compilateur, particulièrement pour les phases d’optimisation à l’édition des liens.

On note également la prise en charge du langage D.

Plus d’informations dans la suite de la dépêche.

Sommaire

Cette dépêche reprend en grande partie les notes de version de GCC.

Améliorations globales

Toutes les options de la ligne de commande qui attendent un nombre d’octets (comme les paramètres de taille de cache si l’on cible une version de processeur précise) acceptent un entier sur 64 bits mais aussi les suffixes standard SI et IEC comme kb, KiB, MB, MiB, GB et GiB.

Une nouvelle option -flive-patching=[inline-only-static|inline-clone] a été ajoutée pour faciliter la correction en direct dans un code en cours d’exécution. Ce mécanisme est utilisé pour introduire des modifications à chaud dans le noyau Linux (ksplices d’Oracle, kgraft de SUSE ou kpatch de Red Hat IBM). Ces options permettent de faire varier le niveau d’optimisation du code généré pour que la correction puisse tout simplement être applicable.

Des options de complétion ont été ajoutées pour faciliter l’utilisation de GCC en ligne de commande. L’idée est de faciliter l’utilisation de bash-completion.
Les diagnostics de GCC indiquent maintenant le numéro de la ligne de code concernée dans une marge à gauche, mais une option permet de désactiver cette information au cas où elle ne vous intéresserait pas (ou pour éviter de casser certains scripts).

Les diagnostics de GCC peuvent également donner des informations intéressantes sur le code concerné par le diagnostic, comme les types d’une expression, mais vous pouvez heureusement les désactiver :

    $ g++ t.cc
    t.cc: In function 'int test(const shape&, const shape&)':
    t.cc:15:4: error: no match for 'operator+' (operand types are 'boxed_value<double>' and 'boxed_value<double>')
       14 |   return (width(s1) * height(s1)
          |           ~~~~~~~~~~~~~~~~~~~~~~
          |                     |
          |                     boxed_value<[...]>
       15 |    + width(s2) * height(s2));
          |    ^ ~~~~~~~~~~~~~~~~~~~~~~
          |                |
          |                boxed_value<[...]>

Il est maintenant possible d’exporter les diagnostics au format JSON pour les gérer plus facilement par un programme derrière (option -fdiagnostics-format=json).

L’alignement consiste à mettre certaines fonctions, étiquettes, sauts et boucles à une adresse qui est souvent un nombre rond en hexadécimal pour faciliter la gestion mémoire par le processeur, par exemple une lecture en mémoire charge toujours une ligne de cache complète de 64 octets sur x86. Les options d’alignement prennent maintenant un paramètre supplémentaire afin de pouvoir éviter de sauter trop loin dans la mémoire (par exemple, au‐delà d’une ligne de cache ou pire d’une page), perdant ainsi le bénéfice éventuel de l’alignement.

Des options permettent de sélectionner quels fichiers de sources doivent être instrumentés lors d’une compilation avec profilage du code.

Enfin l’outil AddressSanitizer qui permet de détecter dynamiquement les problèmes de mémoire lors du développement (souvent en fracassant interrompant le programme et en indiquant l’endroit de l’erreur mémoire) génère des zones rouges plus compactes pour les variables automatiques, ce qui permet de réduire l’empreinte mémoire d’un code binaire assaini compilé en vue de ces tests.

Information sur les optimisations « -fopt-info »

De nombreuses améliorations ont été ajoutées à l’option -fopt-info qui explique quelles optimisations ont pu (ou non) être réalisées sur le code.
Les messages sont préfixés par « optimisé », « raté » ou « note » plutôt que « note » pour tous.
La sortie de -fopt-info contient maintenant des informations sur les choix de mise en ligne d’inlining des fonctions :

$ g++ -c inline.cc -O2 -fopt-info-inline-all
    inline.cc:24:11: note: Considering inline candidate void foreach(T, T, void (*)(E)) [with T = char**; E = char*]/2.
    inline.cc:24:11: optimized:  Inlining void foreach(T, T, void (*)(E)) [with T = char**; E = char*]/2 into int main(int, char**)/1.
    inline.cc:19:12: missed:   not inlinable: void inline_me(char*)/0 -> int std::puts(const char*)/3, function body not available
    inline.cc:13:8: optimized:  Inlined void inline_me(char*)/4 into int main(int, char**)/1 which now has time 127.363637 and size 11, net change of +0.
    Unit growth for small function inlining: 16->16 (0%)
    Inlined 2 calls, eliminated 1 functions

La sortie du vectoriseur a été rationalisée de sorte que les essais de vectorisation qui ont avorté sont affichés sous la forme :
[LOOP-LOCATION]: couldn't vectorize this loop
[PROBLEM-LOCATION]: because of [REASON]
plutôt que par le journal exhaustif de toutes les décisions faites par le vectoriseur.

Par exemple :

    $ gcc -c v.c -O3 -fopt-info-all-vec
    v.c:7:3: missed: couldn't vectorize loop
    v.c:10:7: missed: statement clobbers memory: __asm__ __volatile__("" :  :  : "memory");
    v.c:3:6: note: vectorized 0 loops in function.
    v.c:10:7: missed: statement clobbers memory: __asm__ __volatile__("" :  :  : "memory");

Bien sûr, des options permettent de retrouver l’ancien comportement. Une nouvelle option permet d’enregistrer les choix d’optimisation faits par GCC dans un fichier nommé SRCFILE.opt-record.json.gz. Il est similaire à la sortie de -fopt-info, avec des informations additionnelles comme la chaîne d’inlining des fonctions et les informations de profilage si elles étaient utilisées.

La propagation de l’alignement de pile est maintenant contrôlable, de même que celle de l’« adressabilité » ou des propriétés « lecture seule » ou « écriture seule » des variables statiques.

Les fonctions intégrées suivantes ont été ajoutées :

  • __builtin_expect_with_probability, pour donner des idées de probabilités de succès de la prédiction de branchement à l’optimiseur ;
  • __builtin_has_attribute, pour déterminer si une fonction, un type ou une variable a été déclaré avec un attribut particulier (par exemple des attributs de placement en mémoire) ;
  • __builtin_speculation_safe_value peut être utilisé pour limiter les attaques par exécution spéculative (type Spectre ou Meltdown).

En parlant d’attributs, il existe maintenant un attribut de copie qui permet de prendre les attributs d’une autre fonction et de les appliquer à la fonction courante. Cela marche également avec les définitions de type et les déclarations de variables.

Améliorations de la génération du code

La liste suivante n’est pas exhaustive.
Certains blocs de type switch … case ont été développés en utilisant de nouvelles stratégies (table de sauts, test de bits, arbre de décision).
Notamment, si le bloc affecte une variable qui est une fonction affine de l’entrée, l’arbre de décision peut être remplacé par l’expression correspondante. Par exemple :

        int
        foo (int how)
        {
          switch (how) {
            case 2: how = 205; break;
            case 3: how = 305; break;
            case 4: how = 405; break;
            case 5: how = 505; break;
            case 6: how = 605; break;
          }
          return how;
        }

sera transformé en 100 * how + 5 pour les valeurs définies dans l’expression switch.

Optimisation interprocédurale

Les réglages par défaut de la passe d’inlining avaient plus les bases de données C++ en tête, spécialement en la couplant avec une passe d’optimisation à l’édition des liens (link‐time optimization, LTO). Elle est maintenant paramétrable finement pour les bases de code qui pourraient l’exiger (et le temps nécessaire au réglage de ces paramètres le justifie dans votre projet de développement).
Le partitionnement en fonctions chaudes et froides (qui cherche à déterminer quelles fonctions ne nécessiteront pas d’optimisation car peu utilisées) est plus précis et plus agressif.

Le passage à l’échelle a été fortement amélioré pour les grosses unités de compilation, particulièrement celles qu’on obtient avec l’optimisation à l’édition des liens sur de gros programmes. Honza Hubička, développeur de GCC, avait fait un gros travail qui avait été repris dans certains journaux ici même

Amélioration de l’optimisation après profilage

fprofile-use active maintenant des optimisations supplémentaires comme -fversion-loops-for-strides, -floop-interchange, -floop-unroll-and-jam et -ftree-loop-distribution.
Les histogrammes de comptage ont été retirés, ce qui réduit la taille des fichiers de profil. Les histogrammes sont calculés à la volée lors de l’optimisation à l’édition des liens. Un meilleur paramétrage a été effectué (pour les lecteurs intéressés, regardez la documentation de hot-bb-count-ws-permille).

Amélioration de l’optimisation à l’édition des liens (LTO)

Les types sont simplifiés avant d’être envoyés à l’étape suivante, ce qui réduit significativement la taille des objets avant la LTO, l’utilisation de la mémoire lors de l’optimisation à l’édition des liens, et ce qui facilite la parallélisation de cette optimisation.
Le nombre de partitions possibles pour cette parallélisation a justement été augmenté de 32 à 128 par défaut, pour tenir compte des processeurs qui auraient plus de 32 fils d’exécution virtuels comme les processeurs ThreadRipper d’AMD. Bien sûr, ce paramètre est modifiable pour les développeurs qui auraient la chance d’avoir une machine avec encore plus de cœurs !
Les alertes sur les violations de la règle C++ qui exige qu’il n’y ait qu’une seule déclaration sont maintenant plus informatives et moins redondantes. Ces violations sont souvent détectées à la LTO, puisque c’est seulement là que le compilateur peut avoir une vision globale du programme.
Au final, les compilations de Firefox 66 et de LibreOffice 6.2.3 sur une machine à huit cœurs ont été réduites de 5 % comparées à GCC 8.3. La taille des fichiers objets pré‐LTO a été réduite de 7 %. Le temps nécessaire à l’étape LTO a été réduit de 11 % et passe significativement mieux à l’échelle pour les environnements de développement encore plus parallèles. L’étape séquentielle de la LTO est 28 % plus rapide, et consomme 20 % de mémoire en moins. Dans l’étape parallèle, chaque fil utilise 30 % de mémoire en moins.

Enfin, l’outil gcov a une nouvelle option qui lui permet de colorier les fonctions chaudes comme l’outil perf fourni avec le noyau Linux. De plus, il a changé son format interne pour JSON.

Améliorations spécifiques à certains langages

La prise en charge d’OpenACC en C, C++ et Fortran continue d’être maintenue et améliorée. La plupart de la spécification d’OpenACC 2.5 est implémentée.

C et C++

La version 5.0 de la spécification OpenMP est partiellement prise en charge pour les langages C et C++. Les évolutions sont très nombreuses et il faut s’attendre au développement de nouvelles fonctionnalités dans les versions ultérieures de GCC.
De nouvelles extensions et remontées d’alertes ont été ajoutées (notamment sur le format des paramètres de fonctions d’entrée‐sortie type printf qui pourraient dépasser les chaînes fournies en entrée et donner lieu à des dépassements de tampon).
Lorsque le compilateur suggère une correction pour une erreur, la détection et la gestion des fautes de frappe ont été améliorées.

C

Une prise en charge préliminaire partielle de la version à venir du langage C, actuellement nommée C2X, a été ajoutée. C’est une véritable révolution qui s’annonce dans le monde des développeurs C. Pour le moment GCC prend en charge les assertions statiques Static_assert à un seul argument (contre deux dans la version C11, ajoutée dans GCC 4.6). Les extensions GNU sont disponibles avec l’option -std=gnu2x et les habituelles alertes de compatibilité ont également leur option dédiée (la rédaction recommande l’utilisation de -Wpedantic pour résoudre ce genre de problèmes).
Plus sérieusement, ce nouveau standard sera peut‐être l’occasion pour Microsoft de mettre sa bibliothèque C à jour, lui qui a toujours refusé de passer au standard C11.

Enfin, une nouvelle alerte spécifique à certaines fonctions standard a été ajoutée. Par exemple, l’utilisation de la fonction valeur absolue abs sur des flottants fera émettre la suggestion d’utiliser fabs.

C++

De nouvelles alertes sont remontées quand on compile un code qui utilise des déclarations implicites de constructeurs (de copie ou d’opérateur d’affectation) quand un seul des deux est explicitement fourni. D’autres alertes appellent l’attention du développeur sur un risque d’utiliser des pointeurs dans le vide en cas de retour ou d’affectation depuis de listes temporaires. Des alertes d’optimisation manquée ou d’appels redondants concernent la construction std::move. Une alerte concerne les fonctions de conversion qui ne peuvent pas être appelées en raison du typage.

L’interface C++ de GCC prend maintenant en charge quelques fonctionnalités du futur standard C++2a telles que basé sur la plage pour les instructions avec initialiseur range‐based for statements with initializer, les fonctions lambda constructibles et assignables ou dans un contexte non évalué, les membres vides, les attributs probables/improbables, des appels de fonctions virtuelles dans des expressions constantes, rendre des constructeurs explicites dans des concepts pour simplifier l’écriture et éviter les constructions de type SFINAE, l’imbrication d’espaces de nommage, faciliter la capture des arguments dans une fonction lambda qui en a un nombre variable (en évitant de devoir utiliser std::tuple<…>)…
Vous l’aurez compris le C++ est un langage très vivant et sa prise en charge sera au top dans GCC une fois le standard finalisé !

Le compilateur peut maintenant indiquer la localisation pertinente de certains problèmes d’initialisation. Par exemple :

    $ g++ -c bad-inits.cc
    bad-inits.cc:10:14: error: cannot convert 'json' to 'int' in initialization
       10 |   { 3, json::object },
          |        ~~~~~~^~~~~~
          |              |
          |              json
    bad-inits.cc:14:31: error: initializer-string for array of chars is too long [-fpermissive]
       14 | char buffers[3][5] = { "red", "green", "blue" };
          |                               ^~~~~~~
    bad-inits.cc: In constructor 'X::X()':
    bad-inits.cc:17:13: error: invalid conversion from 'int' to 'void*' [-fpermissive]
       17 |   X() : one(42), two(42), three(42)
          |             ^~
          |             |
          |             int

Auparavant, GCC indiquait une erreur à la parenthèse (ou accolade) fermante.

La remontée d’erreur liées à une mauvaise résolution des fonctions ou opérateurs surchargés a été améliorée. Dans l’exemple suivant, le compilateur met en évidence l’argument problématique et le paramètre auquel il ne peut pas être converti :

    $ g++ param-type-mismatch.cc
    param-type-mismatch.cc: In function 'int test(int, const char*, float)':
    param-type-mismatch.cc:8:32: error: cannot convert 'const char*' to 'const char**'
        8 |   return foo::member_1 (first, second, third);
          |                                ^~~~~~
          |                                |
          |                                const char*
    param-type-mismatch.cc:3:46: note:   initializing argument 2 of 'static int foo::member_1(int, const char**, float)'
        3 |   static int member_1 (int one, const char **two, float three);
          |                                 ~~~~~~~~~~~~~^~~

Les diagnostics au sujet d’opérateurs binaires utilisent des couleurs pour les distinguer et les soulignent différemment. Les diagnostics qui concernent les appels de fonctions soulignent plus facilement le paramètre pertinent de la déclaration :

    $ g++ bad-conversion.cc
    bad-conversion.cc: In function 'void caller()':
    bad-conversion.cc:9:14: error: cannot convert 'bool' to 'void*'
        9 |   callee (0, false, 2);
          |              ^~~~~
          |              |
          |              bool
    bad-conversion.cc:3:19: note:   initializing argument 2 of 'void callee(int, void*, int)'
        3 | void callee (int, void *, int)
          |                   ^~~~~~

Comme GCC le fait pour le C depuis la version 7, dorénavant, en C++, l’option -Wformat (qui vérifie les appels à scanf et consorts) montre la localisation précise du problème détecté au sein des chaînes de caractères avec les arguments et soulignera l’argument concerné lors de l’appel de la fonction.
Par exemple :

    $ g++ -c bad-printf.cc -Wall
    bad-printf.cc: In function 'void print_field(const char*, float, long int, long int)':
    bad-printf.cc:6:17: warning: field width specifier '*' expects argument of type 'int', but argument 3 has type 'long int' [-Wformat=]
        6 |   printf ("%s: %*ld ", fieldname, column - width, value);
          |                ~^~~               ~~~~~~~~~~~~~~
          |                 |                        |
          |                 int                      long int
    bad-printf.cc:6:19: warning: format '%ld' expects argument of type 'long int', but argument 4 has type 'double' [-Wformat=]
        6 |   printf ("%s: %*ld ", fieldname, column - width, value);
          |                ~~~^                               ~~~~~
          |                   |                               |
          |                   long int                        double
          |                %*f

De nombreuses suggestions ont été ajoutées qui pourraient concerner l’oubli d’un return *this. Cela concerne plusieurs opérateurs. Par exemple :

    $ g++ -c operator.cc
    operator.cc: In member function 'boxed_ptr& boxed_ptr::operator=(const boxed_ptr&)':
    operator.cc:7:3: warning: no return statement in function returning non-void [-Wreturn-type]
        6 |     m_ptr = other.m_ptr;
      +++ |+    return *this;
        7 |   }
          |   ^

Ou bien quand le compilateur s’attend à avoir un nom de type :

    $ g++ -c template.cc
    template.cc:3:3: error: need 'typename' before 'Traits::type' because 'Traits' is a dependent scope
        3 |   Traits::type type;
          |   ^~~~~~
          |   typename

Ou encore quand le développeur essaye d’utiliser un membre accesseur comme s’il s’agissait d’un membre de données :

    $ g++ -c fncall.cc
    fncall.cc: In function 'void hangman(const mystring&)':
    fncall.cc:12:11: error: invalid use of member function 'int mystring::get_length() const' (did you forget the '()' ?)
       12 |   if (str.get_length > 0)
          |       ~~~~^~~~~~~~~~
          |                     ()

Ou pour les énumérations à portée limitée (apparues avec C++11) :

    $ g++ -c enums.cc
    enums.cc: In function 'void json::test(const json::value&)':
    enums.cc:12:26: error: 'STRING' was not declared in this scope; did you mean 'json::kind::STRING'?
       12 |     if (v.get_kind () == STRING)
          |                          ^~~~~~
          |                          json::kind::STRING
    enums.cc:3:44: note: 'json::kind::STRING' declared here
        3 |   enum class kind { OBJECT, ARRAY, NUMBER, STRING, TRUE, FALSE, NULL_ };
          |                                            ^~~~~~

Et une variante pour intégrer les suggestions pour les fautes de frappes pour les membres de données avec accesseur :

    $ g++ -c accessor-fixit.cc
    accessor-fixit.cc: In function 'int test(t*)':
    accessor-fixit.cc:17:15: error: 'class t' has no member named 'ratio'; did you mean 'int t::m_ratio'? (accessible via 'int t::get_ratio() const')
       17 |   return ptr->ratio;
          |               ^~~~~
          |               get_ratio()

Enfin, bon nombre de diagnostics ont été améliorés en reliant la suggestion à l’erreur initiale plutôt que d’émettre les fameuses « notes » :

    $ g++ typo.cc
    typo.cc:5:13: error: 'BUFSIZE' was not declared in this scope; did you mean 'BUF_SIZE'?
        5 | uint8_t buf[BUFSIZE];
          |             ^~~~~~~
          |             BUF_SIZE

Bibliothèque standard C++ (libstdc++)

La prise en charge de C++17 a été améliorée :

  • tout d’abord, elle n’est plus marquée comme expérimentale ;
  • on peut choisir la politique d’exécution parallèle dans l’en‐tête <execution> ;
  • l’interface abstraite <memory_resource> a été ajoutée ;
  • les types et fonctions de <filesystem> ne nécessitent plus de lier avec -lstdc++fs.

La prise en charge expérimentale de C++2a comprend :

  • les traits std::remove_cvref, std::unwrap_reference, std::unwrap_decay_ref, std::is_nothrow_convertible et std::type_identity ;
  • les en‐têtes <bit> et <version> ;
  • l’effacement uniforme de conteneurs std::erase_if ;
  • la vérification de préfixe ou de suffixes de chaînes (fonctions starts_with et ends_with) ;
  • les fonctions utiles en interpolation std::midpoint et std::lerp ;
  • std::bind_front, std::visit<R>, std::assume_aligned, std::pmr::polymorphic_allocator<std::byte> et std::is_constant_evaluated() ;
  • des utilitaires de construction de type « utilisation‐allocation » ;
  • la prise en charge du type char8_t ;
  • la prise en charge d’un delete efficace pour les classes de taille variable (similaire à delete[]) ;
  • la prise en charge de l’ouverture de flux sur des fichiers avec des noms utilisant des caractères étendus sous Windows ;
  • la prise en charge incomplète de la bibliothèque C++17 Filesystem et de la spécification technique ISO/IEC Filesystem sous Windows ;
  • la prise en charge incomplète et expérimentale de la spécification technique ISO/IEC Networking.

D

Le langage D (et la bibliothèque standard associée) est pris en charge en version 2.076.

Fondé sur l’utilisation d’un ramasse‐miettes comme Java, de la programmation par contrats comme Eiffel, multi‐paradigme comme C++, dont il s’inspire, va‐t‐il se faire une place là où Rust est en plein essor et Go continue sur sa lancée ?

Fortran

Les entrées‐sorties asynchrones sont maintenant prises en charge en totalité pour les systèmes qui ne proposent pas les variables conditionnelles POSIX (au contraire d’AIX). Les programmes doivent être liés avec la bibliothèque pthreads pour les utiliser, sinon les entrées‐sorties sont faites de manière synchrone.
Diverses fonctionnalités utiles ont été ajoutées (MINLOC et MAXLOC acceptent l’argument BACK, IS_CONTIGUUOUS ou FINDLOC…). Les variables complexes donnent maintenant accès à leur partie réelle et leur partie imaginaire via c%re et c%im. Certains paramètres de types peuvent être récupérés, par exemple str%len ou a%kind. Les descripteurs C et le fichier d’en‐tête ISO_Fortran_binding.h ont été implémentés.
Les fonctions MAX et MIN ne garantissent plus un retour si l’un de leurs arguments est NaN, ce qui est conforme au standard Fortran et que font les autre compilateurs Fortran. Si besoin, il faut vérifier l’entrée de manière explicite avec les fonctions intrinsèques IEEE_IS_NAN du module IEEE_ARITHMETIC.

Une nouvelle option -fdec-include, activée aussi par -fdec, a été ajoutée à la ligne de commande comme extension de compatibilité pour du code ancien. Avec cette option, la directive INCLUDE est analysée comme une déclaration, ce qui permet à la déclaration d’être écrite sur plusieurs lignes en utilisant le symbole de continuation de ligne.

Une nouvelle directive BUILTIN a été ajoutée. Son utilité réside dans la fourniture d’une API entre le compilateur GCC et la bibliothèque GNU C qui définirait des implémentations vectorisées de fonctions mathématiques.

libgccjit

Rappelons qu’il s’agit d’une bibliothèque fournie depuis la version 5.2 de GCC, et qui permet de l’utiliser comme un compilateur à la volée (just‐in‐time). Autrement dit, c’est une manière d’utiliser GCC non pas comme un exécutable séparé mais comme une bibliothèque dans un programme existant. Cela rend l’écriture de compilateurs très facile.

L’interface de programmation (API) de libgccjit a un nouveau point d’entrée, gcc_jit_context_add_driver_option.

Nouvelles architectures cibles et améliorations particulières

AArch64 et ARM

Changement d’interface binaire (ABI)

Un bogue dans l’implémentation du standard d’appels de procédure (AAPCS) a été corrigé. Il affectait les versions 6, 7 et 8 de GCC. En effet, une structure contenant un champ de bits basé sur un type entier de 64 bits et ne contenant aucun autre élément nécessitant un alignement sur 64 bits pouvait être passé de manière incorrecte en paramètre lors d’un appel de fonction. Ce changement d’interface binaire peut casser les applications existantes ; aussi, l’option -Wpsabi fournit une alerte pour le code qui pourrait être affecté.

De nouveaux processeurs sont maintenant pris en charge : ARM Cortex-A76 (cortex-a76), ARM Cortex-A55 et Cortex-A76 DynamIQ big.LITTLE (cortex-a76.cortex-a55), ARM Neoverse N1 (neoverse-n1). Les identificateurs GCC peuvent être utilisés comme arguments pour les options -mcpu ou -mtune si l’on veut compiler spécialement pour un de ces processeurs.

Les instructions pour manipuler des nombres complexes de la spécification ACLE ARMv8.3-A sont prises en charge au travers de fonctions intégrées quand l’option -march=armv8.3-a (ou équivalent) est ajoutée. C’est même possible si l’on utilise des flottants en demi‐précision (qui tiennent sur 16 bits seulement) en ajoutant le drapeau +fp16, par exemple -march=armv8.3-a+fp16.

L’architecture ARMv8.5-A est maintenant prise en charge, y compris avec ses fonctionnalités de sécurité (notamment pour contrer l’attaque Spectre) qui ne touchent que l’assembleur généré. Ainsi, il est possible d’ajouter une instruction Speculation Barrier, des instructions restreignant l’exécution et la prédiction de données, ou encore des instructions qui sont sûres face aux attaques de type « Speculative Store Bypass ».

AArch64

Nouveau processeur pris en charge, l’ARM Neoverse E1, nouvelles fonctionnalités (génération d’aléa, marquage mémoire, protection de branche).
Dans GCC, la prise en charge de l’architecture AArch64 inclut maintenant des protections contre les attaques de type stack clash qui, si elles ne sont pas nouvelles dans le principe, connaissent toujours des développements contournant les mécanismes mis en place (comme une page vide autour de la pile qui génèrera une interruption en cas d’accès). Ainsi, la taille de l’espace intouchable autour de la pile est paramétrable entre 4 Kio et 64 Kio.

ARM

Les architectures ARMv2 (datant de 1986) et ARMv3 ont été retirées, comme ARMv5 et ARMv5E qui ne sont utilisées par aucune puce connue (à l’inverse des ARMv5T, ARMv5TE et ARMv5TEJ, qui sont toujours prises en charge par GCC).
La configuration de l’unité de virgule flottante des Cortex-R7 et Cortex-R8 avec l’option -mcpu kivabien a été corrigée.

Prise en charge des cartes graphiques AMD à cœurs GCN

Dans le but de pouvoir utiliser les cartes graphiques AMD récentes comme unité de calcul dans des programmes utilisant OpenMP ou OpenACC, GCC peut maintenant générer du code pour les cœurs AMD Fiji et Vega10 (gfx900). Il est pour le moment limité à des programmes complets à un seul fil d’exécution (autrement dit : inutile en l’état), mais c’est un premier pas très important pour préparer l’avenir.

ARC

Ceux qui utilisent un des processeurs très modulaires Argonaut peuvent maintenant demander à utiliser une passe d’allocation de registre similaire à celle utilisée par défaut dans la majorité des autres architectures plutôt que l’algorithme par rechargement, ancien et qui produit du code moins efficace. De plus il est maintenant possible de compiler du code haute densité pour les processeurs qui l’acceptent et d’utiliser l’instruction branch‐and‐index.

C-SKY

Les processeurs de conception chinoise C-SKY sont maintenant pris en charge par GCC après l’avoir été par le noyau Linux tout récemment. Il s’agit d’une conception nouvelle de parenté inspirée par RISC-V.

Sera‐ce la dernière nouvelle architecture à être intégrée à GCC ? En effet, la question se pose quand la majorité de l’industrie hors ARM et AMD64 se tourne vers RISC-V.

IA-32 et x86-64

La prise en charge des instructions de protection mémoire Intel MPX (Memory Protection Extensions) a été retirée. Ces instructions supplémentaires étaient prévues pour mieux protéger la mémoire lors de l’accès par pointeur, pour éviter les failles de sécurité de type « dépassement de tampon ». Toutefois, l’aide d’Intel aux développeurs des projets libres pour leur prise en charge dans le compilateur et le noyau fut assez parcellaire, et leur prise en charge a été retirée dans le noyau Linux depuis la version 4.20.

De plus, ce jeu d’instructions entrait en conflit avec d’autres jeux d’instructions pour les architectures IA-32 et X86-64 (également proposées par Intel, telles les Intel TSX et Intel SGX), elles ne protégeaient pas contre les attaques de type Spectre et Meltdown, ralentissaient inutilement les programmes tournant sur les processeurs qui ne les gèrent pas et forçaient les développeurs C/C++ à ne pas utiliser des constructions de programmation pourtant très classiques.

OpenRISC

Les processeurs OpenRISC sont maintenant pris en charge. Plus ancien que RISC-V, mais aux choix techniques différents, cette architecture est complètement ouverte et devient ainsi pleinement prise en charge par les outils GNU.

Systèmes d’exploitation

Windows

Un bogue de l’ABI C++ Microsoft a été corrigé. Il concernait la gestion des champs de bits. L’ABI Microsoft est utilisée pour les cibles Mingw, pour PowerPC, IA-32 et x86-64 , si vous insistez, voire SuperH. Mais à ce niveau de technicité, vous savez probablement ce que vous faites.

Architectures et systèmes d’exploitation marqués comme obsolètes

Les prises en charge de Solaris 10 et du processeur Cell (qu’on trouvait dans la Playstation 3) ont été déclarées obsolètes et seront retirées dans les versions futures de GCC.

Gestion des greffons

Les développeurs de greffons verront leur vie facilitée, car le sous‐système de diagnostics de GCC peut maintenant regrouper les diagnostics associés (et les hiérarchiser dans un rapport au format JSON).
GCC a également un ensemble de recommandations pour l’utilisabilité, avec des informations et des conseils sur la manière de développer de nouveaux diagnostics.

Autres améliorations notables

La suite de tests internes de gcc (selftest) fonctionne maintenant en C++ et en C, au moins quand on compile GCC en mode de déverminage (debug).

Aller plus loin

  • # correction

    Posté par . Évalué à 1.

    exploitaion => exploitation

    • [^] # Re: correction

      Posté par (page perso) . Évalué à 2.

      corrigé, merci

      "La liberté est à l'homme ce que les ailes sont à l'oiseau" Jean-Pierre Rosnay

      • [^] # Re: correction

        Posté par . Évalué à 1.

        Une autre coquille :
        "Les types et fonctions de ne nécessitent plus de lier avec"

        • [^] # Re: correction

          Posté par (page perso) . Évalué à 3.

          Corrigé, merci. (plus qu'une coquille un souci de <truc ressemblant à une balise html> qui se fait dégager)

      • [^] # Re: correction

        Posté par . Évalué à 1.

        autres coquilles :
        - dans la table des matières, le 2e titre est vide
        - dans la section Fortran, 1ère phrase, il manque le "ne" de la négation.

        • [^] # Re: correction

          Posté par (page perso) . Évalué à 3.

          Corrigé, merci.

          • [^] # Re: correction

            Posté par (page perso) . Évalué à 2.

            Cette dépêche n'ayant été relue que par des « anciens » modérateurs, ça prouve qu'on est tous fatigués ! Sur ce RDV à Deauville, je me tire avec la Tesla (j'ai chipé les clefs à la dernière réunion).

            "La liberté est à l'homme ce que les ailes sont à l'oiseau" Jean-Pierre Rosnay

      • [^] # Re: correction

        Posté par (page perso) . Évalué à 2.

        Lien cassé:

        Le langage [D] est pris en charge en version 2.076.

        • la référence à D est au fraises.

        Sed fugit interea, fugit inreparabile tempus, singula dum capti circumvectamur amore

    • [^] # Re: correction

      Posté par (page perso) . Évalué à 1.

      complémentationcomplétion ou achèvement (aucun des deux ne correspond exactement à l'anglais « completion, » mais « complémentation » est encore plus éloigné).

    • [^] # Re: correction

      Posté par . Évalué à 2.

      Encore quelques corrections.

      Fortran :
      leur partie imaginaire viac%re : manque une espace ;
      des implémentations vectorisées de fonctions mathématiquesx : un point au lieu (ou en plus) du x.

      libgccjit :
      Rappelons qu'il s'agit d'une bibliothèqe : manque un u.

      Changement d'interface binaire (ABI) :
      De nouveaux processeurs sont maintenant prix en charge : celle-là, je l'aime bien ;
      Les instructions […] sont prises en charges : sans s.

      Et merci pour la dépêche.

      • [^] # Re: correction

        Posté par (page perso) . Évalué à 3.

        C'est corrigé. Merci pour le signalement.

        « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

    • [^] # Re: correction

      Posté par . Évalué à 3.

      • Les alertes sur les violations […) sont maintenant plus informatives et moins redondantes.

      • Au final, la compilation de Firefox 66 et de LibreOffice 6.2.3 sur une machine à 8 cœurs a été réduite de 5%, comparée à GCC 8.3.
        (ou alors, "les compilations […] ont été réduites, comparées")

      • [^] # Re: correction

        Posté par . Évalué à 3.

        Je viens de faire ma passe de post-correction, elles ne m’avaient pas échappé. ;-)

  • # Nouveau processeur ?

    Posté par (page perso) . Évalué à 5.

    AArch64

    Nouveau processeur pris en charge, le Arm Neoverse E1, nouvelles fonctionnalités (génération d'aléa, marquage mémoire, protection de branche).

    Save-vous pourquoi il faut un support d'un processeur spécifique dans GCC ?

    • [^] # Re: Nouveau processeur ?

      Posté par (page perso) . Évalué à 5. Dernière modification le 07/05/19 à 11:29.

      Ça me semble tellement évident que j'écris peut-être une grosse bêtise :
      Chaque famille de processeurs a son propre langage machine à prendre en charge. Leurs variantes et les évolutions d'architectures ajoutent ou modifient des jeux d'instructions, donc des optimisations à prendre en charge. Sans oublier les bugs, la gestion de la mémoire, les niveaux de cache, les sécurités, …

      "La liberté est à l'homme ce que les ailes sont à l'oiseau" Jean-Pierre Rosnay

      • [^] # Re: Nouveau processeur ?

        Posté par (page perso) . Évalué à 3.

        A ce sujet, c'est une prise en charge «officielle», le travail sur cette architecture était déjà en cours, sous le nom de code «ares».

        On peut toujours l'utiliser:

        -mcpu=ares

      • [^] # Re: Nouveau processeur ?

        Posté par . Évalué à 4.

        Ce n'est pas un problème de jeu d'instruction, c'est surtout un problème de description du comportement dynamique à l'exécution. Le générateur de code doit anticiper le comportement à l'exécution pour produire des instructions dans le bon ordre supposé. Suivant que le processeur réordonne ou non, suivant qu'il est risc, superscalaire ou wliw, le générateur de code doit s'assurer de saturer le chemin de données.

  • # Coquille

    Posté par . Évalué à 1.

    « Une partie d'icelles a été motivée » ? De celles-ci ?

  • # Une nouvelle corde à son ARC

    Posté par . Évalué à 5.

    ARC: De plus il est maintenant possible de compiler du code haute densité pour les processeurs qui l'acceptent […]

    Pas vraiment, les instructions « haute densité » étaient déjà supportées ; la différence est l'utilisation des instructions multiple load/store (effectivement HD) en début et fin de fonction (frame en VO).

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.