@@ -5726,65 +5726,47 @@ struct OptimizeInstructions
57265726 // curr, and so they must be compatible to allow for a proper new
57275727 // type after the transformation.
57285728 //
5729- // At minimum an LUB is required, as shown here:
5729+ // The children must have a shared supertype. For example, we cannot
5730+ // fold out the `drop` here because there would be no valid result
5731+ // type for the if afterward:
57305732 //
57315733 // (if
57325734 // (condition)
57335735 // (drop (i32.const 1))
57345736 // (drop (f64.const 2.0))
57355737 // )
57365738 //
5737- // However, that may not be enough, as with nominal types we can
5738- // have things like this:
5739+ // However, having a shared supertype may not be enough. If $A and
5740+ // $B have a shared supertype, but that supertype does not have a
5741+ // field at index 1, then we cannot fold the duplicated struct.get
5742+ // here:
57395743 //
57405744 // (if
57415745 // (condition)
57425746 // (struct.get $A 1 (..))
57435747 // (struct.get $B 1 (..))
57445748 // )
57455749 //
5746- // It is possible that the LUB of $A and $B does not contain field
5747- // "1". With structural types this specific problem is not possible,
5748- // and it appears to be the case that with the GC MVP there is no
5749- // instruction that poses a problem, but in principle it can happen
5750- // there as well, if we add an instruction that returns the number
5751- // of fields in a type, for example. For that reason, and to avoid
5752- // a difference between structural and nominal typing here, disallow
5753- // subtyping in both. (Note: In that example, the problem only
5754- // happens because the type is not part of the struct.get - we infer
5755- // it from the reference. That is why after hoisting the struct.get
5756- // out, and computing a new type for the if that is now the child of
5757- // the single struct.get, we get a struct.get of a supertype. So in
5758- // principle we could fix this by modifying the IR as well, but the
5759- // problem is more general, so avoid that.)
5750+ // (Note: In that example, the problem only happens because the type
5751+ // is not part of the struct.get - we infer it from the reference.
5752+ // That is why after hoisting the struct.get out, and computing a
5753+ // new type for the if that is now the child of the single
5754+ // struct.get, we get a struct.get of a supertype. So in principle
5755+ // we could fix this by modifying the IR as well, but the problem is
5756+ // more general, so avoid that.)
5757+ //
5758+ // For now, only support the case where the types of the children
5759+ // are the same.
5760+ //
5761+ // TODO: We could analyze whether the LUB of the children types
5762+ // would satisfy the constraints imposed by the shared parent
5763+ // instruction. This would require a version of ChildTyper that
5764+ // allows for generalizing type annotations.
57605765 ChildIterator ifFalseChildren (curr->ifFalse );
57615766 auto * ifTrueChild = *ifTrueChildren.begin ();
57625767 auto * ifFalseChild = *ifFalseChildren.begin ();
57635768 bool validTypes = ifTrueChild->type == ifFalseChild->type ;
57645769
5765- // In addition, after we move code outside of curr then we need to
5766- // not change unreachability - if we did, we'd need to propagate
5767- // that further, and we leave such work to DCE and Vacuum anyhow.
5768- // This can happen in something like this for example, where the
5769- // outer type changes from i32 to unreachable if we move the
5770- // returns outside:
5771- //
5772- // (if (result i32)
5773- // (local.get $x)
5774- // (return
5775- // (local.get $y)
5776- // )
5777- // (return
5778- // (local.get $z)
5779- // )
5780- // )
5781- assert (curr->ifTrue ->type == curr->ifFalse ->type );
5782- auto newOuterType = curr->ifTrue ->type ;
5783- if ((newOuterType == Type::unreachable) !=
5784- (curr->type == Type::unreachable)) {
5785- validTypes = false ;
5786- }
5787-
57885770 // If the expression we are about to move outside has side effects,
57895771 // then we cannot do so in general with a select: we'd be reducing
57905772 // the amount of the effects as well as moving them. For an if,
0 commit comments