Optimize publish - #9091
Conversation
Optimize out publishes of allocations and publishes of publishes where it is clearly not possible for there to be a write to the published object between the allocation or former publish and the outer publish. Also optimize out publishes of unshared and immutable reference types.
| if (!ht.isShared() || ht.isBottom()) { | ||
| return false; | ||
| } | ||
| if (ht.isStruct() || ht.isArray()) { | ||
| return true; | ||
| } | ||
| if (ht.isBasic()) { | ||
| switch (ht.getBasic(Unshared)) { | ||
| case HeapType::any: | ||
| case HeapType::eq: | ||
| case HeapType::struct_: | ||
| case HeapType::array: | ||
| return true; | ||
| default: | ||
| return false; | ||
| } | ||
| } | ||
| return false; |
There was a problem hiding this comment.
Can this work?
| if (!ht.isShared() || ht.isBottom()) { | |
| return false; | |
| } | |
| if (ht.isStruct() || ht.isArray()) { | |
| return true; | |
| } | |
| if (ht.isBasic()) { | |
| switch (ht.getBasic(Unshared)) { | |
| case HeapType::any: | |
| case HeapType::eq: | |
| case HeapType::struct_: | |
| case HeapType::array: | |
| return true; | |
| default: | |
| return false; | |
| } | |
| } | |
| return false; | |
| if (!ht.isShared()) { | |
| return false; | |
| } | |
| return HeapType::isSubType(ht, HeapType::any.getShared(true)); |
There was a problem hiding this comment.
Yeah, almost. Just have to exclude bottom types as well.
| ;; RefCast is a transparent fallthrough, so publish of ref.cast of an | ||
| ;; allocation can be removed. | ||
| (publish | ||
| (ref.cast (ref $shared-struct) |
There was a problem hiding this comment.
Maybe have a cast that is not trivially removed?
- To show that we only remove the publish
- The cast is removed before we even optimize the publish, so I don't think this is testing an ignoring of a cast?
There was a problem hiding this comment.
Oh hmm, this is actually trickier than I thought. The struct.new has a non-nullable exact type, so there is no cast we can do on it that cannot be trivially removed. If we try to work around that by e.g. inserting a block that will forget the type, then we end up seeing through it when we optimize the cast and actually end up not removing the publish.
I'll just remove this test because there is nothing cast-specific in the new logic anyway.
| ;; CHECK-NEXT: ) | ||
| (func $publish-unreachable-block (result (ref (shared any))) | ||
| ;; Publish of a block containing an unreachable instruction is eliminated | ||
| ;; during dead code removal. |
There was a problem hiding this comment.
Looks like it was removed right here!
(maybe add a nop so the block is not trivial, if that's the issue?)
| (func $publish-tee (result (ref null $shared-struct)) | ||
| ;; An intervening local.tee does not prevent the publish from being removed. | ||
| ;; If the teed local was used to write to the object before publishing it, | ||
| ;; we would not remove the publish. |
There was a problem hiding this comment.
| ;; we would not remove the publish. | |
| ;; we would not remove the publish (see next test). |
| (local $s (ref null $shared-struct)) | ||
| (block $l (result (ref null (shared any))) | ||
| ;; Now the tee is used to write to the published object. We do not | ||
| ;; optimize. |
There was a problem hiding this comment.
Where in the code is this case handled?
Optimize out publishes of allocations and publishes of publishes where it is clearly not possible for there to be a write to the published object between the allocation or former publish and the outer publish. Also optimize out publishes of unshared and immutable reference types.