aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorYvan Roux <yvan.roux@linaro.org>2017-06-12 10:57:45 +0200
committerYvan Roux <yvan.roux@linaro.org>2017-06-13 12:02:41 +0000
commit9e47cb881a229f1ad45675c8720d793bb7caefc8 (patch)
treee4e751c60ce846d57740d37f0870ed301539aff8 /gcc
parent6b43d93b2865e2dd7a40d2754a7d9714719c7d8b (diff)
gcc/
Backport from trunk r247720. 2017-05-06 Richard Sandiford <richard.sandiford@linaro.org> * lra-constraints.c (lra_copy_reg_equiv): New function. (split_reg): Use it to copy equivalence information from the original register to the spill register. gcc/testsuite/ Backport from trunk r247720. 2017-05-06 Richard Sandiford <richard.sandiford@linaro.org> * gcc.target/aarch64/spill_1.c: New test. Change-Id: Ifa5d6a13371c098b77bbc76c8153acf05cc57b51
Diffstat (limited to 'gcc')
-rw-r--r--gcc/lra-constraints.c42
-rw-r--r--gcc/testsuite/gcc.target/aarch64/spill_1.c18
2 files changed, 54 insertions, 6 deletions
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index c8bc9b9a66f..b0ae0fe3d9a 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -5394,6 +5394,29 @@ choose_split_class (enum reg_class allocno_class,
#endif
}
+/* Copy any equivalence information from ORIGINAL_REGNO to NEW_REGNO.
+ It only makes sense to call this function if NEW_REGNO is always
+ equal to ORIGINAL_REGNO. */
+
+static void
+lra_copy_reg_equiv (unsigned int new_regno, unsigned int original_regno)
+{
+ if (!ira_reg_equiv[original_regno].defined_p)
+ return;
+
+ ira_expand_reg_equiv ();
+ ira_reg_equiv[new_regno].defined_p = true;
+ if (ira_reg_equiv[original_regno].memory)
+ ira_reg_equiv[new_regno].memory
+ = copy_rtx (ira_reg_equiv[original_regno].memory);
+ if (ira_reg_equiv[original_regno].constant)
+ ira_reg_equiv[new_regno].constant
+ = copy_rtx (ira_reg_equiv[original_regno].constant);
+ if (ira_reg_equiv[original_regno].invariant)
+ ira_reg_equiv[new_regno].invariant
+ = copy_rtx (ira_reg_equiv[original_regno].invariant);
+}
+
/* Do split transformations for insn INSN, which defines or uses
ORIGINAL_REGNO. NEXT_USAGE_INSNS specifies which instruction in
the EBB next uses ORIGINAL_REGNO; it has the same form as the
@@ -5515,6 +5538,7 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn,
new_reg = lra_create_new_reg (mode, original_reg, rclass, "split");
reg_renumber[REGNO (new_reg)] = hard_regno;
}
+ int new_regno = REGNO (new_reg);
save = emit_spill_move (true, new_reg, original_reg);
if (NEXT_INSN (save) != NULL_RTX && !call_save_p)
{
@@ -5523,7 +5547,7 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn,
fprintf
(lra_dump_file,
" Rejecting split %d->%d resulting in > 2 save insns:\n",
- original_regno, REGNO (new_reg));
+ original_regno, new_regno);
dump_rtl_slim (lra_dump_file, save, NULL, -1, 0);
fprintf (lra_dump_file,
" ))))))))))))))))))))))))))))))))))))))))))))))))\n");
@@ -5538,18 +5562,24 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn,
fprintf (lra_dump_file,
" Rejecting split %d->%d "
"resulting in > 2 restore insns:\n",
- original_regno, REGNO (new_reg));
+ original_regno, new_regno);
dump_rtl_slim (lra_dump_file, restore, NULL, -1, 0);
fprintf (lra_dump_file,
" ))))))))))))))))))))))))))))))))))))))))))))))))\n");
}
return false;
}
+ /* Transfer equivalence information to the spill register, so that
+ if we fail to allocate the spill register, we have the option of
+ rematerializing the original value instead of spilling to the stack. */
+ if (!HARD_REGISTER_NUM_P (original_regno)
+ && mode == PSEUDO_REGNO_MODE (original_regno))
+ lra_copy_reg_equiv (new_regno, original_regno);
after_p = usage_insns[original_regno].after_p;
- lra_reg_info[REGNO (new_reg)].restore_rtx = regno_reg_rtx[original_regno];
- bitmap_set_bit (&check_only_regs, REGNO (new_reg));
+ lra_reg_info[new_regno].restore_rtx = regno_reg_rtx[original_regno];
+ bitmap_set_bit (&check_only_regs, new_regno);
bitmap_set_bit (&check_only_regs, original_regno);
- bitmap_set_bit (&lra_split_regs, REGNO (new_reg));
+ bitmap_set_bit (&lra_split_regs, new_regno);
for (;;)
{
if (GET_CODE (next_usage_insns) != INSN_LIST)
@@ -5565,7 +5595,7 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn,
if (lra_dump_file != NULL)
{
fprintf (lra_dump_file, " Split reuse change %d->%d:\n",
- original_regno, REGNO (new_reg));
+ original_regno, new_regno);
dump_insn_slim (lra_dump_file, as_a <rtx_insn *> (usage_insn));
}
}
diff --git a/gcc/testsuite/gcc.target/aarch64/spill_1.c b/gcc/testsuite/gcc.target/aarch64/spill_1.c
new file mode 100644
index 00000000000..847425895d4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/spill_1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+typedef int v4si __attribute__ ((vector_size (16)));
+
+void bar (void);
+void
+foo (void)
+{
+ v4si x = { 1, 1, 1, 1 };
+ asm ("# %0" :: "w" (x));
+ bar ();
+ asm ("# %0" :: "w" (x));
+}
+
+/* { dg-final { scan-assembler-times {\tmovi\tv[0-9]+\.4s,} 2 } } */
+/* { dg-final { scan-assembler-not {\tldr\t} } } */
+/* { dg-final { scan-assembler-not {\tstr\t} } } */