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.
Summary
Building the FP16 (
_Float16) kernels with Arm GNU GCC 14.x at-O1/-O2/-O3for Cortex-M55 (hard-float) fails with an internal compiler error. 6 translation units are affected:Source/ConvolutionFunctions/arm_convolve_f16.cSource/ConvolutionFunctions/arm_convolve_1_x_n_f16.cSource/ConvolutionFunctions/arm_depthwise_conv_f16.cSource/FullyConnectedFunctions/arm_batch_matmul_f16.cSource/NNSupportFunctions/arm_nn_lstm_step_f16.cSource/SVDFunctions/arm_svdf_f16.cFailure signature
Root cause
GCC PR target/118460 — a GCC 14 regression (from r14-2699). The arm backend's
movhfccexpander emits a VSEL-formif_then_else:HFthat the backend's ownarm_vsel_comparison_operatorpredicate rejects. Trigger: the ssa-phiopt pass converts scalar_Float16ternary/min/max/clamp if-diamonds (e.g. theCLAMPsites in the f16 kernels) intoCOND_EXPRs that reachemit_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=hardand-mfloat-abi=softfp; only pure-mfloat-abi=softis 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..-O3hits a hard build failure — including direct consumers outside helia-rt (e.g. AoT-compiler flows).-Ofastmasks it only via-ffast-math(changes FP semantics);-O0kills performance.Workarounds / fix
-fno-ssa-phiopton the f16 TUs (applied in helia-rt's build).vminnm.f16/vmaxnm.f16/vabs.f16inline-asm helpers (arm_nn_min_f16h/arm_nn_max_f16h/arm_nn_clamp_f16h/arm_nn_abs_f16hinarm_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
_Float16ternary selects /MIN/MAX/CLAMPmacros in new f16 sources; use thearm_nn_*_f16hhelpers.