https://gcc.gnu.org/g:560766f6e239a8192c42ac5f009f0a4ee2478a61

commit r16-7464-g560766f6e239a8192c42ac5f009f0a4ee2478a61
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:
---
 gcc/lra-constraints.cc | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 87b18f30c980..8c8c9d69a965 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

Reply via email to