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.
PR109813 reports the same Thumb-1 __bf16 move ICE and is a duplicate;
this patch resolves both.
gcc/ChangeLog:
PR target/99764
PR target/109813
* 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
PR target/109813
* gcc.target/arm/pr99764.c: New test.
Signed-off-by: Dominic P <[email protected]>
---
Testing (cross arm-none-eabi; no native bootstrap was done): built cc1 at this
patch's base and with the patch applied and ran the full gcc.target/arm DejaGnu
suite (arm.exp) with each. The two runs are identical except for the new test,
which adds 3 PASSes (pr99764.c); every pre-existing pass/fail/unresolved/
unsupported count is unchanged -- no regressions. A gcc.c-torture/compile A/B
at
-O2 -mcpu=cortex-m0 -mthumb (a Thumb-1 core -- the path this patch touches) over
the 1589 files that compile for arm-none-eabi gave byte-identical assembly on
all
1589 -- 0 differences, 0 new ICEs.
This patch was prepared with the assistance of an AI coding tool. Every line of
code, every test and every measurement was written, reviewed and verified by the
author, who takes responsibility for the patch; the Signed-off-by above
certifies
the Developer Certificate of Origin.
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