We have two styles of HARD_REG_SET: a single integer based on HOST_WIDEST_FAST_INT (used when FIRST_PSEUDO_REGISTER is small enough) or an array of integers. One of the nice properties of this arrangement is that:
void foo (const HARD_REG_SET); is passed by value as an integer when the set is small enough and by reference otherwise. (This is in constrast to "const HARD_REG_SET &", which would always be passed by reference, and in contrast to passing a structure wrapper like "struct s { T elts[1]; }" by value, where the structure might be passed like a T or by reference, depending on the ABI.) However, one of the disadvantages of using an array is that simple assignment doesn't work. We need to use COPY_HARD_REG_SET instead. This patch uses a structure wrapper around the array, and preserves the above "nice property" using a new const_hard_reg_set typedef. The patch also removes the manual unrolling for small array sizes; I think these days we can rely on the compiler to do that for us. This meant fixing two port-specific quirks: - epiphany passed NULL as a HARD_REG_SET whose value doesn't matter. The patch passes the NO_REGS set instead. - ia64 reused TEST_HARD_REG_BIT and SET_HARD_REG_BIT for arrays that are bigger than HARD_REG_SET. The patch just open-codes them. The patch is probably being too conservative. Very few places actually take advantage of the "nice property" above, and we could have a cleaner interface if we used a structure wrapper for all cases. 2019-09-09 Richard Sandiford <richard.sandif...@arm.com> gcc/ * hard-reg-set.h (HARD_REG_SET): Define using a typedef rather than a #define. Use a structure rather than an array as the fallback definition. Remove special cases for low array sizes. (const_hard_reg_set): New typedef. (hard_reg_set_subset_p): Use it instead of "const HARD_REG_SET". (hard_reg_set_equal_p, hard_reg_set_intersect_p): Likewise. (hard_reg_set_empty_p): Likewise. (SET_HARD_REG_BIT): Use a function rather than a macro to handle the case in which HARD_REG_SET is a structure. (CLEAR_HARD_REG_BIT, TEST_HARD_REG_BIT, CLEAR_HARD_REG_SET) (SET_HARD_REG_SET, COPY_HARD_REG_SET, COMPL_HARD_REG_SET) (AND_HARD_REG_SET, AND_COMPL_HARD_REG_SET, IOR_HARD_REG_SET) (IOR_COMPL_HARD_REG_SET): Likewise. (hard_reg_set_iterator::pset): Constify the pointer target. (hard_reg_set_iter_init): Take a const_hard_reg_set instead of a "const HARD_REG_SET". Update the handling of non-integer HARD_REG_SETs. * recog.h: Test HARD_CONST instead of CLEAR_HARD_REG_SET. * reload.h: Likewise. * rtl.h (choose_hard_reg_mode): Remove unnecessary line break. * regs.h (in_hard_reg_set_p): Take a const_hard_reg_set instead of a "const HARD_REG_SET". (overlaps_hard_reg_set_p, range_overlaps_hard_reg_set_p): Likewise. (range_in_hard_reg_set_p): Likewise. * ira-costs.c (restrict_cost_classes): Likewise. * shrink-wrap.c (move_insn_for_shrink_wrap): Likewise. * config/epiphany/resolve-sw-modes.c (pass_resolve_sw_modes::execute): Pass a NO_REGS HARD_REG_SET rather than NULL to emit_set_fp_mode. * config/ia64/ia64.c (rws_insn): In the CHECKING_P version, use unsigned HOST_WIDEST_FAST_INT rather than HARD_REG_ELT_TYPE. (rws_insn_set, rws_insn_test): In the CHECKING_P version, take an unsigned int and open-code the HARD_REG_SET operations. Index: gcc/hard-reg-set.h =================================================================== *** gcc/hard-reg-set.h 2019-09-09 16:53:27.837266363 +0100 --- gcc/hard-reg-set.h 2019-09-09 16:53:27.829266420 +0100 *************** typedef unsigned HOST_WIDEST_FAST_INT HA *** 42,55 **** #if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_WIDEST_FAST_INT ! #define HARD_REG_SET HARD_REG_ELT_TYPE #else #define HARD_REG_SET_LONGS \ ((FIRST_PSEUDO_REGISTER + HOST_BITS_PER_WIDEST_FAST_INT - 1) \ / HOST_BITS_PER_WIDEST_FAST_INT) ! typedef HARD_REG_ELT_TYPE HARD_REG_SET[HARD_REG_SET_LONGS]; #endif --- 42,61 ---- #if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_WIDEST_FAST_INT ! typedef HARD_REG_ELT_TYPE HARD_REG_SET; ! typedef const HARD_REG_SET const_hard_reg_set; #else #define HARD_REG_SET_LONGS \ ((FIRST_PSEUDO_REGISTER + HOST_BITS_PER_WIDEST_FAST_INT - 1) \ / HOST_BITS_PER_WIDEST_FAST_INT) ! ! struct HARD_REG_SET ! { ! HARD_REG_ELT_TYPE elts[HARD_REG_SET_LONGS]; ! }; ! typedef const HARD_REG_SET &const_hard_reg_set; #endif *************** #define HARD_CONST(X) ((HARD_REG_ELT_TYP *** 98,104 **** #define UHOST_BITS_PER_WIDE_INT ((unsigned) HOST_BITS_PER_WIDEST_FAST_INT) ! #ifdef HARD_REG_SET #define SET_HARD_REG_BIT(SET, BIT) \ ((SET) |= HARD_CONST (1) << (BIT)) --- 104,110 ---- #define UHOST_BITS_PER_WIDE_INT ((unsigned) HOST_BITS_PER_WIDEST_FAST_INT) ! #if FIRST_PSEUDO_REGISTER <= HOST_BITS_PER_WIDEST_FAST_INT #define SET_HARD_REG_BIT(SET, BIT) \ ((SET) |= HARD_CONST (1) << (BIT)) *************** #define AND_HARD_REG_SET(TO, FROM) ((TO) *** 119,513 **** #define AND_COMPL_HARD_REG_SET(TO, FROM) ((TO) &= ~ (FROM)) static inline bool ! hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) { return (x & ~y) == HARD_CONST (0); } static inline bool ! hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) { return x == y; } static inline bool ! hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) { return (x & y) != HARD_CONST (0); } static inline bool ! hard_reg_set_empty_p (const HARD_REG_SET x) { return x == HARD_CONST (0); } #else ! #define SET_HARD_REG_BIT(SET, BIT) \ ! ((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \ ! |= HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT)) ! ! #define CLEAR_HARD_REG_BIT(SET, BIT) \ ! ((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \ ! &= ~(HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT))) ! ! #define TEST_HARD_REG_BIT(SET, BIT) \ ! (!!((SET)[(BIT) / UHOST_BITS_PER_WIDE_INT] \ ! & (HARD_CONST (1) << ((BIT) % UHOST_BITS_PER_WIDE_INT)))) ! ! #if FIRST_PSEUDO_REGISTER <= 2*HOST_BITS_PER_WIDEST_FAST_INT ! #define CLEAR_HARD_REG_SET(TO) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! scan_tp_[0] = 0; \ ! scan_tp_[1] = 0; } while (0) ! ! #define SET_HARD_REG_SET(TO) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! scan_tp_[0] = -1; \ ! scan_tp_[1] = -1; } while (0) ! ! #define COPY_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] = scan_fp_[0]; \ ! scan_tp_[1] = scan_fp_[1]; } while (0) ! ! #define COMPL_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] = ~ scan_fp_[0]; \ ! scan_tp_[1] = ~ scan_fp_[1]; } while (0) ! ! #define AND_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] &= scan_fp_[0]; \ ! scan_tp_[1] &= scan_fp_[1]; } while (0) ! ! #define AND_COMPL_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] &= ~ scan_fp_[0]; \ ! scan_tp_[1] &= ~ scan_fp_[1]; } while (0) ! ! #define IOR_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] |= scan_fp_[0]; \ ! scan_tp_[1] |= scan_fp_[1]; } while (0) ! ! #define IOR_COMPL_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] |= ~ scan_fp_[0]; \ ! scan_tp_[1] |= ~ scan_fp_[1]; } while (0) ! ! static inline bool ! hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) { ! return (x[0] & ~y[0]) == 0 && (x[1] & ~y[1]) == 0; } ! static inline bool ! hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) { ! return x[0] == y[0] && x[1] == y[1]; } ! static inline bool ! hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) { ! return (x[0] & y[0]) != 0 || (x[1] & y[1]) != 0; } ! static inline bool ! hard_reg_set_empty_p (const HARD_REG_SET x) { ! return x[0] == 0 && x[1] == 0; } ! #else ! #if FIRST_PSEUDO_REGISTER <= 3*HOST_BITS_PER_WIDEST_FAST_INT ! #define CLEAR_HARD_REG_SET(TO) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! scan_tp_[0] = 0; \ ! scan_tp_[1] = 0; \ ! scan_tp_[2] = 0; } while (0) ! ! #define SET_HARD_REG_SET(TO) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! scan_tp_[0] = -1; \ ! scan_tp_[1] = -1; \ ! scan_tp_[2] = -1; } while (0) ! ! #define COPY_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] = scan_fp_[0]; \ ! scan_tp_[1] = scan_fp_[1]; \ ! scan_tp_[2] = scan_fp_[2]; } while (0) ! ! #define COMPL_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] = ~ scan_fp_[0]; \ ! scan_tp_[1] = ~ scan_fp_[1]; \ ! scan_tp_[2] = ~ scan_fp_[2]; } while (0) ! ! #define AND_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] &= scan_fp_[0]; \ ! scan_tp_[1] &= scan_fp_[1]; \ ! scan_tp_[2] &= scan_fp_[2]; } while (0) ! ! #define AND_COMPL_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] &= ~ scan_fp_[0]; \ ! scan_tp_[1] &= ~ scan_fp_[1]; \ ! scan_tp_[2] &= ~ scan_fp_[2]; } while (0) ! ! #define IOR_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] |= scan_fp_[0]; \ ! scan_tp_[1] |= scan_fp_[1]; \ ! scan_tp_[2] |= scan_fp_[2]; } while (0) ! ! #define IOR_COMPL_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] |= ~ scan_fp_[0]; \ ! scan_tp_[1] |= ~ scan_fp_[1]; \ ! scan_tp_[2] |= ~ scan_fp_[2]; } while (0) ! ! static inline bool ! hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) ! { ! return ((x[0] & ~y[0]) == 0 ! && (x[1] & ~y[1]) == 0 ! && (x[2] & ~y[2]) == 0); ! } ! ! static inline bool ! hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) { ! return x[0] == y[0] && x[1] == y[1] && x[2] == y[2]; } ! static inline bool ! hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) { ! return ((x[0] & y[0]) != 0 ! || (x[1] & y[1]) != 0 ! || (x[2] & y[2]) != 0); } ! static inline bool ! hard_reg_set_empty_p (const HARD_REG_SET x) { ! return x[0] == 0 && x[1] == 0 && x[2] == 0; } ! #else ! #if FIRST_PSEUDO_REGISTER <= 4*HOST_BITS_PER_WIDEST_FAST_INT ! #define CLEAR_HARD_REG_SET(TO) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! scan_tp_[0] = 0; \ ! scan_tp_[1] = 0; \ ! scan_tp_[2] = 0; \ ! scan_tp_[3] = 0; } while (0) ! ! #define SET_HARD_REG_SET(TO) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! scan_tp_[0] = -1; \ ! scan_tp_[1] = -1; \ ! scan_tp_[2] = -1; \ ! scan_tp_[3] = -1; } while (0) ! ! #define COPY_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] = scan_fp_[0]; \ ! scan_tp_[1] = scan_fp_[1]; \ ! scan_tp_[2] = scan_fp_[2]; \ ! scan_tp_[3] = scan_fp_[3]; } while (0) ! ! #define COMPL_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] = ~ scan_fp_[0]; \ ! scan_tp_[1] = ~ scan_fp_[1]; \ ! scan_tp_[2] = ~ scan_fp_[2]; \ ! scan_tp_[3] = ~ scan_fp_[3]; } while (0) ! ! #define AND_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] &= scan_fp_[0]; \ ! scan_tp_[1] &= scan_fp_[1]; \ ! scan_tp_[2] &= scan_fp_[2]; \ ! scan_tp_[3] &= scan_fp_[3]; } while (0) ! ! #define AND_COMPL_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] &= ~ scan_fp_[0]; \ ! scan_tp_[1] &= ~ scan_fp_[1]; \ ! scan_tp_[2] &= ~ scan_fp_[2]; \ ! scan_tp_[3] &= ~ scan_fp_[3]; } while (0) ! ! #define IOR_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] |= scan_fp_[0]; \ ! scan_tp_[1] |= scan_fp_[1]; \ ! scan_tp_[2] |= scan_fp_[2]; \ ! scan_tp_[3] |= scan_fp_[3]; } while (0) ! ! #define IOR_COMPL_HARD_REG_SET(TO, FROM) \ ! do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ ! const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ ! scan_tp_[0] |= ~ scan_fp_[0]; \ ! scan_tp_[1] |= ~ scan_fp_[1]; \ ! scan_tp_[2] |= ~ scan_fp_[2]; \ ! scan_tp_[3] |= ~ scan_fp_[3]; } while (0) ! ! static inline bool ! hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) { ! return ((x[0] & ~y[0]) == 0 ! && (x[1] & ~y[1]) == 0 ! && (x[2] & ~y[2]) == 0 ! && (x[3] & ~y[3]) == 0); } ! static inline bool ! hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) { ! return x[0] == y[0] && x[1] == y[1] && x[2] == y[2] && x[3] == y[3]; } ! static inline bool ! hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) { ! return ((x[0] & y[0]) != 0 ! || (x[1] & y[1]) != 0 ! || (x[2] & y[2]) != 0 ! || (x[3] & y[3]) != 0); } ! static inline bool ! hard_reg_set_empty_p (const HARD_REG_SET x) { ! return x[0] == 0 && x[1] == 0 && x[2] == 0 && x[3] == 0; } - #else /* FIRST_PSEUDO_REGISTER > 4*HOST_BITS_PER_WIDEST_FAST_INT */ - - #define CLEAR_HARD_REG_SET(TO) \ - do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - int i; \ - for (i = 0; i < HARD_REG_SET_LONGS; i++) \ - *scan_tp_++ = 0; } while (0) - - #define SET_HARD_REG_SET(TO) \ - do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - int i; \ - for (i = 0; i < HARD_REG_SET_LONGS; i++) \ - *scan_tp_++ = -1; } while (0) - - #define COPY_HARD_REG_SET(TO, FROM) \ - do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ - int i; \ - for (i = 0; i < HARD_REG_SET_LONGS; i++) \ - *scan_tp_++ = *scan_fp_++; } while (0) - - #define COMPL_HARD_REG_SET(TO, FROM) \ - do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ - int i; \ - for (i = 0; i < HARD_REG_SET_LONGS; i++) \ - *scan_tp_++ = ~ *scan_fp_++; } while (0) - - #define AND_HARD_REG_SET(TO, FROM) \ - do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ - int i; \ - for (i = 0; i < HARD_REG_SET_LONGS; i++) \ - *scan_tp_++ &= *scan_fp_++; } while (0) - - #define AND_COMPL_HARD_REG_SET(TO, FROM) \ - do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ - int i; \ - for (i = 0; i < HARD_REG_SET_LONGS; i++) \ - *scan_tp_++ &= ~ *scan_fp_++; } while (0) - - #define IOR_HARD_REG_SET(TO, FROM) \ - do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ - int i; \ - for (i = 0; i < HARD_REG_SET_LONGS; i++) \ - *scan_tp_++ |= *scan_fp_++; } while (0) - - #define IOR_COMPL_HARD_REG_SET(TO, FROM) \ - do { HARD_REG_ELT_TYPE *scan_tp_ = (TO); \ - const HARD_REG_ELT_TYPE *scan_fp_ = (FROM); \ - int i; \ - for (i = 0; i < HARD_REG_SET_LONGS; i++) \ - *scan_tp_++ |= ~ *scan_fp_++; } while (0) - static inline bool ! hard_reg_set_subset_p (const HARD_REG_SET x, const HARD_REG_SET y) { ! int i; ! ! for (i = 0; i < HARD_REG_SET_LONGS; i++) ! if ((x[i] & ~y[i]) != 0) ! return false; ! return true; } static inline bool ! hard_reg_set_equal_p (const HARD_REG_SET x, const HARD_REG_SET y) { ! int i; ! ! for (i = 0; i < HARD_REG_SET_LONGS; i++) ! if (x[i] != y[i]) ! return false; ! return true; } static inline bool ! hard_reg_set_intersect_p (const HARD_REG_SET x, const HARD_REG_SET y) { ! int i; ! ! for (i = 0; i < HARD_REG_SET_LONGS; i++) ! if ((x[i] & y[i]) != 0) ! return true; ! return false; } static inline bool ! hard_reg_set_empty_p (const HARD_REG_SET x) { ! int i; ! ! for (i = 0; i < HARD_REG_SET_LONGS; i++) ! if (x[i] != 0) ! return false; ! return true; } - - #endif - #endif - #endif #endif /* Iterator for hard register sets. */ --- 125,266 ---- #define AND_COMPL_HARD_REG_SET(TO, FROM) ((TO) &= ~ (FROM)) static inline bool ! hard_reg_set_subset_p (const_hard_reg_set x, const_hard_reg_set y) { return (x & ~y) == HARD_CONST (0); } static inline bool ! hard_reg_set_equal_p (const_hard_reg_set x, const_hard_reg_set y) { return x == y; } static inline bool ! hard_reg_set_intersect_p (const_hard_reg_set x, const_hard_reg_set y) { return (x & y) != HARD_CONST (0); } static inline bool ! hard_reg_set_empty_p (const_hard_reg_set x) { return x == HARD_CONST (0); } #else ! inline void ! SET_HARD_REG_BIT (HARD_REG_SET &set, unsigned int bit) { ! set.elts[bit / UHOST_BITS_PER_WIDE_INT] ! |= HARD_CONST (1) << (bit % UHOST_BITS_PER_WIDE_INT); } ! inline void ! CLEAR_HARD_REG_BIT (HARD_REG_SET &set, unsigned int bit) { ! set.elts[bit / UHOST_BITS_PER_WIDE_INT] ! &= ~(HARD_CONST (1) << (bit % UHOST_BITS_PER_WIDE_INT)); } ! inline bool ! TEST_HARD_REG_BIT (const_hard_reg_set set, unsigned int bit) { ! return (set.elts[bit / UHOST_BITS_PER_WIDE_INT] ! & (HARD_CONST (1) << (bit % UHOST_BITS_PER_WIDE_INT))); } ! inline void ! CLEAR_HARD_REG_SET (HARD_REG_SET &set) { ! for (unsigned int i = 0; i < ARRAY_SIZE (set.elts); ++i) ! set.elts[i] = 0; } ! inline void ! SET_HARD_REG_SET (HARD_REG_SET &set) { ! for (unsigned int i = 0; i < ARRAY_SIZE (set.elts); ++i) ! set.elts[i] = -1; } ! inline void ! COPY_HARD_REG_SET (HARD_REG_SET &to, const_hard_reg_set from) { ! to = from; } ! inline void ! COMPL_HARD_REG_SET (HARD_REG_SET &to, const_hard_reg_set from) { ! for (unsigned int i = 0; i < ARRAY_SIZE (to.elts); ++i) ! to.elts[i] = ~from.elts[i]; } ! inline void ! AND_HARD_REG_SET (HARD_REG_SET &to, const_hard_reg_set from) { ! for (unsigned int i = 0; i < ARRAY_SIZE (to.elts); ++i) ! to.elts[i] &= from.elts[i]; } ! inline void ! AND_COMPL_HARD_REG_SET (HARD_REG_SET &to, const_hard_reg_set from) { ! for (unsigned int i = 0; i < ARRAY_SIZE (to.elts); ++i) ! to.elts[i] &= ~from.elts[i]; } ! inline void ! IOR_HARD_REG_SET (HARD_REG_SET &to, const_hard_reg_set from) { ! for (unsigned int i = 0; i < ARRAY_SIZE (to.elts); ++i) ! to.elts[i] |= from.elts[i]; } ! inline void ! IOR_COMPL_HARD_REG_SET (HARD_REG_SET &to, const_hard_reg_set from) { ! for (unsigned int i = 0; i < ARRAY_SIZE (to.elts); ++i) ! to.elts[i] |= ~from.elts[i]; } static inline bool ! hard_reg_set_subset_p (const_hard_reg_set x, const_hard_reg_set y) { ! HARD_REG_ELT_TYPE bad = 0; ! for (unsigned int i = 0; i < ARRAY_SIZE (x.elts); ++i) ! bad |= (x.elts[i] & ~y.elts[i]); ! return bad == 0; } static inline bool ! hard_reg_set_equal_p (const_hard_reg_set x, const_hard_reg_set y) { ! HARD_REG_ELT_TYPE bad = 0; ! for (unsigned int i = 0; i < ARRAY_SIZE (x.elts); ++i) ! bad |= (x.elts[i] ^ y.elts[i]); ! return bad == 0; } static inline bool ! hard_reg_set_intersect_p (const_hard_reg_set x, const_hard_reg_set y) { ! HARD_REG_ELT_TYPE good = 0; ! for (unsigned int i = 0; i < ARRAY_SIZE (x.elts); ++i) ! good |= (x.elts[i] & y.elts[i]); ! return good != 0; } static inline bool ! hard_reg_set_empty_p (const_hard_reg_set x) { ! HARD_REG_ELT_TYPE bad = 0; ! for (unsigned int i = 0; i < ARRAY_SIZE (x.elts); ++i) ! bad |= x.elts[i]; ! return bad == 0; } #endif /* Iterator for hard register sets. */ *************** hard_reg_set_empty_p (const HARD_REG_SET *** 515,521 **** struct hard_reg_set_iterator { /* Pointer to the current element. */ ! HARD_REG_ELT_TYPE *pelt; /* The length of the set. */ unsigned short length; --- 268,274 ---- struct hard_reg_set_iterator { /* Pointer to the current element. */ ! const HARD_REG_ELT_TYPE *pelt; /* The length of the set. */ unsigned short length; *************** #define HARD_REG_ELT_BITS UHOST_BITS_PER *** 534,544 **** /* The implementation of the iterator functions is fully analogous to the bitmap iterators. */ static inline void ! hard_reg_set_iter_init (hard_reg_set_iterator *iter, HARD_REG_SET set, unsigned min, unsigned *regno) { #ifdef HARD_REG_SET_LONGS ! iter->pelt = set; iter->length = HARD_REG_SET_LONGS; #else iter->pelt = &set; --- 287,297 ---- /* The implementation of the iterator functions is fully analogous to the bitmap iterators. */ static inline void ! hard_reg_set_iter_init (hard_reg_set_iterator *iter, const_hard_reg_set set, unsigned min, unsigned *regno) { #ifdef HARD_REG_SET_LONGS ! iter->pelt = set.elts; iter->length = HARD_REG_SET_LONGS; #else iter->pelt = &set; Index: gcc/recog.h =================================================================== *** gcc/recog.h 2019-09-09 16:53:27.837266363 +0100 --- gcc/recog.h 2019-09-09 16:53:27.829266420 +0100 *************** extern void preprocess_constraints (rtx_ *** 142,148 **** extern rtx_insn *peep2_next_insn (int); extern int peep2_regno_dead_p (int, int); extern int peep2_reg_dead_p (int, rtx); ! #ifdef CLEAR_HARD_REG_SET extern rtx peep2_find_free_register (int, int, const char *, machine_mode, HARD_REG_SET *); #endif --- 142,148 ---- extern rtx_insn *peep2_next_insn (int); extern int peep2_regno_dead_p (int, int); extern int peep2_reg_dead_p (int, rtx); ! #ifdef HARD_CONST extern rtx peep2_find_free_register (int, int, const char *, machine_mode, HARD_REG_SET *); #endif Index: gcc/reload.h =================================================================== *** gcc/reload.h 2019-09-09 16:53:27.837266363 +0100 --- gcc/reload.h 2019-09-09 16:53:27.829266420 +0100 *************** #define reg_equiv_init(ELT) \ *** 274,280 **** extern int num_not_at_initial_offset; ! #if defined SET_HARD_REG_BIT && defined CLEAR_REG_SET /* This structure describes instructions which are relevant for reload. Apart from all regular insns, this also includes CODE_LABELs, since they must be examined for register elimination. */ --- 274,280 ---- extern int num_not_at_initial_offset; ! #if defined HARD_CONST && defined CLEAR_REG_SET /* This structure describes instructions which are relevant for reload. Apart from all regular insns, this also includes CODE_LABELs, since they must be examined for register elimination. */ *************** #define reg_equiv_init(ELT) \ *** 326,332 **** extern class insn_chain *new_insn_chain (void); #endif ! #if defined SET_HARD_REG_BIT extern void compute_use_by_pseudos (HARD_REG_SET *, bitmap); #endif --- 326,332 ---- extern class insn_chain *new_insn_chain (void); #endif ! #if defined HARD_CONST extern void compute_use_by_pseudos (HARD_REG_SET *, bitmap); #endif Index: gcc/rtl.h =================================================================== *** gcc/rtl.h 2019-09-09 16:53:27.837266363 +0100 --- gcc/rtl.h 2019-09-09 16:53:27.833266392 +0100 *************** extern bool val_signbit_known_clear_p (m *** 3383,3390 **** unsigned HOST_WIDE_INT); /* In reginfo.c */ ! extern machine_mode choose_hard_reg_mode (unsigned int, unsigned int, ! bool); extern const HARD_REG_SET &simplifiable_subregs (const subreg_shape &); /* In emit-rtl.c */ --- 3383,3389 ---- unsigned HOST_WIDE_INT); /* In reginfo.c */ ! extern machine_mode choose_hard_reg_mode (unsigned int, unsigned int, bool); extern const HARD_REG_SET &simplifiable_subregs (const subreg_shape &); /* In emit-rtl.c */ Index: gcc/regs.h =================================================================== *** gcc/regs.h 2019-09-09 16:53:27.837266363 +0100 --- gcc/regs.h 2019-09-09 16:53:27.829266420 +0100 *************** remove_from_hard_reg_set (HARD_REG_SET * *** 298,304 **** /* Return true if REGS contains the whole of (reg:MODE REGNO). */ static inline bool ! in_hard_reg_set_p (const HARD_REG_SET regs, machine_mode mode, unsigned int regno) { unsigned int end_regno; --- 298,304 ---- /* Return true if REGS contains the whole of (reg:MODE REGNO). */ static inline bool ! in_hard_reg_set_p (const_hard_reg_set regs, machine_mode mode, unsigned int regno) { unsigned int end_regno; *************** in_hard_reg_set_p (const HARD_REG_SET re *** 323,329 **** /* Return true if (reg:MODE REGNO) includes an element of REGS. */ static inline bool ! overlaps_hard_reg_set_p (const HARD_REG_SET regs, machine_mode mode, unsigned int regno) { unsigned int end_regno; --- 323,329 ---- /* Return true if (reg:MODE REGNO) includes an element of REGS. */ static inline bool ! overlaps_hard_reg_set_p (const_hard_reg_set regs, machine_mode mode, unsigned int regno) { unsigned int end_regno; *************** remove_range_from_hard_reg_set (HARD_REG *** 363,369 **** /* Like overlaps_hard_reg_set_p, but use a REGNO/NREGS range instead of REGNO and MODE. */ static inline bool ! range_overlaps_hard_reg_set_p (const HARD_REG_SET set, unsigned regno, int nregs) { while (nregs-- > 0) --- 363,369 ---- /* Like overlaps_hard_reg_set_p, but use a REGNO/NREGS range instead of REGNO and MODE. */ static inline bool ! range_overlaps_hard_reg_set_p (const_hard_reg_set set, unsigned regno, int nregs) { while (nregs-- > 0) *************** range_overlaps_hard_reg_set_p (const HAR *** 375,381 **** /* Like in_hard_reg_set_p, but use a REGNO/NREGS range instead of REGNO and MODE. */ static inline bool ! range_in_hard_reg_set_p (const HARD_REG_SET set, unsigned regno, int nregs) { while (nregs-- > 0) if (!TEST_HARD_REG_BIT (set, regno + nregs)) --- 375,381 ---- /* Like in_hard_reg_set_p, but use a REGNO/NREGS range instead of REGNO and MODE. */ static inline bool ! range_in_hard_reg_set_p (const_hard_reg_set set, unsigned regno, int nregs) { while (nregs-- > 0) if (!TEST_HARD_REG_BIT (set, regno + nregs)) Index: gcc/ira-costs.c =================================================================== *** gcc/ira-costs.c 2019-09-09 16:53:27.837266363 +0100 --- gcc/ira-costs.c 2019-09-09 16:53:27.829266420 +0100 *************** setup_cost_classes (cost_classes_t from) *** 237,243 **** allocated. */ static cost_classes_t restrict_cost_classes (cost_classes_t full, machine_mode mode, ! const HARD_REG_SET ®s) { static struct cost_classes narrow; int map[N_REG_CLASSES]; --- 237,243 ---- allocated. */ static cost_classes_t restrict_cost_classes (cost_classes_t full, machine_mode mode, ! const_hard_reg_set regs) { static struct cost_classes narrow; int map[N_REG_CLASSES]; Index: gcc/shrink-wrap.c =================================================================== *** gcc/shrink-wrap.c 2019-09-09 16:53:27.837266363 +0100 --- gcc/shrink-wrap.c 2019-09-09 16:53:27.833266392 +0100 *************** live_edge_for_reg (basic_block bb, int r *** 151,158 **** static bool move_insn_for_shrink_wrap (basic_block bb, rtx_insn *insn, ! const HARD_REG_SET uses, ! const HARD_REG_SET defs, bool *split_p, struct dead_debug_local *debug) { --- 151,158 ---- static bool move_insn_for_shrink_wrap (basic_block bb, rtx_insn *insn, ! const_hard_reg_set uses, ! const_hard_reg_set defs, bool *split_p, struct dead_debug_local *debug) { Index: gcc/config/epiphany/resolve-sw-modes.c =================================================================== *** gcc/config/epiphany/resolve-sw-modes.c 2019-09-09 16:53:27.837266363 +0100 --- gcc/config/epiphany/resolve-sw-modes.c 2019-09-09 16:53:27.825266448 +0100 *************** pass_resolve_sw_modes::execute (function *** 167,173 **** } start_sequence (); emit_set_fp_mode (EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN, ! jilted_mode, FP_MODE_NONE, NULL); seq = get_insns (); end_sequence (); need_commit = true; --- 167,174 ---- } start_sequence (); emit_set_fp_mode (EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN, ! jilted_mode, FP_MODE_NONE, ! reg_class_contents[NO_REGS]); seq = get_insns (); end_sequence (); need_commit = true; Index: gcc/config/ia64/ia64.c =================================================================== *** gcc/config/ia64/ia64.c 2019-09-09 16:53:27.837266363 +0100 --- gcc/config/ia64/ia64.c 2019-09-09 16:53:27.829266420 +0100 *************** struct reg_write_state *** 6230,6249 **** struct reg_write_state rws_sum[NUM_REGS]; #if CHECKING_P /* Bitmap whether a register has been written in the current insn. */ ! HARD_REG_ELT_TYPE rws_insn[(NUM_REGS + HOST_BITS_PER_WIDEST_FAST_INT - 1) ! / HOST_BITS_PER_WIDEST_FAST_INT]; static inline void ! rws_insn_set (int regno) { ! gcc_assert (!TEST_HARD_REG_BIT (rws_insn, regno)); ! SET_HARD_REG_BIT (rws_insn, regno); } static inline int ! rws_insn_test (int regno) { ! return TEST_HARD_REG_BIT (rws_insn, regno); } #else /* When not checking, track just REG_AR_CFM and REG_VOLATILE. */ --- 6230,6254 ---- struct reg_write_state rws_sum[NUM_REGS]; #if CHECKING_P /* Bitmap whether a register has been written in the current insn. */ ! unsigned HOST_WIDEST_FAST_INT rws_insn ! [(NUM_REGS + HOST_BITS_PER_WIDEST_FAST_INT - 1) ! / HOST_BITS_PER_WIDEST_FAST_INT]; static inline void ! rws_insn_set (unsigned int regno) { ! unsigned int elt = regno / HOST_BITS_PER_WIDEST_FAST_INT; ! unsigned int bit = regno % HOST_BITS_PER_WIDEST_FAST_INT; ! gcc_assert (!((rws_insn[elt] >> bit) & 1)); ! rws_insn[elt] |= (unsigned HOST_WIDEST_FAST_INT) 1 << bit; } static inline int ! rws_insn_test (unsigned int regno) { ! unsigned int elt = regno / HOST_BITS_PER_WIDEST_FAST_INT; ! unsigned int bit = regno % HOST_BITS_PER_WIDEST_FAST_INT; ! return (rws_insn[elt] >> bit) & 1; } #else /* When not checking, track just REG_AR_CFM and REG_VOLATILE. */