This patch adds the function reg_is_clobbered_by_clobber_high. Given a CLOBBER_HIGH expression and a register, it checks if the register will be clobbered.
A second version exists for the cases where the expressions are not available. The function will be used throughout the following patches. Alan. 2017-11-16 Alan Hayward <alan.hayw...@arm.com> * rtl.h (reg_is_clobbered_by_clobber_high): Add declarations. * rtlanal.c (reg_is_clobbered_by_clobber_high): Add function. diff --git a/gcc/rtl.h b/gcc/rtl.h index bdb05d00120e7fadeb7f2d29bd67afc7a77262c1..5a85eb42ea4455cf3a975b3adbdb9d0415441d3b 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -3417,6 +3417,16 @@ extern bool tablejump_p (const rtx_insn *, rtx_insn **, rtx_jump_table_data **); extern int computed_jump_p (const rtx_insn *); extern bool tls_referenced_p (const_rtx); extern bool contains_mem_rtx_p (rtx x); +extern bool reg_is_clobbered_by_clobber_high (unsigned int, machine_mode, + const_rtx); + +/* Convenient wrapper for reg_is_clobbered_by_clobber_high. */ +inline bool +reg_is_clobbered_by_clobber_high (const_rtx x, const_rtx clobber_high_op) +{ + return reg_is_clobbered_by_clobber_high (REGNO (x), GET_MODE (x), + clobber_high_op); +} /* Overload for refers_to_regno_p for checking a single register. */ inline bool diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c index 79a5ae197c14ba338240123f2fc912f2ea60e178..923e3314d25c05f9055907c61b4a24186701cc23 100644 --- a/gcc/rtlanal.c +++ b/gcc/rtlanal.c @@ -6519,3 +6519,32 @@ tls_referenced_p (const_rtx x) return true; return false; } + +/* Return true if reg REGNO with mode REG_MODE would be clobbered by the + clobber_high operand in CLOBBER_HIGH_OP. */ + +bool +reg_is_clobbered_by_clobber_high (unsigned int regno, machine_mode reg_mode, + const_rtx clobber_high_op) +{ + unsigned int clobber_regno = REGNO (clobber_high_op); + machine_mode clobber_mode = GET_MODE (clobber_high_op); + unsigned char regno_nregs = hard_regno_nregs (regno, reg_mode); + + /* Clobber high should always span exactly one register. */ + gcc_assert (REG_NREGS (clobber_high_op) == 1); + + /* Clobber high needs to match with one of the registers in X. */ + if (clobber_regno < regno || clobber_regno >= regno + regno_nregs) + return false; + + gcc_assert (reg_mode != BLKmode && clobber_mode != BLKmode); + + if (reg_mode == VOIDmode) + return clobber_mode != VOIDmode; + + /* Clobber high will clobber if its size might be greater than the size of + register regno. */ + return may_gt (exact_div (GET_MODE_SIZE (reg_mode), regno_nregs), + GET_MODE_SIZE (clobber_mode)); +}