Motivation
Prior to the switch to opaque pointers, LLVM’s type system used to be recursive. A linked list may e.g. be implemented as %node = { %node*, ... }
. With opaque pointers this is no longer the case, as pointer types no longer have an element type. Directly recursive struct types such as %foo = { %foo }
have also never been allowed which is verified eagerly since https://github.com/llvm/llvm-project/commit/4831e0aa88debb3b7d0528bfd85db73a6a03aeff
To support recursion the LLVMStructType
required to be mutable (to be able to first construct the type before then using it within its own body using a setBody
method).
As the support for mutable types in MLIR is immature compared to immutable types and requires a lot more complexity, this RFC proposes to switch the struct type to be immutable instead.
Please see the PR implementing the RFC here: [mlir][LLVM] Make struct types immutable by zero9178 · Pull Request #116035 · llvm/llvm-project · GitHub
Note that lines changed currently consist of 195 added and 1110 lines removed.
A similar discussion for LLVM proper has occurred here: Recursive types - #4 by nikic
Semantics changes
One affordance it being a mutable type gives us is the ability to autorename structs: One could use LLVMStructType::getNewIdentified
which would be guaranteed to have a unique name within the MLIR context.
Implementing this with immutable types is much more difficult and I believe redundant.
Instead, this RFC proposes making the name a normal type parameter that is part of uniquing as any others. Two struct types are then considered equal if both the name and the body matches.
This retains advantages of named structs from LLVM:
- We retain type inequality between two structs with the same body but different names.
- Structs remain more readable thanks to being able to be named.
Unlike LLVM IR, two structs may share the same name (e.g. struct<"foo", ()>
and struct<"foo", (i32)>
).
These would nevertheless not be considered equal in MLIR and will get assigned unique names once exported to LLVM IR.
Besides readability, I am not aware of any issues with allowing this case.
API Changes
Care has been taken to make sure as many of the APIs remain compatible as possible to reduce downstream breakage.
Nevertheless, due to the semantic changes, some APIs had to be changed or removed instead:
getIdentified
,getIdentifiedChecked
andgetNewIdentified
have been removed in favour of the more conventionalget
method.
getIdentified
,getIdentifiedChecked
would previously create structs with empty bodies that could be set later.getNewIdentified
would assign a unique name to the struct.
Neither functionality is supported once struct types are immutable.setBody
andisInitialized
are no longer supported as the type is now immutable.
Corresponding C APIs have also been removed.
Out of scope changes
Following changes may be done or discussed in the future but are out of scope for this PR:
- Removing opaque structs. I believe these no longer have any uses with opaque pointers as well.
- Removing named structs. This could theoretically be done and literal types used everywhere.
I don’t see great motivation to do so.
CC @gysit @Dinistro @definelicht @Mogball @bcardosolopes @nikic