Page MenuHomePhabricator

[Tablegen/RFC] Introduce Mask to limit generation of inferred register classes
Needs ReviewPublic

Authored by kariddi on Sep 24 2018, 6:19 PM.

Details

Summary

Hello,

this patch adds a mechanism to control the inferring of new register classes.

The main issue this is trying to solve is that when we have overlapping register classes and register tuples like in this example:

def SRegs : MyClass<16, [i16], (sequence "S%u", 0, 15)>;
def SRegslow : MyClass<16, [i16], (trunc SRegs, 5)>;
def SRegshigh : MyClass<16, [i16], (shl SRegs, 5)>;
def Stup3 : RegisterTuples<[ssub0, ssub1, ssub3], [

 (shl SRegs, 0),
 (shl SRegs, 1),
 (shl SRegs, 2)
]>;

def SRegs3 : MyClass<32, [untyped], (add Stup3)>;

Then tablegen tries to generate all the possible register classes definitions to answer to getMatchingSuperRegClass().
This includes classes like:
SRegs3_with_ssub1_in_SRegslow_and_SRegs3_with_ssub2_in_SRegshigh
or
SRegs3_with_ssub0_in_SRegslow_and_SRegs3_with_ssub2_in_SRegshigh

The more tuples you have and the more overlapping constraints you have the worse this can become.

This approach tries to give knob to use to stop tablegen to infer classes for certain register classes.
This knob consist in a mask (tentatively called a ClassMask) that partitions the register file in sections. If the masks of two register classes are disjoint we do not generate inferred classes out of them.

If we rewrote the above definitions for SReglow and SReghigh like this

def SRegslow : MyClass<16, [i16], (trunc SRegs, 5)>
{

let ClassMask = 1;

}
def SRegshigh : MyClass<16, [i16], (shl SRegs, 5)>
{

let ClassMask = 2;

}

Then the two masks for the two classes would be disjoint (0x1 and 0x2) and tablegen wouldn't generate inferred classes for the combinations of those two classes.

I have to admit that I'm not an expert in the generation of the register representations, so I'm not 100% sure this is the best approach, but this is a step in the direction of limiting the generation of inferred classes for this case.

This patch is also a kind of RFC in figuring out if there is a better solution for this issue when you have register tuples and you try to add constrained register classes.
I wonder if anybody else encountered a similar problem with their targets

Diff Detail

Repository
rL LLVM

Event Timeline

kariddi created this revision.Sep 24 2018, 6:19 PM
bjope added a comment.Oct 3 2018, 9:43 AM

I don't know the history behind the inferred classes, I thought they were generated because they might be needed :-)

To use this "knob" I guess I need to know which classes that are used by different instructions in my target, and which register classes that I might get copied between etc. And by using that knowledge I might know that the register coalescer and regalloc etc doesn't need constrain to certain inferred classes. And then I can use the knob to get rid of classes that I believe never is used. Is that a correct interpretation?

To understand a little bit more about what you are trying to achieve it would be nice with some more information about the problem with having those inferred classes.
Are they for example invalid or overlapping in some way (do you get several classes that contain exactly the same registers)?
Or do you hit some maximum limit regarding number of register classes?
Or are you afraid that it costs compile time to have many classes?
Or are you just annoyed that your generated <target>GenRegisterInfo.inc file is hard to read?

The concept makes sense to me, but I don't see what the meaning of the values is / how you are supposed to compute them for the mask. Is it supposed to be one bit per regunit in the generated registers of the class?

arsenm added inline comments.Feb 13 2020, 4:42 PM
include/llvm/Target/Target.td
286

Typo paritioned

Herald added a project: Restricted Project. · View Herald TranscriptFeb 13 2020, 4:43 PM