Most operations get expanded to cmpxchg at i128 because it's the only primitive we have. So this is the bulk of the support needed for all i128 atomics.
There are three essentially different cases to handle:
- -O0, no LSE. The IR is expanded to ldxp/stxp and we need patterns & code to select them.
- -O1, no LSE. We get G_ATOMIC_CMPXCHG, and need to produce CMP_SWAP_N pseudos. The registers are all 64-bit so this is easy in the existing framework.
- LSE. We get G_ATOMIC_CMPXCHG and need to produce a CASP instruction with XSeqPair registers.
The last case is by far the hardest, and and adds 128-bit GPR support as a byproduct. The only way I could get it through all phases (and I tried many variants) was:
G_UNMERGE REG_SEQUENCE CAS G_EXTRACT G_MERGE
The merge/unmerge pair are needed to cancel out similar in surrounding instructions, but then the REG_SEQUENCE and G_EXTRACT are needed to put the values back into 128-bit vregs again.
Unfortunately the G_EXTRACT had to be handled with quite a nasty hack in RegisterBankInfo. Please tell me if anyone has any better ideas, but I couldn't make a RegBank stick from Legalizer to there, or think of any other way to check for an int op.