From: Stefan Schulze Frielinghaus <[email protected]>
During costing of IRA, pseudos with an equivalence are taken out of the
equation by assigning MEM to those. However, during LRA, some
equivalences are rejected which means those previously spilled pseudos
are then definitely spilled. In some cases, like for PIC, we already
know during IRA that an equivalence will be rejected during LRA.
Therefore, do not assign MEM to those pseudos during IRA which means
there is a fair chance that they get a register assigned in the end.
The attached tests are all derived from glibc. Without this patch some
pseudos are spilled resulting in stack frames just due to those spills.
With this patch, no pseudos are spilled and no unnecessary stack frames
are set up.
Note, the added conjunct in find_costs_and_classes() is basically the
negated form of the disjunct from lra_constraints()
|| (pic_offset_table_rtx
&& ((const_pool_ok_p (PSEUDO_REGNO_MODE (i), x)
&& (targetm.preferred_reload_class
(x, lra_get_allocno_class (i)) == NO_REGS))
|| contains_symbol_ref_p (x))))
except that IRAs reg_allocno_class() is used instead of LRAs
lra_get_allocno_class().
gcc/ChangeLog:
* ira-costs.cc (find_costs_and_classes): Do not honour equivs if
they get rejected by LRA anyway.
* ira-int.h (CONST_POOL_OK_P): Move CONST_POOL_OK_P here ...
* lra-constraints.cc (CONST_POOL_OK_P): from there.
gcc/testsuite/ChangeLog:
* gcc.target/s390/ira-pic-spill-1.c: New test.
* gcc.target/s390/ira-pic-spill-2.c: New test.
* gcc.target/s390/ira-pic-spill-3.c: New test.
---
Notes:
Bootstrapped and regtested on
- aarch64-unknown-linux-gnu
- powerpc64le-unknown-linux-gnu
- s390x-ibm-linux-gnu
- x86_64-pc-linux-gnu
Ok for mainline?
gcc/ira-costs.cc | 13 +++++++++++-
gcc/ira-int.h | 9 ++++++++
gcc/lra-constraints.cc | 10 +--------
.../gcc.target/s390/ira-pic-spill-1.c | 14 +++++++++++++
.../gcc.target/s390/ira-pic-spill-2.c | 21 +++++++++++++++++++
.../gcc.target/s390/ira-pic-spill-3.c | 20 ++++++++++++++++++
6 files changed, 77 insertions(+), 10 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/s390/ira-pic-spill-1.c
create mode 100644 gcc/testsuite/gcc.target/s390/ira-pic-spill-2.c
create mode 100644 gcc/testsuite/gcc.target/s390/ira-pic-spill-3.c
diff --git a/gcc/ira-costs.cc b/gcc/ira-costs.cc
index 8a731422761..b4c550ca2bb 100644
--- a/gcc/ira-costs.cc
+++ b/gcc/ira-costs.cc
@@ -2165,7 +2165,18 @@ find_costs_and_classes (void)
i_mem_cost = 0;
else if (ira_use_lra_p)
{
- if (equiv_savings > 0)
+ rtx x;
+ if (equiv_savings > 0
+ /* During LRA constraint pass, some equivalences are
+ invalidated. Align IRA with LRA here and do not consider
+ those equivalences since otherwise those pseudos are
+ spilled. */
+ && (!pic_offset_table_rtx
+ || (x = ira_reg_equiv[i].constant) == NULL
+ || ((!CONST_POOL_OK_P (PSEUDO_REGNO_MODE (i), x)
+ || targetm.preferred_reload_class
+ (x, reg_allocno_class (i)) != NO_REGS)
+ && !contains_symbol_ref_p (x))))
{
i_mem_cost = 0;
if (ira_dump_file != NULL && internal_flag_ira_verbose > 5)
diff --git a/gcc/ira-int.h b/gcc/ira-int.h
index 6726a0f4cad..ce823661961 100644
--- a/gcc/ira-int.h
+++ b/gcc/ira-int.h
@@ -1727,4 +1727,13 @@ ira_caller_save_loop_spill_p (ira_allocno_t a,
ira_allocno_t subloop_a,
return call_cost && call_cost >= spill_cost;
}
+/* True if X is a constant that can be forced into the constant pool.
+ MODE is the mode of the operand, or VOIDmode if not known. */
+#define CONST_POOL_OK_P(MODE, X) \
+ ((MODE) != VOIDmode \
+ && CONSTANT_P (X) \
+ && GET_CODE (X) != HIGH \
+ && GET_MODE_SIZE (MODE).is_constant () \
+ && !targetm.cannot_force_const_mem (MODE, X))
+
#endif /* GCC_IRA_INT_H */
diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc
index 2b5b4ba1bbd..8d9914e98cb 100644
--- a/gcc/lra-constraints.cc
+++ b/gcc/lra-constraints.cc
@@ -123,6 +123,7 @@
#include "optabs.h"
#include "regs.h"
#include "ira.h"
+#include "ira-int.h"
#include "recog.h"
#include "output.h"
#include "addresses.h"
@@ -1013,15 +1014,6 @@ operands_match_p (rtx x, rtx y, int y_hard_regno)
return true;
}
-/* True if X is a constant that can be forced into the constant pool.
- MODE is the mode of the operand, or VOIDmode if not known. */
-#define CONST_POOL_OK_P(MODE, X) \
- ((MODE) != VOIDmode \
- && CONSTANT_P (X) \
- && GET_CODE (X) != HIGH \
- && GET_MODE_SIZE (MODE).is_constant () \
- && !targetm.cannot_force_const_mem (MODE, X))
-
/* If REG is a reload pseudo, try to make its class satisfying CL. */
static void
narrow_reload_pseudo_class (rtx reg, enum reg_class cl)
diff --git a/gcc/testsuite/gcc.target/s390/ira-pic-spill-1.c
b/gcc/testsuite/gcc.target/s390/ira-pic-spill-1.c
new file mode 100644
index 00000000000..0ba04778e6d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/ira-pic-spill-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=z14 -fPIC" } */
+/* { dg-final { scan-assembler-not {lay\t%r15,-[0-9]+\(%r15\)} } } */
+
+/* Ensure no spills and ultimately that no stack frame is allocated. */
+
+long strstr_ifunc_hwcap;
+void __redirect_strstr();
+__typeof(__redirect_strstr) __strstr_vx __attribute__((visibility("hidden")));
+__typeof(__redirect_strstr) __strstr_arch13
__attribute__((visibility("hidden")));
+__typeof(__redirect_strstr) *strstr_ifunc()
+{
+ return strstr_ifunc_hwcap ? __strstr_arch13 : __strstr_vx;
+}
diff --git a/gcc/testsuite/gcc.target/s390/ira-pic-spill-2.c
b/gcc/testsuite/gcc.target/s390/ira-pic-spill-2.c
new file mode 100644
index 00000000000..41689ab835b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/ira-pic-spill-2.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=z14 -fPIC" } */
+/* { dg-final { scan-assembler-not {lay\t%r15,-[0-9]+\(%r15\)} } } */
+
+/* Ensure no spills and ultimately that no stack frame is allocated. */
+
+typedef long int __time_t;
+typedef long int __syscall_slong_t;
+struct timespec
+{
+ __time_t tv_sec;
+ __syscall_slong_t tv_nsec;
+};
+
+struct timespec
+support_timespec_normalize (struct timespec time)
+{
+ struct timespec norm;
+ norm.tv_sec = time.tv_nsec ? 1073741824 : 65536;
+ return norm;
+}
diff --git a/gcc/testsuite/gcc.target/s390/ira-pic-spill-3.c
b/gcc/testsuite/gcc.target/s390/ira-pic-spill-3.c
new file mode 100644
index 00000000000..a7b4625f5f5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/ira-pic-spill-3.c
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=z14 -fPIC" } */
+/* { dg-final { scan-assembler-not {lay\t%r15,-[0-9]+\(%r15\)} } } */
+
+/* Ensure no spills and ultimately that no stack frame is allocated. */
+
+int _mode;
+struct _IO_FILE_plus {
+ int vtable;
+};
+enum { IO_FILE_JUMPS_MAYBE_MMAP, IO_WFILE_JUMPS_MAYBE_MMAP };
+extern int __io_vtables[] __attribute__((visibility("hidden")));
+void __fopen_maybe_mmap_fp() {
+ if (_mode)
+ *(__typeof__(&(struct _IO_FILE_plus){}.vtable) *)__fopen_maybe_mmap_fp =
+ &__io_vtables[IO_FILE_JUMPS_MAYBE_MMAP];
+ else
+ *(__typeof__(&(struct _IO_FILE_plus){}.vtable) *)__fopen_maybe_mmap_fp =
+ &__io_vtables[IO_WFILE_JUMPS_MAYBE_MMAP];
+}
--
2.53.0