TableGen and register banks

I'm beginning to investigate register banks and how a TableGen backend might generate more of the data structures describing them. This is a bit tricky since I am not yet familiar enough with the code generator to understand all the ramifications.

I'm hoping someone can suggest where to start. That is, which data structures would be the simplest to generate. In particular, is there sufficient information in the register info, instruction info, and instruction selection TableGen files to gather the information needed, or is additional information required in xxxRegisterBanks.td file?

Three targets have xxxGenRegisterBankInfo.def files, which contain data structures tagged for generation by TableGen. Three other targets have similar data structures in C++ files. But looking at the AArch64 and AMDGPU files, for example, I see quite a variation in the organization of those data structures.

I think perhaps a need a mentor for this little project.

Hi Paul,

it's great to see you tackle all of these things. Although I cannot tell you where to start, I might be able to give at least some info on your other questions. I think Gabriel already explained the idea behind register banks in a previous email. The pass where these register banks are assigned is the RegisterBankSelect pass. It calls into the target specific RegisterBankInfos to assign register banks to generic instructions. This is also where those .def files are being used.

As far as I understand, the actual data structures are just used as a complex lookup table so you don't have to compute the mapping by hand for each and every instruction. I also noticed that AArch64 and AMDGPU have quite differing implementations there and from previous GISel round tables during the dev conference, I remember that AMDGPU seems to do even more work than simply assigning mappings. You should probably get in touch with Matt or someone else from the AMD backend to get some details there. But all in all, I don't see why those lookup tables could not be tablegen'd.

The register classes and register banks are already available in TableGen. So the only missing piece should be which operands of a generic instruction should be put on which bank. You could try to infer that information from ISel patterns as there you have a mapping from the generic instructions to target specific instructions including register classes (from which you can get the register banks). Although this could get quite complex once you start hitting some of the more complicated patterns I guess. Also this would miss instructions that are not selected with TableGen patterns, but only with C++. Also this would not capture any associated costs, unless the cost for the mapping would also be inferred by TableGen by how complex the pattern was the mapping was derived from.

I don't think it's impossible or even unfeasible to try to derive as much as possible from already existing ISel patterns. But what I could also envision is to have some description in TableGen that defines the operand mappings for generic instructions and some associated cost. It should support declaring multiple mappings for the same instruction, since you might be able to implement the instruction on multiple register banks. Our downstream target has a lot of those cases already and at the moment we have to manually add all of those mappings in C++. It would be nice if we could simply include some .inc file for this instead.

I haven't thought about how this could look like in TableGen before I started typing this email, so I don't have any concrete suggestions at this point.

I hope I was able to shed a little bit of light on these things. Like I said, I'm just a mere user of GlobalISel myself, so these are just my own experiences I gathered up to this point. I'm sure one of the actual GISel developers could give you much more info on this should you need it.

Cheers,

Dominik