On 2014-06-16, 12:12 PM, Robert Suchanek wrote:
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.


Sorry, Robert. I thought you are waiting for some Richard's comment (actually he knows the code well and wrote address decoding in rtlanal.c).

The patch is ok for me and makes LRA even more portable as it adds a new profitable address transformation and the code can be useful for other targets too.

  Thanks.


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


Reply via email to