[PATCH] D67423: [RISCV] Consistently use Register arithmetic
Luís Marques via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 10 17:13:57 PDT 2019
luismarques created this revision.
luismarques added reviewers: asb, lenary.
Herald added subscribers: llvm-commits, pzheng, s.egerton, Jim, benna, psnobl, jocewei, PkmX, rkruppe, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, MaskRay, jrtc27, shiva0217, kito-cheng, niosHD, sabuasal, apazos, simoncook, johnrusso, rbar, fedor.sergeev, hiraditya, kristof.beyls, jyknight.
Herald added a project: LLVM.
`Register`s, as currently employed in LLVM, have the following properties:
- You **can't** rely on a `Register` object having a specific numerical value;
- You **can** rely on two consecutively enumerated `Register`s having consecutive numerical values (or having operator overloads that provide equivalent semantics);
- `Register` are enumerated using a well-defined algorithm that provides some guarantees about enumeration order, given some reasonable assumptions.
This last point may seem surprising but it is a de facto guarantee that many targets rely on, frequently making use of `Register` arithmetic based on that assumption. In fact, you can see that multiple targets guard against that assumption being violated:
ARMBaseRegisterInfo.cpp:203
static_assert(ARM::D31 == ARM::D16 + 15, "Register list not consecutive!");
X86FloatingPoint.cpp:130
static_assert(X86::FP6 - X86::FP0 == 6, "sequential regnums");
SparcISelLowering.cpp:189
static_assert(SP::I0 + 7 == SP::I7 && SP::O0 + 7 == SP::O7,
AArch64CollectLOH.cpp:259
static_assert(AArch64::X28 - AArch64::X0 + 3 == N_GPR_REGS, "Number of GPRs");
static_assert(AArch64::W30 - AArch64::W0 + 1 == N_GPR_REGS, "Number of GPRs");
The registers are enumerated by `RegisterInfoEmitter.cpp`, but the order is set by `CodeGenRegBank`, which sorts all of the `Register` records using a `LessRecordRegister` function object. That comparator uses the following sorting logic:
- The names are split into consecutive alphabetical and numerical parts (e.g. `Foo42Bar7 -> [Foo, 42, Bar, 7]`);
- The alphabetical parts take precedence over the numerical parts in setting the order;
- The number of parts takes precedence over the content of the parts in setting the order.
That last rule explains some less-than-intuitive orderings, such as X86's `R8B` appearing after `ZMM31`.
The RISC-V target also makes use of `Register` arithmetic when it comes to GPR registers. Unfortunately the sorting algorithm doesn't play particularly well with the names of our FPR `Register`s, resulting in a less-than-ideal ordering: `F0_32`, `F0_64`, `F1_32`, `...`, `F31_64`. Probably because of this, the RISC-V target had so far relied on explicit tables of FPR `Register`s, rather than also using arithmetic for them, which is inconsistent, verbose and slightly more costly.
There are several ways to solve this problem:
1. Tweak or customize the sorting algorithm. Adding the customizability infrastructure would probably be non-trivial, but it might be a good approach long-term, since the current approach of having a common but hard-coded algorithm is fairly limiting;
2. Use `Register` arithmetic consistently, even with the less-than-ideal ordering. The ordering is still fairly reasonable, and the sorting algorithm makes it extremely unlikely that any new registers would disrupt it;
3. Change the `Register` names. For instance, you can rename `F0_32 -> F0_F`, `F0_64 -> F0_D`, etc. This ensures that the registers within the same class are enumerated sequentially, and is consistent with the `F`/`D` distinction used in other parts of the target.
This patch implements the option #2, but could be easily changed to adopt option #3.
Code review concerns:
- It might be a good idea to have a single place (e.g. a couple of conversion functions) encapsulating the concept of the `F`/`D` registers being enumerated in an interleaved fashion. Yet, none of the existing files seem like an ideal place to put them -- `RISCVBaseInfo.h` and `RISCV.h` are okayish options but still not a great match. In any case, I would make that transition in two commits anyway, so this patch does not introduce such utility functions.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D67423
Files:
llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
llvm/lib/Target/RISCV/RISCVISelLowering.cpp
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D67423.219614.patch
Type: text/x-patch
Size: 7811 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190911/f15b328a/attachment-0001.bin>
More information about the llvm-commits
mailing list