Dopo un anno di sviluppo, è stato rilasciato il set di compilatori GCC 11.1, il primo significante rilascio nella nuova serie GCC 11.x. In base al nuovo schema di numerazione delle versioni, la versione 11.0 è stata utilizzata durante lo sviluppo, e poco prima del rilascio di GCC 11.1 è già stata ramificata la serie GCC 12.0, da cui sarà composto il prossimo importante rilascio, GCC 12.1.
GCC 11.1 è notevole per il passaggio predefinito al formato dei file di debug DWARF 5, l'inclusione predefinita dello standard C++17 («-std=gnu++17»), significativi miglioramenti nel supporto dello standard C++20, supporto sperimentale per C++23, miglioramenti legati al futuro standard del linguaggio C (C2x), e nuove ottimizzazioni delle prestazioni.
Principali modifiche:
- La modalità predefinita per il linguaggio C++ è stata cambiata per utilizzare lo standard C++17 (-std=gnu++17) al posto del precedentemente proposto C++14. È possibile disabilitare selettivamente il nuovo comportamento di C++17 nella gestione dei template, nei quali come parametro vengono utilizzati altri template (-fno-new-ttp-matching).
- È stato aggiunto il supporto per l'accelerazione hardware dello strumento AddressSanitizer, permettendo di rilevare l'accesso a aree di memoria liberate, l'uscita dai confini di un buffer allocato e alcuni altri tipi di errori di gestione della memoria. L'accelerazione hardware è attualmente disponibile solo per l'architettura AArch64 ed è focalizzata sull'utilizzo durante la compilazione del kernel Linux. Per abilitare l'accelerazione hardware di AddressSanitizer durante la compilazione dei componenti dell'utente è stato aggiunto il flag "-fsanitize=hwaddress", e per il kernel "-fsanitize=kernel-hwaddress".
- Quando viene generata l'informativa di debug, viene utilizzato di default il formato DWARF 5, che consente di generare dati di debug il 25% più compatti rispetto alle versioni precedenti. Per un supporto completo di DWARF 5 è necessaria almeno la versione 2.35.2 di binutils. Nella strumenti di debug, il formato DWARF 5 è supportato a partire da GDB 8.0, valgrind 3.17.0, elfutils 0.172 e dwz 0.14. Per generare file di debug utilizzando altre versioni di DWARF, è possibile utilizzare le opzioni "-gdwarf-2", "-gdwarf-3" e "-gdwarf-4".
- Sono aumentati i requisiti per i compilatori che possono essere utilizzati per compilare GCC. Ora il compilatore deve supportare lo standard C++11 (prima era richiesto C++98), ovvero se per compilare GCC 10 era sufficiente avere GCC 3.4, per compilare GCC 11 ora è necessario avere almeno GCC 4.8.
- È stato cambiato il nome e la posizione dei file per il salvataggio dei dump, dei file temporanei e delle informazioni aggiuntive necessarie per l'ottimizzazione LTO. Questi file ora vengono sempre salvati nella directory corrente, a meno che il percorso non venga esplicitamente modificato tramite i parametri «-dumpbase», «-dumpdir» e «-save-temps=*».
- È stata dichiarata obsoleta e verrà presto rimossa la supporto per il formato binario BRIG, destinato all'uso con il linguaggio HSAIL (Heterogeneous System Architecture Intermediate Language).
- Sono state ampliate le funzionalità della modalità ThreadSanitizer (-fsanitize=thread), progettata per rilevare le condizioni di race nell'accesso concorrente agli stessi dati da diversi thread di un'applicazione multithread. Nella nuova versione è stata aggiunta la compatibilità con runtime e ambienti alternativi, così come il supporto per lo strumento di debug KCSAN (Kernel Concurrency Sanitizer), progettato per identificare dinamicamente le condizioni di race all'interno del kernel Linux. Sono state aggiunte nuove opzioni «—param tsan-distinguish-volatile» e «—param tsan-instrument-func-entry-exit».
- I numeri di colonna nei messaggi diagnostici ora riflettono non il conteggio dei byte dall'inizio della riga, ma i veri numeri di colonna, tenendo conto dei caratteri multibyte e dei caratteri che occupano più posizioni all'interno della riga (ad esempio, il carattere 🙂 occupa due posizioni e viene codificato in 4 byte). Analogamente, i caratteri di tabulazione vengono ora gestiti come un numero definito di spazi (configurabile tramite l'opzione -ftabstop, predefinito 8). Per ripristinare il comportamento precedente è stata proposta l'opzione «-fdiagnostics-column-unit=byte», e per determinare il valore iniziale (numerazione da 0 o 1) è l'opzione «-fdiagnostics-column-origin=».
- Il vettorizzatore tiene conto di tutto il contenuto della funzione e include la gestione delle possibilità legate alle intersezioni e ai riferimenti a blocchi precedenti nel grafo di flusso di controllo (CFG, control-flow graph).
- L'ottimizzatore implementa la possibilità di convertire in un'espressione switch una serie di operazioni condizionali che confrontano la stessa variabile. In seguito, l'espressione switch può essere codificata utilizzando istruzioni di test bit per gestire tale conversione (è stata aggiunta l'opzione «-fbit-tests» per il controllo di questa trasformazione).
- Migliorate le ottimizzazioni interprocedurali. È stato aggiunto un nuovo passaggio IPA-modref (-fipa-modref) per monitorare gli effetti collaterali durante le chiamate di funzioni e aumentare la precisione dell'analisi. È stata migliorata l'implementazione del passaggio IPA-ICF (-fipa-icf), riducendo il consumo di memoria durante la compilazione e aumentando il numero di funzioni unificate per cui viene eseguita la fusione di blocchi di codice identici. Nel passaggio IPA-CP (Interprocedural constant propagation) è stata migliorata l'euristica di previsione tenendo conto dei limiti noti e delle caratteristiche di funzionamento dei cicli.
- Nella realizzazione delle ottimizzazioni durante la fase di collegamento (LTO), il formato del bytecode è stato ottimizzato per ridurre le dimensioni e aumentare la velocità di elaborazione. È stato ridotto il picco di consumo di memoria durante la fase di collegamento.
- Nell'ambito dell'ottimizzazione basata sui risultati della profilazione del codice (PGO - ottimizzazione guidata da profilo), che consente di generare codice più ottimale sulla base dell'analisi delle caratteristiche di esecuzione, è stata ridotta la dimensione dei file dati GCOV grazie a una compressione più compatta dei contatori zero. Migliorata la modalità "-fprofile-values", grazie al monitoraggio di un numero maggiore di parametri durante le chiamate indirette.
- Prosegue l'implementazione dello standard OpenMP 5.0 (Open Multi-Processing), che definisce l'API e i metodi per l'applicazione delle tecniche di programmazione parallela su sistemi multi-core e ibridi (CPU+GPU/DSP) con memoria condivisa e blocchi di vettorizzazione (SIMD). È stato aggiunto il supporto iniziale per la direttiva allocate e la possibilità di utilizzare cicli eterogenei nelle strutture OpenMP. Implementato il supporto per la variabile d'ambiente OMP_TARGET_OFFLOAD.
- È stata migliorata l'implementazione della specifica di programmazione parallela OpenACC 2.6 per i linguaggi C, C++ e Fortran, definendo strumenti per il trasferimento di operazioni (offloading) su GPU e processori specializzati, come NVIDIA PTX.
- Per i linguaggi della famiglia C è stato introdotto un nuovo attributo "no_stack_protector", progettato per contrassegnare le funzioni per le quali non deve essere abilitata la protezione dello stack ("-fstack-protector"). L'attributo "malloc" è stato ampliato con il supporto per l'identificazione di coppie di chiamate per l'allocazione e la deallocazione della memoria (allocator/deallocator), utilizzato nell'analisi statica per identificare errori tipici nella gestione della memoria (perdite di memoria, utilizzo dopo la liberazione, chiamata doppia a free, ecc.) e negli avvisi del compilatore "-Wmismatched-dealloc", "-Wmismatched-new-delete" e "-Wfree-nonheap-object", che informano della incoerenza tra le operazioni di liberazione e allocazione di memoria.
- Per il linguaggio C sono stati aggiunti nuovi avvisi:
- "-Wmismatched-dealloc" (abilitato di default) — avverte su operazioni di liberazione della memoria in cui viene utilizzato un puntatore incompatibile con le funzioni di allocazione della memoria.
- «-Wsizeof-array-div» (attivato con «-Wall») — avverte di una divisione tra due operatori sizeof, se il divisore non corrisponde alla dimensione dell'elemento dell'array.
- «-Wstringop-overread» (attivato per impostazione predefinita) — avverte di una chiamata a una funzione di stringa che legge dati da un'area al di fuori dei confini dell'array.
- «-Wtsan» (attivato per impostazione predefinita) — avverte dell'uso di funzionalità (come std::atomic_thread_fence) che non sono supportate in ThreadSanitizer.
- «-Warray-parameter» e «-Wvla-parameter» (attivato con «-Wall») — avverte sulla ridefinizione di funzioni con dichiarazioni di argomenti non compatibili, relative ad array di lunghezza fissa e variabile.
- L'avviso «-Wuninitialized» ora identifica i tentativi di lettura da memoria dinamicamente allocata non inizializzata.
- Nell'avviso «-Wfree-nonheap-object» è stata ampliata la gamma di casi definiti per le chiamate alle funzioni di liberazione della memoria con puntatori ottenuti da funzioni di allocazione dinamica.
- Nell'avviso «-Wmaybe-uninitialized» è stata estesa l'identificazione del passaggio a funzioni di puntatori che fanno riferimento a aree di memoria non inizializzate.
- Per il linguaggio C, è stata implementata una serie di nuove funzionalità sviluppate nell'ambito dello standard C2X (attivabile usando -std=c2x e -std=gnu2x): macro BOOL_MAX e BOOL_WIDTH, facoltatività di indicare i nomi dei parametri non utilizzati nelle definizioni delle funzioni (come in C++), l'attributo "[[nodiscard]]", l'operatore del preprocessore "__has_c_attribute", le macro FLT_IS_IEC_60559, DBL_IS_IEC_60559, LDBL_IS_IEC_60559, __STDC_WANT_IEC_60559_EXT__, INFINITY, NAN, FLT_SNAN, DBL_SNAN, LDBL_SNAN, DEC_INFINITY e DEC_NAN, macro NaN per FloatN, _FloatNx e _DecimalN, e la possibilità di indicare etichette di salto prima delle dichiarazioni e alla fine di operatori composti.
- Per C++, è stata introdotta una serie di modifiche e novità proposte nello standard C++20, incluse le funzioni virtuali "consteval virtual", i pseudodecostruttori per la fine del ciclo di vita degli oggetti, l'uso della classe enum e il calcolo della dimensione dell'array nell'espressione "new".
- Per C++, è stato aggiunto il supporto sperimentale per alcuni miglioramenti sviluppati per il futuro standard C++23 (-std=c++23, -std=gnu++23, -std=c++2b, -std=gnu++2b). Ad esempio, è stata introdotta la supporto per il suffisso letterale "zu" per i valori signed di size_t.
- In libstdc++, è stato migliorato il supporto per lo standard C++17, con l'introduzione dell'implementazione std::from_chars e std::to_chars per i tipi a virgola mobile. Sono stati implementati nuovi elementi dello standard C++20, inclusi std::bit_cast, std::source_location, operazioni atomiche wait e notify, , , , , così come elementi del futuro standard C++23 (std::to_underlying, std::is_scoped_enum). È stato aggiunto il supporto sperimentale per i tipi per l'elaborazione parallela dei dati (SIMD, Data-Parallel Types). È stata accelerata l'implementazione di std::uniform_int_distribution.
- Rimosso il segno di qualità alfa da libgccjit, una libreria condivisa per l'integrazione di un generatore di codice in altri processi e per l'organizzazione della compilazione JIT di bytecode in codice macchina. È stata aggiunta la possibilità di compilare libgccjit per MinGW.
- Aggiunto il supporto per l'architettura AArch64 Armv8-R (-march=armv8-r). Per le architetture AArch64 e ARM è stato aggiunto il supporto per i seguenti processori (parametri -mcpu e -mtune): Arm Cortex-A78 (cortex-a78), Arm Cortex-A78AE (cortex-a78ae), Arm Cortex-A78C (cortex-a78c), Arm Cortex-X1 (cortex-x1), Arm Neoverse V1 (neoverse-v1) e Arm Neoverse N2 (neoverse-n2). Sono stati inoltre aggiunti i CPU Fujitsu A64FX (a64fx) e Arm Cortex-R82 (cortex-r82), che supportano solo l'architettura AArch64.
- Aggiunta il supporto per l'uso delle istruzioni SIMD Armv8.3-a (AArch64/AArch32), SVE (AArch64), SVE2 (AArch64) e MVE (AArch32 M-profile) per l'auto-vettorizzazione delle operazioni che eseguono addizioni, sottrazioni, moltiplicazioni e varianti di addizione/sottrazione su numeri complessi. Per ARM è stata aggiunta una prima supporto per l'auto-vettorizzazione utilizzando il set di istruzioni MVE.
- Per le piattaforme ARM è stato fornito un set completo di funzioni intrinseche integrate nel compilatore C, sostituite da istruzioni vettoriali estese (SIMD), coprendo tutte le istruzioni NEON documentate nella specifica ACLE Q3 2020.
- Nel backend per la generazione di codice per GPU AMD basate su microarchitettura GCN è stato aggiunto il supporto per GPU gfx908.
- Aggiunto il supporto per nuovi processori e nuove estensioni del set di istruzioni implementate in essi:
- Intel Sapphire Rapids (-march=sapphirerapids, include il supporto per le istruzioni MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD, CLDEMOTE, SERIALIZE, PTWRITE, WAITPKG, TSXLDTRK, AMT-TILE, AMX-INT8, AMX-BF16 e AVX-VNNI).
- Intel Alderlake (-march=alderlake, include il supporto per le istruzioni CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, KEYLOCKER, AVX-VNNI e HRESET).
- Intel Rocketlake (-march=rocketlake, variante di Rocket Lake senza supporto per SGX).
- AMD Zen 3 (-march=znver3).
- Per i sistemi IA-32/x86-64 basati su processori Intel, è stata aggiunta la supporto per nuove istruzioni del processore TSXLDTRK, SERIALIZE, HRESET, UINTRKEYLOCKER, AMX-TILE, AMX-INT8, AMX-BF16, AVX-VNNI.
- È stata aggiunta la supporto per i flag «-march=x86-64-v[234]» per selezionare i livelli dell'architettura x86-64 (v2 — comprende le estensioni SSE4.2, SSSE3, POPCNT e CMPXCHG16B; v3 — AVX2 e MOVBE; v4 — AVX-512).
- È stata aggiunta la supporto per sistemi RISC-V con ordine di byte «big-endian». È stata aggiunta l'opzione «-misa-spec=*» per selezionare la versione della specifica dell'architettura del set di istruzioni RISC-V. È stata aggiunta la supporto per AddressSanitizer e la protezione dello stack tramite etichette canarie.
- È proseguito il miglioramento della modalità di analisi statica «-fanalyzer», che esegue un'analisi interprocedurale ad alta intensità di risorse dei percorsi di esecuzione del codice e dei flussi di dati nel programma. La modalità è in grado, durante la compilazione, di identificare problemi come la doppia chiamata della funzione free() per un unico blocco di memoria, perdite di descrittori di file, dereferenziazione e passaggio di puntatori nulli, accesso a blocchi di memoria liberati, utilizzo di valori non inizializzati, ecc. Nella nuova versione:
- Il codice per il monitoraggio dello stato del programma è stato completamente riscritto. I problemi con la verifica di file C di dimensioni molto grandi sono stati risolti.
- Aggiunto il supporto iniziale per C++.
- L'analisi dell'allocazione e della liberazione della memoria è stata astratta dalle funzioni specifiche malloc e free, e ora supporta new/delete e new[]/delete[].
- Aggiunti nuovi avvisi: -Wanalyzer-shift-count-negative, -Wanalyzer-shift-count-overflow, -Wanalyzer-write-to-const e -Wanalyzer-write-to-string-literal.
- Aggiunte nuove opzioni di debug: -fdump-analyzer-json e -fno-analyzer-feasibility.
- Implementata la possibilità di estendere l'analizzatore tramite plugin per GCC (ad esempio, è stato preparato un plugin per controllare l'uso scorretto della Global Interpreter Lock (GIL) in CPython).
Fonte: opennet.ru
