Record equivalences for spill registers
authorRichard Sandiford <richard.sandiford@linaro.org>
Sat, 6 May 2017 07:46:48 +0000 (07:46 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Sat, 6 May 2017 07:46:48 +0000 (07:46 +0000)
If we decide to allocate a call-clobbered register R to a value that
is live across a call, LRA will create a new spill register TMPR,
insert:

   TMPR <- R

before the call and

   R <- TMPR

after it.  But if we then failed to allocate a register to TMPR, we would
always spill it to the stack, even if R was known to be equivalent to
a constant or to some existing memory location.  And on AArch64, we'd
always fail to allocate such a register for 128-bit Advanced SIMD modes,
since no registers of those modes are call-preserved.

This patch avoids the problem by copying the equivalence information
from the original pseudo to the spill register.  It means that the
code for the testcase is as good with -O2 as it is with -O,
whereas previously the -O code was better.

[Based on the code ARM contributed in branches/ARM/sve-branch@247248]

2017-05-06  Richard Sandiford  <richard.sandiford@linaro.org>

gcc/
* 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/
* gcc.target/aarch64/spill_1.c: New test.

From-SVN: r247720

gcc/ChangeLog
gcc/lra-constraints.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/aarch64/spill_1.c [new file with mode: 0644]

index 58f09a19f6d5c724e673b964c7c4bb027e50af9a..b0c253b09aea0c496a51b4220ff2a91016858a62 100644 (file)
@@ -1,3 +1,9 @@
+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.
+
 2017-05-06  Richard Sandiford  <richard.sandiford@linaro.org>
 
        PR rtl-optimization/75964
index c8bc9b9a66f3c47aa6b7cf34e1c8b96092490cf2..b0ae0fe3d9a815e7eca5935c2fa4e786ef51123c 100644 (file)
@@ -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));
        }
     }
index 587e4821b658e8881b322bbc8278423caa9988b3..fca5b87e7983c09dc6bc3e4f297dccbad9f6d5c1 100644 (file)
@@ -1,3 +1,7 @@
+2017-05-06  Richard Sandiford  <richard.sandiford@linaro.org>
+
+       * gcc.target/aarch64/spill_1.c: New test.
+
 2017-05-06  Richard Sandiford  <richard.sandiford@linaro.org>
 
        PR rtl-optimization/75964
diff --git a/gcc/testsuite/gcc.target/aarch64/spill_1.c b/gcc/testsuite/gcc.target/aarch64/spill_1.c
new file mode 100644 (file)
index 0000000..8474258
--- /dev/null
@@ -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} } } */