[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:
parent
a834414794
commit
f1dea0fed9
2 changed files with 55 additions and 0 deletions
|
@ -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"
|
||||
|
|
9
gcc/testsuite/gcc.target/m68k/pr110934.c
Normal file
9
gcc/testsuite/gcc.target/m68k/pr110934.c
Normal 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 ();
|
||||
}
|
Loading…
Add table
Reference in a new issue