[PATCH] Avoid ICE on m68k -fzero-call-used-regs -fpic [PR110934]

PR110934 is a problem on m68k where -fzero-call-used-regs -fpic ICEs
when clearing an FP register.

The generic code generates an XFmode move of zero to that register,
which becomes an XFmode load from initialized data, which due to -fpic
uses a non-constant address, which the backend rejects.  The
zero-call-used-regs pass runs very late, after register allocation and
frame layout, and at that point we can't allow new uses of the PIC
register or new pseudos.

To clear an FP register on m68k it's enough to do the move in SFmode,
but the generic code can't be told to do that, so this patch updates
m68k to use its own TARGET_ZERO_CALL_USED_REGS.

Bootstrapped and regression tested on m68k-linux-gnu.

Ok for master? (I don't have commit rights.)

gcc/

	PR target/110934
	* config/m68k/m68k.cc (m68k_zero_call_used_regs): New function.
	(TARGET_ZERO_CALL_USED_REGS): Define.

gcc/testsuite/

	PR target/110934
	* gcc.target/m68k/pr110934.c: New test.
This commit is contained in:
Mikael Pettersson 2024-01-19 16:23:34 -07:00 committed by Jeff Law
parent a834414794
commit f1dea0fed9
2 changed files with 55 additions and 0 deletions

View file

@ -197,6 +197,7 @@ static bool m68k_modes_tieable_p (machine_mode, machine_mode);
static machine_mode m68k_promote_function_mode (const_tree, machine_mode,
int *, const_tree, int);
static void m68k_asm_final_postscan_insn (FILE *, rtx_insn *insn, rtx [], int);
static HARD_REG_SET m68k_zero_call_used_regs (HARD_REG_SET);
/* Initialize the GCC target structure. */
@ -361,6 +362,9 @@ static void m68k_asm_final_postscan_insn (FILE *, rtx_insn *insn, rtx [], int);
#undef TARGET_ASM_FINAL_POSTSCAN_INSN
#define TARGET_ASM_FINAL_POSTSCAN_INSN m68k_asm_final_postscan_insn
#undef TARGET_ZERO_CALL_USED_REGS
#define TARGET_ZERO_CALL_USED_REGS m68k_zero_call_used_regs
TARGET_GNU_ATTRIBUTES (m68k_attribute_table,
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req,
@ -7166,4 +7170,46 @@ m68k_promote_function_mode (const_tree type, machine_mode mode,
return mode;
}
/* Implement TARGET_ZERO_CALL_USED_REGS. */
static HARD_REG_SET
m68k_zero_call_used_regs (HARD_REG_SET need_zeroed_hardregs)
{
rtx zero_fpreg = NULL_RTX;
for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (need_zeroed_hardregs, regno))
{
rtx reg, zero;
if (INT_REGNO_P (regno))
{
reg = regno_reg_rtx[regno];
zero = CONST0_RTX (SImode);
}
else if (FP_REGNO_P (regno))
{
reg = gen_raw_REG (SFmode, regno);
if (zero_fpreg == NULL_RTX)
{
/* On the 040/060 clearing an FP reg loads a large
immediate. To reduce code size use the first
cleared FP reg to clear remaining ones. Don't do
this on cores which use fmovecr. */
zero = CONST0_RTX (SFmode);
if (TUNE_68040_60)
zero_fpreg = reg;
}
else
zero = zero_fpreg;
}
else
gcc_unreachable ();
emit_move_insn (reg, zero);
}
return need_zeroed_hardregs;
}
#include "gt-m68k.h"

View file

@ -0,0 +1,9 @@
/* { dg-do compile } */
/* { do-options "-fzero-call-used-regs=used -fpic -O2" } */
extern double clobber_fp0 (void);
void foo (void)
{
clobber_fp0 ();
}