diff options
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 28 | ||||
-rw-r--r-- | test/emcc_hello_world.fromasm | 300 | ||||
-rw-r--r-- | test/emcc_hello_world.fromasm.imprecise | 300 | ||||
-rw-r--r-- | test/passes/optimize-instructions.txt | 77 | ||||
-rw-r--r-- | test/passes/optimize-instructions.wast | 15 |
5 files changed, 342 insertions, 378 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index f467b395e..7547f332a 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -223,6 +223,19 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions, return Builder(*getModule()).makeUnary(EqZInt32, binary->right); } } + } else if (binary->op == AndInt32) { + if (auto* load = binary->left->dynCast<Load>()) { + if (auto* right = binary->right->dynCast<Const>()) { + if (right->type == i32) { + auto mask = right->value.geti32(); + if ((load->bytes == 1 && mask == 0xff) || + (load->bytes == 2 && mask == 0xffff)) { + load->signed_ = false; + return load; + } + } + } + } } } else if (auto* unary = curr->dynCast<Unary>()) { // de-morgan's laws @@ -294,6 +307,21 @@ struct OptimizeInstructions : public WalkerPass<PostWalker<OptimizeInstructions, if (br->condition) { br->condition = optimizeBoolean(br->condition); } + } else if (auto* store = curr->dynCast<Store>()) { + // stores of fewer bits truncates anyhow + if (auto* value = store->value->dynCast<Binary>()) { + if (value->op == AndInt32) { + if (auto* right = value->right->dynCast<Const>()) { + if (right->type == i32) { + auto mask = right->value.geti32(); + if ((store->bytes == 1 && mask == 0xff) || + (store->bytes == 2 && mask == 0xffff)) { + store->value = value->left; + } + } + } + } + } } return nullptr; } diff --git a/test/emcc_hello_world.fromasm b/test/emcc_hello_world.fromasm index ddcd0c5de..e5f68f021 100644 --- a/test/emcc_hello_world.fromasm +++ b/test/emcc_hello_world.fromasm @@ -314,11 +314,8 @@ (loop $while-in (br_if $jumpthreading$inner$0 (i32.eq - (i32.and - (i32.load8_s offset=687 - (get_local $1) - ) - (i32.const 255) + (i32.load8_u offset=687 + (get_local $1) ) (get_local $0) ) @@ -1651,15 +1648,12 @@ ) (i32.store8 (get_local $2) - (i32.and - (i32.or - (i32.add - (get_local $1) - (i32.const 255) - ) + (i32.or + (i32.add (get_local $1) + (i32.const 255) ) - (i32.const 255) + (get_local $1) ) ) (if i32 @@ -1728,10 +1722,7 @@ (block (i32.store8 (get_local $0) - (i32.and - (get_local $1) - (i32.const 255) - ) + (get_local $1) ) (br $do-once (i32.const 1) @@ -1746,28 +1737,22 @@ (block (i32.store8 (get_local $0) - (i32.and - (i32.or - (i32.shr_u - (get_local $1) - (i32.const 6) - ) - (i32.const 192) + (i32.or + (i32.shr_u + (get_local $1) + (i32.const 6) ) - (i32.const 255) + (i32.const 192) ) ) (i32.store8 offset=1 (get_local $0) - (i32.and - (i32.or - (i32.and - (get_local $1) - (i32.const 63) - ) - (i32.const 128) + (i32.or + (i32.and + (get_local $1) + (i32.const 63) ) - (i32.const 255) + (i32.const 128) ) ) (br $do-once @@ -1792,44 +1777,35 @@ (block (i32.store8 (get_local $0) - (i32.and - (i32.or - (i32.shr_u - (get_local $1) - (i32.const 12) - ) - (i32.const 224) + (i32.or + (i32.shr_u + (get_local $1) + (i32.const 12) ) - (i32.const 255) + (i32.const 224) ) ) (i32.store8 offset=1 (get_local $0) - (i32.and - (i32.or - (i32.and - (i32.shr_u - (get_local $1) - (i32.const 6) - ) - (i32.const 63) + (i32.or + (i32.and + (i32.shr_u + (get_local $1) + (i32.const 6) ) - (i32.const 128) + (i32.const 63) ) - (i32.const 255) + (i32.const 128) ) ) (i32.store8 offset=2 (get_local $0) - (i32.and - (i32.or - (i32.and - (get_local $1) - (i32.const 63) - ) - (i32.const 128) + (i32.or + (i32.and + (get_local $1) + (i32.const 63) ) - (i32.const 255) + (i32.const 128) ) ) (br $do-once @@ -1848,60 +1824,48 @@ (block i32 (i32.store8 (get_local $0) - (i32.and - (i32.or - (i32.shr_u - (get_local $1) - (i32.const 18) - ) - (i32.const 240) + (i32.or + (i32.shr_u + (get_local $1) + (i32.const 18) ) - (i32.const 255) + (i32.const 240) ) ) (i32.store8 offset=1 (get_local $0) - (i32.and - (i32.or - (i32.and - (i32.shr_u - (get_local $1) - (i32.const 12) - ) - (i32.const 63) + (i32.or + (i32.and + (i32.shr_u + (get_local $1) + (i32.const 12) ) - (i32.const 128) + (i32.const 63) ) - (i32.const 255) + (i32.const 128) ) ) (i32.store8 offset=2 (get_local $0) - (i32.and - (i32.or - (i32.and - (i32.shr_u - (get_local $1) - (i32.const 6) - ) - (i32.const 63) + (i32.or + (i32.and + (i32.shr_u + (get_local $1) + (i32.const 6) ) - (i32.const 128) + (i32.const 63) ) - (i32.const 255) + (i32.const 128) ) ) (i32.store8 offset=3 (get_local $0) - (i32.and - (i32.or - (i32.and - (get_local $1) - (i32.const 63) - ) - (i32.const 128) + (i32.or + (i32.and + (get_local $1) + (i32.const 63) ) - (i32.const 255) + (i32.const 128) ) ) (i32.const 4) @@ -3737,10 +3701,7 @@ (i32.load (get_local $18) ) - (i32.and - (get_local $15) - (i32.const 65535) - ) + (get_local $15) ) (set_local $1 (get_local $5) @@ -3754,10 +3715,7 @@ (i32.load (get_local $18) ) - (i32.and - (get_local $15) - (i32.const 255) - ) + (get_local $15) ) (set_local $1 (get_local $5) @@ -3884,15 +3842,12 @@ (i32.const -1) ) ) - (i32.and - (i32.or - (i32.and - (get_local $1) - (i32.const 7) - ) - (i32.const 48) + (i32.or + (i32.and + (get_local $1) + (i32.const 7) ) - (i32.const 255) + (i32.const 48) ) ) (br_if $while-in32 @@ -4077,11 +4032,8 @@ ) (i32.store8 (get_local $46) - (i32.and - (i32.load - (get_local $1) - ) - (i32.const 255) + (i32.load + (get_local $1) ) ) (set_local $6 @@ -4440,18 +4392,15 @@ ) (i32.const -1) ) - (i32.and - (i32.add - (i32.and - (i32.shr_s - (get_local $5) - (i32.const 31) - ) - (i32.const 2) + (i32.add + (i32.and + (i32.shr_s + (get_local $5) + (i32.const 31) ) - (i32.const 43) + (i32.const 2) ) - (i32.const 255) + (i32.const 43) ) ) (i32.store8 @@ -4461,12 +4410,9 @@ (i32.const -2) ) ) - (i32.and - (i32.add - (get_local $16) - (i32.const 15) - ) - (i32.const 255) + (i32.add + (get_local $16) + (i32.const 15) ) ) (set_local $12 @@ -4489,24 +4435,18 @@ (loop $while-in56 (i32.store8 (get_local $5) - (i32.and - (i32.or - (i32.and - (i32.load8_s - (i32.add - (tee_local $6 - (call $f64-to-int - (get_local $14) - ) - ) - (i32.const 4075) + (i32.or + (i32.load8_u + (i32.add + (tee_local $6 + (call $f64-to-int + (get_local $14) ) ) - (i32.const 255) + (i32.const 4075) ) - (get_local $9) ) - (i32.const 255) + (get_local $9) ) ) (set_local $14 @@ -6023,18 +5963,15 @@ (get_local $7) (i32.const -1) ) - (i32.and - (i32.add - (i32.and - (i32.shr_s - (get_local $11) - (i32.const 31) - ) - (i32.const 2) + (i32.add + (i32.and + (i32.shr_s + (get_local $11) + (i32.const 31) ) - (i32.const 43) + (i32.const 2) ) - (i32.const 255) + (i32.const 43) ) ) (i32.store8 @@ -6044,10 +5981,7 @@ (i32.const -2) ) ) - (i32.and - (get_local $6) - (i32.const 255) - ) + (get_local $6) ) (set_local $6 (i32.sub @@ -6788,23 +6722,17 @@ (i32.const -1) ) ) - (i32.and - (i32.or - (i32.and - (i32.load8_s - (i32.add - (i32.and - (get_local $10) - (i32.const 15) - ) - (i32.const 4075) - ) + (i32.or + (i32.load8_u + (i32.add + (i32.and + (get_local $10) + (i32.const 15) ) - (i32.const 255) + (i32.const 4075) ) - (get_local $9) ) - (i32.const 255) + (get_local $9) ) ) (br_if $while-in123 @@ -7892,12 +7820,9 @@ (i32.const -1) ) ) - (i32.and - (i32.or - (get_local $3) - (i32.const 48) - ) - (i32.const 255) + (i32.or + (get_local $3) + (i32.const 48) ) ) (set_local $3 @@ -7957,18 +7882,15 @@ (i32.const -1) ) ) - (i32.and - (i32.or - (i32.and - (call $i32u-rem - (get_local $0) - (i32.const 10) - ) - (i32.const -1) + (i32.or + (i32.and + (call $i32u-rem + (get_local $0) + (i32.const 10) ) - (i32.const 48) + (i32.const -1) ) - (i32.const 255) + (i32.const 48) ) ) (set_local $2 diff --git a/test/emcc_hello_world.fromasm.imprecise b/test/emcc_hello_world.fromasm.imprecise index 931831ccc..589114f82 100644 --- a/test/emcc_hello_world.fromasm.imprecise +++ b/test/emcc_hello_world.fromasm.imprecise @@ -307,11 +307,8 @@ (loop $while-in (br_if $jumpthreading$inner$0 (i32.eq - (i32.and - (i32.load8_s offset=687 - (get_local $1) - ) - (i32.const 255) + (i32.load8_u offset=687 + (get_local $1) ) (get_local $0) ) @@ -1644,15 +1641,12 @@ ) (i32.store8 (get_local $2) - (i32.and - (i32.or - (i32.add - (get_local $1) - (i32.const 255) - ) + (i32.or + (i32.add (get_local $1) + (i32.const 255) ) - (i32.const 255) + (get_local $1) ) ) (if i32 @@ -1721,10 +1715,7 @@ (block (i32.store8 (get_local $0) - (i32.and - (get_local $1) - (i32.const 255) - ) + (get_local $1) ) (br $do-once (i32.const 1) @@ -1739,28 +1730,22 @@ (block (i32.store8 (get_local $0) - (i32.and - (i32.or - (i32.shr_u - (get_local $1) - (i32.const 6) - ) - (i32.const 192) + (i32.or + (i32.shr_u + (get_local $1) + (i32.const 6) ) - (i32.const 255) + (i32.const 192) ) ) (i32.store8 offset=1 (get_local $0) - (i32.and - (i32.or - (i32.and - (get_local $1) - (i32.const 63) - ) - (i32.const 128) + (i32.or + (i32.and + (get_local $1) + (i32.const 63) ) - (i32.const 255) + (i32.const 128) ) ) (br $do-once @@ -1785,44 +1770,35 @@ (block (i32.store8 (get_local $0) - (i32.and - (i32.or - (i32.shr_u - (get_local $1) - (i32.const 12) - ) - (i32.const 224) + (i32.or + (i32.shr_u + (get_local $1) + (i32.const 12) ) - (i32.const 255) + (i32.const 224) ) ) (i32.store8 offset=1 (get_local $0) - (i32.and - (i32.or - (i32.and - (i32.shr_u - (get_local $1) - (i32.const 6) - ) - (i32.const 63) + (i32.or + (i32.and + (i32.shr_u + (get_local $1) + (i32.const 6) ) - (i32.const 128) + (i32.const 63) ) - (i32.const 255) + (i32.const 128) ) ) (i32.store8 offset=2 (get_local $0) - (i32.and - (i32.or - (i32.and - (get_local $1) - (i32.const 63) - ) - (i32.const 128) + (i32.or + (i32.and + (get_local $1) + (i32.const 63) ) - (i32.const 255) + (i32.const 128) ) ) (br $do-once @@ -1841,60 +1817,48 @@ (block i32 (i32.store8 (get_local $0) - (i32.and - (i32.or - (i32.shr_u - (get_local $1) - (i32.const 18) - ) - (i32.const 240) + (i32.or + (i32.shr_u + (get_local $1) + (i32.const 18) ) - (i32.const 255) + (i32.const 240) ) ) (i32.store8 offset=1 (get_local $0) - (i32.and - (i32.or - (i32.and - (i32.shr_u - (get_local $1) - (i32.const 12) - ) - (i32.const 63) + (i32.or + (i32.and + (i32.shr_u + (get_local $1) + (i32.const 12) ) - (i32.const 128) + (i32.const 63) ) - (i32.const 255) + (i32.const 128) ) ) (i32.store8 offset=2 (get_local $0) - (i32.and - (i32.or - (i32.and - (i32.shr_u - (get_local $1) - (i32.const 6) - ) - (i32.const 63) + (i32.or + (i32.and + (i32.shr_u + (get_local $1) + (i32.const 6) ) - (i32.const 128) + (i32.const 63) ) - (i32.const 255) + (i32.const 128) ) ) (i32.store8 offset=3 (get_local $0) - (i32.and - (i32.or - (i32.and - (get_local $1) - (i32.const 63) - ) - (i32.const 128) + (i32.or + (i32.and + (get_local $1) + (i32.const 63) ) - (i32.const 255) + (i32.const 128) ) ) (i32.const 4) @@ -3730,10 +3694,7 @@ (i32.load (get_local $18) ) - (i32.and - (get_local $15) - (i32.const 65535) - ) + (get_local $15) ) (set_local $1 (get_local $5) @@ -3747,10 +3708,7 @@ (i32.load (get_local $18) ) - (i32.and - (get_local $15) - (i32.const 255) - ) + (get_local $15) ) (set_local $1 (get_local $5) @@ -3877,15 +3835,12 @@ (i32.const -1) ) ) - (i32.and - (i32.or - (i32.and - (get_local $1) - (i32.const 7) - ) - (i32.const 48) + (i32.or + (i32.and + (get_local $1) + (i32.const 7) ) - (i32.const 255) + (i32.const 48) ) ) (br_if $while-in32 @@ -4070,11 +4025,8 @@ ) (i32.store8 (get_local $46) - (i32.and - (i32.load - (get_local $1) - ) - (i32.const 255) + (i32.load + (get_local $1) ) ) (set_local $6 @@ -4433,18 +4385,15 @@ ) (i32.const -1) ) - (i32.and - (i32.add - (i32.and - (i32.shr_s - (get_local $5) - (i32.const 31) - ) - (i32.const 2) + (i32.add + (i32.and + (i32.shr_s + (get_local $5) + (i32.const 31) ) - (i32.const 43) + (i32.const 2) ) - (i32.const 255) + (i32.const 43) ) ) (i32.store8 @@ -4454,12 +4403,9 @@ (i32.const -2) ) ) - (i32.and - (i32.add - (get_local $16) - (i32.const 15) - ) - (i32.const 255) + (i32.add + (get_local $16) + (i32.const 15) ) ) (set_local $12 @@ -4482,24 +4428,18 @@ (loop $while-in56 (i32.store8 (get_local $5) - (i32.and - (i32.or - (i32.and - (i32.load8_s - (i32.add - (tee_local $6 - (i32.trunc_s/f64 - (get_local $14) - ) - ) - (i32.const 4075) + (i32.or + (i32.load8_u + (i32.add + (tee_local $6 + (i32.trunc_s/f64 + (get_local $14) ) ) - (i32.const 255) + (i32.const 4075) ) - (get_local $9) ) - (i32.const 255) + (get_local $9) ) ) (set_local $14 @@ -6016,18 +5956,15 @@ (get_local $7) (i32.const -1) ) - (i32.and - (i32.add - (i32.and - (i32.shr_s - (get_local $11) - (i32.const 31) - ) - (i32.const 2) + (i32.add + (i32.and + (i32.shr_s + (get_local $11) + (i32.const 31) ) - (i32.const 43) + (i32.const 2) ) - (i32.const 255) + (i32.const 43) ) ) (i32.store8 @@ -6037,10 +5974,7 @@ (i32.const -2) ) ) - (i32.and - (get_local $6) - (i32.const 255) - ) + (get_local $6) ) (set_local $6 (i32.sub @@ -6781,23 +6715,17 @@ (i32.const -1) ) ) - (i32.and - (i32.or - (i32.and - (i32.load8_s - (i32.add - (i32.and - (get_local $10) - (i32.const 15) - ) - (i32.const 4075) - ) + (i32.or + (i32.load8_u + (i32.add + (i32.and + (get_local $10) + (i32.const 15) ) - (i32.const 255) + (i32.const 4075) ) - (get_local $9) ) - (i32.const 255) + (get_local $9) ) ) (br_if $while-in123 @@ -7885,12 +7813,9 @@ (i32.const -1) ) ) - (i32.and - (i32.or - (get_local $3) - (i32.const 48) - ) - (i32.const 255) + (i32.or + (get_local $3) + (i32.const 48) ) ) (set_local $3 @@ -7950,18 +7875,15 @@ (i32.const -1) ) ) - (i32.and - (i32.or - (i32.and - (i32.rem_u - (get_local $0) - (i32.const 10) - ) - (i32.const -1) + (i32.or + (i32.and + (i32.rem_u + (get_local $0) + (i32.const 10) ) - (i32.const 48) + (i32.const -1) ) - (i32.const 255) + (i32.const 48) ) ) (set_local $2 diff --git a/test/passes/optimize-instructions.txt b/test/passes/optimize-instructions.txt index bda6fd97f..07cc7e895 100644 --- a/test/passes/optimize-instructions.txt +++ b/test/passes/optimize-instructions.txt @@ -1,5 +1,6 @@ (module (type $0 (func (param i32 i64))) + (type $1 (func)) (memory $0 0) (func $f (type $0) (param $i1 i32) (param $i2 i64) (if @@ -213,4 +214,80 @@ ) ) ) + (func $load-store (type $1) + (drop + (i32.load8_u + (i32.const 0) + ) + ) + (drop + (i32.load8_u + (i32.const 1) + ) + ) + (drop + (i32.and + (i32.load8_s + (i32.const 2) + ) + (i32.const 254) + ) + ) + (drop + (i32.and + (i32.load8_u + (i32.const 3) + ) + (i32.const 1) + ) + ) + (drop + (i32.load16_u + (i32.const 4) + ) + ) + (drop + (i32.load16_u + (i32.const 5) + ) + ) + (drop + (i32.and + (i32.load16_s + (i32.const 6) + ) + (i32.const 65534) + ) + ) + (drop + (i32.and + (i32.load16_u + (i32.const 7) + ) + (i32.const 1) + ) + ) + (i32.store8 + (i32.const 8) + (i32.const -1) + ) + (i32.store8 + (i32.const 9) + (i32.and + (i32.const -2) + (i32.const 254) + ) + ) + (i32.store16 + (i32.const 10) + (i32.const -3) + ) + (i32.store16 + (i32.const 11) + (i32.and + (i32.const -4) + (i32.const 65534) + ) + ) + ) ) diff --git a/test/passes/optimize-instructions.wast b/test/passes/optimize-instructions.wast index b1a7ab47e..939b07ffc 100644 --- a/test/passes/optimize-instructions.wast +++ b/test/passes/optimize-instructions.wast @@ -252,4 +252,19 @@ ) ) ) + (func $load-store + (drop (i32.and (i32.load8_s (i32.const 0)) (i32.const 255))) + (drop (i32.and (i32.load8_u (i32.const 1)) (i32.const 255))) + (drop (i32.and (i32.load8_s (i32.const 2)) (i32.const 254))) + (drop (i32.and (i32.load8_u (i32.const 3)) (i32.const 1))) + (drop (i32.and (i32.load16_s (i32.const 4)) (i32.const 65535))) + (drop (i32.and (i32.load16_u (i32.const 5)) (i32.const 65535))) + (drop (i32.and (i32.load16_s (i32.const 6)) (i32.const 65534))) + (drop (i32.and (i32.load16_u (i32.const 7)) (i32.const 1))) + ;; + (i32.store8 (i32.const 8) (i32.and (i32.const -1) (i32.const 255))) + (i32.store8 (i32.const 9) (i32.and (i32.const -2) (i32.const 254))) + (i32.store16 (i32.const 10) (i32.and (i32.const -3) (i32.const 65535))) + (i32.store16 (i32.const 11) (i32.and (i32.const -4) (i32.const 65534))) + ) ) |