-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[sil] add instruction copy_to_ref #30787
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
Conversation
This sil instruction can be used to copy an address to a class reference. It does this by memcpying the address to the first element in the class reference (the element after the reference count object). The source must contain all stored properties of the class reference and must be an address. See SIL.rst for more details.
var x : Int | ||
} | ||
|
||
// CHECK-LABEL: define swiftcc void @test_int |
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.
As you can see, even without any added optimizations, the llvm-ir codegen is substantially better.
Some discussion points: We need to think about ownership. This doesn't matter for trivial types, like A "store_to_ref" is a shortcut for a series of
The question we have to answer is: what benefit would such a new instruction give us compared to using this series of instructions? Note that converting such a series to a memcpy can also be done by IRGen or an llvm optimization. There are some optimizations, like LetPropertiesOpt, which rely on ref_element_addr to be there to check all possible accesses to a specific class property. Those optimizations would need to take "store_to_ref" into account. I'd like to bring up two alternatives. I'm not sure by myself if they are better - just for brainstorming:
|
@eeckstein thanks for those suggestions. I like that neither of your alternatives use addresses. This will make it easier to optimize all the allocations away. The only downside is that in order to replace all ref_element_addrs with tuple_element_addrs we would have to have to create a load. It's rare that a class will have no uses other than initialization but, it's fairly common that a class's only use after initialization will be ref_element_addr instructions. If we can replace all those, we can remove the class and there's a good chance that mem2reg can get rid of the tuple alloc_stack. Anyway, I don't think that should be an issue at all, just a thing to keep in mind. I tested some various implementations and found that both using the ref_element_addr/tuple_extract/store and copy_to_ref (or whatever equivilat instruction we come up with) genereate the **exact** same llvm-ir.
Given that, it seems like the best course of action may be not to add any instructions. What do you think? Is it worth the sil code size/clarity improvements? |
I agree
IMO, no |
@eeckstein great, glad we're in agreement. See #30810. |
Storing class properties as a tuple or struct can be beneficial because most optimization passes only work on non-class datatypes (struct, tuple, and enum). To get the best performance it's ideal to memcpy the entire object to the first element of the class reference (rather than emit a dozen ref_element_addr, tuple_extract, and store instructions). That's where this instruction comes into play (from SIL.rst):
Given an instance of a tuple or struct,
copy_to_ref
bitcasts the "from" value to a bytepointer and emits a memcpy to the "to" operand which is a reference. The "from" value must have all stored properties of the "to" operand. Here's an example use:
See #30736 for previous discussion/rational.