Quoting Jakub Jelinek <ja...@redhat.com>:
The middle-end uses HARD_REG_SET in lots of places, so supposedly
when you want to support more than one target, you need to ensure
that hard-reg-set.h header won't use FIRST_PSEUDO_REGISTER of one randomly
selected target you want to support, but instead somehow computed
MAX_FIRST_PSEUDO_REGISTER which is a maximum of FIRST_PSEUDO_REGISTER
values for all targets you want to support.
This can also be handled by compiling all the affected compilation units
once for each target, using target-specifically mangled function names.
C++ namespaces can be used to make this a fairly mechanical process,
as I have shown earlier.
But where HARD_REG_SETS make no material difference in speed, and the
compilation unit has no other tight coupling with tm.h, it would really
be cleaner to move from HARD_REG_SETS to a target-independent type,
like sbitmap or bitmap. Maybe we want something more lightweight than
an sbitmap, like passing in a HARD_REG_ELT_TYPE *base, int n_elements
pair to describe the data - n_elements would be set to HARD_REG_SET_LONGS.
When you are doing anything time-critical with hard register sets,
there is little point having the same size stored in multiple places,
you might as well keep it in a register and pass it around.
Basic operations could presumably be inlined, so the main overhead would
be loop overhead. With the right loop unrolling applied, these loops
should be well predictable.
In fact perhaps all uses of FIRST_PSEUDO_REGISTER in the middle-end
should be that value.
That can be wasteful when you have disparate regset sizes.
I'd rather have a first_pseudo_register data member of the target vector.
This might even make some use cases faster, like when you have a processor
architecture family with lots of vector registers, and you compile for
a variant without vector support (or code that's should not touch them),
you might have a much smaller range of registers to loop through if
you are using a specific target vector with a smaller
first_pseudo_register.