Skip to content
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

Which forms of extending loads and truncating stores do we want? #139

Closed
sunfishcode opened this issue Jun 10, 2015 · 12 comments
Closed

Which forms of extending loads and truncating stores do we want? #139

sunfishcode opened this issue Jun 10, 2015 · 12 comments
Milestone

Comments

@sunfishcode
Copy link
Member

#135 adds a Load[Int64] and Store[Int64] which presumably load and store with a 64-bit memory location with no extension or truncation. If we do nothing else, we should clarify that this is the case, but we may also consider the following:

Split Load into Int32Load, Int64Load, Float32Load, Float64Load. They'd still support memory types (though the float versions would only support float memory types, and integer versions would only support integer types). This would:

  • make a very clean way to have 8-bit and 16-bit loads which extend directly to Int64, so you don't have to do a 32-bit extending load and then separately extend to Int64
  • add support for a single-operation 32-bit Load that extends to Int64
  • make a nice space for Float16 loads that directly promote to Float32 or Float64 in the future
  • minimize unnecessary differences between 32-bit code and 64-bit code

And analogous changes for Store.

I imagine the main argument against this will be redundancy in functionality. Why have operations that can be built out of other operations and pattern-matched in implementations (since it's often a single instruction)? My answers are that these operators will be very commonly used, and so they will be appreciated by humans reading the code, and they'll be easier for very-simple implementations to emit good code for.

@jfbastien jfbastien added this to the Public Announcement milestone Jun 10, 2015
@MikeHolman
Copy link
Member

Seems reasonable, but wouldn't we still need opcodes for each legal permutation? If so I think we should still enumerate them. If this does impact opcode space I think we should limit the permutations further than you are suggesting, because for example Int32Load[Uint64] is unnecessary.

@lukewagner
Copy link
Member

FWIW, having module-local index spaces should allow the compiler to order ops so that all the hot ops take a single byte (assuming a variable-length encoding of opcodes)). This is what makes me less worried about bloating our opcode space.

@MikeHolman
Copy link
Member

Yeah, and I'm not all that concerned about opcode space (probably shouldn't have mentioned it), but I'd still prefer we avoid adding ops which are completely useless.

@lukewagner
Copy link
Member

Definitely agreed about not having "dead" ops.

@titzer
Copy link

titzer commented Jun 11, 2015

On Wed, Jun 10, 2015 at 9:15 PM, Dan Gohman notifications@github.com
wrote:

#135 WebAssembly/spec#135 adds a Load[Int64]
and Store[Int64] which presumably load and store with a 64-bit memory
location with no extension or truncation. If we do nothing else, we should
clarify that this is the case, but we may also consider the following:

Split Load into Int32Load, Int64Load, Float32Load, Float64Load. They'd
still support memory types (though the float versions would only support
float memory types, and integer versions would only support integer types).
This would:

That sounds reasonable for the heap, since there is one load per local
type. What about loading from globals? Right now they have a specified
memory type. It seems like we'd still need to have either local
extend/truncate operations for them or have Int32LoadGlobal,
Int64LoadGlobal, etc.

  • make a very clean way to have 8-bit and 16-bit loads which extend
    directly to Int64, so you don't have to do a 32-bit extending load and then
    separately extend to Int64
  • add support for a single-operation 32-bit Load that extends to Int64
  • make a nice space for Float16 loads that directly promote to Float32
    or Float64 in the future
  • minimize unnecessary differences between 32-bit code and 64-bit code

And analogous changes for Store.

I imagine the main argument against this will be redundancy in
functionality. Why have operations that can be built out of other
operations and pattern-matched in implementations (since it's often a
single instruction)? My answers are that these operators will be very
commonly used, and so they will be appreciated by humans reading the code,
and they'll be easier for very-simple implementations to emit good code for.


Reply to this email directly or view it on GitHub
WebAssembly/spec#139.

@lukewagner
Copy link
Member

My expectation is that global variables would have (misnamed, perhaps) local types, not memory types.

@titzer
Copy link

titzer commented Jun 11, 2015

On Thu, Jun 11, 2015 at 8:21 AM, Luke Wagner notifications@github.com
wrote:

My expectation is that global variables would have (misnamed, perhaps)
local types, not memory types.

Is there any particular reason for that? One view is that accesses to them
logically are loads and stores to memory, since they will need atomicity
annotations in the future.


Reply to this email directly or view it on GitHub
#139 (comment).

@lukewagner
Copy link
Member

Good point. For MVP, I expect we don't even really need globals; before dynamic loading (and thus the need for a GOT), the only advantage they have is that they can't be aliased by loads/stores, but I expect that's insignificant (LLVM will have already taken advantage of this).

Once we have dynamic loading, the question is how to efficiently implement global data since you can't have modules just sticking their globals at fixed offsets in memory. The more I think about it, the more I think about variations from what is currently in AstSemantics.md (e.g., having globals just be aliased names for locations in the full heap that are auto-relocated and thus more efficient than what you could do otherwise) so I wonder if we should just take globals out of the MVP and make them part of the dynamic linking feature (or threads, which also hit upon the same issues via TLS and I hope have a symmetric solution).

@jfbastien
Copy link
Member

@lukewagner sgtm.

I think TLS should be discussed separately from globals, though the solution may be similar. There are a bunch of different usecases for TLS, some of which we need to respect and some I hope to change.

Could you file bugs for both, capturing your thoughts?

@jfbastien jfbastien modified the milestones: MVP, Public Announcement Jun 12, 2015
@lukewagner
Copy link
Member

With globals split off (hopefully removed, if #154 makes sense), then that just leaves @MikeHolman's point about explicitly enumerating the set of ops instead of specifying a Cartesian product where some of the tuples don't make sense.

@titzer
Copy link

titzer commented Jun 12, 2015

At some point we want to make room for SIMD memory accesses, right? So it
seems like Load/Store are type polymorphic.

For loads, nother option is to make implicit extension/truncation dependent
be part of the "usage context" of the load. E.g.

Load[Int8] in a Int32 context => legal, implicit sign extension
Load[Uint8] in an Int64 context => legal, implicit zero extension
Load[Float32] in an Int32 context => illegal.

Since we already need to do verification when decoding, we could just allow
these implicit (int only) extensions.

On Fri, Jun 12, 2015 at 9:01 AM, Luke Wagner notifications@github.com
wrote:

With globals split off (hopefully removed, if #154
#154 makes sense), then
that just leaves @MikeHolman https://github.com/MikeHolman's point
about explicitly enumerating the set of ops instead of specifying a
Cartesian product where some of the tuples don't make sense.


Reply to this email directly or view it on GitHub
#139 (comment).

@sunfishcode
Copy link
Member Author

The SIMD loads won't have builtin conversions, so in the spec syntax we have at the moment, they'll look like int32x4.load[int32x4] and so on. It's possible that this will evolve further over time, but for now it looks like we have what we need.

With #175, we have the operators we want. Deciding how to encode them will be a topic for another day.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants