summaryrefslogtreecommitdiff
path: root/gcc/lra-spills.c
diff options
context:
space:
mode:
authorVladimir Makarov <vmakarov@redhat.com>2015-10-20 16:26:05 +0000
committerVladimir Makarov <vmakarov@gcc.gnu.org>2015-10-20 16:26:05 +0000
commit8cda1c3eb263349536beb300cf6c278f51f2fead (patch)
tree21ee9ffc4a802d51f929fd032e0aa58524c64e7a /gcc/lra-spills.c
parentbfb792b6044c340b54a9d04b2a1e6e0e608b3aa6 (diff)
re PR rtl-optimization/67609 (Generates wrong code for SSE2 _mm_load_pd)
2015-10-20 Vladimir Makarov <vmakarov@redhat.com> PR rtl-optimization/67609 * lra-splill.c (lra_final_code_change): Don't remove all sub-registers. 2015-10-20 Vladimir Makarov <vmakarov@redhat.com> PR rtl-optimization/67609 * gcc.target/i386/pr67609.c: New. From-SVN: r229087
Diffstat (limited to 'gcc/lra-spills.c')
-rw-r--r--gcc/lra-spills.c46
1 files changed, 38 insertions, 8 deletions
diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c
index a210c41da31..9c1207f5057 100644
--- a/gcc/lra-spills.c
+++ b/gcc/lra-spills.c
@@ -727,14 +727,44 @@ lra_final_code_change (void)
lra_insn_recog_data_t id = lra_get_insn_recog_data (insn);
struct lra_static_insn_data *static_id = id->insn_static_data;
bool insn_change_p = false;
-
- for (i = id->insn_static_data->n_operands - 1; i >= 0; i--)
- if ((DEBUG_INSN_P (insn) || ! static_id->operand[i].is_operator)
- && alter_subregs (id->operand_loc[i], ! DEBUG_INSN_P (insn)))
- {
- lra_update_dup (id, i);
- insn_change_p = true;
- }
+
+ for (i = id->insn_static_data->n_operands - 1; i >= 0; i--)
+ {
+ if (! DEBUG_INSN_P (insn) && static_id->operand[i].is_operator)
+ continue;
+
+ rtx op = *id->operand_loc[i];
+
+ if (static_id->operand[i].type == OP_OUT
+ && GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op))
+ && ! LRA_SUBREG_P (op))
+ {
+ hard_regno = REGNO (SUBREG_REG (op));
+ /* We can not always remove sub-registers of
+ hard-registers as we may lose information that
+ only a part of registers is changed and
+ subsequent optimizations may do wrong
+ transformations (e.g. dead code eliminations).
+ We can not also keep all sub-registers as the
+ subsequent optimizations can not handle all such
+ cases. Here is a compromise which works. */
+ if ((GET_MODE_SIZE (GET_MODE (op))
+ < GET_MODE_SIZE (GET_MODE (SUBREG_REG (op))))
+ && (hard_regno_nregs[hard_regno][GET_MODE (SUBREG_REG (op))]
+ == hard_regno_nregs[hard_regno][GET_MODE (op)])
+#ifdef STACK_REGS
+ && (hard_regno < FIRST_STACK_REG
+ || hard_regno > LAST_STACK_REG)
+#endif
+ )
+ continue;
+ }
+ if (alter_subregs (id->operand_loc[i], ! DEBUG_INSN_P (insn)))
+ {
+ lra_update_dup (id, i);
+ insn_change_p = true;
+ }
+ }
if (insn_change_p)
lra_update_operator_dups (id);
}