https://gcc.gnu.org/g:398bdccce49e0ed5774cf05f7f1fa5aa00f54afe
commit r17-1505-g398bdccce49e0ed5774cf05f7f1fa5aa00f54afe Author: Stefan Schulze Frielinghaus <[email protected]> Date: Fri Jun 12 09:53:48 2026 +0200 Align IRA and LRA when it comes to rejecting equivalences 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. Diff: --- gcc/ira-costs.cc | 13 ++++++++++++- gcc/ira-int.h | 9 +++++++++ gcc/lra-constraints.cc | 10 +--------- gcc/testsuite/gcc.target/s390/ira-pic-spill-1.c | 14 ++++++++++++++ gcc/testsuite/gcc.target/s390/ira-pic-spill-2.c | 21 +++++++++++++++++++++ gcc/testsuite/gcc.target/s390/ira-pic-spill-3.c | 20 ++++++++++++++++++++ 6 files changed, 77 insertions(+), 10 deletions(-) diff --git a/gcc/ira-costs.cc b/gcc/ira-costs.cc index d2ea0cc49e39..65cb75895b84 100644 --- a/gcc/ira-costs.cc +++ b/gcc/ira-costs.cc @@ -2185,7 +2185,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 0b7bd4e9f023..c14bd3d749cc 100644 --- a/gcc/ira-int.h +++ b/gcc/ira-int.h @@ -1715,4 +1715,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 9664b9165f64..bd45d32cc59a 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 000000000000..0ba04778e6d3 --- /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 000000000000..41689ab835ba --- /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 000000000000..a7b4625f5f59 --- /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]; +}
