https://gcc.gnu.org/g:9f009e8865cda01310c52f7ec8bdaa3c557a2745
commit r15-7008-g9f009e8865cda01310c52f7ec8bdaa3c557a2745 Author: Vladimir N. Makarov <vmaka...@redhat.com> Date: Fri Jan 17 15:56:29 2025 -0500 [PR118067][LRA]: Check secondary memory mode for the reg class This is the second patch for the PR for the new test. The patch solves problem in the case when secondary memory mode (SImode in the PR test) returned by hook secondary_memory_needed_mode can not be used for reg class (ALL_MASK_REGS) involved in secondary memory moves. The patch uses reg mode instead of one returned by secondary_memory_needed_mode in this case. gcc/ChangeLog: PR rtl-optimization/118067 * lra-constraints.cc (invalid_mode_reg_p): New function. (curr_insn_transform): Use it to check mode returned by target secondary_memory_needed_mode. gcc/testsuite/ChangeLog: * gcc.target/i386/pr118067-2.c: New. Diff: --- gcc/lra-constraints.cc | 17 +++++++++++++++++ gcc/testsuite/gcc.target/i386/pr118067-2.c | 16 ++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/gcc/lra-constraints.cc b/gcc/lra-constraints.cc index 3d5abcfaeb0b..cd19da294db3 100644 --- a/gcc/lra-constraints.cc +++ b/gcc/lra-constraints.cc @@ -4129,6 +4129,19 @@ swap_operands (int nop) lra_update_dup (curr_id, nop + 1); } +/* Return TRUE if X is a (subreg of) reg and there are no hard regs of X class + which can contain value of MODE. */ +static bool invalid_mode_reg_p (enum machine_mode mode, rtx x) +{ + if (SUBREG_P (x)) + x = SUBREG_REG (x); + if (! REG_P (x)) + return false; + enum reg_class rclass = get_reg_class (REGNO (x)); + return hard_reg_set_subset_p (ira_prohibited_class_mode_regs[rclass][mode], + reg_class_contents[rclass]); +} + /* Main entry point of the constraint code: search the body of the current insn to choose the best alternative. It is mimicking insn alternative cost calculation model of former reload pass. That is @@ -4389,6 +4402,10 @@ curr_insn_transform (bool check_only_p) rld = partial_subreg_p (GET_MODE (src), GET_MODE (dest)) ? src : dest; rld_mode = GET_MODE (rld); sec_mode = targetm.secondary_memory_needed_mode (rld_mode); + if (rld_mode != sec_mode + && (invalid_mode_reg_p (sec_mode, dest) + || invalid_mode_reg_p (sec_mode, src))) + sec_mode = rld_mode; new_reg = lra_create_new_reg (sec_mode, NULL_RTX, NO_REGS, NULL, "secondary"); /* If the mode is changed, it should be wider. */ diff --git a/gcc/testsuite/gcc.target/i386/pr118067-2.c b/gcc/testsuite/gcc.target/i386/pr118067-2.c new file mode 100644 index 000000000000..831871db0b43 --- /dev/null +++ b/gcc/testsuite/gcc.target/i386/pr118067-2.c @@ -0,0 +1,16 @@ +/* { dg-do compile { target { ! ia32 } } } */ +/* { dg-options "-O -fno-split-wide-types -mavx512f -mcpu=k8" } */ + +typedef unsigned short U __attribute__((__vector_size__(64))); +typedef int V __attribute__((__vector_size__(64))); +typedef __int128 W __attribute__((__vector_size__(64))); + +W +foo(U u, V v) +{ + W w; + /* __asm__ volatile ("" : "=v"(w)); prevents the -Wuninitialized warning */ + u[0] >>= 1; + v %= (V)w; + return (W)u + (W)v; +}