aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Suchanek <robert.suchanek@imgtec.com>2014-06-18 19:50:00 +0000
committerMatthew Fortune <mpf@gcc.gnu.org>2014-06-18 19:50:00 +0000
commitc31d2d11a994f2b3aefafb9f77d8e1586048eb53 (patch)
tree389f1006b29e705c3c3e92328e7820427aa705ff
parent786077082ee3d554cc3dc22212b77c67e378d3aa (diff)
downloadgcc-c31d2d11a994f2b3aefafb9f77d8e1586048eb53.zip
gcc-c31d2d11a994f2b3aefafb9f77d8e1586048eb53.tar.gz
gcc-c31d2d11a994f2b3aefafb9f77d8e1586048eb53.tar.bz2
Add support for reloading a frame address with an invalid base
gcc/ * lra-constraints.c (base_to_reg): New function. (process_address): Use new function. From-SVN: r211802
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/lra-constraints.c44
2 files changed, 47 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 564c503..988122e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index b1904e1..baed7e7 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -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