This is an archive of the discontinued LLVM Phabricator instance.

[LangRef] Add elementtype attribute
ClosedPublic

Authored by nikic on Jul 4 2021, 7:06 AM.

Details

Reviewers
aeubanks
Group Reviewers
Restricted Project
Commits
rG1fd23a065bf7: [LangRef] Add elementtype attribute
Summary

This adds an elementtype(<ty>) attribute, which can be used to attach an element type to a pointer typed argument. It is similar to byval/byref in purpose, but unlike those does not carry any specific semantics by itself. However, certain intrinsics may require it and interpret it in specific ways.

The in-tree use cases for this that I'm currently aware of are:

call ptr @llvm.preserve.array.access.index.p0(ptr elementtype(%ty) %base, i32 %dim, i32 %index)
call ptr @llvm.preserve.struct.access.index.p0(ptr elementtype(%ty) %base, i32 %gep_index, i32 %di_index)
; Possibly also @llvm.preserve.union.access.index.p0(), though I think it doesn't need it.

call token @llvm.experimental.gc.statepoint.p0(i64 0, i32 0, ptr elementtype(void ()) @foo, i32 0, i32 0, i32 0, i32 0, ptr addrspace(1) %obj)

Notably, the gc.statepoint case needs a function as element type, in which case the workaround of adding a separate %ty undef argument would not work, as arguments cannot be unsized.

Diff Detail

Event Timeline

nikic created this revision.Jul 4 2021, 7:06 AM
nikic requested review of this revision.Jul 4 2021, 7:06 AM
Herald added a project: Restricted Project. · View Herald TranscriptJul 4 2021, 7:06 AM

General thought: This seems unfortunately open-ended & could be used to used more generally in a way that might defeat some of the goals of the opaque pointers work (eg: if this gets added to arbitrary functions/used by transformations, etc).

Could/should we limit this to only apply to intrinsics? And can we possibly make it so this is not visible on the function decl, so transformations can't accidentally start depending on its presence (this attribute only really describes a feature of the implementation of the function, right? Not any requirement on callers about how they call such a function (they could pass in whatever pointer they like/doesn't really matter what it points to))

nikic added a comment.Jul 6 2021, 1:02 PM

General thought: This seems unfortunately open-ended & could be used to used more generally in a way that might defeat some of the goals of the opaque pointers work (eg: if this gets added to arbitrary functions/used by transformations, etc).

I think there's not a lot of danger of this being misused, at least in-tree, simply due to the fact that clang is not going to emit this attribute for normal pointer arguments. It's only going to be added by IRBuilder for some intrinsic calls, e.g. in IRBuilderBase::CreatePreserveArrayAccessIndex() .

Could/should we limit this to only apply to intrinsics?

That said, limiting it to intrinsics makes sense to me. For the future I have another possible use in mind with inlineasm+memsanitizer, but we can expand as needed later.

And can we possibly make it so this is not visible on the function decl, so transformations can't accidentally start depending on its presence (this attribute only really describes a feature of the implementation of the function, right? Not any requirement on callers about how they call such a function (they could pass in whatever pointer they like/doesn't really matter what it points to))

Not sure I quite understand what you mean here. But if you're suggesting that this attribute should only be allowed on call arguments, but not on function parameters, then yes, that makes sense to me.

nikic updated this revision to Diff 356806.Jul 6 2021, 1:11 PM

Restrict attribute to intrinsics and calls only.

General thought: This seems unfortunately open-ended & could be used to used more generally in a way that might defeat some of the goals of the opaque pointers work (eg: if this gets added to arbitrary functions/used by transformations, etc).

I think there's not a lot of danger of this being misused, at least in-tree, simply due to the fact that clang is not going to emit this attribute for normal pointer arguments. It's only going to be added by IRBuilder for some intrinsic calls, e.g. in IRBuilderBase::CreatePreserveArrayAccessIndex() .

Yeah, I was thinking more intentional - "oh, we have this attribute, we could start emitting it and using it in this other way" - at least documenting and constraining it in certain ways might provide someone a little more hesitation were they to think about using it for something else. Actually revisit the wording in the LangRef and have a design discussion about the new uses.

Could/should we limit this to only apply to intrinsics?

That said, limiting it to intrinsics makes sense to me. For the future I have another possible use in mind with inlineasm+memsanitizer, but we can expand as needed later.

And can we possibly make it so this is not visible on the function decl, so transformations can't accidentally start depending on its presence (this attribute only really describes a feature of the implementation of the function, right? Not any requirement on callers about how they call such a function (they could pass in whatever pointer they like/doesn't really matter what it points to))

Not sure I quite understand what you mean here. But if you're suggesting that this attribute should only be allowed on call arguments, but not on function parameters, then yes, that makes sense to me.

I was thinking the opposite, sort of - only on the function declaration, but if there was some way to make it so they wouldn't be readily observed by analysis/transformations, etc. Really the type is an implementation detail of the function, not part of its signature/not something callers should be observing/making choices based on, I think? But I doubt we have any infrastructure to provide that sort of private implementation detail property for an intrinsic.

if we add it to the function declaration, we'll have issues with mangling right? that's another reason to only have it on the caller

nikic added a comment.Jul 7 2021, 12:07 PM

And can we possibly make it so this is not visible on the function decl, so transformations can't accidentally start depending on its presence (this attribute only really describes a feature of the implementation of the function, right? Not any requirement on callers about how they call such a function (they could pass in whatever pointer they like/doesn't really matter what it points to))

Not sure I quite understand what you mean here. But if you're suggesting that this attribute should only be allowed on call arguments, but not on function parameters, then yes, that makes sense to me.

I was thinking the opposite, sort of - only on the function declaration, but if there was some way to make it so they wouldn't be readily observed by analysis/transformations, etc. Really the type is an implementation detail of the function, not part of its signature/not something callers should be observing/making choices based on, I think? But I doubt we have any infrastructure to provide that sort of private implementation detail property for an intrinsic.

I'm still not sure I follow. Optimizations for an intrinsic using elementtype do need to inspect the attribute. It's effectively part of the ABI for that intrinsic.

if we add it to the function declaration, we'll have issues with mangling right? that's another reason to only have it on the caller

Right. Adding the attribute to the declaration would require including the element type in the intrinsic mangling, as we'd need multiple declarations that only differ by the elementtype attribute, rather than types in the signature. Not sure whether doing that would cause any problems.

This revision is now accepted and ready to land.Jul 7 2021, 12:48 PM

@aeubanks approval's fine by me - I'll figure out my confusion/concerns eventually, no worries.

This revision was automatically updated to reflect the committed changes.