diff options
-rw-r--r-- | src/passes/AlignmentLowering.cpp | 178 | ||||
-rw-r--r-- | test/passes/alignment-lowering.txt | 1422 | ||||
-rw-r--r-- | test/passes/alignment-lowering.wast | 40 |
3 files changed, 1613 insertions, 27 deletions
diff --git a/src/passes/AlignmentLowering.cpp b/src/passes/AlignmentLowering.cpp index 818189056..26815b389 100644 --- a/src/passes/AlignmentLowering.cpp +++ b/src/passes/AlignmentLowering.cpp @@ -27,16 +27,15 @@ namespace wasm { struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> { - void visitLoad(Load* curr) { + // Core lowering of a 32-bit load: ensures it is done using aligned + // operations, which means we can leave it alone if it's already aligned, or + // else we break it up into smaller loads that are. + Expression* lowerLoadI32(Load* curr) { if (curr->align == 0 || curr->align == curr->bytes) { - return; + return curr; } Builder builder(*getModule()); - if (curr->type == Type::unreachable) { - replaceCurrent(curr->ptr); - return; - } - assert(curr->type == Type::i32); // TODO: i64, f32, f64 + assert(curr->type == Type::i32); auto temp = builder.addVar(getFunction(), Type::i32); Expression* ret; if (curr->bytes == 2) { @@ -125,21 +124,16 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> { } else { WASM_UNREACHABLE("invalid size"); } - replaceCurrent( - builder.makeBlock({builder.makeLocalSet(temp, curr->ptr), ret})); + return builder.makeBlock({builder.makeLocalSet(temp, curr->ptr), ret}); } - void visitStore(Store* curr) { + // Core lowering of a 32-bit store. + Expression* lowerStoreI32(Store* curr) { if (curr->align == 0 || curr->align == curr->bytes) { - return; + return curr; } Builder builder(*getModule()); - if (curr->type == Type::unreachable) { - replaceCurrent(builder.makeBlock( - {builder.makeDrop(curr->ptr), builder.makeDrop(curr->value)})); - return; - } - assert(curr->value->type == Type::i32); // TODO: i64, f32, f64 + assert(curr->value->type == Type::i32); auto tempPtr = builder.addVar(getFunction(), Type::i32); auto tempValue = builder.addVar(getFunction(), Type::i32); auto* block = @@ -222,7 +216,155 @@ struct AlignmentLowering : public WalkerPass<PostWalker<AlignmentLowering>> { WASM_UNREACHABLE("invalid size"); } block->finalize(); - replaceCurrent(block); + return block; + } + + void visitLoad(Load* curr) { + // If unreachable, just remove the load, which removes the unaligned + // operation in a trivial way. + if (curr->type == Type::unreachable) { + replaceCurrent(curr->ptr); + return; + } + if (curr->align == 0 || curr->align == curr->bytes) { + // Nothing to do: leave the node unchanged. All code lower down assumes + // the operation is unaligned. + return; + } + Builder builder(*getModule()); + auto type = curr->type.getSingle(); + Expression* replacement; + switch (type) { + default: + WASM_UNREACHABLE("unhandled unaligned load"); + case Type::i32: + replacement = lowerLoadI32(curr); + break; + case Type::f32: + curr->type = Type::i32; + replacement = builder.makeUnary(ReinterpretInt32, lowerLoadI32(curr)); + break; + case Type::i64: + case Type::f64: + if (type == Type::i64 && curr->bytes != 8) { + // A load of <64 bits. + curr->type = Type::i32; + replacement = builder.makeUnary( + curr->signed_ ? ExtendSInt32 : ExtendUInt32, lowerLoadI32(curr)); + break; + } + // Load two 32-bit pieces, and combine them. + auto temp = builder.addVar(getFunction(), Type::i32); + auto* set = builder.makeLocalSet(temp, curr->ptr); + Expression* low = + lowerLoadI32(builder.makeLoad(4, + false, + curr->offset, + curr->align, + builder.makeLocalGet(temp, Type::i32), + Type::i32)); + low = builder.makeUnary(ExtendUInt32, low); + // Note that the alignment is assumed to be the same here, even though + // we add an offset of 4. That is because this is an unaligned load, so + // the alignment is 1, 2, or 4, which means it stays the same after + // adding 4. + Expression* high = + lowerLoadI32(builder.makeLoad(4, + false, + curr->offset + 4, + curr->align, + builder.makeLocalGet(temp, Type::i32), + Type::i32)); + high = builder.makeUnary(ExtendUInt32, high); + high = + builder.makeBinary(ShlInt64, high, builder.makeConst(int64_t(32))); + auto* combined = builder.makeBinary(OrInt64, low, high); + replacement = builder.makeSequence(set, combined); + // Ensure the proper output type. + if (type == Type::f64) { + replacement = builder.makeUnary(ReinterpretInt64, replacement); + } + break; + } + replaceCurrent(replacement); + } + + void visitStore(Store* curr) { + Builder builder(*getModule()); + // If unreachable, just remove the store, which removes the unaligned + // operation in a trivial way. + if (curr->type == Type::unreachable) { + replaceCurrent(builder.makeBlock( + {builder.makeDrop(curr->ptr), builder.makeDrop(curr->value)})); + return; + } + if (curr->align == 0 || curr->align == curr->bytes) { + // Nothing to do: leave the node unchanged. All code lower down assumes + // the operation is unaligned. + return; + } + auto type = curr->value->type.getSingle(); + Expression* replacement; + switch (type) { + default: + WASM_UNREACHABLE("unhandled unaligned store"); + case Type::i32: + replacement = lowerStoreI32(curr); + break; + case Type::f32: + curr->type = Type::i32; + curr->value = builder.makeUnary(ReinterpretFloat32, curr->value); + replacement = lowerStoreI32(curr); + break; + case Type::i64: + case Type::f64: + if (type == Type::i64 && curr->bytes != 8) { + // A store of <64 bits. + curr->type = Type::i32; + curr->value = builder.makeUnary(WrapInt64, curr->value); + replacement = lowerStoreI32(curr); + break; + } + // Otherwise, fall through to f64 case for a 64-bit load. + // Ensure an integer input value. + auto* value = curr->value; + if (type == Type::f64) { + value = builder.makeUnary(ReinterpretFloat64, value); + } + // Store as two 32-bit pieces. + auto tempPtr = builder.addVar(getFunction(), Type::i32); + auto* setPtr = builder.makeLocalSet(tempPtr, curr->ptr); + auto tempValue = builder.addVar(getFunction(), Type::i64); + auto* setValue = builder.makeLocalSet(tempValue, value); + Expression* low = builder.makeUnary( + WrapInt64, builder.makeLocalGet(tempValue, Type::i64)); + low = lowerStoreI32( + builder.makeStore(4, + curr->offset, + curr->align, + builder.makeLocalGet(tempPtr, Type::i32), + low, + Type::i32)); + Expression* high = + builder.makeBinary(ShrUInt64, + builder.makeLocalGet(tempValue, Type::i64), + builder.makeConst(int64_t(32))); + high = builder.makeUnary(WrapInt64, high); + // Note that the alignment is assumed to be the same here, even though + // we add an offset of 4. That is because this is an unaligned store, so + // the alignment is 1, 2, or 4, which means it stays the same after + // adding 4. + high = lowerStoreI32( + builder.makeStore(4, + curr->offset + 4, + curr->align, + builder.makeLocalGet(tempPtr, Type::i32), + high, + Type::i32)); + replacement = builder.makeBlock({setPtr, setValue, low, high}); + break; + } + replaceCurrent(replacement); } }; diff --git a/test/passes/alignment-lowering.txt b/test/passes/alignment-lowering.txt index b3e276a9f..0ea97136f 100644 --- a/test/passes/alignment-lowering.txt +++ b/test/passes/alignment-lowering.txt @@ -437,9 +437,7 @@ ) ) (drop - (i32.load offset=100 - (unreachable) - ) + (unreachable) ) (i32.store8 (i32.const 4) @@ -457,13 +455,21 @@ (i32.const 4) (i32.const 8) ) - (i32.store8 offset=100 - (unreachable) - (i32.const 8) + (block + (drop + (unreachable) + ) + (drop + (i32.const 8) + ) ) - (i32.store8 offset=100 - (i32.const 4) - (unreachable) + (block + (drop + (i32.const 4) + ) + (drop + (unreachable) + ) ) ) (func $func_signed @@ -541,4 +547,1402 @@ (unreachable) ) ) + (func $i64-load + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i32) + (drop + (block (result i64) + (local.set $0 + (i32.const 12) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $1 + (local.get $0) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $1) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $1) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $1) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $1) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $2 + (local.get $0) + ) + (i32.or + (i32.or + (i32.load8_u offset=4 + (local.get $2) + ) + (i32.shl + (i32.load8_u offset=5 + (local.get $2) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=6 + (local.get $2) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=7 + (local.get $2) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + (drop + (block (result i64) + (local.set $3 + (i32.const 16) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $4 + (local.get $3) + ) + (i32.or + (i32.load16_u + (local.get $4) + ) + (i32.shl + (i32.load16_u offset=2 + (local.get $4) + ) + (i32.const 16) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $5 + (local.get $3) + ) + (i32.or + (i32.load16_u offset=4 + (local.get $5) + ) + (i32.shl + (i32.load16_u offset=6 + (local.get $5) + ) + (i32.const 16) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + (drop + (block (result i64) + (local.set $6 + (i32.const 20) + ) + (i64.or + (i64.extend_i32_u + (i32.load + (local.get $6) + ) + ) + (i64.shl + (i64.extend_i32_u + (i32.load offset=4 + (local.get $6) + ) + ) + (i64.const 32) + ) + ) + ) + ) + (drop + (block (result i64) + (local.set $7 + (i32.const 20) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $8 + (local.get $7) + ) + (i32.or + (i32.or + (i32.load8_u offset=3 + (local.get $8) + ) + (i32.shl + (i32.load8_u offset=4 + (local.get $8) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=5 + (local.get $8) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=6 + (local.get $8) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $9 + (local.get $7) + ) + (i32.or + (i32.or + (i32.load8_u offset=7 + (local.get $9) + ) + (i32.shl + (i32.load8_u offset=8 + (local.get $9) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=9 + (local.get $9) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=10 + (local.get $9) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + (drop + (i64.extend_i32_s + (block (result i32) + (local.set $10 + (i32.const 28) + ) + (i32.shr_s + (i32.shl + (i32.or + (i32.load8_u + (local.get $10) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $10) + ) + (i32.const 8) + ) + ) + (i32.const 16) + ) + (i32.const 16) + ) + ) + ) + ) + (drop + (i64.extend_i32_s + (block (result i32) + (local.set $11 + (i32.const 32) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $11) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $11) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $11) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $11) + ) + (i32.const 24) + ) + ) + ) + ) + ) + ) + (drop + (i64.extend_i32_u + (block (result i32) + (local.set $12 + (i32.const 40) + ) + (i32.or + (i32.load8_u + (local.get $12) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $12) + ) + (i32.const 8) + ) + ) + ) + ) + ) + (drop + (i64.extend_i32_u + (block (result i32) + (local.set $13 + (i32.const 44) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $13) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $13) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $13) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $13) + ) + (i32.const 24) + ) + ) + ) + ) + ) + ) + ) + (func $f32-load + (local $0 i32) + (local $1 i32) + (local $2 i32) + (drop + (f32.reinterpret_i32 + (block (result i32) + (local.set $0 + (i32.const 12) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $0) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $0) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $0) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $0) + ) + (i32.const 24) + ) + ) + ) + ) + ) + ) + (drop + (f32.reinterpret_i32 + (block (result i32) + (local.set $1 + (i32.const 16) + ) + (i32.or + (i32.load16_u + (local.get $1) + ) + (i32.shl + (i32.load16_u offset=2 + (local.get $1) + ) + (i32.const 16) + ) + ) + ) + ) + ) + (drop + (f32.reinterpret_i32 + (block (result i32) + (local.set $2 + (i32.const 20) + ) + (i32.or + (i32.or + (i32.load8_u offset=3 + (local.get $2) + ) + (i32.shl + (i32.load8_u offset=4 + (local.get $2) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=5 + (local.get $2) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=6 + (local.get $2) + ) + (i32.const 24) + ) + ) + ) + ) + ) + ) + ) + (func $f64-load + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i32) + (local $8 i32) + (local $9 i32) + (drop + (f64.reinterpret_i64 + (block (result i64) + (local.set $0 + (i32.const 12) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $1 + (local.get $0) + ) + (i32.or + (i32.or + (i32.load8_u + (local.get $1) + ) + (i32.shl + (i32.load8_u offset=1 + (local.get $1) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=2 + (local.get $1) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=3 + (local.get $1) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $2 + (local.get $0) + ) + (i32.or + (i32.or + (i32.load8_u offset=4 + (local.get $2) + ) + (i32.shl + (i32.load8_u offset=5 + (local.get $2) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=6 + (local.get $2) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=7 + (local.get $2) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + ) + (drop + (f64.reinterpret_i64 + (block (result i64) + (local.set $3 + (i32.const 16) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $4 + (local.get $3) + ) + (i32.or + (i32.load16_u + (local.get $4) + ) + (i32.shl + (i32.load16_u offset=2 + (local.get $4) + ) + (i32.const 16) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $5 + (local.get $3) + ) + (i32.or + (i32.load16_u offset=4 + (local.get $5) + ) + (i32.shl + (i32.load16_u offset=6 + (local.get $5) + ) + (i32.const 16) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + ) + (drop + (f64.reinterpret_i64 + (block (result i64) + (local.set $6 + (i32.const 20) + ) + (i64.or + (i64.extend_i32_u + (i32.load + (local.get $6) + ) + ) + (i64.shl + (i64.extend_i32_u + (i32.load offset=4 + (local.get $6) + ) + ) + (i64.const 32) + ) + ) + ) + ) + ) + (drop + (f64.reinterpret_i64 + (block (result i64) + (local.set $7 + (i32.const 20) + ) + (i64.or + (i64.extend_i32_u + (block (result i32) + (local.set $8 + (local.get $7) + ) + (i32.or + (i32.or + (i32.load8_u offset=3 + (local.get $8) + ) + (i32.shl + (i32.load8_u offset=4 + (local.get $8) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=5 + (local.get $8) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=6 + (local.get $8) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.shl + (i64.extend_i32_u + (block (result i32) + (local.set $9 + (local.get $7) + ) + (i32.or + (i32.or + (i32.load8_u offset=7 + (local.get $9) + ) + (i32.shl + (i32.load8_u offset=8 + (local.get $9) + ) + (i32.const 8) + ) + ) + (i32.or + (i32.shl + (i32.load8_u offset=9 + (local.get $9) + ) + (i32.const 16) + ) + (i32.shl + (i32.load8_u offset=10 + (local.get $9) + ) + (i32.const 24) + ) + ) + ) + ) + ) + (i64.const 32) + ) + ) + ) + ) + ) + ) + (func $i64-store + (local $0 i32) + (local $1 i64) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i64) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i64) + (local $14 i32) + (local $15 i64) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (local $19 i32) + (local $20 i32) + (local $21 i32) + (local $22 i32) + (local $23 i32) + (block + (local.set $0 + (i32.const 12) + ) + (local.set $1 + (i64.const 100) + ) + (block + (local.set $2 + (local.get $0) + ) + (local.set $3 + (i32.wrap_i64 + (local.get $1) + ) + ) + (i32.store8 + (local.get $2) + (local.get $3) + ) + (i32.store8 offset=1 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 24) + ) + ) + ) + (block + (local.set $4 + (local.get $0) + ) + (local.set $5 + (i32.wrap_i64 + (i64.shr_u + (local.get $1) + (i64.const 32) + ) + ) + ) + (i32.store8 offset=4 + (local.get $4) + (local.get $5) + ) + (i32.store8 offset=5 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + (i32.store8 offset=6 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 16) + ) + ) + (i32.store8 offset=7 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 24) + ) + ) + ) + ) + (block + (local.set $6 + (i32.const 16) + ) + (local.set $7 + (i64.const 200) + ) + (block + (local.set $8 + (local.get $6) + ) + (local.set $9 + (i32.wrap_i64 + (local.get $7) + ) + ) + (i32.store16 + (local.get $8) + (local.get $9) + ) + (i32.store16 offset=2 + (local.get $8) + (i32.shr_u + (local.get $9) + (i32.const 16) + ) + ) + ) + (block + (local.set $10 + (local.get $6) + ) + (local.set $11 + (i32.wrap_i64 + (i64.shr_u + (local.get $7) + (i64.const 32) + ) + ) + ) + (i32.store16 offset=4 + (local.get $10) + (local.get $11) + ) + (i32.store16 offset=6 + (local.get $10) + (i32.shr_u + (local.get $11) + (i32.const 16) + ) + ) + ) + ) + (block + (local.set $12 + (i32.const 20) + ) + (local.set $13 + (i64.const 300) + ) + (i32.store + (local.get $12) + (i32.wrap_i64 + (local.get $13) + ) + ) + (i32.store offset=4 + (local.get $12) + (i32.wrap_i64 + (i64.shr_u + (local.get $13) + (i64.const 32) + ) + ) + ) + ) + (block + (local.set $14 + (i32.const 24) + ) + (local.set $15 + (i64.const 400) + ) + (block + (local.set $16 + (local.get $14) + ) + (local.set $17 + (i32.wrap_i64 + (local.get $15) + ) + ) + (i32.store8 offset=3 + (local.get $16) + (local.get $17) + ) + (i32.store8 offset=4 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 8) + ) + ) + (i32.store8 offset=5 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 16) + ) + ) + (i32.store8 offset=6 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 24) + ) + ) + ) + (block + (local.set $18 + (local.get $14) + ) + (local.set $19 + (i32.wrap_i64 + (i64.shr_u + (local.get $15) + (i64.const 32) + ) + ) + ) + (i32.store8 offset=7 + (local.get $18) + (local.get $19) + ) + (i32.store8 offset=8 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 8) + ) + ) + (i32.store8 offset=9 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 16) + ) + ) + (i32.store8 offset=10 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 24) + ) + ) + ) + ) + (block + (local.set $20 + (i32.const 20) + ) + (local.set $21 + (i32.wrap_i64 + (i64.const 600) + ) + ) + (i32.store8 + (local.get $20) + (local.get $21) + ) + (i32.store8 offset=1 + (local.get $20) + (i32.shr_u + (local.get $21) + (i32.const 8) + ) + ) + ) + (block + (local.set $22 + (i32.const 20) + ) + (local.set $23 + (i32.wrap_i64 + (i64.const 700) + ) + ) + (i32.store8 + (local.get $22) + (local.get $23) + ) + (i32.store8 offset=1 + (local.get $22) + (i32.shr_u + (local.get $23) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $22) + (i32.shr_u + (local.get $23) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $22) + (i32.shr_u + (local.get $23) + (i32.const 24) + ) + ) + ) + ) + (func $f32-store + (local $0 i32) + (local $1 i32) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (block + (local.set $0 + (i32.const 12) + ) + (local.set $1 + (i32.reinterpret_f32 + (f32.const 100) + ) + ) + (i32.store8 + (local.get $0) + (local.get $1) + ) + (i32.store8 offset=1 + (local.get $0) + (i32.shr_u + (local.get $1) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $0) + (i32.shr_u + (local.get $1) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $0) + (i32.shr_u + (local.get $1) + (i32.const 24) + ) + ) + ) + (block + (local.set $2 + (i32.const 16) + ) + (local.set $3 + (i32.reinterpret_f32 + (f32.const 200) + ) + ) + (i32.store16 + (local.get $2) + (local.get $3) + ) + (i32.store16 offset=2 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 16) + ) + ) + ) + (block + (local.set $4 + (i32.const 24) + ) + (local.set $5 + (i32.reinterpret_f32 + (f32.const 400) + ) + ) + (i32.store8 offset=3 + (local.get $4) + (local.get $5) + ) + (i32.store8 offset=4 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + (i32.store8 offset=5 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 16) + ) + ) + (i32.store8 offset=6 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 24) + ) + ) + ) + ) + (func $f64-store + (local $0 i32) + (local $1 i64) + (local $2 i32) + (local $3 i32) + (local $4 i32) + (local $5 i32) + (local $6 i32) + (local $7 i64) + (local $8 i32) + (local $9 i32) + (local $10 i32) + (local $11 i32) + (local $12 i32) + (local $13 i64) + (local $14 i32) + (local $15 i64) + (local $16 i32) + (local $17 i32) + (local $18 i32) + (local $19 i32) + (block + (local.set $0 + (i32.const 12) + ) + (local.set $1 + (i64.reinterpret_f64 + (f64.const 100) + ) + ) + (block + (local.set $2 + (local.get $0) + ) + (local.set $3 + (i32.wrap_i64 + (local.get $1) + ) + ) + (i32.store8 + (local.get $2) + (local.get $3) + ) + (i32.store8 offset=1 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 8) + ) + ) + (i32.store8 offset=2 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 16) + ) + ) + (i32.store8 offset=3 + (local.get $2) + (i32.shr_u + (local.get $3) + (i32.const 24) + ) + ) + ) + (block + (local.set $4 + (local.get $0) + ) + (local.set $5 + (i32.wrap_i64 + (i64.shr_u + (local.get $1) + (i64.const 32) + ) + ) + ) + (i32.store8 offset=4 + (local.get $4) + (local.get $5) + ) + (i32.store8 offset=5 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 8) + ) + ) + (i32.store8 offset=6 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 16) + ) + ) + (i32.store8 offset=7 + (local.get $4) + (i32.shr_u + (local.get $5) + (i32.const 24) + ) + ) + ) + ) + (block + (local.set $6 + (i32.const 16) + ) + (local.set $7 + (i64.reinterpret_f64 + (f64.const 200) + ) + ) + (block + (local.set $8 + (local.get $6) + ) + (local.set $9 + (i32.wrap_i64 + (local.get $7) + ) + ) + (i32.store16 + (local.get $8) + (local.get $9) + ) + (i32.store16 offset=2 + (local.get $8) + (i32.shr_u + (local.get $9) + (i32.const 16) + ) + ) + ) + (block + (local.set $10 + (local.get $6) + ) + (local.set $11 + (i32.wrap_i64 + (i64.shr_u + (local.get $7) + (i64.const 32) + ) + ) + ) + (i32.store16 offset=4 + (local.get $10) + (local.get $11) + ) + (i32.store16 offset=6 + (local.get $10) + (i32.shr_u + (local.get $11) + (i32.const 16) + ) + ) + ) + ) + (block + (local.set $12 + (i32.const 20) + ) + (local.set $13 + (i64.reinterpret_f64 + (f64.const 300) + ) + ) + (i32.store + (local.get $12) + (i32.wrap_i64 + (local.get $13) + ) + ) + (i32.store offset=4 + (local.get $12) + (i32.wrap_i64 + (i64.shr_u + (local.get $13) + (i64.const 32) + ) + ) + ) + ) + (block + (local.set $14 + (i32.const 24) + ) + (local.set $15 + (i64.reinterpret_f64 + (f64.const 400) + ) + ) + (block + (local.set $16 + (local.get $14) + ) + (local.set $17 + (i32.wrap_i64 + (local.get $15) + ) + ) + (i32.store8 offset=3 + (local.get $16) + (local.get $17) + ) + (i32.store8 offset=4 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 8) + ) + ) + (i32.store8 offset=5 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 16) + ) + ) + (i32.store8 offset=6 + (local.get $16) + (i32.shr_u + (local.get $17) + (i32.const 24) + ) + ) + ) + (block + (local.set $18 + (local.get $14) + ) + (local.set $19 + (i32.wrap_i64 + (i64.shr_u + (local.get $15) + (i64.const 32) + ) + ) + ) + (i32.store8 offset=7 + (local.get $18) + (local.get $19) + ) + (i32.store8 offset=8 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 8) + ) + ) + (i32.store8 offset=9 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 16) + ) + ) + (i32.store8 offset=10 + (local.get $18) + (i32.shr_u + (local.get $19) + (i32.const 24) + ) + ) + ) + ) + ) ) diff --git a/test/passes/alignment-lowering.wast b/test/passes/alignment-lowering.wast index 135fd281e..bbfdd5cb2 100644 --- a/test/passes/alignment-lowering.wast +++ b/test/passes/alignment-lowering.wast @@ -60,4 +60,44 @@ (drop (i32.load16_s offset=100 align=2 (i32.const 4))) (drop (i32.load16_s offset=100 align=1 (unreachable))) ) + (func $i64-load + (drop (i64.load align=1 (i32.const 12))) + (drop (i64.load align=2 (i32.const 16))) + (drop (i64.load align=4 (i32.const 20))) + (drop (i64.load align=1 offset=3 (i32.const 20))) + (drop (i64.load16_s align=1 (i32.const 28))) + (drop (i64.load32_s align=1 (i32.const 32))) + (drop (i64.load16_u align=1 (i32.const 40))) + (drop (i64.load32_u align=1 (i32.const 44))) + ) + (func $f32-load + (drop (f32.load align=1 (i32.const 12))) + (drop (f32.load align=2 (i32.const 16))) + (drop (f32.load align=1 offset=3 (i32.const 20))) + ) + (func $f64-load + (drop (f64.load align=1 (i32.const 12))) + (drop (f64.load align=2 (i32.const 16))) + (drop (f64.load align=4 (i32.const 20))) + (drop (f64.load align=1 offset=3 (i32.const 20))) + ) + (func $i64-store + (i64.store align=1 (i32.const 12) (i64.const 100)) + (i64.store align=2 (i32.const 16) (i64.const 200)) + (i64.store align=4 (i32.const 20) (i64.const 300)) + (i64.store align=1 offset=3 (i32.const 24) (i64.const 400)) + (i64.store16 align=1 (i32.const 20) (i64.const 600)) + (i64.store32 align=1 (i32.const 20) (i64.const 700)) + ) + (func $f32-store + (f32.store align=1 (i32.const 12) (f32.const 100)) + (f32.store align=2 (i32.const 16) (f32.const 200)) + (f32.store align=1 offset=3 (i32.const 24) (f32.const 400)) + ) + (func $f64-store + (f64.store align=1 (i32.const 12) (f64.const 100)) + (f64.store align=2 (i32.const 16) (f64.const 200)) + (f64.store align=4 (i32.const 20) (f64.const 300)) + (f64.store align=1 offset=3 (i32.const 24) (f64.const 400)) + ) ) |