The following patch solves https://gcc.gnu.org/bugzilla/show_bug.cgi?id=121191
The patch was successfully tested on sparc64 and bootstrapped and tested on x86-64, ppc64, ppc64be, aarch64.
commit 560766f6e239a8192c42ac5f009f0a4ee2478a61 Author: Vladimir N. Makarov <[email protected]> Date: Wed Feb 11 13:46:34 2026 -0500 [PR121191, LRA]: Check int modes to generate the right subreg offset when matching reload regs of different modes In the PR test case (gcc.c-torture/compile/pr35318.c), LRA chose to match operands in DFmode and SImode modes. On big endian targets, this resulted in wrong subreg offset generation and wrong insn generation. The offset would be right if the both operands were scalar integers (see call of reload.cc:operands_match_p in recog.cc:constrain_operands). The patch solves the problem. gcc/ChangeLog: PR rtl-optimization/121191 * lra-constraints.cc (get_matching_reload_reg_subreg): New. (get_reload_reg, match_reload): Use it. diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index 87b18f30c98..8c8c9d69a96 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -682,6 +682,18 @@ canonicalize_reload_addr (rtx addr) return addr; } +/* Return rtx accessing reload REG matching another reload reg in MODE. */ +static rtx +get_matching_reload_reg_subreg (machine_mode mode, rtx reg) +{ + if (SCALAR_INT_MODE_P (mode) && SCALAR_INT_MODE_P (GET_MODE (reg))) + /* For matching scalar int modes generate the right subreg byte offset for + BE targets -- see call of reload.cc:operands_match_p in + recog.cc:constrain_operands. */ + return lowpart_subreg (mode, reg, GET_MODE (reg)); + return gen_rtx_SUBREG (mode, reg, 0); +} + /* Create a new pseudo using MODE, RCLASS, EXCLUDE_START_HARD_REGS, ORIGINAL or reuse an existing reload pseudo. Don't reuse an existing reload pseudo if IN_SUBREG_P is true and the reused pseudo should be wrapped up in a SUBREG. @@ -766,7 +778,7 @@ get_reload_reg (enum op_type type, machine_mode mode, rtx original, if (maybe_lt (GET_MODE_SIZE (GET_MODE (reg)), GET_MODE_SIZE (mode))) continue; - reg = lowpart_subreg (mode, reg, GET_MODE (reg)); + reg = get_matching_reload_reg_subreg (mode, reg); if (reg == NULL_RTX || GET_CODE (reg) != SUBREG) continue; } @@ -1134,7 +1146,7 @@ match_reload (signed char out, signed char *ins, signed char *outs, = lra_create_new_reg_with_unique_value (inmode, in_rtx, goal_class, exclude_start_hard_regs, ""); - new_out_reg = gen_lowpart_SUBREG (outmode, reg); + new_out_reg = get_matching_reload_reg_subreg (outmode, reg); LRA_SUBREG_P (new_out_reg) = 1; /* If the input reg is dying here, we can use the same hard register for REG and IN_RTX. We do it only for original @@ -1153,7 +1165,7 @@ match_reload (signed char out, signed char *ins, signed char *outs, goal_class, exclude_start_hard_regs, ""); - new_in_reg = gen_lowpart_SUBREG (inmode, reg); + new_in_reg = get_matching_reload_reg_subreg (inmode, reg); /* NEW_IN_REG is non-paradoxical subreg. We don't want NEW_OUT_REG living above. We add clobber clause for this. This is just a temporary clobber. We can remove
