aboutsummaryrefslogtreecommitdiff
path: root/gcc/lra-constraints.c
diff options
context:
space:
mode:
authorVladimir Makarov <vmakarov@redhat.com>2015-01-30 22:22:58 +0000
committerVladimir Makarov <vmakarov@gcc.gnu.org>2015-01-30 22:22:58 +0000
commit895ff86f2e5391df7a550aad27f6e5ae588bd38e (patch)
tree154cb926be6887899fb3f09d2ae3dd113e663dd5 /gcc/lra-constraints.c
parent1c9cc1d30401ff075f1195f648f5223d233349f6 (diff)
downloadgcc-895ff86f2e5391df7a550aad27f6e5ae588bd38e.zip
gcc-895ff86f2e5391df7a550aad27f6e5ae588bd38e.tar.gz
gcc-895ff86f2e5391df7a550aad27f6e5ae588bd38e.tar.bz2
re PR rtl-optimization/64688 (internal compiler error: Max. number of generated reload insns per insn is achieved (90))
2015-01-30 Vladimir Makarov <vmakarov@redhat.com> PR target/64688 * lra-constraints.c (original_subreg_reg_mode): New. (simplify_operand_subreg): Try to simplify subreg of const. Use original_subreg_reg_mode for it. (swap_operands): Update original_subreg_reg_mode. (curr_insn_transform): Set up original_subreg_reg_mode. 2015-01-30 Vladimir Makarov <vmakarov@redhat.com> PR target/64688 * g++.dg/pr64688-2.C: New. From-SVN: r220297
Diffstat (limited to 'gcc/lra-constraints.c')
-rw-r--r--gcc/lra-constraints.c51
1 files changed, 39 insertions, 12 deletions
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index 762889c..827c453 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -170,6 +170,10 @@ static basic_block curr_bb;
static lra_insn_recog_data_t curr_id;
static struct lra_static_insn_data *curr_static_id;
static machine_mode curr_operand_mode[MAX_RECOG_OPERANDS];
+/* Mode of the register substituted by its equivalence with VOIDmode
+ (e.g. constant) and whose subreg is given operand of the current
+ insn. VOIDmode in all other cases. */
+static machine_mode original_subreg_reg_mode[MAX_RECOG_OPERANDS];
@@ -1382,13 +1386,13 @@ static int valid_address_p (machine_mode mode, rtx addr, addr_space_t as);
/* Make reloads for subreg in operand NOP with internal subreg mode
REG_MODE, add new reloads for further processing. Return true if
- any reload was generated. */
+ any change was done. */
static bool
simplify_operand_subreg (int nop, machine_mode reg_mode)
{
int hard_regno;
rtx_insn *before, *after;
- machine_mode mode;
+ machine_mode mode, innermode;
rtx reg, new_reg;
rtx operand = *curr_id->operand_loc[nop];
enum reg_class regclass;
@@ -1401,6 +1405,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
mode = GET_MODE (operand);
reg = SUBREG_REG (operand);
+ innermode = GET_MODE (reg);
type = curr_static_id->operand[nop].type;
/* If we change address for paradoxical subreg of memory, the
address might violate the necessary alignment or the access might
@@ -1419,7 +1424,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
alter_subreg (curr_id->operand_loc[nop], false);
subst = *curr_id->operand_loc[nop];
lra_assert (MEM_P (subst));
- if (! valid_address_p (GET_MODE (reg), XEXP (reg, 0),
+ if (! valid_address_p (innermode, XEXP (reg, 0),
MEM_ADDR_SPACE (reg))
|| valid_address_p (GET_MODE (subst), XEXP (subst, 0),
MEM_ADDR_SPACE (subst)))
@@ -1434,6 +1439,20 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
alter_subreg (curr_id->operand_loc[nop], false);
return true;
}
+ else if (CONSTANT_P (reg))
+ {
+ /* Try to simplify subreg of constant. It is usually result of
+ equivalence substitution. */
+ if (innermode == VOIDmode
+ && (innermode = original_subreg_reg_mode[nop]) == VOIDmode)
+ innermode = curr_static_id->operand[nop].mode;
+ if ((new_reg = simplify_subreg (mode, reg, innermode,
+ SUBREG_BYTE (operand))) != NULL_RTX)
+ {
+ *curr_id->operand_loc[nop] = new_reg;
+ return true;
+ }
+ }
/* Put constant into memory when we have mixed modes. It generates
a better code in most cases as it does not need a secondary
reload memory. It also prevents LRA looping when LRA is using
@@ -1453,9 +1472,9 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
&& (hard_regno = lra_get_regno_hard_regno (REGNO (reg))) >= 0
/* Don't reload paradoxical subregs because we could be looping
having repeatedly final regno out of hard regs range. */
- && (hard_regno_nregs[hard_regno][GET_MODE (reg)]
+ && (hard_regno_nregs[hard_regno][innermode]
>= hard_regno_nregs[hard_regno][mode])
- && simplify_subreg_regno (hard_regno, GET_MODE (reg),
+ && simplify_subreg_regno (hard_regno, innermode,
SUBREG_BYTE (operand), mode) < 0
/* Don't reload subreg for matching reload. It is actually
valid subreg in LRA. */
@@ -1481,7 +1500,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg));
insert_before = (type != OP_OUT
- || GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (mode));
+ || GET_MODE_SIZE (innermode) > GET_MODE_SIZE (mode));
insert_after = (type != OP_IN);
insert_move_for_subreg (insert_before ? &before : NULL,
insert_after ? &after : NULL,
@@ -1524,7 +1543,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
else if (REG_P (reg)
&& REGNO (reg) >= FIRST_PSEUDO_REGISTER
&& (hard_regno = lra_get_regno_hard_regno (REGNO (reg))) >= 0
- && (hard_regno_nregs[hard_regno][GET_MODE (reg)]
+ && (hard_regno_nregs[hard_regno][innermode]
< hard_regno_nregs[hard_regno][mode])
&& (regclass = lra_get_allocno_class (REGNO (reg)))
&& (type != OP_IN
@@ -1542,7 +1561,7 @@ simplify_operand_subreg (int nop, machine_mode reg_mode)
bool insert_before, insert_after;
PUT_MODE (new_reg, mode);
- subreg = simplify_gen_subreg (GET_MODE (reg), new_reg, mode, 0);
+ subreg = simplify_gen_subreg (innermode, new_reg, mode, 0);
bitmap_set_bit (&lra_subreg_reload_pseudos, REGNO (new_reg));
insert_before = (type != OP_OUT);
@@ -3286,6 +3305,9 @@ swap_operands (int nop)
machine_mode mode = curr_operand_mode[nop];
curr_operand_mode[nop] = curr_operand_mode[nop + 1];
curr_operand_mode[nop + 1] = mode;
+ mode = original_subreg_reg_mode[nop];
+ original_subreg_reg_mode[nop] = original_subreg_reg_mode[nop + 1];
+ original_subreg_reg_mode[nop + 1] = mode;
rtx x = *curr_id->operand_loc[nop];
*curr_id->operand_loc[nop] = *curr_id->operand_loc[nop + 1];
*curr_id->operand_loc[nop + 1] = x;
@@ -3389,21 +3411,26 @@ curr_insn_transform (bool check_only_p)
if (GET_CODE (old) == SUBREG)
old = SUBREG_REG (old);
subst = get_equiv_with_elimination (old, curr_insn);
+ original_subreg_reg_mode[i] = VOIDmode;
if (subst != old)
{
subst = copy_rtx (subst);
lra_assert (REG_P (old));
- if (GET_CODE (op) == SUBREG)
- SUBREG_REG (op) = subst;
- else
+ if (GET_CODE (op) != SUBREG)
*curr_id->operand_loc[i] = subst;
+ else
+ {
+ SUBREG_REG (op) = subst;
+ if (GET_MODE (subst) == VOIDmode)
+ original_subreg_reg_mode[i] = GET_MODE (old);
+ }
if (lra_dump_file != NULL)
{
fprintf (lra_dump_file,
"Changing pseudo %d in operand %i of insn %u on equiv ",
REGNO (old), i, INSN_UID (curr_insn));
dump_value_slim (lra_dump_file, subst, 1);
- fprintf (lra_dump_file, "\n");
+ fprintf (lra_dump_file, "\n");
}
op_change_p = change_p = true;
}