This is an archive of the discontinued LLVM Phabricator instance.

[TableGen][GlobalISel] Account for HwMode in RegisterBank register sizes
ClosedPublic

Authored by nitinjohnraj on Mar 11 2020, 10:15 AM.

Details

Summary

This patch adds logic for determining RegisterBank size to RegisterBankInfo, which allows accounting for the HwMode of the target. Individual RegisterBanks cannot be constructed with HwMode information as construction is generated by TableGen, but a RegisterBankInfo subclass can provide the HwMode as a constructor argument. The HwMode is used to select the appropriate RegisterBank size from an array relating sizes to RegisterBanks.

Targets simply need to provide the HwMode argument to the <target>GenRegisterBankInfo constructor. The RISC-V RegisterBankInfo constructor has been updated accordingly (plus an unused argument removed).

Diff Detail

Event Timeline

lewis-revill created this revision.Mar 11 2020, 10:15 AM
simoncook accepted this revision.Mar 13 2020, 3:26 PM

Patch makes sense, and looking at the newly generated XRegisterBank.inc files, all LGTM

This revision is now accepted and ready to land.Mar 13 2020, 3:26 PM
This revision was automatically updated to reflect the committed changes.
akuegel added inline comments.
llvm/lib/CodeGen/GlobalISel/RegisterBankInfo.cpp
61

bkramer already commented on this on the llvm-commits mailing list. Copying it here for visibility:

This can write to a global variable, which is thread-hostile. I see
tsan complain about concurrent writes to llvm::X86::GPRRegBank.

I reverted the patch (commit baa6f6a7828a46c37b96227282938717220f8b34).

My initial thoughts are that this may only be an issue if there can be potentially more than one instance of RegisterBankInfo? And indeed, if it is possible for each of these to have been constructed with differing HwModes? I'll try and look into it in more detail and find out.

lewis-revill reopened this revision.Mar 23 2020, 9:27 AM
This revision is now accepted and ready to land.Mar 23 2020, 9:27 AM

I'm lacking an understanding of how concurrency is expected to work within LLVM, but since there is only one RegisterBankInfo constructed per subtarget I don't see how there is a problem with updating the global RegBanks array? Likewise the HwMode is constant for the subtarget, so the write will be of the same value.

I'm lacking an understanding of how concurrency is expected to work within LLVM, but since there is only one RegisterBankInfo constructed per subtarget I don't see how there is a problem with updating the global RegBanks array? Likewise the HwMode is constant for the subtarget, so the write will be of the same value.

There can be many subtargets around, and those can be created concurrently. Having state in a global variable is not going to work.

lewis-revill retitled this revision from [TableGen][GlobalISel] Account for HwMode in RegisterBank register sizes to [WIP][TableGen][GlobalISel] Account for HwMode in RegisterBank register sizes.
lewis-revill edited the summary of this revision. (Show Details)

Rewrote the global RegBanks array to be constant. Instead of modifying RegisterBanks after construction, provide HwMode to the constructor of RegisterBankInfo and move size calculation logic for RegisterBanks to that class.

lenary removed a subscriber: lenary.Jan 14 2022, 7:49 AM

I'm not sure I understand why the RegisterBankInfo needs to be aware of the hwmode. HWmode changes the size of the classes during selection, but the registerbankinfo just needs to assign sizes to banks. The concrete classes don't matter so much

I'm not sure I understand why the RegisterBankInfo needs to be aware of the hwmode. HWmode changes the size of the classes during selection, but the registerbankinfo just needs to assign sizes to banks. The concrete classes don't matter so much

Unsure if I understood your comment! The patch itself was necessary since the assignment of a single size to each register bank is wrong for targets with different register sizes for different hardware modes. If the RegisterBankInfo is aware of the hardware mode then we can query what the size of a given register bank actually is for the current hardware mode. The register bank array itself is also constructed once by TableGen so we can't change sizes when they're constructed. And it isn't safe to change the size after construction.

lewis-revill retitled this revision from [WIP][TableGen][GlobalISel] Account for HwMode in RegisterBank register sizes to [TableGen][GlobalISel] Account for HwMode in RegisterBank register sizes.Feb 9 2022, 3:09 AM

Bump - is anyone able to review this?

arsenm added a comment.Feb 9 2022, 8:49 AM

I'm not sure I understand why the RegisterBankInfo needs to be aware of the hwmode. HWmode changes the size of the classes during selection, but the registerbankinfo just needs to assign sizes to banks. The concrete classes don't matter so much

Unsure if I understood your comment! The patch itself was necessary since the assignment of a single size to each register bank is wrong for targets with different register sizes for different hardware modes. If the RegisterBankInfo is aware of the hardware mode then we can query what the size of a given register bank actually is for the current hardware mode. The register bank array itself is also constructed once by TableGen so we can't change sizes when they're constructed. And it isn't safe to change the size after construction.

Register banks do not have sizes. A register bank mapping is a bank plus a size/offset that you can change based on the target's size, not part of the bank itself.

Register banks do not have sizes. A register bank mapping is a bank plus a size/offset that you can change based on the target's size, not part of the bank itself.

Right. But before this patch there was a max size associated to the bank itself, which is queried by the verifier. And if we want to keep that concept of a maximum size surely we should have it be accurate? So for different hardware modes it should be possible for it to be different.

Register banks do not have sizes. A register bank mapping is a bank plus a size/offset that you can change based on the target's size, not part of the bank itself.

Right. But before this patch there was a max size associated to the bank itself, which is queried by the verifier. And if we want to keep that concept of a maximum size surely we should have it be accurate? So for different hardware modes it should be possible for it to be different.

Why is there a maximum size concept? What is it used for? I haven't noticed thisb efore

Herald added a project: Restricted Project. · View Herald TranscriptMar 28 2022, 3:38 PM

Register banks do not have sizes. A register bank mapping is a bank plus a size/offset that you can change based on the target's size, not part of the bank itself.

Right. But before this patch there was a max size associated to the bank itself, which is queried by the verifier. And if we want to keep that concept of a maximum size surely we should have it be accurate? So for different hardware modes it should be possible for it to be different.

Why is there a maximum size concept? What is it used for? I haven't noticed thisb efore

If it is a maximum, why can't you set to the maximum possible size?

Register banks do not have sizes. A register bank mapping is a bank plus a size/offset that you can change based on the target's size, not part of the bank itself.

Right. But before this patch there was a max size associated to the bank itself, which is queried by the verifier. And if we want to keep that concept of a maximum size surely we should have it be accurate? So for different hardware modes it should be possible for it to be different.

Why is there a maximum size concept? What is it used for? I haven't noticed thisb efore

If it is a maximum, why can't you set to the maximum possible size?

Because this size isn't 'set' by a target, it's determined by tablegen to be the maximum size of the register class covered by the register bank. So for the RISC-V GPR banks that size will always depend on hardware mode, and as such the bank size should also reflect that - that's what this patch addresses.

Register banks do not have sizes. A register bank mapping is a bank plus a size/offset that you can change based on the target's size, not part of the bank itself.

Right. But before this patch there was a max size associated to the bank itself, which is queried by the verifier. And if we want to keep that concept of a maximum size surely we should have it be accurate? So for different hardware modes it should be possible for it to be different.

Why is there a maximum size concept? What is it used for? I haven't noticed thisb efore

It's purely used for the verifier (and for similar assertions about type sizes in backends).

arsenm added inline comments.Mar 30 2022, 6:05 AM
llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
588

getMaximumSize?

589

Braces

nitinjohnraj commandeered this revision.Apr 7 2023, 2:30 PM
nitinjohnraj added a reviewer: lewis-revill.
craig.topper added inline comments.
llvm/include/llvm/CodeGen/GlobalISel/RegisterBankInfo.h
589

Can we get the ID from the RegisterBank object instead of searching?

Updating getSize to getMaximumSize and using the register bank ID

Use DefaultMode instead of 0.

nitinjohnraj added inline comments.Jun 1 2023, 6:16 PM
llvm/utils/TableGen/RegisterBankEmitter.cpp
270

Use predefined constant DefaultMode

nitinjohnraj requested review of this revision.Jun 1 2023, 6:19 PM

This was approved a long while ago, could I get a review to confirm that it's good to go?

craig.topper added inline comments.Jun 1 2023, 6:21 PM
llvm/include/llvm/CodeGen/RegisterBankInfo.h
589 ↗(On Diff #527686)

Do we need a loop at al

Can it just be return Sizes[RegBankID + HwMode * NumRegBanks];

nitinjohnraj marked an inline comment as done.

Removed loop in getMaximumSize.

This revision is now accepted and ready to land.Jun 2 2023, 2:54 PM