aboutsummaryrefslogtreecommitdiff
path: root/gcc/function.cc
diff options
context:
space:
mode:
authorQing Zhao <qing.zhao@oracle.com>2022-04-01 16:09:43 +0000
committerQing Zhao <qing.zhao@oracle.com>2022-04-01 16:09:43 +0000
commit31933f4f788b6cd64cbb7ee42076997f6d0fe212 (patch)
tree5daa89e8f0c580f945687dc4a47f4eb9d1e7032e /gcc/function.cc
parent413187b0b3c873333253838e4afbf8463b288b59 (diff)
downloadgcc-31933f4f788b6cd64cbb7ee42076997f6d0fe212.zip
gcc-31933f4f788b6cd64cbb7ee42076997f6d0fe212.tar.gz
gcc-31933f4f788b6cd64cbb7ee42076997f6d0fe212.tar.bz2
Add an assertion: the zeroed_hardregs set is a subset of all call used regs.
We should make sure that the hard register set that is actually cleared by the target hook zero_call_used_regs should be a subset of all call used registers. At the same time, update documentation for the target hook TARGET_ZERO_CALL_USED_REGS. This new assertion identified a bug in the i386 implemenation, which incorrectly set the zeroed_hardregs for stack registers. Fixed this bug in i386 implementation. gcc/ChangeLog: 2022-04-01 Qing Zhao <qing.zhao@oracle.com> * config/i386/i386.cc (zero_all_st_registers): Return the value of num_of_st. (ix86_zero_call_used_regs): Update zeroed_hardregs set according to the return value of zero_all_st_registers. * doc/tm.texi: Update the documentation of TARGET_ZERO_CALL_USED_REGS. * function.cc (gen_call_used_regs_seq): Add an assertion. * target.def: Update the documentation of TARGET_ZERO_CALL_USED_REGS.
Diffstat (limited to 'gcc/function.cc')
-rw-r--r--gcc/function.cc22
1 files changed, 18 insertions, 4 deletions
diff --git a/gcc/function.cc b/gcc/function.cc
index d5ed51a..ad0096a 100644
--- a/gcc/function.cc
+++ b/gcc/function.cc
@@ -5892,7 +5892,9 @@ gen_call_used_regs_seq (rtx_insn *ret, unsigned int zero_regs_type)
df_simulate_one_insn_backwards (bb, ret, live_out);
HARD_REG_SET selected_hardregs;
+ HARD_REG_SET all_call_used_regs;
CLEAR_HARD_REG_SET (selected_hardregs);
+ CLEAR_HARD_REG_SET (all_call_used_regs);
for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
{
if (!crtl->abi->clobbers_full_reg_p (regno))
@@ -5901,6 +5903,13 @@ gen_call_used_regs_seq (rtx_insn *ret, unsigned int zero_regs_type)
continue;
if (REGNO_REG_SET_P (live_out, regno))
continue;
+#ifdef LEAF_REG_REMAP
+ if (crtl->uses_only_leaf_regs && LEAF_REG_REMAP (regno) < 0)
+ continue;
+#endif
+ /* This is a call used register that is dead at return. */
+ SET_HARD_REG_BIT (all_call_used_regs, regno);
+
if (only_gpr
&& !TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], regno))
continue;
@@ -5908,10 +5917,6 @@ gen_call_used_regs_seq (rtx_insn *ret, unsigned int zero_regs_type)
continue;
if (only_arg && !FUNCTION_ARG_REGNO_P (regno))
continue;
-#ifdef LEAF_REG_REMAP
- if (crtl->uses_only_leaf_regs && LEAF_REG_REMAP (regno) < 0)
- continue;
-#endif
/* Now this is a register that we might want to zero. */
SET_HARD_REG_BIT (selected_hardregs, regno);
@@ -5925,6 +5930,15 @@ gen_call_used_regs_seq (rtx_insn *ret, unsigned int zero_regs_type)
HARD_REG_SET zeroed_hardregs;
start_sequence ();
zeroed_hardregs = targetm.calls.zero_call_used_regs (selected_hardregs);
+
+ /* For most targets, the returned set of registers is a subset of
+ selected_hardregs, however, for some of the targets (for example MIPS),
+ clearing some registers that are in selected_hardregs requires clearing
+ other call used registers that are not in the selected_hardregs, under
+ such situation, the returned set of registers must be a subset of
+ all call used registers. */
+ gcc_assert (hard_reg_set_subset_p (zeroed_hardregs, all_call_used_regs));
+
rtx_insn *seq = get_insns ();
end_sequence ();
if (seq)