https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116236
--- Comment #6 from Michael Matz <matz at gcc dot gnu.org> --- This works for me for the full testcase. a) accept pseudos during lra_in_progress only when they're allocated to the right hardreg b) but _only_ do (a) if the pseudo is not one of those generated _during_ LRA (the >= lra_new_regno_start test) c) when base+disp (and base being allocated the wrong class) needs to be reloaded into a new reg, then accept the base as deconstructed, don't insist on base and base_term being the same Case (c) is for insns like the problematic one, where the address needs to be reloaded for whatever reason. We have for instance: (insn 49 48 52 6 (set (reg/v:SI 96 [ __y0 ]) (plus:SI (plus:SI (sign_extend:SI (reg/v:HI 134 [ y ])) (reg:SI 144)) (const_int 1468000 [0x166660]))) "../../include/chrono":1768:18 421 {*lea} The address operand here is (plus:SI (plus:SI (sign_extend:SI (reg/v:HI 134 [ y ])) (reg:SI 144)) (const_int 1468000 [0x166660])) and decomposition makes ad->base be '(sign_extend:SI (reg/v:HI 134 [ y ]))' (and hence ad->base_term be '(reg/v:HI 134 [ y ])'). That's suboptimal but okay. Further, this base+index+disp operand needs reloading (due to the suboptimal decomposition and hence suboptimal register class assignment). So LRA wants to reload base+disp (i.e. (sign_extend:SI (reg/v:HI 134 [ y ])) plus (const_int 1468000 [0x166660])), via base_plus_disp_to_reg(), but for whatever reason insists on the base being the same as the base_term, i.e. be a simple pseudo only. But in this case it's completely fine (and correct) to just form the plus of the given base plus offset. (As I don't know the reason for the assert it's of course quite possible that this will create problems in other cases). I haven't checked more that just compilation of the large and small testcases here. Probably stuff is miscompiled. I lack an overview of how LRA is supposed to work in presence of more complicated address forms given that it doesn't call the backend with any strict checking. ---- diff --git a/gcc/config/m68k/m68k.cc b/gcc/config/m68k/m68k.cc index 79ba4d5343c..650084566e2 100644 --- a/gcc/config/m68k/m68k.cc +++ b/gcc/config/m68k/m68k.cc @@ -306,8 +306,8 @@ static machine_mode m68k_c_mode_for_floating_type (enum tre #define TARGET_ASM_OUTPUT_DWARF_DTPREL m68k_output_dwarf_dtprel #endif -#undef TARGET_LRA_P -#define TARGET_LRA_P hook_bool_void_false +//#undef TARGET_LRA_P +//#define TARGET_LRA_P hook_bool_void_false #undef TARGET_LEGITIMATE_ADDRESS_P #define TARGET_LEGITIMATE_ADDRESS_P m68k_legitimate_address_p @@ -2026,20 +2026,27 @@ m68k_output_bftst (rtx zxop0, rtx zxop1, rtx zxop2, rtx return code; } ^L +extern int lra_new_regno_start; /* Return true if X is a legitimate base register. STRICT_P says whether we need strict checking. */ bool m68k_legitimate_base_reg_p (rtx x, bool strict_p) { + int regno; /* Allow SUBREG everywhere we allow REG. This results in better code. */ if (!strict_p && GET_CODE (x) == SUBREG) x = SUBREG_REG (x); - return (REG_P (x) - && (strict_p - ? REGNO_OK_FOR_BASE_P (REGNO (x)) - : REGNO_OK_FOR_BASE_NONSTRICT_P (REGNO (x)))); + if (!REG_P (x)) + return false; + regno = REGNO (x); + if (lra_in_progress && regno >= lra_new_regno_start) + return true; + + return (strict_p || lra_in_progress + ? REGNO_OK_FOR_BASE_P (regno) + : REGNO_OK_FOR_BASE_NONSTRICT_P (regno)); } /* Return true if X is a legitimate index register. STRICT_P says @@ -2048,13 +2055,19 @@ m68k_legitimate_base_reg_p (rtx x, bool strict_p) bool m68k_legitimate_index_reg_p (rtx x, bool strict_p) { + int regno; if (!strict_p && GET_CODE (x) == SUBREG) x = SUBREG_REG (x); - return (REG_P (x) - && (strict_p - ? REGNO_OK_FOR_INDEX_P (REGNO (x)) - : REGNO_OK_FOR_INDEX_NONSTRICT_P (REGNO (x)))); + if (!REG_P (x)) + return false; + regno = REGNO (x); + if (lra_in_progress && regno >= lra_new_regno_start) + return true; + + return (strict_p || lra_in_progress + ? REGNO_OK_FOR_INDEX_P (regno) + : REGNO_OK_FOR_INDEX_NONSTRICT_P (regno)); } /* Return true if X is a legitimate index expression for a (d8,An,Xn) or diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index 92b343fa99a..4ccab7e3395 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -3473,12 +3473,11 @@ base_plus_disp_to_reg (struct address_info *ad, rtx dis enum reg_class cl; rtx new_reg; - lra_assert (ad->base == ad->base_term); cl = base_reg_class (ad->mode, ad->as, ad->base_outer_code, get_index_code (ad)); - new_reg = lra_create_new_reg (GET_MODE (*ad->base_term), NULL_RTX, cl, NULL, + new_reg = lra_create_new_reg (GET_MODE (*ad->base), NULL_RTX, cl, NULL, "base + disp"); - lra_emit_add (new_reg, *ad->base_term, disp); + lra_emit_add (new_reg, *ad->base, disp); return new_reg; }