Pinging for approval. This part of the patch will be needed for MIPS16. The second part to enable LRA in MIPS has been already approved.
> Hi Richard, > > >> Robert: you also had an LRA change, but is it still needed after this one? > >> If so, could you repost it and explain the case it handles? > > For just turning the LRA for the MIPS backend is not needed but we have issues > with the code size for MIPS16. LRA inserted a lot of reloads and the code size > increased on average by about 10% IIRC. To fix this, a number of patterns > have to accept the stack pointer and a new class, M16_SP_REGS with > M16_REGS + $sp was added. > > However, this triggered a reloading problem as the stack pointer was rejected > by the back end and LRA tried to insert base+disp with the displacement not > always present. It only affects $sp not directly accessible as in MIPS16 case. > > Regards, > Robert > > gcc/ > * lra-constraints.c (base_to_reg): New function. > (process_address): Use new function. > > diff --git gcc/lra-constraints.c gcc/lra-constraints.c > index 08716fe..d5ed37f 100644 > --- gcc/lra-constraints.c > +++ gcc/lra-constraints.c > @@ -2686,6 +2686,39 @@ process_alt_operands (int only_alternative) > return ok_p; > } > > +/* Make reload base reg from address AD. */ > +static rtx > +base_to_reg (struct address_info *ad) > +{ > + enum reg_class cl; > + int code = -1; > + rtx new_inner = NULL_RTX; > + rtx new_reg = NULL_RTX; > + rtx insn; > + rtx last_insn = get_last_insn(); > + > + lra_assert (ad->base == ad->base_term && ad->disp == ad->disp_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, "base"); > + new_inner = simplify_gen_binary (PLUS, GET_MODE (new_reg), new_reg, > + ad->disp_term == NULL > + ? gen_int_mode (0, ad->mode) > + : *ad->disp_term); > + if (!valid_address_p (ad->mode, new_inner, ad->as)) > + return NULL_RTX; > + insn = emit_insn (gen_rtx_SET (ad->mode, new_reg, *ad->base_term)); > + code = recog_memoized (insn); > + if (code < 0) > + { > + delete_insns_since (last_insn); > + return NULL_RTX; > + } > + > + return new_inner; > +} > + > /* Make reload base reg + disp from address AD. Return the new pseudo. */ > static rtx > base_plus_disp_to_reg (struct address_info *ad) > @@ -2908,6 +2941,8 @@ process_address_1 (int nop, rtx *before, rtx *after) > > 3) the address is a frame address with an invalid offset. > > + 4) the address is a frame address with an invalid base. > + > All these cases involve a non-autoinc address, so there is no > point revalidating other types. */ > if (ad.autoinc_p || valid_address_p (&ad)) > @@ -2989,14 +3024,19 @@ process_address_1 (int nop, rtx *before, rtx *after) > int regno; > enum reg_class cl; > rtx set, insns, last_insn; > + /* Try to reload base into register only if the base is invalid > + for the address but with valid offset, case (4) above. */ > + start_sequence (); > + new_reg = base_to_reg (&ad); > + > /* base + disp => new base, cases (1) and (3) above. */ > /* Another option would be to reload the displacement into an > index register. However, postreload has code to optimize > address reloads that have the same base and different > displacements, so reloading into an index register would > not necessarily be a win. */ > - start_sequence (); > - new_reg = base_plus_disp_to_reg (&ad); > + if (new_reg == NULL_RTX) > + new_reg = base_plus_disp_to_reg (&ad); > insns = get_insns (); > last_insn = get_last_insn (); > /* If we generated at least two insns, try last insn source as