summaryrefslogtreecommitdiff
path: root/gcc/lra-constraints.c
diff options
context:
space:
mode:
authorvmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>2014-03-28 22:14:36 +0000
committervmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>2014-03-28 22:14:36 +0000
commit28f7a2af1cd69fbd585093981ef571de5aa67df1 (patch)
treefdee9bbb1c36405dbb87776539318c3b64c8c6df /gcc/lra-constraints.c
parent6e70f6fbe70fe7ec5fcd0fd680dd299276d1a9e0 (diff)
downloadgcc-28f7a2af1cd69fbd585093981ef571de5aa67df1.tar.gz
2014-03-28 Vladimir Makarov <vmakarov@redhat.com>
PR target/60697 * lra-constraints.c (index_part_to_reg): New. (process_address): Use it. 2014-03-28 Vladimir Makarov <vmakarov@redhat.com> PR target/60697 * gcc.target/aarch64/pr60697.c: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@208926 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/lra-constraints.c')
-rw-r--r--gcc/lra-constraints.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index ba4d489e9e5..cfc3d7eaaee 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -2631,6 +2631,20 @@ base_plus_disp_to_reg (struct address_info *ad)
return new_reg;
}
+/* Make reload of index part of address AD. Return the new
+ pseudo. */
+static rtx
+index_part_to_reg (struct address_info *ad)
+{
+ rtx new_reg;
+
+ new_reg = lra_create_new_reg (GET_MODE (*ad->index), NULL_RTX,
+ INDEX_REG_CLASS, "index term");
+ expand_mult (GET_MODE (*ad->index), *ad->index_term,
+ GEN_INT (get_index_scale (ad)), new_reg, 1);
+ return new_reg;
+}
+
/* Return true if we can add a displacement to address AD, even if that
makes the address invalid. The fix-up code requires any new address
to be the sum of the BASE_TERM, INDEX and DISP_TERM fields. */
@@ -2935,7 +2949,7 @@ process_address (int nop, rtx *before, rtx *after)
emit_insn (insns);
*ad.inner = new_reg;
}
- else
+ else if (ad.disp_term != NULL)
{
/* base + scale * index + disp => new base + scale * index,
case (1) above. */
@@ -2943,6 +2957,18 @@ process_address (int nop, rtx *before, rtx *after)
*ad.inner = simplify_gen_binary (PLUS, GET_MODE (new_reg),
new_reg, *ad.index);
}
+ else
+ {
+ /* base + scale * index => base + new_reg,
+ case (1) above.
+ Index part of address may become invalid. For example, we
+ changed pseudo on the equivalent memory and a subreg of the
+ pseudo onto the memory of different mode for which the scale is
+ prohibitted. */
+ new_reg = index_part_to_reg (&ad);
+ *ad.inner = simplify_gen_binary (PLUS, GET_MODE (new_reg),
+ *ad.base_term, new_reg);
+ }
*before = get_insns ();
end_sequence ();
return true;