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