I have a series of patches that allows several ABIs to be used interoperably within the same translation unit. Part of that involves removing our reliance on global register sets that describe "the ABI".
One of the difficulties is that we have several global sets that contain related information. E.g.: call_used_reg_set == regs_invalidated_by_call | fixed_reg_set call_fixed_reg_set is derived from call_used_reg_set. no_caller_save_reg_set is in turn derived from call_fixed_reg_set. I don't think there's a strong efficiency reason for having a global cache of things like call_used_reg_set above. On most targets the "|" operation is two (parallel) 64-bit logical ORs of nearby data and so should be very cheap to compute. I think the sets are more there for convenience. And I think the main reason they're convenient is that HARD_REG_SET is so unwieldly to use. E.g. if you want to do: a &= b | c; you have to write: HARD_REG_SET tmp; COPY_HARD_REG_SET (tmp, b); IOR_HARD_REG_SET (tmp, c); AND_HARD_REG_SET (a, tmp); Again, each of these operations is individually very cheap on most targets (a couple of moves or logic ops each). But because it takes so much code to write, there's a strong temptation to cache "b | c" if it's used often. This series therefore provides the following operators for HARD_REG_SET and converts existing code to use them: = ~ & &= | |= == != The reason for picking (only) these is that they work on plain integer bitmasks too, and so we can continue to treat HARD_REG_SET as a plain integer when FIRST_PSEUDO_REGISTER is small enough. As noted at the end of the covering note for the first patch, that might be overly conservative, since the sets aren't passed by value all that often and so the performance gain is probably very slight in practice. I nevertheless stopped here because the series seems like a strict improvement compared to the status quo and is all that I need for the motivating follow-on series. Tested on aarch64-linux-gnu and x86_64-linux-gnu. Also tested by compiling one target for each CPU directory and making sure that there were no changes in assembly code for gcc.c-torture, gcc.dg and g++.dg. (This was before the eBPF port went in, but that's conveniently free of HARD_REG_SETs.) Richard