This is one more patch for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127326
The patch was successfully bootstrapped and tested on x86-64, aarch64, ppc64le.
commit d8824000c0fd0d82d4c286c02a375e1225e91240 Author: Vladimir N. Makarov <[email protected]> Date: Fri Sep 25 10:13:41 2026 -0400 [PR 127326][LRA]: Fall back to memory when won operand is already a MEM The previous fix resolves 'g' operand to memory when no hard register of can hold the operand mode, but it only does so when OFFMEMOK is set. In case 'g' OFFMEMOK is set for reg operands only, so an operand which is already a MEM never gets marked and stays recorded as GENERAL_REGS. An operand matching it then inherits that class, finds no hard register able to hold the mode, and LRA rejects the asm. Treating won MEM operand the same way as an OFFMEMOK one solves the issue. gcc/ChangeLog: PR rtl-optimization/127326 * lra-constraints.cc (process_alt_operands): Resolve the operand to memory when it is a winning MEM and the value can be held in a register. gcc/testsuite/ChangeLog: PR rtl-optimization/127326 * gcc.target/i386/pr127326.c (test2): New test. diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index 72430d51732..76489c976ba 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -3065,8 +3065,11 @@ process_alt_operands (int only_alternative) the operand to memory. Mark it so that an operand matching this one can also fall back to memory, otherwise the matched operand would try to reload into an impossible hard reg and - LRA would cycle (e.g. TDmode "+g" asm on 32-bit x86). */ - if (offmemok && this_alternative != NO_REGS + LRA would cycle (e.g. TDmode "+g" asm on 32-bit x86). + An operand which is already memory and won implies the + constraint accepts memory too, even if nothing set + OFFMEMOK for it. */ + if ((offmemok || MEM_P (op)) && this_alternative != NO_REGS && hard_reg_set_subset_p (reg_class_contents[this_alternative], ira_prohibited_class_mode_regs [this_alternative][mode] diff --git a/gcc/testsuite/gcc.target/i386/pr127326.c b/gcc/testsuite/gcc.target/i386/pr127326.c index ed618cf7092..a45c033e1df 100644 --- a/gcc/testsuite/gcc.target/i386/pr127326.c +++ b/gcc/testsuite/gcc.target/i386/pr127326.c @@ -15,3 +15,16 @@ test (void) __asm ("" : "+g" (u.d)); /* { dg-bogus "inconsistent operand constraints" } */ return u.d; } + +/* Here the union is also read as integers, so it stays in memory and the asm + operand is MEM. The matched input operand still has to be resolved in + memory. */ + +unsigned long long +test2 (void) +{ + union { _Decimal128 d; unsigned long long u[2]; } u; + u.d = 1.0DL; + __asm ("" : "+g" (u.d)); /* { dg-bogus "inconsistent operand constraints" } */ + return u.u[0] + u.u[1]; +}
