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

Add support for self referential metadata #895

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

aseyboldt
Copy link

@aseyboldt aseyboldt commented Dec 6, 2022

Metadata definitions that refer to themselves like !0 = { !0 } are allowed by llvm, and used to make some metadata entries globally unique (see for instance https://llvm.org/docs/LangRef.html#noalias-and-alias-scope-metadata). It seems this isn't supported by llvmlite currently.

In this PR I add support for this by adding a new self_ref argument to Model.add_metadata, that will always return a new metadata entry, but prepending self as the first operand. So this only supports references to self as the first entry, I haven't seen any usage in llvm at other locations however.

Update I probably should also mention that I'm still pretty new to llvm, and this proposed API might not actually be the best as a result...

@esc
Copy link
Member

esc commented Dec 7, 2022

@aseyboldt thank you for submitting this PR. I have labelled it as Ready for Review for now. It will hopefully be assigned a reviewer and milestone during the next issue triage meeting on Tuesdays.

@twiecki
Copy link

twiecki commented Dec 21, 2022

@esc Just checking in if a reviewer has been assigned?

@sklam sklam self-assigned this Jan 10, 2023
Copy link
Member

@sklam sklam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The situation with self-referential metadata is a bit unclear in LLVM. There are discussion about removing them https://lists.llvm.org/pipermail/llvm-dev/2021-February/148674.html. I'm not sure if the distinct keyword has make this self-referential trick outdated. For now, LLVM still contains code to create self-referential MD. It is done so by first building a metadata node without self-reference then replace the first operand with the self-reference; e.g. https://github.com/llvm/llvm-project/blob/080a07199e8c146a58ef3506cfcbf554eced21fc/llvm/lib/Analysis/LoopInfo.cpp#L1159-L1161.

The patch here adds a self_ref keyword argument to prepend a self-reference to the operands. I think this logic is okay given any self-referential MD node seems to always be just a bag of stuff. I don't think we should overengineer it too much.

Given the code changes here are small, I am ok to accept this patch once the following suggestions are addressed.

Comment on lines 52 to 54
A self referential metadata entry has itself as the first
operand to ensure uniquencess. These references are never
cached.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add few words to relate this to the self_ref argument? e.g. the self_ref creates a self referential metadata by prepending itself to the operands?.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I extended the description.

"""
Add an unnamed metadata to the module with the given *operands*
(a sequence of values) or return a previous equivalent metadata.
A MDValue instance is returned, it can then be associated to
e.g. an instruction.

A self referential metadata entry has itself as the first
operand to ensure uniquencess. These references are never
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
operand to ensure uniquencess. These references are never
operand to ensure uniqueness. These references are never

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Comment on lines 326 to 335
def test_self_relf_metadata(self):
mod = self.module()
value = mod.add_metadata((), self_ref=True)
self.assert_ir_line('!0 = !{ !0 }', mod)
value2 = mod.add_metadata((value,))
assert value is not value2
self.assert_ir_line('!1 = !{ !0 }', mod)
value3 = mod.add_metadata((), self_ref=True)
self.assert_ir_line('!2 = !{ !2 }', mod)
assert value is not value3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add test for metadata that has other operands?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@aseyboldt
Copy link
Author

@sklam Thanks, I added a test and extended the docs a little as you suggested.
I think the test failure is unrelated?

Warning, treated as error:
failed to reach any of the inventories with the following issues:
intersphinx inventory 'https://docs.python.org/3/objects.inv' not fetchable due to <class 'requests.exceptions.ConnectionError'>: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer'))
make: *** [Makefile:55: html] Error 2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants