GCC 16이 출시됨

1 week ago 12
  • GNU 컴파일러 컬렉션의 새 릴리스는 C++ 기본 표준을 gnu++20으로 변경하고, C++20 구현을 더 이상 experimental로 보지 않는 중요한 전환점이 됨
  • C++26 reflection·contracts·constexpr 기능, C++23 기능, experimental C++23·C++26 library 지원이 추가되었고, template 오류와 type trait constraint failure 진단은 계층형 메시지로 더 자세해짐
  • OpenMP와 OpenACC는 GPU 메모리 할당, target memset, device memcpy API를 확장했고, Ada·Fortran·Modula-2·Algol 68 front end에도 새 언어 기능과 실험적 컴파일러가 들어감
  • x86-64는 AMD Zen6, Intel Wildcat Lake, Intel Nova Lake를 지원하고, AMD GPU·LoongArch·IBM z Systems·Solaris·Windows 쪽에서도 타깃별 기능과 ABI 변화가 추가됨
  • JSON 진단 형식 제거와 SARIF·HTML 진단 강화, static analyzer 개선, libgdiagnostics의 37개 entrypoint 추가로 도구 연동과 진단 인프라가 크게 넓어짐

호환성 변경과 공통 개선

  • Solaris에서 int8_t 등은 C99 표준 준수를 위해 signed char 가 되었고, 이는 호환되지 않는 변경임
  • Solaris에서 -pthread 옵션은 더 이상 _REENTRANT 를 미리 정의하지 않음
  • -fdiagnostics-format=의 json 형식은 제거되었고, 기계 판독 가능한 진단에는 SARIF를 써야 함
  • Link-Time Optimization은 -flto-toplevel-asm-heuristics로 최상위 asm 문 처리를 더 잘 다루게 됨
  • speculative devirtualization은 일반 간접 함수 호출을 처리하고, 둘 이상의 대상 추측을 지원함
  • vectorizer는 reduction의 루프 내부 병렬성 식별이 더 유연해졌고, 반복 횟수를 알 수 없는 루프와 uncounted loop 벡터화를 지원함
    • masking을 쓰는 vector length agnostic loop의 정렬용 peeling, mutual peeling for alignment, early break 루프의 vector induction 계산 제거도 지원함
  • GCC Command Optionsoption index는 이전에 빠졌던 많은 옵션을 담도록 수정됨
  • GCC-specific attributes 문서는 GCC가 지원하는 모든 C/C++ dialect에서 허용하는 표준 attribute 문법을 더 강조하도록 현대화됨
    • attribute 자료는 반복을 줄이도록 재구성되었고 새 attribute index가 추가됨
    • parameter와 option spec file 문서는 GCC 개발자와 custom GCC 구성이 필요한 사용자를 위한 GCC internals manual로 이동함

언어별 주요 변경

  • OpenMP와 OpenACC

    • OpenMP 메모리 할당 지원이 강화되어 pinned trait allocator와 ompx_gnu_pinned_mem_alloc은 사용 가능할 때 CUDA API를 사용하며, Nvidia GPU에서 해당 메모리 접근 성능을 개선함
    • GNU 확장인 ompx_gnu_managed_mem_alloc allocator와 ompx_gnu_managed_mem_space는 host에서 device-accessible memory를 할당함
      • unified-shared memory가 지원되지 않아도 device 접근이 가능하며, 모든 host memory가 device-accessible인 시스템에서도 다른 메모리와 page-migration 동작이 다를 수 있음
    • OpenMP 5.0은 C/C++에서 제한적 declare mapper 지원을 추가했고, uses_allocators clause는 OpenMP 5.2 문법 변경과 OpenMP 6.0 semicolon 지원까지 포함함
    • OpenMP 5.1은 C/C++에서 map clause와 target update construct의 iterator modifier 초기 지원을 추가함
    • OpenMP 5.2는 C/C++에서 begin declare variant directive를 지원함
    • OpenMP 6.0은 omp_target_memsetomp_target_memset_async API routine을 추가했고, no_openmp_constructs assumptions clause도 사용할 수 있음
    • OpenMP 5.0, 5.1, 5.2에서 deprecated 된 directive와 clause는 기본적으로 deprecation warning을 내며, -Wno-deprecated-openmp로 끌 수 있음
      • deprecated named constant 또는 API routine 사용 시에도 warning이 나오며, -Wno-deprecated-declarations로 끌 수 있음
    • OpenACC는 C/C++/Fortran용 acc_memcpy_device와 acc_memcpy_device_async API routine을 추가함
    • OpenACC 3.0의 wait directive는 if clause를 받으며, OpenACC 3.3의 Fortran API routine acc_attach와 acc_detach는 OpenACC 2.6 C/C++ counterpart를 보강함
    • OpenACC 3.4에서는 Fortran data clause의 named constant PARAMETER 사용이 사양과 GCC에서 허용되지만, GCC에서는 compile-time과 runtime 동작에 영향을 주지 않음
  • Ada, Fortran, Modula-2, Algol 68

    • Ada GNAT 확장에는 ConstructorDestructor가 추가되어 표준 Ada와 상당히 다른 construction/finalization 메커니즘을 제공함
    • Ada의 Implicit with, Structural Generic instantiation, Extended_Access aspect가 추가됨
      • Extended_Access는 unconstrained array subtype을 가리키는 general access type declaration에 지정 가능하며, pointer representation을 바꾸고 Ada가 할당하지 않은 메모리를 foreign language와 연동하기 쉽게 함
    • Ada는 -gnatd_V 또는 verbose mode의 -gnatd_W로 compiler debugging용 VAST를 사용할 수 있고, Ada 2022 Reduction Expressions semantic analysis, Ada.Containers.Bounded_Indefinite_Holders, accessibility rule 구현, Android 지원이 개선됨
    • Fortran은 single node machine에서 native shared memory multithreading을 쓰는 coarray와 Fortran 2018 TEAM feature를 다룸
    • Fortran 2003 Parameterized Derived Types 지원이 개선되었고, LEN parameter 처리는 동작하지만 PR82649에 따른 향후 representation 변경이 필요함
    • Fortran 2018은 IMPORT statement 확장, REDUCE intrinsic, 새 GENERIC statement를 지원함
    • Fortran 2023은 sinpi 같은 trigonometric function 추가분, split intrinsic subroutine, optional lower bound를 인자로 받는 c_f_pointer를 지원함
    • -fexternal-blas64 옵션은 MATMUL에서 64-bit integer argument로 external BLAS routine을 호출하며, 64-bit system과 -ffrontend-optimize 적용 시에만 유효함
    • Modula-2는 import list, module name, nested scope symbol 처리 중 spelling hint를 내고, 새 wide set 구현과 M2WIDESET library module을 도입함
      • wide set 변경은 ABI를 바꿔 이전 GCC 버전의 object file과 link-time error를 만들 수 있음
    • Modula-2 기본 library에는 BinDict binary dictionary module이 추가되었고, 여러 module에 Write와 WriteLn procedure가 제공되며, -fm2-pathname-root= 옵션으로 external library module 접근이 개선됨
    • GCC에는 experimental Algol 68 compiler인 ga68이 포함되며, Revised Report와 IFIP WG2.1 Algol 68 Support subcommittee가 승인한 errata 구현을 목표로 함
      • 일부 GNU extension과 POSIX prelude도 구현되며, 언어 정보는 Algol 68 website, front end 정보는 wiki 참고

C++와 libstdc++

  • C++ compilation의 기본 언어 버전은 -std=gnu++17에서 -std=gnu++20 으로 바뀜
    • 이전 C++ 표준에 의존하는 코드는 build flag에 -std=을 추가하거나 코드를 porting해야 하며, porting notes 참고
    • C++20 modules 지원은 여전히 experimental이며 -fmodules로 활성화해야 함
  • C++26 기능은 reflection, annotations for reflection, base class subobject splicing, function parameter reflection, contracts, constexpr exceptions, constexpr virtual inheritance 등 다수가 구현됨
    • P2996R13 Reflection은 -std=c++26 -freflection으로 활성화됨
    • 일부 P2686R4는 부분 지원이며, structured binding은 constexpr 가능하지만 constexpr automatic variable 참조는 아직 허용되지 않음
  • C++23 기능은 P2036R3, P2590R2, P2246R1이 구현됨
  • C++ error message는 template 관련 문제 등에서 계층 구조를 가지며, indentation과 bullet point로 message nesting을 표시함
  • experimental C++20 modules 지원은 --compile-std-module 옵션을 추가해 <bits/stdc++.h> header unit과 std, std.compat module을 source file compile 전에 빌드함
    • <bits/stdc++.h> header unit이 빌드되어 있으면 importable standard library header의 #include를 <bits/stdc++.h> import로 투명하게 변환함
    • 보고된 많은 bug가 수정됨
  • standard library type trait의 constraint failure diagnostics는 is_constructible_v, is_invocable_v 등이 왜 false인지 더 자세히 알려줌
  • libstdc++에서 128-bit integer를 지원하는 target은 std::is_integral<__int128>와 유사 trait가 항상 true가 됨
    • 이전에는 GNU dialect에서는 true였지만 strict dialect에서는 그렇지 않았음
  • P0952R2: A new specification for std::generate_canonical이 C++11 이후 영향을 받는 모든 mode에 구현되어 관찰되는 output에 영향을 줌
    • 이전 동작은 _GLIBCXX_USE_OLD_GENERATE_CANONICAL 정의로 복원 가능함
  • std::variant ABI는 C++20 이상 mode와 일관되도록 갱신되었고, 특정 C++17 mode class layout에 영향을 줌
    • 이전 동작은 _GLIBCXX_USE_VARIANT_CXX17_OLD_ABI 정의로 복원 가능하며, 영향은 C++17 mode에만 해당함
  • std::regex execution은 system stack 대신 heap-based stack을 쓰도록 다시 작성되어, 더 큰 string matching 중 stack overflow를 피함
  • C++20 구현은 더 이상 experimental이 아니며, Windows에서 std::chrono::current_zone()이 동작함
  • GCC 16 이전 C++20 지원은 experimental이었기 때문에, C++20 component 사용 program은 older release와 호환되지 않는다고 봐야 함
    • ABI 변경 대상에는 <atomic> waiting/notifying function, <semaphore> semaphore type, <syncstream> synchronization, std::format args와 std::formatter representation, <compare>의 std::partial_ordering, 일부 <ranges> adaptor representation 등이 포함됨
  • experimental C++23 library 지원은 std::mdspan, ranges::starts_with, ranges::ends_with, ranges::shift_left, ranges::shift_right, std::allocator_traits::allocate_at_least를 포함함
  • experimental C++26 library 지원은 std::simd, std::inplace_vector, std::optional<T&>, std::copyable_function, std::function_ref, std::indirect, std::polymorphic, shared pointer용 std::owner_equal, <debugging> header 등을 포함함

타깃과 운영체제 지원

  • IA-32/x86-64

    • AMD Zen6 기반 CPU는 -march=znver6로 지원되며, Zen5에 활성화된 ISA extension 위에 AVX512_BMM, AVX_NE_CONVERT, AVX_IFMA, AVX_VNNI_INT8, AVX512_FP16을 활성화함
    • AVX512 지원이 켜져 있고 znver4, znver5, znver6 tuning이면 auto-vectorization이 masked vector epilog 사용을 시도해 code size를 줄이고 성능을 개선함
    • Intel Wildcat Lake는 -march=wildcatlake, Intel Nova Lake는 -march=novalake로 지원됨
      • -march=novalake는 Panther Lake 기반 ISA extension에 APX_F, AVX10.1, AVX10.2, PREFETCHI를 추가로 활성화함
    • GCC 16부터 여러 -march= switch에서 AMX-TRANSPOSE, USER_MSR, CLDEMOTE, KL, WIDEKL, PREFETCHI 활성화가 제거됨
    • -mavx10.1-256, -mavx10.1-512, -mevex512는 제거되었고, -mavx10.1 behavior change warning도 함께 사라짐
    • AMX-TRANSPOSE 지원은 GCC 16에서 제거되었고, GCC는 더 이상 -mamx-transpose를 받지 않음
    • 새 --enable-x86-64-mfentry configure option은 x86-64 profiling에 mcount 대신 __fentry__를 쓰는 -mfentry를 활성화하며, glibc target에서는 기본 활성화됨
    • --enable-tls=DIALECT는 기본 TLS dialect 제어를 지원하고, 기본값은 gnu이며 허용값은 gnu와 TLS descriptor용 gnu2임
  • AMD GPU, LoongArch, IBM z Systems

    • AMD GPU offloading에서 OpenMP target region과 OpenACC compute region launch overhead가 크게 줄어듦
    • AMD Instinct MI300 gfx942 device experimental 지원이 추가되었고, generic gfx9-4-generic과 대부분 호환되는 gfx950도 포함됨
    • AMD GPU 기본 multilib build set은 gfx908, gfx90a, gfx9-generic, gfx9-4-generic, gfx10-3-generic, gfx11-generic으로 바뀜
      • generic arch가 있으면 specific device용 multilib는 기본으로 더 이상 빌드되지 않음
      • generic architecture는 ROCm 6.4.0 이상 필요
      • 새 기본 multilib set은 LLVM 20 이상 assembler와 linker 필요
      • GCC의 AMD installation notesconfiguration notes 참고
    • LoongArch는 _BitInt (N)와 unsigned _BitInt (N) 같은 bit-precise integer type을 지원함
    • LoongArch는 target_clones attribute로 CPU feature별 function version을 만들고 runtime에 최적 version을 자동 선택하는 FunctionMulti-Versioning을 지원함
    • LoongArch32 architecture 지원이 추가되어 ilp32d 기본 ABI와 ilp32f, ilp32s ABI를 포함함
      • 표준 32-bit version LA32와 reduced 32-bit version LA32R을 모두 다루며, embedded application을 위한 32-bit target code 생성을 가능하게 함
      • 해당 기능은 Binutils와 glibc 지원에 의존함
    • S/390, System z, IBM z Systems는 bit-precise integer type과 _Float16 floating-point type을 지원함
      • _Float16 operation은 software 또는 float instruction으로 수행됨
    • S/390 계열에는 Linux kernel의 canary address loading runtime patching을 지원하기 위한 global stack protector가 -mstack-protector-guard=global로 추가되었고, -mstack-protector-guard-record도 추가됨
    • S/390 계열의 -m31 지원은 deprecated 되었고 향후 release에서 제거될 예정임
  • 운영체제

    • Solaris는 -gsctf 옵션으로 Solaris CTF, 즉 Compact C Type Format 생성을 쉽게 지원함
    • Windows는 native TLS, 즉 Thread-Local Storage를 지원함
      • 활성화하려면 configure 시 --enable-tls 지정과 GNU binutils 2.44 이상이 필요함

진단, 플러그인, 정적 분석

  • GCC는 -fdiagnostics-add-output=experimental-htmlHTML 형식 진단 출력을 지원함
  • SARIF 출력은 dump directory를 따르며, build-dir/foo.o 출력 예시에서는 GCC 16이 build-dir/foo.c.sarif에 SARIF를 기록함
    • GCC 15는 같은 예시에서 foo.c.sarif에 기록했음
  • SARIF 출력은 logical location nesting을 캡처하고, 많은 경우 fix object에 description property를 포함함
  • SARIF threadFlowLocation의 kinds property는 비표준 control flow 표현을 위해 throw, catch, unwind, setjmp, longjmp 값을 새로 얻음
  • GCC diagnostics는 directed graph를 연결할 수 있고, global directed graph도 report 가능함
    • graph는 text sink에서는 무시되지만 SARIF sink에 캡처되며, experimental-html은 dot을 사용해 SVG 기반으로 렌더링함
    • SARIF 또는 HTML diagnostic sink에서 cfgs=yes를 설정하면 모든 optimization pass의 모든 function에 대한 GCC intermediate representation 캡처가 활성화됨
  • GCC diagnostics는 XML과 JSON file 내부의 logical location을 참조할 수 있음
    • sarif-replay tool은 이를 사용해 SARIF input issue report 시 JSON pointer를 제공함
  • GCC_DIAGNOSTICS_LOG가 environment에 설정되면 diagnostic subsystem이 stderr 또는 named file에 text log를 내보냄
    • diagnostic이 정확히 언제, 왜 reject 되는지 같은 내부 결정 추적에 사용됨
  • EXPERIMENTAL_SARIF_SOCKET이 environment에 설정되면 GCC는 startup 시 해당 socket에 연결을 시도하고, 발생한 모든 diagnostic에 대해 JSON-RPC notification을 보냄
  • Plugin author를 위해 publish/subscribe framework가 추가되어 loosely-coupled sender와 receiver 사이에서 strongly-typed message를 전달함
    • 이번 release에서 plugin이 subscribe 가능한 topic은 특정 function의 optimization pass start/stop event와 static analyzer 관련 event뿐임
  • GCC diagnostic sink는 finalizer hook을 가진 extension object를 가질 수 있고, plugin은 이를 사용해 SARIF output file에 추가 정보를 캡처할 수 있음
  • GCC 16에서 diagnostic machinery가 크게 정리되었고, diagnostic-core.h만 쓰는 plugin에는 영향이 없어야 함
    • diagnostics를 더 복잡하게 쓰는 plugin maintainer는 porting guide 참고 필요
  • Static analyzer는 C++ Named Return Value Optimization과 exception 초기 지원을 처리해 simple C++ example에서 사용 가능함
    • scaling issue 때문에 이번 release에서는 production C++ code에 쓰기 어려울 가능성이 큼
  • -fanalyzer는 -fexceptions가 활성화된 경우 nothrow attribute가 없는 external function call이 exception을 던질 수 있다고 가정함
    • -fanalyzer-assume-nothrow 옵션은 이 가정을 비활성화함
    • C++ interoperability를 위해 C code에서 -fexceptions를 쓰지만 사용 중인 C API가 exception을 던질 가능성이 낮은 project의 warning 증가를 우회하는 용도임
  • -fanalyzer의 user code representation 자료구조는 이해와 debugging이 더 쉽도록 다시 작성되었고, diagnostic location이 약간 개선됨
    • 대신 analyzer memory usage가 증가함
  • -fanalyzer의 memory contents simulation 자료구조는 다시 구현되어 더 빠르고 유지보수하기 쉬워짐
  • analyzer는 GCC의 value_range machinery를 사용하기 시작해 일부 false positive를 제거함

libgdiagnostics와 수정된 문제

Read Entire Article