]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Add support for reloading a frame address with an invalid base
authorRobert Suchanek <robert.suchanek@imgtec.com>
Wed, 18 Jun 2014 19:50:00 +0000 (19:50 +0000)
committerMatthew Fortune <mpf@gcc.gnu.org>
Wed, 18 Jun 2014 19:50:00 +0000 (19:50 +0000)
gcc/

* lra-constraints.c (base_to_reg): New function.
(process_address): Use new function.

From-SVN: r211802

gcc/ChangeLog
gcc/lra-constraints.c

index 564c503e3dd8daf67ba4521eabfd2df3f33ec8a4..988122e825eb6425363b7872e0b02e572e5d1eba 100644 (file)
@@ -1,3 +1,8 @@
+2014-06-18  Robert Suchanek  <robert.suchanek@imgtec.com>
+
+       * lra-constraints.c (base_to_reg): New function.       
+       (process_address): Use new function.                   
+
 2014-06-18  Tom de Vries  <tom@codesourcery.com>
 
        * config/aarch64/aarch64-protos.h (aarch64_emit_call_insn): Declare.
index b1904e1bf65493fd664736f9edafedecf4073083..baed7e7d57c2e8840bd52bb74d24a27b0fd4a13d 100644 (file)
@@ -2556,6 +2556,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)
@@ -2775,6 +2808,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))
@@ -2856,14 +2891,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