-
Notifications
You must be signed in to change notification settings - Fork 0
MLIR SROA #15
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
MLIR SROA #15
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall very nice!
I dropped a lot of comments and will need a second review to get more in depth with some parts of the algorithm. Especially some of the blocking uses handling was a bit confusing. And also the GEP stuff. I think it may make sense to add some more comments for the complicating things.
Returns whether all accesses in this operation to the provided slot are | ||
done in a type-safe manner. To be type-safe, the access must only load | ||
the value in this type as the type of the slot, and without assuming any | ||
context around the slot. For example, a type-safe load must not load |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it misses the inbounds aspect but we can keep it if you prefer the name.
@@ -214,6 +214,13 @@ def SCCP : Pass<"sccp"> { | |||
let constructor = "mlir::createSCCPPass()"; | |||
} | |||
|
|||
def SROA : Pass<"sroa"> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still needs some polishing :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tell me if what I wrote is satisfying.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good! Should we also add a pass flag that limits the size of the aggregates we consider for destruction (probably in terms of number of elements?).
@@ -198,6 +200,12 @@ class LLVMStructType | |||
|
|||
LogicalResult verifyEntries(DataLayoutEntryListRef entries, | |||
Location loc) const; | |||
|
|||
/// Destructs the struct into its indexed field types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does "destruct" mean here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's go for destructure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would explicitly mention which interfaces are SROA-related in the source code
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So it's not super clear where the boundary is. There is "PromotableOpInterface" which is used by both, "TypeSafeOpInterface" which is used by SROA but has nothing SROA-specific to it. Generally I think those interfaces are meant to be used in any setting and happen to be used by mem2reg and SROA.
/// This is a DAG structure because an operation that must eliminate some of | ||
/// its uses always comes from a request from an operation that must | ||
/// eliminate some of its own uses. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
omg this sentence 😂 Please add some structure to help parsing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tell me if you prefer the new one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do I know what's new? 🥲
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Blame Torvalds!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added some NIT comments.
Optional<DenseMap<Attribute, Type>> getDestructedLayout(); | ||
|
||
/// Returns which type is stored at a given integer index within the struct. | ||
Type getTypeAtIndex(Attribute index); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At a first glance, it seems odd to use an Attribute
type for index
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the reason for this is that sometimes indices are not integers but fancy things. For example, if you wanted to use SROA on for example a hashmap dialect, your indices could be anything.
InterfaceMethod<[{ | ||
Returns the list of slots for which destruction should be attempted, | ||
specifying in which way the slot should be destructed into subslots. The | ||
subslots are indexed by attributes. This computes the type of the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: "by integer/index attributes"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well no, because of what I mentioned above. I don't really know how to word it otherwise :/
may belong to a different allocator. The original slot must still exist | ||
at the end of this call. | ||
|
||
The builder is located at the beginning of the block where the slot |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems a bit odd that the insertion point of the builder is part of the precondition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. This comes from suggestions upstream, though. I don't know if I should try to fight it too much.
InterfaceMethod<[{ | ||
Destructures this slot into multiple subslots. The newly generated slots | ||
may belong to a different allocator. The original slot must still exist | ||
at the end of this call. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original slot must still exist at the end of this call.
Does this mean that destroy
doesn't destroy the slot?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
destruct
destructs the slot but does not destroy it yes :)
I'm changing the name for destructure
to make Johannes happy.
I'm going to squash all this and manually separate it into two different PRs. Feel free to finish the ongoing discussions here and move further comments to the new PRs once they are ready. |
A case for this transformation, https://gcc.godbolt.org/z/nhYcWq1WE Fold mov w8, llvm#56952 movk w8, #15, lsl #16 ldrb w0, [x0, x8] into add x0, x0, 1036288 ldrb w0, [x0, 3704] Only LDRBBroX is supported for the first time. Fix llvm#71917
Implementation of a simple form of generic SROA in MLIR.