-
Notifications
You must be signed in to change notification settings - Fork 694
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
Support int8 and int16? #85
Comments
I think we should support all the numeric types, but it's fine to promote them internally to machine int sized registers. It will enable packing in cases where you want to pack, and more importantly if we introduce typed objects or equivalent, at that point those types will enter our domain anyway. This also eliminates the need to patternmatch a bunch of different things. Java's decision to not have unsigned types was a huge mistake. We shouldn't repeat anything of the sort by leaving out key, frequently-used primitives (like bytes). |
I agree, makes sense to add these. It does make the polyfill to JS a little more complex, but it makes wasm more of a "normal" platform. |
-Filip |
-Filip |
I think you can compile wasm just fine if it only includes 32-bit/64-bit int math. In fact, it would be easier. Then it would be up to the wasm generator to legalize small-int math up to 32-bit math, and to do so without any obvious badness.
-Filip |
I agree with @pizlonator. I think it would be easier to exclude int8/int16, and I don't really see the benefit. From wasm->machine code side of things it would certainly be harder for us if we had them. Our backend already has good support for int32s, and adding int8/int16 would certainly require additional work to reach the same code quality. Of course this is a JS engine centric view, so I'm willing to concede that isn't a great reason against them in a general sense, but it certainly isn't a reason for including them. I'd like to see something a little more compelling before we commit to adding int8/int16. |
On Wed, May 27, 2015 at 8:28 PM, K. Gadd notifications@github.com wrote:
Bytes are not left out; they're memory types. When you load from memory And unsigned arithmetic and comparisons are supported under the current —
|
On Thu, May 28, 2015 at 7:33 AM, Michael Holman notifications@github.com
For background, I did a lot of work for Virgil to support arbitrary I view 8- and 16-bit math as special cases of the above, and WebAssembly as
|
Wait, are we talking about N-bit math or N-bit data types here? The original issue text did not suggest we were talking about introducing things like a 16-bit signed add or a 16-bit unsigned add.
I am profoundly confused by this question, sorry. Bytes are an extremely common unsigned 8-bit integer type that's used in all sorts of applications. You can store your bytes into int32s, of course, but the actual memory operations are 8bit and you're truncating to 8bit. Is it implied/assumed that webasm already solves all these scenarios in a different way? I don't remember seeing this addressed in the draft specs here when I last read them, but maybe I overlooked something.
I'm not clear on what this means or how it interacts with the question of whether things like an int16 type exist. As I understand it here, the point of say, an int16 type is that it makes things like truncation, sign extension and load/store clearer, and in the future when we inevitably support known object layouts (typed objects) we will have those types enter our type system anyway. They also matter when interfacing with the outside world - the type of What is a 'memory type'? Do we have a separate set of types and type hierarchy for 'memory types' that is different from the types of values that exist in other contexts? Do we have a set of rules that govern how memory types interact with non-memory types? I am having a really hard time comprehending how this would work. Promoting to a larger size for arithmetic seems like the obvious choice here - isn't that typically what happens in native runtime environments these days to begin with? For real world applications you're going to see a bunch of non-32bit sized loads/stores, truncations, etc. Maybe less in certain types of applications. If we have to patternmatch to do the 'right thing' with those operations, and end up introducing the types later on anyway, that'll be really regrettable. |
Instead of editing in, I'm just going to follow up to say that I grepped for 'memory types' and found a relevant section that I hadn't seen before. I still find this partitioning confusing but it's at least clearly described. Given the presence of the full set of types in the 'memory types' list I'm actually profoundly confused about what this issue is actually addressing. Are we talking about adding arithmetic variants that operate natively on each type, adding them to the supported set of local types but doing arithmetic with implicit promotion (i.e. C#, C++, etc), or something else? |
On Thu, May 28, 2015 at 2:43 PM, K. Gadd notifications@github.com wrote:
-B
|
If every context for values other than locals supports the full set of types, I don't see any major problem with having all arithmetic operate on 32-bit (or 64-bit) operands. I'm not clear on how unsigned would fit into the picture but I remember that already being addressed for 32-bit operands. There are existing environments that don't define arithmetic for types smaller than 32 bits; the one I'm most familiar with promotes all arithmetic to 32-bit int (or a suitable larger type) and expects you to manually truncate or cast when writing a result back into a smaller type. We should consider whether we want to provide simple truncation intrinsics for each type, since truncation will happen during arithmetic instead of just at the point where a value is stored into the heap. However, that may be relatively uncommon compared to the truncation at heap stores, which we've folded into the stores themselves. If we do allow structured types in locals eventually that will compromise a lot of this, but we wouldn't be allowing arithmetic on those (they'd be function calls) so that wouldn't have the downsides we want to avoid here, I think. How does the 'memory type' / local type split affect applications like the typical emscripten output that emulate a stack by writing into a reserved section of the heap? Are we fine with how all of that works out here? In that case we basically have pseudo-locals that are of memory types, but they constantly get promoted and truncated when being moved onto/off of the stack. That seems like it could get really gross. |
Agreed with @MikeHolman, @pizlonator and @titzer on not wanting int8/int16 as local types w/ all their own arithmetic; just the memory types (ideally w/ built-in sign-/zero-extension/truncation, in my view) seem sufficient. |
I wonder if there is a sense in LLVM that it should not have |
On Thu, May 28, 2015 at 11:02 AM Alon Zakai notifications@github.com
|
Exotic types like i3 and i1337 have uses for high-to-mid-level optimization (e.g. LLVM's optimizer), because they preserve a little more value range information. However, they must be lowered for codegen (e.g. WebAssembly) on any common hardware. Types like i8 and i16 are less exotic, however many platforms don't have i8 or i16 arithmetic at all, and even on x86 which does have them, i16 arithmetic tends to be slow anyway, and i8 arithmetic is only occasionally faster than i32 arithmetic. But even then, C's promotion rules mean that all arithmetic is done at "int" width or wider by default, so codegen only ever sees i8 arithmetic when the optimizer has proven it safe to form. And in those cases, lowering i8 values to i32 usually leaves behind enough hints that a reasonably clever code generator can see that only 8 bits are needed and optimize to 8-bit arithmetic anyway. I think the main arguments for WebAssembly to have i8 and i16 would be that we wouldn't need sign/zero-extending loads and truncating stores, and there'd be a little closer symmetry between SIMD types and scalar types (since SIMD will have 8-bit and 16-bit integer element types). However, since these types aren't actually that useful in scalar, it seems like a greater simplification to just omit them. |
Closing, based on the rationale in the previous comment. If anyone wants to revisit this, we can reopen or open a new issue. |
Should Web Assembly explicitly support int8 and int16?
We've discussed this:
A few thoughts:
We can also add these types to a later version of Web Assembly if just int32 / int64 prove insufficient.
The text was updated successfully, but these errors were encountered: