/* Perform simple optimizations to clean up the result of reload.
- Copyright (C) 1987-2019 Free Software Foundation, Inc.
+ Copyright (C) 1987-2020 Free Software Foundation, Inc.
This file is part of GCC.
#include "cselib.h"
#include "tree-pass.h"
#include "dbgcnt.h"
+#include "function-abi.h"
+#include "rtl-iter.h"
static int reload_cse_noop_set_p (rtx);
static bool reload_cse_simplify (rtx_insn *, rtx);
if (NO_FUNCTION_CSE && CALL_P (insn))
return false;
+ /* Remember if this insn has been sp += const_int. */
+ rtx sp_set = set_for_reg_notes (insn);
+ rtx sp_addend = NULL_RTX;
+ if (sp_set
+ && SET_DEST (sp_set) == stack_pointer_rtx
+ && GET_CODE (SET_SRC (sp_set)) == PLUS
+ && XEXP (SET_SRC (sp_set), 0) == stack_pointer_rtx
+ && CONST_INT_P (XEXP (SET_SRC (sp_set), 1)))
+ sp_addend = XEXP (SET_SRC (sp_set), 1);
+
if (GET_CODE (body) == SET)
{
int count = 0;
for (i = XVECLEN (body, 0) - 1; i >= 0; --i)
{
rtx part = XVECEXP (body, 0, i);
- /* asms can only have full clobbers, not clobber_highs. */
- gcc_assert (GET_CODE (part) != CLOBBER_HIGH);
if (GET_CODE (part) == CLOBBER && REG_P (XEXP (part, 0)))
cselib_invalidate_rtx (XEXP (part, 0));
}
value = SET_DEST (part);
}
}
- else if (GET_CODE (part) != CLOBBER
- && GET_CODE (part) != CLOBBER_HIGH
- && GET_CODE (part) != USE)
+ else if (GET_CODE (part) != CLOBBER && GET_CODE (part) != USE)
break;
}
reload_cse_simplify_operands (insn, testreg);
}
+ /* If sp += const_int insn is changed into sp = reg;, add REG_EQUAL
+ note so that the stack_adjustments pass can undo it if beneficial. */
+ if (sp_addend
+ && SET_DEST (sp_set) == stack_pointer_rtx
+ && REG_P (SET_SRC (sp_set)))
+ set_dst_reg_note (insn, REG_EQUAL,
+ gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ sp_addend), stack_pointer_rtx);
+
done:
return (EDGE_COUNT (insn_bb->succs) != insn_bb_succs);
}
struct reg_use *use = reg_state[regno].reg_use + i;
if (GET_MODE (*use->usep) != mode)
return false;
+ /* Don't try to adjust (use (REGX)). */
+ if (GET_CODE (PATTERN (use->insn)) == USE
+ && &XEXP (PATTERN (use->insn), 0) == use->usep)
+ return false;
}
/* Look for (set (REGX) (CONST_INT))
if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], i)
&& reg_state[i].use_index == RELOAD_COMBINE_MAX_USES
&& reg_state[i].store_ruid <= reg_state[regno].use_ruid
- && (call_used_or_fixed_reg_p (i) || df_regs_ever_live_p (i))
+ && (crtl->abi->clobbers_full_reg_p (i)
+ || df_regs_ever_live_p (i))
&& (!frame_pointer_needed || i != HARD_FRAME_POINTER_REGNUM)
&& !fixed_regs[i] && !global_regs[i]
&& hard_regno_nregs (i, GET_MODE (reg)) == 1
/* Delete the reg-reg addition. */
delete_insn (insn);
- if (reg_state[regno].offset != const0_rtx
- /* Previous REG_EQUIV / REG_EQUAL notes for PREV
- are now invalid. */
- && remove_reg_equal_equiv_notes (prev))
- df_notes_rescan (prev);
+ if (reg_state[regno].offset != const0_rtx)
+ /* Previous REG_EQUIV / REG_EQUAL notes for PREV
+ are now invalid. */
+ remove_reg_equal_equiv_notes (prev);
reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES;
return true;
if (CALL_P (insn))
{
rtx link;
- HARD_REG_SET used_regs;
-
- get_call_reg_set_usage (insn, &used_regs, call_used_or_fixed_regs);
+ HARD_REG_SET used_regs = insn_callee_abi (insn).full_reg_clobbers ();
for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
if (TEST_HARD_REG_BIT (used_regs, r))
}
break;
- case CLOBBER_HIGH:
- gcc_assert (REG_P (SET_DEST (x)));
- return;
-
case PLUS:
/* We are interested in (plus (reg) (const_int)) . */
if (!REG_P (XEXP (x, 0))
}
}
}
+
+ /* There are no REG_INC notes for SP autoinc. */
+ subrtx_var_iterator::array_type array;
+ FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (insn), NONCONST)
+ {
+ rtx mem = *iter;
+ if (mem
+ && MEM_P (mem)
+ && GET_RTX_CLASS (GET_CODE (XEXP (mem, 0))) == RTX_AUTOINC)
+ {
+ if (XEXP (XEXP (mem, 0), 0) == stack_pointer_rtx)
+ reg_mode[STACK_POINTER_REGNUM] = VOIDmode;
+ }
+ }
+
note_stores (insn, move2add_note_store, insn);
/* If INSN is a conditional branch, we try to extract an
unknown values. */
if (CALL_P (insn))
{
+ function_abi callee_abi = insn_callee_abi (insn);
for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
- {
- if (call_used_or_fixed_reg_p (i))
- /* Reset the information about this register. */
- reg_mode[i] = VOIDmode;
- }
+ if (reg_mode[i] != VOIDmode
+ && reg_mode[i] != BLKmode
+ && callee_abi.clobbers_reg_p (reg_mode[i], i))
+ /* Reset the information about this register. */
+ reg_mode[i] = VOIDmode;
}
}
return changed;
unsigned int regno = 0;
scalar_int_mode mode;
- /* Some targets do argument pushes without adding REG_INC notes. */
-
- if (MEM_P (dst))
- {
- dst = XEXP (dst, 0);
- if (GET_CODE (dst) == PRE_INC || GET_CODE (dst) == POST_INC
- || GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC)
- reg_mode[REGNO (XEXP (dst, 0))] = VOIDmode;
- return;
- }
-
if (GET_CODE (dst) == SUBREG)
regno = subreg_regno (dst);
else if (REG_P (dst))
move2add_record_mode (dst);
}
- else if (GET_CODE (set) == CLOBBER_HIGH)
- {
- /* Only invalidate if actually clobbered. */
- if (reg_mode[regno] == BLKmode
- || reg_is_clobbered_by_clobber_high (regno, reg_mode[regno], dst))
- goto invalidate;
- }
else
{
invalidate: