From 934f05eed96df74a0fb4482ba6ea58675c966ae0 Mon Sep 17 00:00:00 2001 From: Max Graey Date: Fri, 7 Dec 2018 16:37:33 +0200 Subject: [PATCH] Optimize array functional loops (#359) --- std/assembly/array.ts | 13 +- tests/compiler/std/array.optimized.wat | 168 ++++++++++----------- tests/compiler/std/array.untouched.wat | 195 +++++++++++++------------ 3 files changed, 178 insertions(+), 198 deletions(-) diff --git a/std/assembly/array.ts b/std/assembly/array.ts index 93a9cf2d..8bdb27cd 100644 --- a/std/assembly/array.ts +++ b/std/assembly/array.ts @@ -74,7 +74,7 @@ export class Array { every(callbackfn: (element: T, index: i32, array: Array) => bool): bool { var buffer = this.buffer_; - for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) { + for (let index = 0, toIndex = this.length_; index < min(toIndex, this.length_); ++index) { if (!callbackfn(LOAD(buffer, index), index, this)) return false; } return true; @@ -82,7 +82,7 @@ export class Array { findIndex(predicate: (element: T, index: i32, array: Array) => bool): i32 { var buffer = this.buffer_; - for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) { + for (let index = 0, toIndex = this.length_; index < min(toIndex, this.length_); ++index) { if (predicate(LOAD(buffer, index), index, this)) return index; } return -1; @@ -262,7 +262,7 @@ export class Array { var length = this.length_; var result = new Array(length); var resultBuffer = result.buffer_; - for (let index = 0; index < length && index < this.length_; ++index) { + for (let index = 0; index < min(length, this.length_); ++index) { STORE(resultBuffer, index, callbackfn(LOAD(buffer, index), index, this)); } return result; @@ -270,9 +270,8 @@ export class Array { filter(callbackfn: (value: T, index: i32, array: Array) => bool): Array { var buffer = this.buffer_; - var length = this.length_; var result = new Array(); - for (let index = 0; index < length && index < this.length_; ++index) { + for (let index = 0, toIndex = this.length_; index < min(toIndex, this.length_); ++index) { let value = LOAD(buffer, index); if (callbackfn(value, index, this)) result.push(value); } @@ -285,7 +284,7 @@ export class Array { ): U { var accum = initialValue; var buffer = this.buffer_; - for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) { + for (let index = 0, toIndex = this.length_; index < min(toIndex, this.length_); ++index) { accum = callbackfn(accum, LOAD(buffer, index), index, this); } return accum; @@ -321,7 +320,7 @@ export class Array { some(callbackfn: (element: T, index: i32, array: Array) => bool): bool { var buffer = this.buffer_; - for (let index = 0, toIndex = this.length_; index < toIndex && index < this.length_; ++index) { + for (let index = 0, toIndex = this.length_; index < min(toIndex, this.length_); ++index) { if (callbackfn(LOAD(buffer, index), index, this)) return true; } return false; diff --git a/tests/compiler/std/array.optimized.wat b/tests/compiler/std/array.optimized.wat index c353fecb..057e3c0f 100644 --- a/tests/compiler/std/array.optimized.wat +++ b/tests/compiler/std/array.optimized.wat @@ -2679,7 +2679,7 @@ if i32.const 0 i32.const 8 - i32.const 337 + i32.const 336 i32.const 42 call $~lib/env/abort unreachable @@ -2731,7 +2731,7 @@ if i32.const 0 i32.const 8 - i32.const 308 + i32.const 307 i32.const 20 call $~lib/env/abort unreachable @@ -3061,22 +3061,19 @@ set_local $4 get_local $0 i32.load offset=4 - set_local $5 + set_local $3 loop $repeat|0 block $break|0 get_local $2 + get_local $3 + get_local $0 + i32.load offset=4 + tee_local $5 + get_local $3 get_local $5 i32.lt_s - tee_local $3 - if - get_local $2 - get_local $0 - i32.load offset=4 - i32.lt_s - set_local $3 - end - get_local $3 - i32.eqz + select + i32.ge_s br_if $break|0 i32.const 3 set_global $~argc @@ -3147,22 +3144,19 @@ set_local $4 get_local $0 i32.load offset=4 - set_local $5 + set_local $3 loop $repeat|0 block $break|0 get_local $2 + get_local $3 + get_local $0 + i32.load offset=4 + tee_local $5 + get_local $3 get_local $5 i32.lt_s - tee_local $3 - if - get_local $2 - get_local $0 - i32.load offset=4 - i32.lt_s - set_local $3 - end - get_local $3 - i32.eqz + select + i32.ge_s br_if $break|0 i32.const 3 set_global $~argc @@ -3233,22 +3227,19 @@ set_local $4 get_local $0 i32.load offset=4 - set_local $5 + set_local $3 loop $repeat|0 block $break|0 get_local $2 + get_local $3 + get_local $0 + i32.load offset=4 + tee_local $5 + get_local $3 get_local $5 i32.lt_s - tee_local $3 - if - get_local $2 - get_local $0 - i32.load offset=4 - i32.lt_s - set_local $3 - end - get_local $3 - i32.eqz + select + i32.ge_s br_if $break|0 i32.const 3 set_global $~argc @@ -3389,27 +3380,25 @@ (local $6 i32) get_local $0 i32.load - set_local $3 + set_local $4 get_local $0 i32.load offset=4 - tee_local $4 + tee_local $3 call $~lib/array/Array#constructor tee_local $5 i32.load set_local $6 loop $repeat|0 get_local $1 - get_local $4 - i32.lt_s + get_local $3 + get_local $0 + i32.load offset=4 tee_local $2 - if - get_local $1 - get_local $0 - i32.load offset=4 - i32.lt_s - set_local $2 - end + get_local $3 get_local $2 + i32.lt_s + select + i32.lt_s if i32.const 3 set_global $~argc @@ -3420,7 +3409,7 @@ get_local $6 i32.add get_local $2 - get_local $3 + get_local $4 i32.add i32.load offset=8 get_local $1 @@ -3460,30 +3449,27 @@ set_local $4 get_local $0 i32.load offset=4 - tee_local $5 + tee_local $3 call $~lib/array/Array#constructor - tee_local $6 + tee_local $5 i32.load - set_local $7 + set_local $6 loop $repeat|0 block $break|0 get_local $2 - get_local $5 - i32.lt_s - tee_local $3 - if - get_local $2 - get_local $0 - i32.load offset=4 - i32.lt_s - set_local $3 - end get_local $3 - i32.eqz + get_local $0 + i32.load offset=4 + tee_local $7 + get_local $3 + get_local $7 + i32.lt_s + select + i32.ge_s br_if $break|0 i32.const 3 set_global $~argc - get_local $7 + get_local $6 get_local $2 i32.const 2 i32.shl @@ -3506,7 +3492,7 @@ br $repeat|0 end end - get_local $6 + get_local $5 ) (func $start~anonymous|23 (; 53 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) get_global $std/array/i @@ -3538,30 +3524,27 @@ (local $6 i32) get_local $0 i32.load - set_local $5 - get_local $0 - i32.load offset=4 set_local $6 i32.const 0 call $~lib/array/Array#constructor set_local $4 + get_local $0 + i32.load offset=4 + set_local $5 loop $repeat|0 block $break|0 get_local $2 - get_local $6 - i32.lt_s - tee_local $3 - if - get_local $2 - get_local $0 - i32.load offset=4 - i32.lt_s - set_local $3 - end - get_local $3 - i32.eqz - br_if $break|0 get_local $5 + get_local $0 + i32.load offset=4 + tee_local $3 + get_local $5 + get_local $3 + i32.lt_s + select + i32.ge_s + br_if $break|0 + get_local $6 get_local $2 i32.const 2 i32.shl @@ -3639,22 +3622,19 @@ set_local $5 get_local $0 i32.load offset=4 - set_local $6 + set_local $4 loop $repeat|0 block $break|0 get_local $3 + get_local $4 + get_local $0 + i32.load offset=4 + tee_local $6 + get_local $4 get_local $6 i32.lt_s - tee_local $4 - if - get_local $3 - get_local $0 - i32.load offset=4 - i32.lt_s - set_local $4 - end - get_local $4 - i32.eqz + select + i32.ge_s br_if $break|0 i32.const 4 set_global $~argc @@ -4202,7 +4182,7 @@ if i32.const 0 i32.const 8 - i32.const 409 + i32.const 408 i32.const 4 call $~lib/env/abort unreachable @@ -4773,7 +4753,7 @@ if i32.const 0 i32.const 8 - i32.const 409 + i32.const 408 i32.const 4 call $~lib/env/abort unreachable @@ -5345,7 +5325,7 @@ if i32.const 0 i32.const 8 - i32.const 409 + i32.const 408 i32.const 4 call $~lib/env/abort unreachable @@ -5734,7 +5714,7 @@ if i32.const 0 i32.const 8 - i32.const 409 + i32.const 408 i32.const 4 call $~lib/env/abort unreachable diff --git a/tests/compiler/std/array.untouched.wat b/tests/compiler/std/array.untouched.wat index 4aa8c006..e2ee0bd2 100644 --- a/tests/compiler/std/array.untouched.wat +++ b/tests/compiler/std/array.untouched.wat @@ -3399,7 +3399,7 @@ if i32.const 0 i32.const 8 - i32.const 337 + i32.const 336 i32.const 42 call $~lib/env/abort unreachable @@ -3474,7 +3474,7 @@ if i32.const 0 i32.const 8 - i32.const 308 + i32.const 307 i32.const 20 call $~lib/env/abort unreachable @@ -3909,6 +3909,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) get_local $0 i32.load set_local $2 @@ -3923,16 +3924,15 @@ loop $repeat|0 get_local $3 get_local $4 - i32.lt_s tee_local $5 - if (result i32) - get_local $3 - get_local $0 - i32.load offset=4 - i32.lt_s - else - get_local $5 - end + get_local $0 + i32.load offset=4 + tee_local $6 + get_local $5 + get_local $6 + i32.lt_s + select + i32.lt_s i32.eqz br_if $break|0 block (result i32) @@ -4014,6 +4014,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) get_local $0 i32.load set_local $2 @@ -4028,16 +4029,15 @@ loop $repeat|0 get_local $3 get_local $4 - i32.lt_s tee_local $5 - if (result i32) - get_local $3 - get_local $0 - i32.load offset=4 - i32.lt_s - else - get_local $5 - end + get_local $0 + i32.load offset=4 + tee_local $6 + get_local $5 + get_local $6 + i32.lt_s + select + i32.lt_s i32.eqz br_if $break|0 block (result i32) @@ -4115,6 +4115,7 @@ (local $3 i32) (local $4 i32) (local $5 i32) + (local $6 i32) get_local $0 i32.load set_local $2 @@ -4129,16 +4130,15 @@ loop $repeat|0 get_local $3 get_local $4 - i32.lt_s tee_local $5 - if (result i32) - get_local $3 - get_local $0 - i32.load offset=4 - i32.lt_s - else - get_local $5 - end + get_local $0 + i32.load offset=4 + tee_local $6 + get_local $5 + get_local $6 + i32.lt_s + select + i32.lt_s i32.eqz br_if $break|0 block (result i32) @@ -4367,7 +4367,8 @@ (local $5 i32) (local $6 i32) (local $7 i32) - (local $8 f32) + (local $8 i32) + (local $9 f32) get_local $0 i32.load set_local $2 @@ -4387,16 +4388,15 @@ loop $repeat|0 get_local $6 get_local $3 - i32.lt_s tee_local $7 - if (result i32) - get_local $6 - get_local $0 - i32.load offset=4 - i32.lt_s - else - get_local $7 - end + get_local $0 + i32.load offset=4 + tee_local $8 + get_local $7 + get_local $8 + i32.lt_s + select + i32.lt_s i32.eqz br_if $break|0 block @@ -4420,7 +4420,7 @@ get_local $1 call_indirect (type $iiif) end - set_local $8 + set_local $9 i32.const 0 set_local $7 get_local $5 @@ -4430,7 +4430,7 @@ i32.add get_local $7 i32.add - get_local $8 + get_local $9 f32.store offset=8 end get_local $6 @@ -4509,16 +4509,15 @@ loop $repeat|0 get_local $6 get_local $3 - i32.lt_s tee_local $7 - if (result i32) - get_local $6 - get_local $0 - i32.load offset=4 - i32.lt_s - else - get_local $7 - end + get_local $0 + i32.load offset=4 + tee_local $8 + get_local $7 + get_local $8 + i32.lt_s + select + i32.lt_s i32.eqz br_if $break|0 block @@ -4594,32 +4593,34 @@ (local $4 i32) (local $5 i32) (local $6 i32) + (local $7 i32) get_local $0 i32.load set_local $2 - get_local $0 - i32.load offset=4 - set_local $3 i32.const 0 i32.const 0 call $~lib/array/Array#constructor - set_local $4 + set_local $3 block $break|0 - i32.const 0 - set_local $5 + block + i32.const 0 + set_local $4 + get_local $0 + i32.load offset=4 + set_local $5 + end loop $repeat|0 + get_local $4 get_local $5 - get_local $3 - i32.lt_s tee_local $6 - if (result i32) - get_local $5 - get_local $0 - i32.load offset=4 - i32.lt_s - else - get_local $6 - end + get_local $0 + i32.load offset=4 + tee_local $7 + get_local $6 + get_local $7 + i32.lt_s + select + i32.lt_s i32.eqz br_if $break|0 block @@ -4627,7 +4628,7 @@ i32.const 0 set_local $6 get_local $2 - get_local $5 + get_local $4 i32.const 2 i32.shl i32.add @@ -4640,7 +4641,7 @@ i32.const 3 set_global $~argc get_local $6 - get_local $5 + get_local $4 get_local $0 get_local $1 call_indirect (type $iiii) @@ -4648,22 +4649,22 @@ i32.const 0 i32.ne if - get_local $4 + get_local $3 get_local $6 call $~lib/array/Array#push drop end end - get_local $5 + get_local $4 i32.const 1 i32.add - set_local $5 + set_local $4 br $repeat|0 unreachable end unreachable end - get_local $4 + get_local $3 ) (func $start~anonymous|26 (; 72 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32) get_local $2 @@ -4710,6 +4711,7 @@ (local $5 i32) (local $6 i32) (local $7 i32) + (local $8 i32) get_local $2 set_local $3 get_local $0 @@ -4726,16 +4728,15 @@ loop $repeat|0 get_local $5 get_local $6 - i32.lt_s tee_local $7 - if (result i32) - get_local $5 - get_local $0 - i32.load offset=4 - i32.lt_s - else - get_local $7 - end + get_local $0 + i32.load offset=4 + tee_local $8 + get_local $7 + get_local $8 + i32.lt_s + select + i32.lt_s i32.eqz br_if $break|0 block (result i32) @@ -4794,6 +4795,7 @@ (local $5 i32) (local $6 i32) (local $7 i32) + (local $8 i32) get_local $2 set_local $3 get_local $0 @@ -4810,16 +4812,15 @@ loop $repeat|0 get_local $5 get_local $6 - i32.lt_s tee_local $7 - if (result i32) - get_local $5 - get_local $0 - i32.load offset=4 - i32.lt_s - else - get_local $7 - end + get_local $0 + i32.load offset=4 + tee_local $8 + get_local $7 + get_local $8 + i32.lt_s + select + i32.lt_s i32.eqz br_if $break|0 block (result i32) @@ -5688,7 +5689,7 @@ if i32.const 0 i32.const 8 - i32.const 409 + i32.const 408 i32.const 4 call $~lib/env/abort unreachable @@ -6469,7 +6470,7 @@ if i32.const 0 i32.const 8 - i32.const 409 + i32.const 408 i32.const 4 call $~lib/env/abort unreachable @@ -7277,7 +7278,7 @@ if i32.const 0 i32.const 8 - i32.const 409 + i32.const 408 i32.const 4 call $~lib/env/abort unreachable @@ -7950,7 +7951,7 @@ if i32.const 0 i32.const 8 - i32.const 409 + i32.const 408 i32.const 4 call $~lib/env/abort unreachable @@ -8654,7 +8655,7 @@ if i32.const 0 i32.const 8 - i32.const 409 + i32.const 408 i32.const 4 call $~lib/env/abort unreachable @@ -9129,7 +9130,7 @@ if i32.const 0 i32.const 8 - i32.const 409 + i32.const 408 i32.const 4 call $~lib/env/abort unreachable @@ -9639,7 +9640,7 @@ if i32.const 0 i32.const 8 - i32.const 409 + i32.const 408 i32.const 4 call $~lib/env/abort unreachable