-
Notifications
You must be signed in to change notification settings - Fork 695
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
Simplify br_if by removing its value operand. #681
Conversation
I don't quite follow. The design discussion you cite is not specific to Also, this question will be pretty much moot when we eliminate implicit dropping, which probably is the way to go. |
If you think it would simplify things even more, then perhaps we should also remove the value operand from all branches, in the MVP. The data in #667 shows that it wouldn't have a big impact on overall code size. Given time to properly design how this feature should work, and data demonstrating that it has significant value, we can reintroduce it. Also, I don't see how implicit dropping affects this. The |
Not simplify "more", but at all. ;) FWIW, I mentioned that very option on #677 a couple of days ago, where Alon replied "I certainly hope not". That other |
What's the problem with having |
Even if there were some small utility for returning the value argument from What's the harm in just making the current With For the predictor proposed to optimize the expressionless encoding, if a 'value' is written in order before the condition is written to a local variable then this value will be predicted to be the next value used, as if it were returned from |
Hah, actually looking again, it appears we've actually already implemented |
@lukewagner Re 'obvious/symmetric thing to do', it's like branching in a stack machine in which case the target and fall-through both have the same number of values on the stack, and accepting value(s) to the break operators gives something similar but on the implicit expression value stack. But in wasm without multiple-value expressions we can not have two or more values on this stack, and for example have the target and fall-through push another value and then make a call consuming these. The predictor for the expressionless encoding assumes a stack-like allocation so could achieve good prediction hits for such cases, and if there's a miss it is a small cost as operators accept immediate local variables, and it can be easily decoded into uses of local variables rather than a stack machine. |
The data in Making |
@sunfishcode Re 'no other language or bytecode or ISA I know of has conditional branches with value operands as wasm does': viewing the wasm expressions as a stack with restricted use, then CIL is a bytecode example that allows a conditional branch with values on the stack which could encode a wasm |
Just to give a concrete example:
could be expressed in a stack machine as:
|
I think you can look at branches with values as phis. More specifically, if A branches either to B with a value, or otherwise continues to C without a value, then at B we would have a phi (consisting of all the other paths branching into B), and C would not have any phis. In that perspective, I don't think there's anything odd about a conditional br with a value. The value "belongs" to the phi, which belongs to the target, not to the brancher. And everything branching to the target will provide a value, and so we have proper symmetry. Instead of SSA form and phis, though, we have non-SSA locals and branches. But the parallel is there. And there is precedent even without the parallel, in Swift, which has SSA form but no phis, instead it has basic block arguments - branches are like calls in that they provide values that are received on the other side. A br with a value is pretty much that. And that's the same with or without a condition on the br. |
@kripken The Swift blocks sound similar to https://github.com/stoklund/cretonne/blob/master/docs/langref.rst But this has separate SSA variables, plus the locals (local stack), and the wasm expression results seem to match the SSA variables. It also claims to be able to convert uses of the locals into SSA form which is what the expressionless wasm encoding depends on and thus has no need for the SSA variables. The question is what is the most compact encoding to get the job done here, and with a low complexity for the runtime, and while not being too complicated to decode to something readable? |
On 2 May 2016 at 21:01, Luke Wagner notifications@github.com wrote:
That was #237. We deferred it because of technicalities with break typing However, isn't this feature obsolete if we want to go down the explicit |
@kripken I agree that phis and wasm's @JSStats That's a good example, and if @rossberg-chromium My understanding of the explicit dropping idea is that it's fairly orthogonal to this issue. Having more values in more places might require more explicit drops, but are there other interactions? |
@sunfishcode, well, our assumption so far was that explicit dropping is only feasible if we reduce the number of "spurious" non-void operators, particularly those whose result isn't providing any information. That includes sets and stores, but clearly, |
@rossberg-chromium You won't need to explicitly drop |
@lukewagner, I don't think that is the relevant metric. The interesting metric is: the percentage of br_if uses of arity 1 whose return value is actually used. If that is way below, say, 30% (implying that way above 70% would require a drop), then it doesn't make sense to return the value by default. Rather, have those few cases fall back to whatever more general mechanism we'll provide to consume a value multiple times. |
@rossberg-chromium Yes, but I think we'll have a hard time convincing ourselves that we have a reliable measurement of that metric. I feel much more confident that branch-with-value is going to be rare which, if anything, supports the original point of this issue that maybe we should, as with multi-value, hold off committing to anything (by fixing arity=0) until we have a better understanding of how code generators can actually use these features. |
@rossberg-chromium
Sounds interesting, where is that being discussed? |
There are interesting discussions here about fixing the underlying issue here by having
|
If Otherwise making a change now seems premature, especially given dropping might be a discussion coming up soon. And removing values from |
It's a question of priorities, I suppose. Closing this, to wait for drop operators, at which point I'll re-evaluate where we are and consider a new proposal. |
#677 is the latest in a long and complex discussion (WebAssembly/spec#179, WebAssembly/spec#180, WebAssembly/spec#271, and others) about how to impose high-level typing rules on an assembly-style branch instruction. I and several other people actively involved in WebAssembly's design have been confused about what the rules are, which is not auspicious for its broader adventures.
The current state, where
br_if
has a value operand, but no return value, may satisfy certain properties relevant to the high-level typing system, but it is awkward from an assembly perspective, which is the perspective that motivated the instruction in the first place. It's essentially creating an optimized path for the case where a value is live on the branch-taken side of the branch but not the fallthrough side.The bigger picture is that I don't think we've had the appropriate chance to figure out how we really want this instruction to work. I propose that
br_if
's arity be limited to 0 in the MVP. We can change it to permit 1 in the future when we work out how we want it to work.Addressing the concern of code size, the numbers being quoted for block return values in general are in the neighborhood of 1%. I don't know the specific fraction of that which involves
br_if
, but even in the worst case, I claim this is rounding error when compared to the broader concern of designing a clean language.