Hi Richard,

On Wed, 2026-07-15 at 09:07 +0200, Richard Biener wrote:
> > I have had a go with Google Gemini at PR target/121847 [1] and it came
> > up with a working fix on first attempt. The fix is trivial and requires
> > patching just a few lines in the function get_matching_reload_reg_subreg()
> > in gcc/lra-constraints.cc.
> > 
> > I don't want to share the patch at the moment as LLM contributions aren't
> > in GCC at the moment from my understanding, so I would like to ask what
> > kind of input is allowed.
> > 
> > Can I share a description of the bug and the solution without posting the
> > actual patch?
> 
> I think you can share the actual patch as well, just don't expect it to be
> merged unless you can explain it yourself at least.

The actual patch is rather simple:

--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -694,14 +694,16 @@ get_matching_reload_reg_subreg (machine_mode mode, rtx 
reg,
                                enum reg_class rclass)
 {
   int hard_regno = ira_class_hard_regs[rclass][0];
+  rtx res;
   if (subreg_regno_offset (hard_regno,
                           GET_MODE (reg),
                           subreg_lowpart_offset (mode, GET_MODE (reg)),
-                          mode) == 0)
+                          mode) == 0
+      && (res = lowpart_subreg (mode, reg, GET_MODE (reg))) != NULL_RTX)
     /* 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 res;
   int offset = (lra_constraint_offset (hard_regno, GET_MODE (reg))
                - lra_constraint_offset (hard_regno, mode)) * UNITS_PER_WORD;
   lra_assert (offset >= 0);

The explanation for the crash as provided by the LLM is:

===================================================================================

  The root cause of this crash is a clash between LRA's reload subreg 
generation and
  the strict RTL validation rules in emit-rtl.cc:validate_subreg, specifically 
regarding
  alignment requirements for mismatched floating-point modes on big-endian 
targets.

  The Mechanism of the Failure:
   1. In s_cexp.i, the inline assembly forces a DFmode (8 bytes) input and an 
XFmode
      (12 bytes) output to match and share the same hardware floating-point 
register.
   2. During constraint matching (lra-constraints.cc:match_reload), LRA 
attempts to
      generate a matching reload subreg via get_matching_reload_reg_subreg.
   3. For m68k FP registers, m68k_hard_regno_nregs returns 1 for both DFmode 
and XFmode.
      Because both modes occupy exactly 1 hard register, subreg_regno_offset 
evaluates to 0.
   4. Seeing a regno offset of 0, get_matching_reload_reg_subreg attempts to 
create a
      mathematical lowpart subreg by calling lowpart_subreg(DFmode, 
reg(XFmode), XFmode).
   5. On a big-endian target, the mathematical lowpart byte offset for 
extracting 8 bytes
      from a 12-byte mode is 4 (12 - 8 = 4).
   6. The RTL validator (validate_subreg) strictly rejects (subreg:DF (reg:XF) 
4). Specifically,
      it enforces that the subreg byte offset must be a multiple of the outer 
mode's size (offset
      % osize == 0). Since 4 % 8 != 0, validation fails.

  The Crash:
   * In older revisions (as seen in the original stack trace), 
gen_lowpart_SUBREG was used,
     which blindly passed the invalid offset 4 into gen_rtx_SUBREG, immediately 
tripping the
     gcc_assert(validate_subreg(...)) and causing the ICE.
   * In the current trunk (after the PR124079 refactor), lowpart_subreg safely 
returns NULL_RTX
     when validation fails. However, get_matching_reload_reg_subreg returns 
this NULL_RTX directly
     to match_reload, where the LRA_SUBREG_P (new_out_reg) = 1 macro 
dereferences the null pointer,
     causing a segmentation fault.

  The Solution:
  The logic in get_matching_reload_reg_subreg needs to gracefully handle the 
case where lowpart_subreg
  returns NULL_RTX due to RTL alignment validation failures. 

  If lowpart_subreg returns NULL_RTX, the function should fall back to the 
standard lra_constraint_offset
  path at the bottom of the function. For floating-point registers, 
lra_constraint_offset yields an offset
  of 0.

===================================================================================

Since all I did was pass the bug description to the LLM as well instructing it 
to find
a solution, I don't claim authorship to that patch and also cannot say whether 
the patch
is correct as my current GCC knowledge is still rather limited, although I'm 
trying to
improve it.

Either way, I hope that the proposed patch will help find a proper solution so 
we can
switch m68k over to using LRA by default.

Adrian

-- 
 .''`.  John Paul Adrian Glaubitz
: :' :  Debian Developer
`. `'   Physicist
  `-    GPG: 62FF 8A75 84E0 2956 9546  0006 7426 3B37 F5B5 F913

Reply via email to