[PATCH 4/6] arm: Add Thumb-1 BFmode moves to fix __bf16 ICE [PR99764]
Dominic P <[email protected]> Sun, 2 Aug 2026 11:56:06 +0100
| Newsgroups | gmane.comp.gcc.patches |
|---|---|
| Message-ID | <[email protected]> |
The Thumb-1 16-bit move pattern *thumb1_movhf only accepted HFmode, so a __bf16 (BFmode) value on a Thumb-1 target -- e.g. -mcpu=cortex-m1, or any armv4t/armv6-m -mthumb configuration -- had no move insn. A bare load, store or register move of a __bf16 therefore reached RTL and aborted: internal compiler error: in extract_insn, at recog.cc:2894 BFmode and HFmode are both opaque 16-bit storage types as far as a move is concerned (a plain 16-bit copy, no interpretation), and the ARM/Thumb-2 mover *arm32_mov<mode> already handles both via the HFBF iterator. Extend the Thumb-1 pattern the same way so __bf16 storage works on Thumb-1 exactly like __fp16, turning the ICE into ordinary ldrh/strh/movs code. Assisted-by: Claude Opus 5 (Anthropic) gcc/ChangeLog: PR target/99764 * config/arm/thumb1.md (*thumb1_movhf): Rename to... (*thumb1_mov<mode>): ...this, using the HFBF mode iterator so it also handles BFmode. gcc/testsuite/ChangeLog: PR target/99764 * gcc.target/arm/pr99764.c: New test. Signed-off-by: Dominic P <[email protected]> --- gcc/config/arm/thumb1.md | 12 ++++----- gcc/testsuite/gcc.target/arm/pr99764.c | 37 ++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/gcc.target/arm/pr99764.c diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md index 0c704c5d8..f6d2851c9 100644 --- a/gcc/config/arm/thumb1.md +++ b/gcc/config/arm/thumb1.md @@ -907,12 +907,12 @@ (set_attr "pool_range" "*,32,*,*,*,*") (set_attr "conds" "clob,nocond,nocond,nocond,nocond,clob")]) -(define_insn "*thumb1_movhf" - [(set (match_operand:HF 0 "nonimmediate_operand" "=l,l,l,m,*r,*h") - (match_operand:HF 1 "general_operand" "l, m,F,l,*h,*r"))] +(define_insn "*thumb1_mov<mode>" + [(set (match_operand:HFBF 0 "nonimmediate_operand" "=l,l,l,m,*r,*h") + (match_operand:HFBF 1 "general_operand" "l, m,F,l,*h,*r"))] "TARGET_THUMB1 - && ( s_register_operand (operands[0], HFmode) - || s_register_operand (operands[1], HFmode))" + && ( s_register_operand (operands[0], <MODE>mode) + || s_register_operand (operands[1], <MODE>mode))" "* switch (which_alternative) { @@ -941,7 +941,7 @@ rtx ops[3]; bits = real_to_target (NULL, CONST_DOUBLE_REAL_VALUE (operands[1]), - HFmode); + <MODE>mode); ops[0] = operands[0]; high = (bits >> 8) & 0xff; ops[1] = GEN_INT (high); diff --git a/gcc/testsuite/gcc.target/arm/pr99764.c b/gcc/testsuite/gcc.target/arm/pr99764.c new file mode 100644 index 000000000..8906366b3 --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr99764.c @@ -0,0 +1,37 @@ +/* PR target/99764: moving a __bf16 value on a Thumb-1 target used to ICE + in extract_insn ("unrecognizable insn") because the Thumb-1 16-bit move + pattern only handled HFmode, leaving BFmode with no move insn. A plain + load/store/move of a __bf16 must compile cleanly, exactly like __fp16. */ +/* { dg-do compile } */ +/* { dg-skip-if "avoid conflicting multilib options" { *-*-* } { "-marm" "-mthumb" "-march=*" "-mcpu=*" } } */ +/* { dg-options "-mcpu=cortex-m1 -mfloat-abi=soft -O2" } */ + +__bf16 g; + +void +store (__bf16 a) +{ + g = a; +} + +__bf16 +load (void) +{ + return g; +} + +__bf16 +pass (__bf16 a, __bf16 b) +{ + return b; +} + +__bf16 +viamem (__bf16 *p, __bf16 a) +{ + *p = a; + return p[1]; +} + +/* { dg-final { scan-assembler "strh" } } */ +/* { dg-final { scan-assembler "ldrh" } } */ -- 2.55.0