On 9/9/19 9:53 AM, Richard Sandiford wrote: > 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. True, but I suspect that few, if any, important targets are able to use the simple integer version.
> > 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. RIght. Clear historical wart. > > 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. Certainly makes sense to me. Most of this was designed in the "early days" when most targets had small register files. > > 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. I wouldn't object to dropping the "nice property". I doubt it matters anymore and if the result is cleaner and easier to work with, then it's a net win. > > > 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. OK jeff