From 91baa6035f46da60c13a67dbd75e0abd1513af70 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 20 Jun 2022 09:46:09 +0300 Subject: [PATCH 1/2] init --- src/compiler.ts | 74 ++++ tests/compiler/std/math.release.wat | 588 ---------------------------- 2 files changed, 74 insertions(+), 588 deletions(-) diff --git a/src/compiler.ts b/src/compiler.ts index f14ec3e787..f04600d904 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -5187,6 +5187,21 @@ export class Compiler extends DiagnosticEmitter { } case TypeKind.I32: case TypeKind.U32: { + if (this.options.willOptimize) { + // Precompute power if LHS and RHS constants + // TODO: move this optimization to AIR + if ( + getExpressionId(leftExpr) == ExpressionId.Const && + getExpressionId(rightExpr) == ExpressionId.Const + ) { + let leftValue = getConstValueI32(leftExpr); + let rightValue = getConstValueI32(rightExpr); + return module.i32(i64_low(i64_pow( + i64_new(leftValue), + i64_new(rightValue) + ))); + } + } let instance = this.i32PowInstance; if (!instance) { let prototype = this.program.lookup(CommonNames.ipow32); @@ -5213,6 +5228,19 @@ export class Compiler extends DiagnosticEmitter { } case TypeKind.I64: case TypeKind.U64: { + if (this.options.willOptimize) { + // Precompute power if LHS and RHS constants + // TODO: move this optimization to AIR + if ( + getExpressionId(leftExpr) == ExpressionId.Const && + getExpressionId(rightExpr) == ExpressionId.Const + ) { + let leftValue = i64_new(getConstValueI64Low(leftExpr), getConstValueI64High(leftExpr)); + let rightValue = i64_new(getConstValueI64Low(rightExpr), getConstValueI64High(rightExpr)); + let result = i64_pow(leftValue, rightValue); + return module.i64(i64_low(result), i64_high(result)); + } + } let instance = this.i64PowInstance; if (!instance) { let prototype = this.program.lookup(CommonNames.ipow64); @@ -5234,6 +5262,28 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.ISIZE: case TypeKind.USIZE: { let isWasm64 = this.options.isWasm64; + if (this.options.willOptimize) { + // Precompute power if LHS and RHS constants + // TODO: move this optimization to AIR + if ( + getExpressionId(leftExpr) == ExpressionId.Const && + getExpressionId(rightExpr) == ExpressionId.Const + ) { + if (isWasm64) { + let leftValue = i64_new(getConstValueI64Low(leftExpr), getConstValueI64High(leftExpr)); + let rightValue = i64_new(getConstValueI64Low(rightExpr), getConstValueI64High(rightExpr)); + let result = i64_pow(leftValue, rightValue); + return module.i64(i64_low(result), i64_high(result)); + } else { + let leftValue = getConstValueI32(leftExpr); + let rightValue = getConstValueI32(rightExpr); + return module.i32(i64_low(i64_pow( + i64_new(leftValue), + i64_new(rightValue) + ))); + } + } + } let instance = isWasm64 ? this.i64PowInstance : this.i32PowInstance; if (!instance) { let prototype = this.program.lookup(isWasm64 ? CommonNames.ipow64 : CommonNames.ipow32); @@ -5258,6 +5308,18 @@ export class Compiler extends DiagnosticEmitter { return this.makeCallDirect(instance, [ leftExpr, rightExpr ], reportNode); } case TypeKind.F32: { + if (this.options.willOptimize) { + // Precompute power if LHS and RHS constants + // TODO: move this optimization to AIR + if ( + getExpressionId(leftExpr) == ExpressionId.Const && + getExpressionId(rightExpr) == ExpressionId.Const + ) { + let leftValue = getConstValueF32(leftExpr); + let rightValue = getConstValueF32(rightExpr); + return module.f32(f32(Math.pow(leftValue, rightValue))); + } + } let instance = this.f32PowInstance; if (!instance) { let namespace = this.program.lookup(CommonNames.Mathf); @@ -5287,6 +5349,18 @@ export class Compiler extends DiagnosticEmitter { } // Math.pow otherwise (result is f64) case TypeKind.F64: { + if (this.options.willOptimize) { + // Precompute power if LHS and RHS constants + // TODO: move this optimization to AIR + if ( + getExpressionId(leftExpr) == ExpressionId.Const && + getExpressionId(rightExpr) == ExpressionId.Const + ) { + let leftValue = getConstValueF64(leftExpr); + let rightValue = getConstValueF64(rightExpr); + return module.f64(Math.pow(leftValue, rightValue)); + } + } let instance = this.f64PowInstance; if (!instance) { let namespace = this.program.lookup(CommonNames.Math); diff --git a/tests/compiler/std/math.release.wat b/tests/compiler/std/math.release.wat index 4c39a4c089..2b4c8cdf80 100644 --- a/tests/compiler/std/math.release.wat +++ b/tests/compiler/std/math.release.wat @@ -19,7 +19,6 @@ (type $f64_=>_none (func (param f64))) (type $i64_i64_i64_i64_i64_=>_none (func (param i64 i64 i64 i64 i64))) (type $i64_i64_=>_i64 (func (param i64 i64) (result i64))) - (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (import "env" "Math.E" (global $~lib/bindings/dom/Math.E f64)) (import "env" "Math.LN2" (global $~lib/bindings/dom/Math.LN2 f64)) (import "env" "Math.LN10" (global $~lib/bindings/dom/Math.LN10 f64)) @@ -11970,191 +11969,6 @@ end local.get $2 ) - (func $~lib/math/ipow32 (param $0 i32) (param $1 i32) (result i32) - (local $2 i32) - i32.const 1 - local.set $2 - local.get $0 - i32.const 2 - i32.eq - if - i32.const 1 - local.get $1 - i32.shl - i32.const 0 - local.get $1 - i32.const 32 - i32.lt_u - select - return - end - local.get $1 - i32.const 0 - i32.le_s - if - local.get $0 - i32.const -1 - i32.eq - if - i32.const -1 - i32.const 1 - local.get $1 - i32.const 1 - i32.and - select - return - end - local.get $1 - i32.eqz - local.get $0 - i32.const 1 - i32.eq - i32.or - return - else - local.get $1 - i32.const 1 - i32.eq - if - local.get $0 - return - else - local.get $1 - i32.const 2 - i32.eq - if - local.get $0 - local.get $0 - i32.mul - return - else - local.get $1 - i32.const 32 - i32.lt_s - if - block $break|0 - block $case4|0 - block $case3|0 - block $case2|0 - block $case1|0 - block $case0|0 - i32.const 31 - local.get $1 - i32.clz - i32.sub - br_table $case4|0 $case3|0 $case2|0 $case1|0 $case0|0 $break|0 - end - local.get $0 - i32.const 1 - local.get $1 - i32.const 1 - i32.and - select - local.set $2 - local.get $1 - i32.const 1 - i32.shr_u - local.set $1 - local.get $0 - local.get $0 - i32.mul - local.set $0 - end - local.get $0 - local.get $2 - i32.mul - local.get $2 - local.get $1 - i32.const 1 - i32.and - select - local.set $2 - local.get $1 - i32.const 1 - i32.shr_u - local.set $1 - local.get $0 - local.get $0 - i32.mul - local.set $0 - end - local.get $0 - local.get $2 - i32.mul - local.get $2 - local.get $1 - i32.const 1 - i32.and - select - local.set $2 - local.get $1 - i32.const 1 - i32.shr_u - local.set $1 - local.get $0 - local.get $0 - i32.mul - local.set $0 - end - local.get $0 - local.get $2 - i32.mul - local.get $2 - local.get $1 - i32.const 1 - i32.and - select - local.set $2 - local.get $1 - i32.const 1 - i32.shr_u - local.set $1 - local.get $0 - local.get $0 - i32.mul - local.set $0 - end - local.get $0 - local.get $2 - i32.mul - local.get $2 - local.get $1 - i32.const 1 - i32.and - select - local.set $2 - end - local.get $2 - return - end - end - end - end - loop $while-continue|1 - local.get $1 - if - local.get $0 - local.get $2 - i32.mul - local.get $2 - local.get $1 - i32.const 1 - i32.and - select - local.set $2 - local.get $1 - i32.const 1 - i32.shr_u - local.set $1 - local.get $0 - local.get $0 - i32.mul - local.set $0 - br $while-continue|1 - end - end - local.get $2 - ) (func $start:std/math (local $0 f64) (local $1 i32) @@ -56366,382 +56180,6 @@ call $~lib/builtins/abort unreachable end - i32.const 1 - i32.const 3 - call $~lib/math/ipow32 - i32.const 1 - i32.ne - if - i32.const 0 - i32.const 1056 - i32.const 4091 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const -2 - i32.const 3 - call $~lib/math/ipow32 - i32.const -8 - i32.ne - if - i32.const 0 - i32.const 1056 - i32.const 4092 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const -1 - i32.const 0 - call $~lib/math/ipow32 - i32.const 1 - i32.ne - if - i32.const 0 - i32.const 1056 - i32.const 4093 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const -1 - i32.const -1 - call $~lib/math/ipow32 - i32.const -1 - i32.ne - if - i32.const 0 - i32.const 1056 - i32.const 4094 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const -1 - i32.const -2 - call $~lib/math/ipow32 - i32.const 1 - i32.ne - if - i32.const 0 - i32.const 1056 - i32.const 4095 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const -1 - i32.const -3 - call $~lib/math/ipow32 - i32.const -1 - i32.ne - if - i32.const 0 - i32.const 1056 - i32.const 4096 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const 0 - i32.const -2 - call $~lib/math/ipow32 - if - i32.const 0 - i32.const 1056 - i32.const 4098 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const 0 - i32.const -1 - call $~lib/math/ipow32 - if - i32.const 0 - i32.const 1056 - i32.const 4099 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const 0 - i32.const 2 - call $~lib/math/ipow32 - if - i32.const 0 - i32.const 1056 - i32.const 4102 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const 1 - i32.const -2 - call $~lib/math/ipow32 - i32.const 1 - i32.ne - if - i32.const 0 - i32.const 1056 - i32.const 4104 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const 1 - i32.const -1 - call $~lib/math/ipow32 - i32.const 1 - i32.ne - if - i32.const 0 - i32.const 1056 - i32.const 4105 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const 1 - i32.const 2 - call $~lib/math/ipow32 - i32.const 1 - i32.ne - if - i32.const 0 - i32.const 1056 - i32.const 4108 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const 1 - i32.const 3 - call $~lib/math/ipow32 - i32.const 255 - i32.and - i32.const 1 - i32.ne - if - i32.const 0 - i32.const 1056 - i32.const 4110 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const -2 - i32.const 3 - call $~lib/math/ipow32 - i32.const 255 - i32.and - i32.const 248 - i32.ne - if - i32.const 0 - i32.const 1056 - i32.const 4111 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const 4 - i32.const 7 - call $~lib/math/ipow32 - i32.const 65535 - i32.and - i32.const 16384 - i32.ne - if - i32.const 0 - i32.const 1056 - i32.const 4112 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const 4 - i32.const 8 - call $~lib/math/ipow32 - i32.const 65535 - i32.and - if - i32.const 0 - i32.const 1056 - i32.const 4113 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i32.const 5 - i32.const 10 - call $~lib/math/ipow32 - i32.const 65535 - i32.and - i32.const 761 - i32.ne - if - i32.const 0 - i32.const 1056 - i32.const 4114 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i64.const 0 - i64.const 0 - call $~lib/math/ipow64 - i64.const 1 - i64.ne - if - i32.const 0 - i32.const 1056 - i32.const 4116 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i64.const 0 - i64.const 1 - call $~lib/math/ipow64 - i64.eqz - i32.eqz - if - i32.const 0 - i32.const 1056 - i32.const 4117 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i64.const 1 - i64.const 3 - call $~lib/math/ipow64 - i64.const 1 - i64.ne - if - i32.const 0 - i32.const 1056 - i32.const 4118 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i64.const 2 - i64.const 3 - call $~lib/math/ipow64 - i64.const 8 - i64.ne - if - i32.const 0 - i32.const 1056 - i32.const 4119 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i64.const 4294967295 - i64.const 3 - call $~lib/math/ipow64 - i64.const 12884901887 - i64.ne - if - i32.const 0 - i32.const 1056 - i32.const 4120 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i64.const 65535 - i64.const 3 - call $~lib/math/ipow64 - i64.const 281462092005375 - i64.ne - if - i32.const 0 - i32.const 1056 - i32.const 4121 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i64.const 65535 - i64.const 8 - call $~lib/math/ipow64 - i64.const -15762478437236735 - i64.ne - if - i32.const 0 - i32.const 1056 - i32.const 4122 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i64.const 61731 - i64.const 4 - call $~lib/math/ipow64 - i64.const -3925184889716469295 - i64.ne - if - i32.const 0 - i32.const 1056 - i32.const 4123 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i64.const 61731 - i64.const 4 - call $~lib/math/ipow64 - i64.const -3925184889716469295 - i64.ne - if - i32.const 0 - i32.const 1056 - i32.const 4124 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i64.const 57055 - i64.const 3 - call $~lib/math/ipow64 - i64.const 339590 - i64.const 3 - call $~lib/math/ipow64 - i64.add - i64.const 340126 - i64.const 3 - call $~lib/math/ipow64 - i64.eq - if - i32.const 0 - i32.const 1056 - i32.const 4126 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - i64.const 57055 - i64.const 3 - call $~lib/math/ipow64 - i64.const 339590 - i64.const 3 - call $~lib/math/ipow64 - i64.add - i64.const 39347712995520375 - i64.ne - if - i32.const 0 - i32.const 1056 - i32.const 4127 - i32.const 1 - call $~lib/builtins/abort - unreachable - end f64.const 1 f64.const 0.5 call $~lib/math/NativeMath.pow @@ -56781,32 +56219,6 @@ call $~lib/builtins/abort unreachable end - f64.const 0 - f64.const 0 - call $~lib/math/NativeMath.pow - f64.const 1 - f64.ne - if - i32.const 0 - i32.const 1056 - i32.const 4132 - i32.const 1 - call $~lib/builtins/abort - unreachable - end - f64.const 1 - f64.const 1 - call $~lib/math/NativeMath.pow - f64.const 1 - f64.ne - if - i32.const 0 - i32.const 1056 - i32.const 4133 - i32.const 1 - call $~lib/builtins/abort - unreachable - end ) (func $~start call $start:std/math From 0a54bd6d437d11974258277408d62332f7b7a56f Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Mon, 20 Jun 2022 11:56:37 +0300 Subject: [PATCH 2/2] set currentType manually --- src/compiler.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/compiler.ts b/src/compiler.ts index f04600d904..74518ef05d 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -5196,6 +5196,7 @@ export class Compiler extends DiagnosticEmitter { ) { let leftValue = getConstValueI32(leftExpr); let rightValue = getConstValueI32(rightExpr); + this.currentType = type; return module.i32(i64_low(i64_pow( i64_new(leftValue), i64_new(rightValue) @@ -5238,6 +5239,7 @@ export class Compiler extends DiagnosticEmitter { let leftValue = i64_new(getConstValueI64Low(leftExpr), getConstValueI64High(leftExpr)); let rightValue = i64_new(getConstValueI64Low(rightExpr), getConstValueI64High(rightExpr)); let result = i64_pow(leftValue, rightValue); + this.currentType = type; return module.i64(i64_low(result), i64_high(result)); } } @@ -5273,10 +5275,12 @@ export class Compiler extends DiagnosticEmitter { let leftValue = i64_new(getConstValueI64Low(leftExpr), getConstValueI64High(leftExpr)); let rightValue = i64_new(getConstValueI64Low(rightExpr), getConstValueI64High(rightExpr)); let result = i64_pow(leftValue, rightValue); + this.currentType = type; return module.i64(i64_low(result), i64_high(result)); } else { let leftValue = getConstValueI32(leftExpr); let rightValue = getConstValueI32(rightExpr); + this.currentType = type; return module.i32(i64_low(i64_pow( i64_new(leftValue), i64_new(rightValue) @@ -5317,6 +5321,7 @@ export class Compiler extends DiagnosticEmitter { ) { let leftValue = getConstValueF32(leftExpr); let rightValue = getConstValueF32(rightExpr); + this.currentType = type; return module.f32(f32(Math.pow(leftValue, rightValue))); } } @@ -5358,6 +5363,7 @@ export class Compiler extends DiagnosticEmitter { ) { let leftValue = getConstValueF64(leftExpr); let rightValue = getConstValueF64(rightExpr); + this.currentType = type; return module.f64(Math.pow(leftValue, rightValue)); } }