Two questions regarding the
- Minor: should this attribute be a
UnitAttr instead of a
BoolAttr? I assume it used the latter when
UnitAttr wasn’t present.
- Currently, the LLVM dialect to LLVM IR translation fails when it finds the
llvm.nolias attribute on a function argument that is not a pointer. I felt it should either (a) just ignore the attribute when it finds it on a non-pointer type (since the IR was valid and doesn’t fail the verifier) or (b) fail the verifier itself when it encounters such attributes on non-pointer types.
The above scenario is common when we attach a
llvm.nolias to a memref function argument - it’s propagated to all the five or six arguments the memref type expands out to when lowering to the LLVM dialect. So perhaps we should just be doing (a) if updating the lowering isn’t appropriate to treat memref arguments specially and we can document it on
llvm.noalias that it is ignored for non-pointer types.
I rather have the verifier strict and match LLVM IR here, so fixing the memref lowering seems better to me.
This attribute existed before much of the modern infrastructure, and before the memref descriptor in the current form
- It should be a
UnitAttr, which did not exist.
- It should be attached to “pointer-like” types only. I’m not sure we had dialect attribute verifiers at the point it was added. We should have a verifier for it, and ideally a “pointer-like” type trait/interface so that we don’t need to list accepted types explicitly.
- It should be propagated to the aligned pointer only (second element of the descriptor struct), allocated and aligned pointer do alias.
A more viable longer term approach would be to model aliasing information properly on memrefs and convert that to LLVM instead of trying to lift LLVM-level information to other types. This is still not implemented
On a side note, the allocated pointer would often get eliminated as an unused argument(?) – it’s pretty rare for it to be used inside the function as the buffer is typically deallocated at the caller. We probably don’t have a pass that removes unused function arguments but it would be great to apply that on the LLVM dialect if there was one. I recall there was code to remove unused Block arguments (non-entry Blocks at least) but I couldn’t find that either.
The problem with removing function arguments is that it only works for functions with internal visibility, i.e. we can simultaneously update all its callers. If there’s a chance that the function is called from a different module, we should preserve its signature. Inside LLVM IR (not dialect), LLVM SROA will remove the struct and then DCE will remove the unnecessary fields, that works most of the time.
I agree that the need to pass the allocated pointer to the callee is rare, folks have been floating around the idea of having two different types to solve that: “allocated” memref and “view” memref, each with one pointer, and only the former can be deallocated.
I’m trying to understand what problem this would solve? If you are passing a memref of choice for special cases, you also know that the callee has internal visibility and so it’s cleaner that the extra unused argument be transparently eliminated via a later pass that eliminates unused arguments post lowering to the LLVM dialect. You get the right trimmed list?