Nach einem Jahr Entwicklung wurde die Freigabe des freien Compiler-Sets GCC 11.1 veröffentlicht, der erste bedeutende Release in der neuen Reihe GCC 11.x. Gemäß dem neuen Versionsnummerierungssystem wurde Version 11.0 während der Entwicklungsphase verwendet, und kurz vor der Veröffentlichung von GCC 11.1 wurde bereits der Branch GCC 12.0 abgezweigt, auf dessen Basis der nächste bedeutende Release GCC 12.1 entwickelt wird.
GCC 11.1 zeichnet sich durch den standardmäßigen Umstieg auf das Debug-Dateiformat DWARF 5 aus, der standardmäßigen Einbeziehung des C++17 Standards („-std=gnu++17“), erheblichen Verbesserungen der Unterstützung für den C++20 Standard, experimenteller Unterstützung für C++23, Fortschritten im Hinblick auf den kommenden C Standard (C2x) sowie neuen Leistungsoptimierungen.
Wesentliche Änderungen:
- Der Standardmodus für die Programmiersprache C++ wurde auf die Verwendung des C++17 Standards (-std=gnu++17) umgestellt, anstelle des zuvor angebotenen C++14. Es ist möglich, das neue Verhalten von C++17 beim Umgang mit Templates, in denen andere Templates als Parameter genutzt werden, selektiv zu deaktivieren (-fno-new-ttp-matching).
- Die Unterstützung für die hardwarebeschleunigte Ausführung des Tools AddressSanitizer wurde hinzugefügt. Dieses Tool erkennt Zugriffe auf bereits freigegebene Speicherbereiche, Pufferüberlauf-Fehler und andere Arten von Speicherfehlern. Die hardwarebasierte Beschleunigung ist derzeit nur für die AArch64-Architektur verfügbar und konzentriert sich auf die Verwendung beim Kompilieren des Linux-Kernels. Um die hardwarebeschleunigte AddressSanitizer-Funktion beim Erstellen von Benutzerraumbestandteilen zu aktivieren, wurde das Flag „-fsanitize=hwaddress“ hinzugefügt, für den Kernel „-fsanitize=kernel-hwaddress“.
- Bei der Standardgenerierung von Debug-Informationen wird das Format DWARF 5 verwendet, das im Vergleich zu früheren Versionen 25 % kompaktere Debug-Daten erzeugt. Für die vollständige Unterstützung von DWARF 5 sind binutils in der Version 2.35.2 oder höher erforderlich. In Debugging-Tools wird das DWARF 5-Format ab GDB 8.0, valgrind 3.17.0, elfutils 0.172 und dwz 0.14 unterstützt. Zur Generierung von Debug-Dateien mit anderen DWARF-Versionen können die Optionen „-gdwarf-2“, „-gdwarf-3“ und „-gdwarf-4“ verwendet werden.
- Die Anforderungen an die Compiler, die zur Erstellung von GCC verwendet werden können, wurden erhöht. Der Compiler muss jetzt den C++11-Standard unterstützen (früher war C++98 erforderlich). Das bedeutet, dass für die Erstellung von GCC 10 GCC 3.4 ausreichte, für die Erstellung von GCC 11 hingegen mindestens GCC 4.8 benötigt wird.
- Die Bezeichnung und der Speicherort der Dateien für das Speichern von Dumps, temporären Dateien und zusätzlichen Informationen, die für die Durchführung von LTO-Optimierungen erforderlich sind, wurden geändert. Solche Dateien werden jetzt immer im aktuellen Verzeichnis gespeichert, es sei denn, der Pfad wird ausdrücklich über die Parameter „-dumpbase“, „-dumpdir“ und „-save-temps=*“ geändert.
- Die Unterstützung für das binäre Format BRIG, das für die Verwendung mit der Sprache HSAIL (Heterogeneous System Architecture Intermediate Language) vorgesehen ist, wurde als veraltet erklärt und wird bald entfernt.
- Die Funktionen des ThreadSanitizer-Modus (-fsanitize=thread) wurden erweitert, um Zustände von Datenrennen beim gleichzeitigen Zugriff auf dieselben Daten aus verschiedenen Threads in einer mehrspurigen Anwendung zu erkennen. Die neue Version bietet Unterstützung für alternative Laufzeitumgebungen sowie für das Debugging-Tool KCSAN (Kernel Concurrency Sanitizer), das zur dynamischen Erkennung von Datenrennen im Linux-Kernel dient. Weitere Optionen wie «—param tsan-distinguish-volatile» und «—param tsan-instrument-func-entry-exit» wurden hinzugefügt.
- Die Spaltennummern in den Diagnosenachrichten spiegeln jetzt nicht mehr den Byte-Zähler vom Zeilenanfang wider, sondern zeigen tatsächlich die Spaltennummern, die mehrbyte Zeichen und Zeichen, die mehrere Positionen in einer Zeile einnehmen, berücksichtigen (zum Beispiel nimmt das Zeichen 🙂 zwei Positionen ein und wird mit 4 Bytes codiert). Ähnlich werden Tabulatorzeichen jetzt als eine bestimmte Anzahl von Leerzeichen behandelt (konfigurierbar über die Option -ftabstop, standardmäßig 8). Um das alte Verhalten wiederherzustellen, wurde die Option «-fdiagnostics-column-unit=byte» vorgeschlagen, und zur Bestimmung des Ausgangswerts (Zählung ab 0 oder 1) gibt es die Option «-fdiagnostics-column-origin=».
- Der Vektorisierer berücksichtigt jetzt den gesamten Funktionsinhalt und bietet eine Verarbeitung von Möglichkeiten, die mit Schnittmengen und Referenzen auf vorherige Blöcke im Kontrollflussdiagramm (CFG, Control Flow Graph) verbunden sind.
- Der Optimierer ermöglicht die Umwandlung in einen Switch-Ausdruck für eine Reihe von Bedingungsoperationen, bei denen dieselbe Variable verglichen wird. Der Switch-Ausdruck kann dann unter Verwendung von Bit-Testinstruktionen kodiert werden (zur Steuerung dieser Umwandlung wurde die Option „-fbit-tests“ hinzugefügt).
- Die interprozeduralen Optimierungen wurden verbessert. Ein neuer Durchgang IPA-modref (-fipa-modref) wurde hinzugefügt, um Nebenwirkungen beim Funktionsaufruf zu verfolgen und die Analysegenauigkeit zu erhöhen. Die Implementierung des Durchgangs IPA-ICF (-fipa-icf) wurde verbessert, wodurch der Speicherverbrauch während der Kompilierung gesenkt und die Anzahl der vereinheitlichten Funktionen erhöht wurde, für die die Zusammenführung identischer Codeblöcke durchgeführt wird. Im Durchgang IPA-CP (interprozedurale konstante Propagation) wurde die Heuristik zur Prognose unter Berücksichtigung bekannter Grenzen und Charakteristika von Schleifen optimiert.
- Bei der Umsetzung von Optimierungen in der Linking-Phase (LTO) wurde das Bytecode-Format optimiert, um die Größe zu reduzieren und die Verarbeitungsgeschwindigkeit zu erhöhen. Der Spitzenverbrauch von Speicher wurde in der Linking-Phase verringert.
- Im Optimierungsmechanismus, der auf den Ergebnissen der Code-Profilierung beruht (PGO – Profile-guided optimization), wurde die Datei-Größe für GCOV-Daten durch eine kompaktere Verpackung null Zähler reduziert, was eine generiertere Optimierung von Code aufgrund der Analyse von Laufzeitmerkmalen ermöglicht. Der Modus „-fprofile-values“ wurde verbessert, indem eine größere Anzahl von Parametern bei indirekten Aufrufen verfolgt wird.
- Die Umsetzung des OpenMP 5.0 Standards (Open Multi-Processing) wird fortgesetzt, der API und Methoden für paralleles Programmieren auf Multi-Core- und hybriden Systemen (CPU+GPU/DSP) mit gemeinsamem Speicher und Vektorisierungsblöcken (SIMD) definiert. Erste Unterstützung für die Direktive allocate sowie die Nutzung von heterogenen Schleifen in OpenMP-Konstruktionen wurde hinzugefügt. Unterstützung für die Umgebungsvariable OMP_TARGET_OFFLOAD wurde implementiert.
- Die Implementierung der OpenACC 2.6-Spezifikation für paralleles Programmieren wurde für die Sprachen C, C++ und Fortran verbessert. Sie definiert Mittel zum Offloading von Operationen auf GPUs und spezialisierte Prozessoren wie NVIDIA PTX.
- Für die C-Familie von Sprachen wurde ein neues Attribut „no_stack_protector“ eingeführt, um Funktionen zu kennzeichnen, für die der Stack-Schutz („-fstack-protector“) nicht aktiviert werden sollte. Das Attribut „malloc“ wurde um die Unterstützung zur Identifizierung von Call-Paaren zur Speicherallokation und -freigabe (Allocator/Deallocator) erweitert, was im statischen Analyzer zur Identifizierung typischer Speicherfehler (Speicherlecks, Nutzung nach Freigabe, doppelte Aufrufe von free usw.) und in den Compiler-Warnungen „-Wmismatched-dealloc“, „-Wmismatched-new-delete“ und „-Wfree-nonheap-object“ verwendet wird, die über Inkonsistenzen bei den Speicherfreigabe- und Allokationsoperationen informieren.
- Für die Programmiersprache C wurden neue Warnungen hinzugefügt:
- „-Wmismatched-dealloc“ (standardmäßig aktiviert) — warnt vor Speicherfreigabeoperationen, bei denen ein Zeiger verwendet wird, der nicht mit den Speicherallokationsfunktionen übereinstimmt.
- «-Wsizeof-array-div» (aktiviert mit «-Wall») — warnt vor der Division zweier sizeof-Operatoren, wenn der Divisor nicht mit der Größe des Array-Elements übereinstimmt.
- «-Wstringop-overread» (standardmäßig aktiviert) — warnt vor dem Aufruf einer String-Funktion, die Daten aus einem Bereich außerhalb der Array-Grenzen liest.
- «-Wtsan» (standardmäßig aktiviert) — warnt vor der Verwendung von Funktionen (wie std::atomic_thread_fence), die im ThreadSanitizer nicht unterstützt werden.
- «-Warray-parameter» und «-Wvla-parameter» (aktiviert mit «-Wall») — warnt vor der Überladung von Funktionen mit nicht kompatiblen Argumentdeklarationen, die sich auf feste und variable Array-Längen beziehen.
- Die Warnung «-Wuninitialized» erkennt jetzt Versuche, aus nicht initialisiertem dynamisch zugewiesenen Speicher zu lesen.
- In der Warnung «-Wfree-nonheap-object» wurde das Spektrum der erkannten Fälle erweitert, bei denen Speicherfreigabefunktionen mit einem Zeiger aufgerufen werden, der nicht über dynamische Zuweisungsfunktionen erhalten wurde.
- In der Warnung «-Wmaybe-uninitialized» wurde die Erkennung erweitert, um die Übergabe von Zeigern, die auf nicht initialisierte Speicherbereiche verweisen, an Funktionen zu identifizieren.
- Für die Programmiersprache C wurden eine Reihe neuer Funktionen im Rahmen des C2X-Standards eingeführt (aktivierbar mit den Optionen -std=c2x und -std=gnu2x): die Makros BOOL_MAX und BOOL_WIDTH, die Möglichkeit, die Namen ungenutzter Parameter in Funktionsdefinitionen (wie in C++) wegzulassen, das Attribut „[[nodiscard]]“, der Präprozessoroperator „__has_c_attribute“, die Makros 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 und DEC_NAN, NaN=Makros für FloatN, _FloatNx und _DecimalN sowie die Möglichkeit, Sprungmarken vor und am Ende zusammengesetzter Anweisungen anzugeben.
- Für C++ wurde eine Reihe von Änderungen und Neuerungen eingeführt, die im C++20-Standard vorgeschlagen wurden, darunter virtuelle Funktionen „consteval virtual“, Pseudodestruktoren zur Beendigung des Lebenszyklus von Objekten, die Verwendung der enum-Klasse und die Berechnung der Array-Größe im Ausdruck „new“.
- Für C++ wurde experimentelle Unterstützung für einige Verbesserungen implementiert, die für den zukünftigen C++23-Standard entwickelt werden (-std=c++23, -std=gnu++23, -std=c++2b, -std=gnu++2b). Zum Beispiel wurde die Unterstützung des literalen Suffixes „zu“ für positive size_t-Werte hinzugefügt.
- In libstdc++ wurde die Unterstützung für den C++17-Standard verbessert, einschließlich der Implementierung von std::from_chars und std::to_chars für Gleitkommatypen. Neue Elemente des C++20-Standards wurden eingeführt, darunter std::bit_cast, std::source_location, atomare Operationen wait und notify, , , , , sowie Elemente des zukünftigen C++23-Standards (std::to_underlying, std::is_scoped_enum). Experimentelle Unterstützung für Typen zur parallelen Datenverarbeitung (SIMD, Daten-parallele Typen) wurde hinzugefügt. Die Implementierung von std::uniform_int_distribution wurde beschleunigt.
- Das Alpha-Qualitätsmerkmal für libgccjit, einer gemeinsamen Bibliothek zur Einbettung eines Codegenerators in andere Prozesse und zur Organisation der JIT-Kompilierung von Bytecode in Maschinencode, wurde entfernt. Es wurde die Möglichkeit hinzugefügt, libgccjit für MinGW zu bauen.
- Die Unterstützung für die Architektur AArch64 Armv8-R (-march=armv8-r) wurde hinzugefügt. Für die Architekturen AArch64 und ARM wurde die Unterstützung für Prozessoren (Parameter -mcpu und -mtune) hinzugefügt: 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) und Arm Neoverse N2 (neoverse-n2). Zudem wurden die CPUs Fujitsu A64FX (a64fx) und Arm Cortex-R82 (cortex-r82) hinzugefügt, die nur die Architektur AArch64 unterstützen.
- Unterstützung für die Verwendung von SIMD-Befehlen Armv8.3-a (AArch64/AArch32), SVE (AArch64), SVE2 (AArch64) und MVE (AArch32 M-Profil) zur automatischen Vektorisierung von Operationen, die Addition, Subtraktion, Multiplikation und Varianten von Addition/Subtraktion an komplexen Zahlen durchführen, wurde hinzugefügt. Für ARM wurde erste Unterstützung für die automatische Vektorisierung mit dem MVE-Befehlssatz hinzugefügt.
- Für ARM-Plattformen wurde ein vollständiger Satz von im Compiler integrierten C-Funktionen (Intrinsics) bereitgestellt, die auf erweiterte Vektorbefehle (SIMD) umgeschrieben werden, und alle NEON-Befehle abdecken, die in der Spezifikation ACLE Q3 2020 dokumentiert sind.
- Im Backend für die Codegenerierung für AMD GPUs basierend auf der Mikroarchitektur GCN wurde Unterstützung für GPU gfx908 hinzugefügt.
- Unterstützung für neue Prozessoren und deren in den neuen Befehlssatz implementierten Erweiterungen wurde hinzugefügt:
- Intel Sapphire Rapids (-march=sapphirerapids, umfasst Unterstützung für die Befehle MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD, CLDEMOTE, SERIALIZE, PTWRITE, WAITPKG, TSXLDTRK, AMT-TILE, AMX-INT8, AMX-BF16 und AVX-VNNI).
- Intel Alder Lake (-march=alderlake, umfasst Unterstützung für die Befehle CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, KEYLOCKER, AVX-VNNI und HRESET).
- Intel Rocket Lake (-march=rocketlake, Analogon zu Rocket Lake ohne Unterstützung für SGX).
- AMD Zen 3 (-march=znver3).
- Für IA-32/x86-64-Systeme auf Basis von Intel-Prozessoren wurde die Unterstützung neuer Prozessoranweisungen TSXLDTRK, SERIALIZE, HRESET, UINTRKEYLOCKER, AMX-TILE, AMX-INT8, AMX-BF16, AVX-VNNI hinzugefügt.
- Die Unterstützung der Flags „-march=x86-64-v[234]“ wurde hinzugefügt, um die Architektur-Level von x86-64 auszuwählen (v2 umfasst die Erweiterungen SSE4.2, SSSE3, POPCNT und CMPXCHG16B; v3 – AVX2 und MOVBE; v4 – AVX-512).
- Die Unterstützung von RISC-V-Systemen mit der Byte-Reihenfolge „big-endian“ wurde hinzugefügt. Eine Option „-misa-spec=*“ zur Auswahl der Versionsspezifikation der RISC-V-Befehlssatzarchitektur wurde eingeführt. Unterstützung für AddressSanitizer und Stack-Schutz mit Hilfe von Canary-Tags wurde ergänzt.
- Die Verbesserung des statischen Analysemodus „-fanalyzer“ wurde fortgesetzt, der eine ressourcenintensive interprozedurale Analyse von Codepfaden und Datenflüssen im Programm durchführt. Der Modus ist in der Lage, während der Kompilierung Probleme wie doppelte Aufrufe der Funktion free() für denselben Speicherbereich, Dateideskriptorlecks, Dereferenzierung und Übergabe von Null-Zeigern, Zugriffe auf freigegebene Speicherblöcke, Verwendung von nicht initialisierten Werten usw. zu erkennen. In der neuen Version:
- Der Code zur Überwachung des Programmstatus wurde vollständig überarbeitet. Probleme mit der Überprüfung sehr großer C-Dateien wurden behoben.
- Die anfängliche Unterstützung für C++ wurde hinzugefügt.
- Die Analyse der Speicherzuweisung und -freigabe ist von den spezifischen Funktionen malloc und free abstrahiert und unterstützt jetzt new/delete sowie new[]/delete[].
- Neue Warnungen hinzugefügt: -Wanalyzer-shift-count-negative, -Wanalyzer-shift-count-overflow, -Wanalyzer-write-to-const und -Wanalyzer-write-to-string-literal.
- Neue Debugging-Optionen -fdump-analyzer-json und -fno-analyzer-feasibility wurden hinzugefügt.
- Die Möglichkeit zur Erweiterung des Analysewerkzeugs über Plugins für GCC wurde implementiert (z. B. wurde ein Plugin zur Überprüfung der fehlerhaften Verwendung von Global Interpreter Lock (GIL) in CPython vorbereitet).
Quelle: opennet.ru
