Skip to content

GCC 14 ICE (PR target/118460) building FP16 kernels at -O1/-O2/-O3 for Cortex-M55 #219

Description

@evanchen11

Summary

Building the FP16 (_Float16) kernels with Arm GNU GCC 14.x at -O1/-O2/-O3 for Cortex-M55 (hard-float) fails with an internal compiler error. 6 translation units are affected:

  • Source/ConvolutionFunctions/arm_convolve_f16.c
  • Source/ConvolutionFunctions/arm_convolve_1_x_n_f16.c
  • Source/ConvolutionFunctions/arm_depthwise_conv_f16.c
  • Source/FullyConnectedFunctions/arm_batch_matmul_f16.c
  • Source/NNSupportFunctions/arm_nn_lstm_step_f16.c
  • Source/SVDFunctions/arm_svdf_f16.c

Failure signature

error: unrecognizable insn:
(insn ... (set (reg:HF ...)
        (if_then_else:HF (lt (reg:CCFPE 100 cc) (const_int 0))
            ...)))
during RTL pass: vregs
internal compiler error: in extract_insn, at recog.cc:...

Root cause

GCC PR target/118460 — a GCC 14 regression (from r14-2699). The arm backend's movhfcc expander emits a VSEL-form if_then_else:HF that the backend's own arm_vsel_comparison_operator predicate rejects. Trigger: the ssa-phiopt pass converts scalar _Float16 ternary/min/max/clamp if-diamonds (e.g. the CLAMP sites in the f16 kernels) into COND_EXPRs that reach emit_conditional_move.

Preconditions: scalar FP16 arithmetic hardware (__ARM_FEATURE_FP16_SCALAR_ARITHMETIC, e.g. -mcpu=cortex-m55) + a float ABI that uses FP registers: verified to ICE with both -mfloat-abi=hard and -mfloat-abi=softfp; only pure -mfloat-abi=soft is unaffected. Not MVE-specific. armclang / Arm Toolchain for Embedded (clang-based) are unaffected.

Fixed upstream on master (r16-4445, r16-5119) and gcc-15 (r15-10491/2 → shipped in Arm GNU 15.2.Rel1). Never backported to gcc-14 (retargeted to 14.5), so all GCC 14 releases customers use today are affected.

Impact

Any consumer building ns-cmsis-nn FP16 kernels with GCC 14 at -O1..-O3 hits a hard build failure — including direct consumers outside helia-rt (e.g. AoT-compiler flows). -Ofast masks it only via -ffast-math (changes FP semantics); -O0 kills performance.

Workarounds / fix

  • Build-flag workaround: -fno-ssa-phiopt on the f16 TUs (applied in helia-rt's build).
  • Source-level fix (preferred, toolchain-agnostic): replace scalar HF conditional-select patterns with tiny always-inline vminnm.f16/vmaxnm.f16/vabs.f16 inline-asm helpers (arm_nn_min_f16h/arm_nn_max_f16h/arm_nn_clamp_f16h/arm_nn_abs_f16h in arm_nnsupportfunctions.h, guarded for GCC + FP16 scalar arithmetic, with plain-C fallbacks), and use them at the 9 CLAMP sites + f16 activation helpers. No HFmode conditional move ever reaches the broken expander; codegen is optimal (these are the instructions a working compiler would emit).

Validated: no ICE at -O2/-O3 with GCC 14.3.Rel1; all FP16 kernel test suites (conv, depthwise_conv, fully_connected, batch_matmul, svdf, activations, lstm) pass on Corstone-300 FVP; hardware smoke test on apollo510_evb matches reference output. Fix branch to follow.

Note for future FP16 code: avoid scalar _Float16 ternary selects / MIN/MAX/CLAMP macros in new f16 sources; use the arm_nn_*_f16h helpers.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions