This is a summary of discussions relative to the merge request created by Torbjörn Svensson (azoff) <[email protected]> titled testsuite: use valid ARM GPR pair in asm-hard-reg-6.c [PR124328] since its creation.
Description: I've tested this change on top of r17-2833-g32657f29f91871 and r16-9480-g967a69a03886ebd6. Ok for trunk and releases/gcc-16? -- CC: [email protected] The full and up to date discussion can be found at https://forge.sourceware.org/gcc/gcc/pulls/217 The merge request has been closed without being merged directly on the forge repository. On 2026-08-17 15:13:02+00:00, Richard Earnshaw (rearnsha) wrote: I can't reproduce the issue you're seeing. If I run ``` $ ./cc1 -O2 -o - ~/gnusrc/gcc/master/gcc/testsuite/gcc.dg/asm-hard-reg-6.c -mthumb -march=armv8.1-m.main -quiet ``` I get (stripping out some of the unnecessary verbiage): ``` .arch armv8.1-m.main .fpu softvfp .eabi_attribute 20, 1 .eabi_attribute 21, 1 .eabi_attribute 23, 3 .eabi_attribute 24, 1 .eabi_attribute 25, 1 .eabi_attribute 26, 1 .eabi_attribute 30, 2 .eabi_attribute 34, 1 .eabi_attribute 18, 4 .file "asm-hard-reg-6.c" .text .align 1 .p2align 2,,3 .global test_reg_reg .syntax unified .thumb .thumb_func .type test_reg_reg, %function test_reg_reg: mov r3, r1 mov r1, r0 foo r1,r3 bx lr .size test_reg_reg, .-test_reg_reg .global test_reg_mem .syntax unified .thumb .thumb_func .type test_reg_mem, %function test_reg_mem: mov r2, r0 bar r2,[r1] bx lr .size test_reg_mem, .-test_reg_mem .ident "GCC: (master) 17.0.0 20260817 (experimental) [master r17-564-g10aa8833b04]" ``` Looking at the testcase itself, we have: ``` void test_reg_mem (int x, long long *y) { __asm__ ("bar\t%0,%1" :: GPR1"m,"GPR2 (x), GPR3",m" (*y)); } ``` Which, after preprocessing becomes: ``` void test_reg_mem (int x, long long *y) { __asm__ ("bar\t%0,%1" :: "{r1}""m,""{r2}" (x), "{r3}"",m" (*y)); } ``` or, more simply: ``` void test_reg_mem (int x, long long *y) { __asm__ ("bar\t%0,%1" :: "{r1}m,{r2}" (x), "{r3},m" (*y)); } ``` These constraints are strange, but I don't think illegal. They're strange in that there are two alternatives. The first alternative permits either a hard reg or a mem for operand `x` and a hard reg for `*y`; the second permits a hard reg for `x` and a mem (read 'load') for *y. The compiler ends up picking the second alternative and then everything is happy as we never need to load the value into core registers. But even if I tweak the testcase to remove the second alternative, the compiler is still producing correct output: it loads the value into an even pair, then shuffles values around to get the result into r3 --- ugly, but it's what the user asked for. ``` test_reg_mem: ldrd r2, [r1] push {r4} mov r1, r0 mov r4, r3 mov r3, r2 bar r1,r3 pop {r4} bx lr ``` On 2026-08-17 15:32:41+00:00, Richard Earnshaw (rearnsha) wrote: Ah, the missing information was that to trip the error, you need `-march=armv8.1-m.main+mve`. armv8.1-m.main is not enough on its own. On 2026-08-17 15:57:43+00:00, Richard Earnshaw (rearnsha) wrote: I want to think about this case for a bit. I'm wondering if the restriction here should be considered an ABI break. We do want to encourage the compiler to use even numbered register pairs as it can generate better code for both Arm state (using LDRD/STRD) and MVE; but I'm not sure we should require this for user assembly code. On 2026-08-28 13:49:08+00:00, Torbjörn Svensson (azoff) wrote: Gentle ping! :) On 2026-09-01 16:34:28+00:00, Richard Earnshaw (rearnsha) wrote: I'm going to reject this. I think the code in the test is OK and the problem is in the compiler rejecting it for certain architecture settings. I've commented on the PR. Note that clang does seem to allow this register allocation for the same settings.
