Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GlobalISel] Hash collisions / hitting EmptyKey or TombstoneKey on map key in RegisterBankInfo #85209

Closed
marcauberer opened this issue Mar 14, 2024 · 2 comments · Fixed by #87033
Assignees

Comments

@marcauberer
Copy link
Member

We experience sporadic failures in RegisterBankInfo::getOperandsMapping. These failures seem to be triggered by

hash_code Hash = hash_combine_range(Begin, End);

hitting the value of EmptyKey or TombstoneKey in the DenseMap member MapOfOperandsMappings. We still use LLVM 13, but the coding seems to have remained the same until to date.

We also see failures in RegisterBankInfo::ValueMapping::verify that seem to be triggered by hash collisions from

hash_code Hash = hash_combine_range(Begin, End);

To us it seems that this coding is not protected against these problems and therefore failures can happen randomly.

Already posted the problem in the Forum, but got no answer there:
https://discourse.llvm.org/t/registerbankinfo-getoperandsmapping-not-protected-against-hash-collisions-emptykey-tombstonekey/77659

@marcauberer
Copy link
Member Author

@qcolombet Do you have an idea how to solve this?

@marcauberer
Copy link
Member Author

What can be done in any case is to change the key type of the four maps to hash_code, so we do not truncate the 64-bit size_t value of the hash to uint32_t for the map key.

mutable DenseMap<unsigned, std::unique_ptr<const PartialMapping>>
MapOfPartialMappings;
/// Keep dynamically allocated ValueMapping in a separate map.
/// This shouldn't be needed when everything gets TableGen'ed.
mutable DenseMap<unsigned, std::unique_ptr<const ValueMapping>>
MapOfValueMappings;
/// Keep dynamically allocated array of ValueMapping in a separate map.
/// This shouldn't be needed when everything gets TableGen'ed.
mutable DenseMap<unsigned, std::unique_ptr<ValueMapping[]>>
MapOfOperandsMappings;
/// Keep dynamically allocated InstructionMapping in a separate map.
/// This shouldn't be needed when everything gets TableGen'ed.
mutable DenseMap<unsigned, std::unique_ptr<const InstructionMapping>>
MapOfInstructionMappings;
/// Getting the minimal register class of a physreg is expensive.
/// Cache this information as we get it.
mutable DenseMap<unsigned, const TargetRegisterClass *> PhysRegMinimalRCs;

This will reduce the likelyhood of hitting EmptyKey or TombstoneKey dramatically. I will prepare a patch for this ...

@marcauberer marcauberer self-assigned this Mar 29, 2024
marcauberer added a commit that referenced this issue Apr 2, 2024
… RegisterBankInfo (#87033)

Fixes #85209

This patch removes the truncation from `hash_code` aka `size_t` down to
`unsigned`, that currently happens on DenseMap accesses in
RegisterBankInfo. This reduces the likelihood of hash collisions, as
well as the likelihood of hitting EmptyKey or TombstoneKey, the special
key values of DenseMap. This is not the ultimate solution to the
problem, but we can do it in any case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
3 participants