/* Save and restore call-clobbered registers which are live across a call.
- Copyright (C) 1989-2019 Free Software Foundation, Inc.
+ Copyright (C) 1989-2020 Free Software Foundation, Inc.
This file is part of GCC.
#include "dumpfile.h"
#include "rtl-iter.h"
#include "target.h"
+#include "function-abi.h"
#define MOVE_MAX_WORDS (MOVE_MAX / UNITS_PER_WORD)
caller_save_initialized_p = true;
- CLEAR_HARD_REG_SET (no_caller_save_reg_set);
/* First find all the registers that we need to deal with and all
the modes that they can have. If we can't find a mode to use,
we can't have the register live over calls. */
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- {
- if (call_used_regs[i]
- && !TEST_HARD_REG_BIT (call_fixed_reg_set, i))
- {
- for (j = 1; j <= MOVE_MAX_WORDS; j++)
- {
- regno_save_mode[i][j] = HARD_REGNO_CALLER_SAVE_MODE (i, j,
- VOIDmode);
- if (regno_save_mode[i][j] == VOIDmode && j == 1)
- {
- SET_HARD_REG_BIT (call_fixed_reg_set, i);
- }
- }
- }
- else
- regno_save_mode[i][1] = VOIDmode;
- }
+ for (j = 1; j <= MOVE_MAX_WORDS; j++)
+ {
+ regno_save_mode[i][j] = HARD_REGNO_CALLER_SAVE_MODE (i, j, VOIDmode);
+ if (regno_save_mode[i][j] == VOIDmode && j == 1)
+ CLEAR_HARD_REG_BIT (savable_regs, i);
+ }
/* The following code tries to approximate the conditions under which
we can easily save and restore a register without scratch registers or
{
regno_save_mode[i][j] = VOIDmode;
if (j == 1)
- {
- SET_HARD_REG_BIT (call_fixed_reg_set, i);
- if (call_used_regs[i])
- SET_HARD_REG_BIT (no_caller_save_reg_set, i);
- }
+ CLEAR_HARD_REG_BIT (savable_regs, i);
}
}
freq = REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn));
REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
&chain->live_throughout);
- get_call_reg_set_usage (insn, &used_regs, call_used_reg_set);
+ used_regs = insn_callee_abi (insn).full_reg_clobbers ();
/* Record all registers set in this call insn. These don't
need to be saved. N.B. the call insn might set a subreg
if (SIBLING_CALL_P (insn) && crtl->return_rtx)
mark_set_regs (crtl->return_rtx, NULL_RTX, &this_insn_sets);
- AND_COMPL_HARD_REG_SET (used_regs, call_fixed_reg_set);
- AND_COMPL_HARD_REG_SET (used_regs, this_insn_sets);
- hard_regs_to_save &= used_regs;
+ used_regs &= ~(fixed_reg_set | this_insn_sets);
+ hard_regs_to_save &= used_regs & savable_regs;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
{
REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
&chain->live_throughout);
- get_call_reg_set_usage (insn, &used_regs, call_used_reg_set);
+ used_regs = insn_callee_abi (insn).full_reg_clobbers ();
/* Record all registers set in this call insn. These don't
need to be saved. N.B. the call insn might set a subreg
if (SIBLING_CALL_P (insn) && crtl->return_rtx)
mark_set_regs (crtl->return_rtx, NULL_RTX, &this_insn_sets);
- AND_COMPL_HARD_REG_SET (used_regs, call_fixed_reg_set);
- AND_COMPL_HARD_REG_SET (used_regs, this_insn_sets);
- hard_regs_to_save &= used_regs;
+ used_regs &= ~(fixed_reg_set | this_insn_sets);
+ hard_regs_to_save &= used_regs & savable_regs;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
{
afterwards. */
CLEAR_HARD_REG_SET (this_insn_sets);
note_stores (insn, mark_set_regs, &this_insn_sets);
- AND_COMPL_HARD_REG_SET (hard_regs_saved, this_insn_sets);
+ hard_regs_saved &= ~this_insn_sets;
}
if (code == CALL_INSN
{
unsigned regno;
HARD_REG_SET hard_regs_to_save;
- HARD_REG_SET call_def_reg_set;
reg_set_iterator rsi;
rtx cheap;
note_stores (insn, mark_set_regs, &this_insn_sets);
/* Compute which hard regs must be saved before this call. */
- AND_COMPL_HARD_REG_SET (hard_regs_to_save, call_fixed_reg_set);
- AND_COMPL_HARD_REG_SET (hard_regs_to_save, this_insn_sets);
- AND_COMPL_HARD_REG_SET (hard_regs_to_save, hard_regs_saved);
- get_call_reg_set_usage (insn, &call_def_reg_set,
- call_used_reg_set);
- hard_regs_to_save &= call_def_reg_set;
+ function_abi callee_abi = insn_callee_abi (insn);
+ hard_regs_to_save &= ~(fixed_reg_set
+ | this_insn_sets
+ | hard_regs_saved);
+ hard_regs_to_save &= savable_regs;
+ hard_regs_to_save &= callee_abi.full_reg_clobbers ();
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
if (cheap
&& HARD_REGISTER_P (cheap)
- && TEST_HARD_REG_BIT (call_used_reg_set, REGNO (cheap)))
+ && callee_abi.clobbers_reg_p (GET_MODE (cheap),
+ REGNO (cheap)))
{
rtx dest, newpat;
rtx pat = PATTERN (insn);