Реліз набору компіляторів GCC 11

Після року розробки опубліковано реліз вільного набору компіляторів GCC 11.1, перший значний випуск у новій гілці GCC 11.x. Відповідно до нової схеми нумерації випусків, версія 11.0 використовувалася в процесі розробки, а незадовго до виходу GCC 11.1 вже відгалужилася гілка GCC 12.0, на базі якої буде сформовано наступний значний реліз GCC 12.1.

GCC 11.1 примітний переходом на використання за умовчанням формату файлів налагодження DWARF 5, включенням за умовчанням стандарту C++17 («-std=gnu++17»), значним поліпшенням підтримки стандарту C++20, експериментальною підтримкою C++23, покращення, пов'язані з майбутнім стандартом мови Сі (C2x), новими оптимізаціями продуктивності.

Основні зміни:

  • Режим за замовчуванням для мови C++ переключений на використання стандарту C++17 (-std=gnu++17) замість C++14, що раніше пропонувався. Можливе вибіркове відключення нової поведінки C++17 під час обробки шаблонів, у яких як параметр використовуються інші шаблони (-fno-new-ttp-matching).
  • Додано підтримку апаратного прискорення роботи інструмента AddressSanitizer, що дозволяє визначити факти звернення до звільнених областей пам'яті, виходу за межі меж виділеного буфера та деякі інші типи помилок під час роботи з пам'яттю. Апаратне прискорення поки що доступне лише для архітектури AArch64 і зосереджено на використання при компіляції ядра Linux. Для увімкнення апаратного прискорення AddressSanitizer при складанні компонентів простору користувача доданий прапор "-fsanitize=hwaddress", а ядра - "-fsanitize=kernel-hwaddress".
  • При генерації налагоджувальної інформації за замовчуванням задіяний формат DWARF 5, в порівнянні з минулими версіями, що дозволяє генерувати на 25% компактніші налагоджувальні дані. Для повної підтримки DWARF 5 потрібно binutils як мінімум версії 2.35.2. У інструментах налагодження формат DWARF 5 підтримується починаючи з GDB 8.0, valgrind 3.17.0, elfutils 0.172 і dwz 0.14. Для генерації налагоджувальних файлів з використанням інших версій DWARF можна використовувати опції "-gdwarf-2", "-gdwarf-3" та "-gdwarf-4".
  • Підвищено вимоги до компіляторів, які можна використовувати для збирання GCC. Компілятор тепер має підтримувати стандарт C++11 (раніше був потрібний C++98), тобто. якщо для збирання GCC 10 достатньо було наявності GCC 3.4, то для збирання GCC 11 тепер потрібно як мінімум GCC 4.8.
  • Змінено найменування та розміщення файлів для збереження дампів, тимчасових файлів та додаткової інформації, необхідної для проведення LTO-оптимізації. Подібні файли тепер завжди зберігаються в поточному каталозі, якщо шлях явно не змінений через параметри "-dumpbase", "-dumpdir" та "-save-temps=*".
  • Оголошено застарілою і незабаром буде видалено підтримку бінарного формату BRIG, призначеного для використання з мовою HSAIL (Heterogeneous System Architecture Intermediate Language).
  • Розширені можливості режиму ThreadSanitizer (-fsanitize=thread), призначеного для виявлення стану гонки при спільному доступі до одних і тих самих даних з різних ниток багатопоточного додатка. У новому випуску додано підтримку альтернативних runtime і оточення, а також підтримку налагоджувального інструменту KCSAN (Kernel Concurrency Sanitizer), призначеного для динамічного виявлення станів гонки всередині ядра Linux. Додані нові опції «param tsan-distinguish-volatile» і «param tsan-instrument-func-entry-exit».
  • Номери стовпців у діагностичних повідомленнях тепер відображають не лічильник байт від початку рядка, а дійсно номери стовпців, що враховують багатобайтові символи та символи, що займають кілька позицій у рядку (наприклад, символ 🙂 займає дві позиції та кодується 4 байтами). Аналогічно символи табуляції тепер обробляються як певну кількість прогалин (налаштовується через опцію -ftabstop, за замовчуванням 8). Для відновлення старої поведінки запропоновано опцію "-fdiagnostics-column-unit=byte", а для визначення початкового значення (нумерація з 0 або 1) - опція "-fdiagnostics-column-origin=".
  • У векторизаторі забезпечено облік всього вмісту функції та додано обробку можливостей, пов'язаних з перетинами та відсиланнями до попередніх блоків у графі потоку управління (CFG, control-flow graph).
  • В оптимізаторі реалізована можливість перетворення у вираз switch серії умовних операцій, в яких порівнюється та сама змінна. Надалі вираз switch може бути закодований із застосуванням інструкцій бітового тестування (для управління подібним перетворенням додана опція "-fbit-tests").
  • Поліпшено міжпроцедурні оптимізації. Додано новий прохід IPA-modref (-fipa-modref) для відстеження побічних ефектів під час виклику функцій та підвищення точності аналізу. Поліпшено реалізацію проходу IPA-ICF (-fipa-icf), в якому скорочено споживання пам'яті при компіляції та збільшено число уніфікованих функцій, для яких виконується об'єднання ідентичних блоків коду. У проході IPA-CP (Interprocedural constant propagation) покращено евристику з прогнозування з урахуванням відомих кордонів та особливостей роботи циклів.
  • У реалізації оптимізації на етапі зв'язування (LTO) формат байткоду оптимізовано для скорочення розміру та підвищення швидкості обробки. Зменшено пікове споживання пам'яті на етапі зв'язування.
  • У механізмі оптимізації на основі результатів профілювання коду (PGO - Profile-guided optimization), що дозволяє генерувати більш оптимальний код на основі аналізу особливостей виконання, скорочено розмір файлів з даними GCOV за рахунок більш компактного пакування нульових лічильників. Покращено режим "-fprofile-values" завдяки відстеженню більшої кількості параметрів при непрямих викликах.
  • Продовжено реалізацію стандарту OpenMP 5.0 (Open Multi-Processing), що визначає API та способи застосування методів паралельного програмування на багатоядерних та гібридних (CPU+GPU/DSP) системах із загальною пам'яттю та блоками векторизації (SIMD). Додана початкова підтримка директиви allocate та можливість використання неоднорідних циклів у конструкціях OpenMP. Реалізовано підтримку змінної оточення OMP_TARGET_OFFLOAD.
  • Покращена реалізація специфікації паралельного програмування OpenACC 2.6, що надається для мов C, C++ і Fortran, що визначає засоби для винесення операцій (offloading) на GPU та спеціалізовані процесори, такі як NVIDIA PTX.
  • Для мов сімейства Сі реалізований новий атрибут "no_stack_protector", призначений для позначення функцій для яких не слід включати захист стеку ("-fstack-protector"). Атрибут «malloc» розширено підтримкою ідентифікації пар викликів для виділення та звільнення пам'яті (allocator/deallocator), що використовується в статичному аналізаторі для визначення типових помилок роботи з пам'яттю (відплив пам'яті, використання після звільнення, подвійний виклик функції free тощо) і в попередженнях компілятора "-Wmismatched-dealloc", "-Wmismatched-new-delete" та "-Wfree-nonheap-object", які інформують про неузгодженість операцій звільнення та виділення пам'яті.
  • Для мови Сі додано нові попередження:
    • "-Wmismatched-dealloc" (включено за замовчуванням) - попереджає про операції звільнення пам'яті в яких використовується покажчик, що не поєднується з функціями виділення пам'яті.
    • -Wsizeof-array-div (включається при вказівці -Wall) - попереджає про поділ двох операторів sizeof, якщо дільник не відповідає розміру елемента масиву.
    • "-Wstringop-overread" (включений за замовчуванням) - попереджає про виклик рядкової функції, що читає дані з області поза межі масиву.
    • "-Wtsan" (ввімкнений за замовчуванням) - попереджає про використання можливостей (таких як std::atomic_thread_fence), що не підтримуються в ThreadSanitizer.
    • "-Warray-parameter" і "-Wvla-parameter" (включається при вказівці "-Wall") - попереджає про перевизначення функцій з оголошенням аргументів, що не поєднується, пов'язаних з масивами фіксованої і змінної довжини.
    • Попередження -Wuninitialized тепер визначає спроби читання з неініціалізованої динамічно виділеної пам'яті.
    • У попередженні "-Wfree-nonheap-object" розширено спектр визначених випадків виклику функцій звільнення пам'яті з покажчиком, отриманим через функції динамічного виділення пам'яті.
    • У попередженні «-Wmaybe-uninitialized» розширено виявлення передачі функції покажчиків, посилаються на неініціалізовані області пам'яті.
  • Для мови Сі реалізована порція нових можливостей, що розвиваються в рамках стандарту C2X (включається через вказівку -std=c2x і -std=gnu2x): макроси BOOL_MAX і BOOL_WIDTH, необов'язковість вказівки імен параметрів, що не використовуються, у визначеннях функцій (як у C++), атрибут «[ [nodiscard]]», оператор препроцесора «__has_c_attribute», макроси FLT_IS_IEC_60559, DBL_IS_IEC_60559, LDBL_IS_IEC_60559, __STDC_WANT_IEC_60559_EXT__, INFINITY, NFINITY, NFIN ITY та DEC_NAN, NaN=макроси для FloatN, _FloatNx та _DecimalN, можливість вказівки міток переходу до оголошень та наприкінці складових операторів.
  • Для C++ реалізовано порцію змін і нововведень, запропонованих у стандарті C++20, включаючи віртуальні функції «consteval virtual», псевдодеструктори закінчення життєвого циклу об'єктів, використання класу enum та обчислення розміру масиву у виразі «new».
  • Для C++ додано експериментальну підтримку деяких поліпшень, що розвиваються для майбутнього стандарту C++23 (-std=c++23, -std=gnu++23, -std=c++2b, -std=gnu++2b). Наприклад, з'явилася підтримка літерального суфікса zu для знакових значень size_t.
  • У libstdc++ покращено підтримку стандарту C++17, включаючи появу реалізації std::from_chars і std::to_chars для типів з плаваючою комою. Реалізовано нові елементи стандарту C++20, включаючи std::bit_cast, std::source_location, атомарні операції wait та notify, , , , , а також елементи майбутнього стандарту C++ 23 (std::to_underlying, std::is_scoped_enum). Додано експериментальну підтримку типів для паралельної обробки даних (SIMD, Data-Parallel Types). Прискорено реалізацію std::uniform_int_distribution.
  • Знято ознаку альфа-якості з libgccjit, бібліотеки, що розділяється, для вбудовування генератора коду в інші процеси і використання для організації JIT-компіляції байткоду в машинний код. Додано можливість складання libgccjit для MinGW.
  • Додано підтримку архітектури AArch64 Armv8-R (-march=armv8-r). Для архітектур AArch64 та ARM додана підтримка процесорів (параметри -mcpu та -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) та Arm Neoverse N2 (neoverse-n2). Також додані CPU Fujitsu A64FX (a64fx) та Arm Cortex-R82 (cortex-r82), що підтримують лише архітектуру AArch64.
  • Додана підтримка використання SIMD-інструкцій Armv8.3-a (AArch64/AArch32), SVE (AArch64), SVE2 (AArch64) та MVE (AArch32 M-profile) для автовекторизації операцій, що виконують додавання, віднімання, множення та варіанти складання/віднімання над комплексними числами. Для ARM додано початкову підтримку автовекторизації за допомогою набору інструкцій MVE.
  • Для ARM-платформ надано повний набір вбудованих у компілятор Сі-функцій (Intrinsics), що замінюються на розширені векторні інструкції (SIMD), що охоплює всі інструкції NEON, документовані специфікацією ACLE Q3 2020.
  • У бекенд для генерації коду для GPU AMD на базі мікроархітектури GCN додано підтримку GPU gfx908.
  • Додано підтримку нових процесорів та реалізованих у них нових розширень набору інструкцій:
    • Intel Sapphire Rapids (-march=sapphirerapids, включає підтримку інструкцій MOVDIRI, MOVDIR64B, AVX512VP2INTERSECT, ENQCMD, CLDEMOTE, SERIALIZE, PTWRITE, WAITPKG, TSXLDTRK, AMT-TILE, AMX.
    • Intel Alderlake (-march=alderlake, включає підтримку інструкцій CLDEMOTE, PTWRITE, WAITPKG, SERIALIZE, KEYLOCKER, AVX-VNNI та HRESET).
    • Intel Rocketlake (-march = rocketlake, аналог Rocket Lake без підтримки SGX).
    • AMD Zen 3 (march=znver3).
  • Для систем IA-32/x86-64 на базі процесорів Intel додано підтримку нових процесорних інструкцій TSXLDTRK, SERIALIZE, HRESET, UINTRKEYLOCKER, AMX-TILE, AMX-INT8, AMX-BF16, AVX-VNNI.
  • Додано підтримку прапорів «-march=x86-64-v[234]» для вибору рівнів архітектури x86-64 (v2 - охоплює розширення SSE4.2, SSSE3, POPCNT і CMPXCHG16B; v3 - AVX2 і MOVBE; v4 - AVX-512) .
  • Додано підтримку систем RISC-V з порядком проходження байт «big-endian». Додано опцію "-misa-spec=*" для вибору версії специфікації архітектури набору команд RISC-V. Додана підтримка AddressSanitizer та захисту стека за допомогою канаркових міток.
  • Продовжено вдосконалення режиму статичного аналізу "-fanalyzer", який виконує ресурсомісткий міжпроцедурний аналіз шляхів виконання коду та потоків даних у програмі. Режим здатний на етапі компіляції виявляти такі проблеми, як подвійний виклик функції free() для однієї області пам'яті, витоку файлових дескрипторів, розіменування та передачу нульових покажчиків, звернення до звільнених блоків пам'яті, використання неініціалізованих значень тощо. У новій версії:
    • Цілком переписаний код для відстеження стану програми. Вирішено проблеми з перевіркою дуже великих Сі-файлів.
    • Додано початкову підтримку C++.
    • Аналіз виділення та звільнення пам'яті абстрагований від конкретних функцій malloc та free, і тепер підтримує new/delete та new[]/delete[].
    • Додано нові попередження: -Wanalyzer-shift-count-negative, -Wanalyzer-shift-count-overflow, -Wanalyzer-write-to-const та -Wanalyzer-write-to-string-literal.
    • Додані нові опції налагодження -fdump-analyzer-json і -fno-analyzer-feasibility.
    • Реалізовано можливість розширення аналізатора через плагіни до GCC (наприклад, підготовлений плагін для перевірки некоректного використання глобального блокування (GIL) у CPython).

Джерело: opennet.ru

Додати коментар або відгук