From ee08839fb6dbe48877dc3f520a2c51fa60470967 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 27 May 2020 11:15:37 +0300 Subject: [PATCH 01/73] implement 64-bit cases for getMaxBits --- src/passes/OptimizeInstructions.cpp | 61 ++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 5 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 3e3863e954b..afcd66cc849 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -67,10 +67,10 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case AddInt32: case SubInt32: case MulInt32: - case DivSInt32: - case DivUInt32: - case RemSInt32: - case RemUInt32: + case DivSInt32: // TODO: could more precise if rhs is constant + case DivUInt32: // TODO: could more precise if rhs is constant + case RemSInt32: // TODO: could more precise if rhs is constant + case RemUInt32: // TODO: could more precise if rhs is constant case RotLInt32: case RotRInt32: return 32; @@ -112,7 +112,55 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { } return 32; } - // 64-bit TODO + + case AddInt64: + case SubInt64: + case MulInt64: + case DivSInt64: // TODO: could more precise if rhs is constant + case DivUInt64: // TODO: could more precise if rhs is constant + case RemSInt64: // TODO: could more precise if rhs is constant + case RemUInt64: // TODO: could more precise if rhs is constant + case RotLInt64: + case RotRInt64: + return 64; + case AndInt64: + return std::min(getMaxBits(binary->left, localInfoProvider), + getMaxBits(binary->right, localInfoProvider)); + case OrInt64: + case XorInt64: + return std::max(getMaxBits(binary->left, localInfoProvider), + getMaxBits(binary->right, localInfoProvider)); + case ShlInt64: { + if (auto* shifts = binary->right->dynCast()) { + return std::min(Index(64), + getMaxBits(binary->left, localInfoProvider) + + Bits::getEffectiveShifts(shifts)); + } + return 64; + } + case ShrUInt64: { + if (auto* shift = binary->right->dynCast()) { + auto maxBits = getMaxBits(binary->left, localInfoProvider); + auto shifts = + std::min(Index(Bits::getEffectiveShifts(shift)), + maxBits); // can ignore more shifts than zero us out + return std::max(Index(0), maxBits - shifts); + } + return 64; + } + case ShrSInt64: { + if (auto* shift = binary->right->dynCast()) { + auto maxBits = getMaxBits(binary->left, localInfoProvider); + if (maxBits == 64) { + return 64; + } + auto shifts = + std::min(Index(Bits::getEffectiveShifts(shift)), + maxBits); // can ignore more shifts than zero us out + return std::max(Index(0), maxBits - shifts); + } + return 64; + } // comparisons case EqInt32: case NeInt32: @@ -124,6 +172,7 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case GtUInt32: case GeSInt32: case GeUInt32: + case EqInt64: case NeInt64: case LtSInt64: @@ -134,12 +183,14 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case GtUInt64: case GeSInt64: case GeUInt64: + case EqFloat32: case NeFloat32: case LtFloat32: case LeFloat32: case GtFloat32: case GeFloat32: + case EqFloat64: case NeFloat64: case LtFloat64: From 374c9b6b9a4917828f6c0bbdd5f829a8c140c414 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 27 May 2020 14:06:23 +0300 Subject: [PATCH 02/73] add ExtendSInt32 & ExtendUInt32 for unary cases --- src/passes/OptimizeInstructions.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index afcd66cc849..82453e1a7cc 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -214,6 +214,8 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case EqZInt64: return 1; case WrapInt64: + case ExtendSInt32: + case ExtendUInt32: return std::min(Index(32), getMaxBits(unary->value, localInfoProvider)); default: {} } From 3a0f72e6a939aab038fc7fcc0f4a35050ed23a6f Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 27 May 2020 14:12:09 +0300 Subject: [PATCH 03/73] fix ExtendSInt32 --- src/passes/OptimizeInstructions.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 82453e1a7cc..f2aae2787f7 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -214,9 +214,10 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case EqZInt64: return 1; case WrapInt64: - case ExtendSInt32: case ExtendUInt32: return std::min(Index(32), getMaxBits(unary->value, localInfoProvider)); + case ExtendSInt32: + return std::min(Index(64), getMaxBits(unary->value, localInfoProvider)); default: {} } } else if (auto* set = curr->dynCast()) { From 091e15e9722584ab54204e55aa7ad6ac4b0db9cd Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 27 May 2020 20:44:25 +0300 Subject: [PATCH 04/73] implement RemUInt32 / RemUInt64 for getMaxBits --- src/passes/OptimizeInstructions.cpp | 36 ++++++++++++++++++++++------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index f2aae2787f7..a6015fa8a26 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -64,16 +64,26 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { } else if (auto* binary = curr->dynCast()) { switch (binary->op) { // 32-bit + case RotLInt32: + case RotRInt32: case AddInt32: case SubInt32: case MulInt32: case DivSInt32: // TODO: could more precise if rhs is constant case DivUInt32: // TODO: could more precise if rhs is constant - case RemSInt32: // TODO: could more precise if rhs is constant - case RemUInt32: // TODO: could more precise if rhs is constant - case RotLInt32: - case RotRInt32: + case RemSInt32: return 32; + case RemUInt32: { + if (auto* const_ = binary->right->dynCast()) { + auto maxBits = getMaxBits(binary->left, localInfoProvider); + auto value = const_->value.geti32(); + return value <= 1 + ? Index(0) + : std::min(maxBits, + 32 - Index(CountLeadingZeroes(value - 1))); + } + return 32; + } case AndInt32: return std::min(getMaxBits(binary->left, localInfoProvider), getMaxBits(binary->right, localInfoProvider)); @@ -113,16 +123,26 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { return 32; } + case RotLInt64: + case RotRInt64: case AddInt64: case SubInt64: case MulInt64: case DivSInt64: // TODO: could more precise if rhs is constant case DivUInt64: // TODO: could more precise if rhs is constant - case RemSInt64: // TODO: could more precise if rhs is constant - case RemUInt64: // TODO: could more precise if rhs is constant - case RotLInt64: - case RotRInt64: + case RemSInt64: return 64; + case RemUInt64: { + if (auto* const_ = binary->right->dynCast()) { + auto value = const_->value.geti64(); + auto maxBits = getMaxBits(binary->left, localInfoProvider); + return value <= 1 + ? Index(0) + : std::min(maxBits, + 64 - Index(CountLeadingZeroes(value - 1))); + } + return 64; + } case AndInt64: return std::min(getMaxBits(binary->left, localInfoProvider), getMaxBits(binary->right, localInfoProvider)); From 18a2aa28852a38151272cd34ac0ceec1c93af6e2 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 27 May 2020 21:41:21 +0300 Subject: [PATCH 05/73] implement DivUInt(32/64) / DivSInt(32/64) --- src/passes/OptimizeInstructions.cpp | 46 +++++++++++++++++-- .../optimize-instructions_all-features.txt | 12 ++--- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index a6015fa8a26..73ebde720a5 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -69,8 +69,6 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case AddInt32: case SubInt32: case MulInt32: - case DivSInt32: // TODO: could more precise if rhs is constant - case DivUInt32: // TODO: could more precise if rhs is constant case RemSInt32: return 32; case RemUInt32: { @@ -84,6 +82,27 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { } return 32; } + case DivUInt32: { + if (auto* const_ = binary->right->dynCast()) { + auto value = const_->value.geti32(); + auto maxBits = getMaxBits(binary->left, localInfoProvider); + return std::max(Index(0), + maxBits - (31 - Index(CountLeadingZeroes(value)))); + } + return 32; + } + case DivSInt32: { + if (auto* const_ = binary->right->dynCast()) { + auto value = const_->value.geti32(); + auto maxBits = getMaxBits(binary->left, localInfoProvider); + if (maxBits == 32) { + return 32; + } + return std::max(Index(0), + maxBits - (31 - Index(CountLeadingZeroes(value)))); + } + return 32; + } case AndInt32: return std::min(getMaxBits(binary->left, localInfoProvider), getMaxBits(binary->right, localInfoProvider)); @@ -128,8 +147,6 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case AddInt64: case SubInt64: case MulInt64: - case DivSInt64: // TODO: could more precise if rhs is constant - case DivUInt64: // TODO: could more precise if rhs is constant case RemSInt64: return 64; case RemUInt64: { @@ -143,6 +160,27 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { } return 64; } + case DivUInt64: { + if (auto* const_ = binary->right->dynCast()) { + auto value = const_->value.geti64(); + auto maxBits = getMaxBits(binary->left, localInfoProvider); + return std::max(Index(0), + maxBits - (63 - Index(CountLeadingZeroes(value)))); + } + return 64; + } + case DivSInt64: { + if (auto* const_ = binary->right->dynCast()) { + auto value = const_->value.geti64(); + auto maxBits = getMaxBits(binary->left, localInfoProvider); + if (maxBits == 64) { + return 64; + } + return std::max(Index(0), + maxBits - (63 - Index(CountLeadingZeroes(value)))); + } + return 64; + } case AndInt64: return std::min(getMaxBits(binary->left, localInfoProvider), getMaxBits(binary->right, localInfoProvider)); diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index d84095b89b7..e61c6accebe 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -884,15 +884,9 @@ ) ) (drop - (i32.shr_s - (i32.shl - (i32.div_s - (i32.const 1) - (i32.const 2) - ) - (i32.const 24) - ) - (i32.const 24) + (i32.div_s + (i32.const 1) + (i32.const 2) ) ) (drop From 168fed4c9d1244f8563ae2b042f0c241a05667c1 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 27 May 2020 22:09:31 +0300 Subject: [PATCH 06/73] Implement RemSInt32 / RemSInt64 --- src/passes/OptimizeInstructions.cpp | 36 ++++++++++++++++++++++++----- 1 file changed, 30 insertions(+), 6 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 73ebde720a5..27696f2411f 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -69,8 +69,20 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case AddInt32: case SubInt32: case MulInt32: - case RemSInt32: + case RemSInt32: { + if (auto* const_ = binary->right->dynCast()) { + auto maxBits = getMaxBits(binary->left, localInfoProvider); + if (maxBits == 32) { + return 32; + } + auto value = const_->value.geti32(); + return value <= 1 + ? Index(0) + : std::min(maxBits, + 32 - Index(CountLeadingZeroes(value - 1))); + } return 32; + } case RemUInt32: { if (auto* const_ = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); @@ -93,11 +105,11 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { } case DivSInt32: { if (auto* const_ = binary->right->dynCast()) { - auto value = const_->value.geti32(); auto maxBits = getMaxBits(binary->left, localInfoProvider); if (maxBits == 32) { return 32; } + auto value = const_->value.geti32(); return std::max(Index(0), maxBits - (31 - Index(CountLeadingZeroes(value)))); } @@ -147,12 +159,24 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case AddInt64: case SubInt64: case MulInt64: - case RemSInt64: + case RemSInt64: { + if (auto* const_ = binary->right->dynCast()) { + auto maxBits = getMaxBits(binary->left, localInfoProvider); + if (maxBits == 64) { + return 64; + } + auto value = const_->value.geti64(); + return value <= 1 + ? Index(0) + : std::min(maxBits, + 64 - Index(CountLeadingZeroes(value - 1))); + } return 64; + } case RemUInt64: { if (auto* const_ = binary->right->dynCast()) { - auto value = const_->value.geti64(); auto maxBits = getMaxBits(binary->left, localInfoProvider); + auto value = const_->value.geti64(); return value <= 1 ? Index(0) : std::min(maxBits, @@ -162,8 +186,8 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { } case DivUInt64: { if (auto* const_ = binary->right->dynCast()) { - auto value = const_->value.geti64(); auto maxBits = getMaxBits(binary->left, localInfoProvider); + auto value = const_->value.geti64(); return std::max(Index(0), maxBits - (63 - Index(CountLeadingZeroes(value)))); } @@ -171,11 +195,11 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { } case DivSInt64: { if (auto* const_ = binary->right->dynCast()) { - auto value = const_->value.geti64(); auto maxBits = getMaxBits(binary->left, localInfoProvider); if (maxBits == 64) { return 64; } + auto value = const_->value.geti64(); return std::max(Index(0), maxBits - (63 - Index(CountLeadingZeroes(value)))); } From d04ae7d61566540b723253cae975cb02acecb9b2 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 27 May 2020 23:18:42 +0300 Subject: [PATCH 07/73] update according review --- src/passes/OptimizeInstructions.cpp | 64 ++++++++++++----------------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 27696f2411f..aab78e7bf8f 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -52,12 +52,12 @@ Name ANY_EXPR = "any.expr"; // local.get. template Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { - if (auto* const_ = curr->dynCast()) { + if (auto* c = curr->dynCast()) { switch (curr->type.getSingle()) { case Type::i32: - return 32 - const_->value.countLeadingZeroes().geti32(); + return 32 - c->value.countLeadingZeroes().geti32(); case Type::i64: - return 64 - const_->value.countLeadingZeroes().geti64(); + return 64 - c->value.countLeadingZeroes().geti64(); default: WASM_UNREACHABLE("invalid type"); } @@ -70,46 +70,40 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case SubInt32: case MulInt32: case RemSInt32: { - if (auto* const_ = binary->right->dynCast()) { + if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); if (maxBits == 32) { return 32; } - auto value = const_->value.geti32(); - return value <= 1 - ? Index(0) - : std::min(maxBits, - 32 - Index(CountLeadingZeroes(value - 1))); + auto value = c->value.geti32(); + return std::min(maxBits, 32 - Index(CountLeadingZeroes(value - 1))); } return 32; } case RemUInt32: { - if (auto* const_ = binary->right->dynCast()) { + if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); - auto value = const_->value.geti32(); - return value <= 1 - ? Index(0) - : std::min(maxBits, - 32 - Index(CountLeadingZeroes(value - 1))); + auto value = c->value.geti32(); + return std::min(maxBits, 32 - Index(CountLeadingZeroes(value - 1))); } return 32; } case DivUInt32: { - if (auto* const_ = binary->right->dynCast()) { - auto value = const_->value.geti32(); + if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); + auto value = c->value.geti32(); return std::max(Index(0), maxBits - (31 - Index(CountLeadingZeroes(value)))); } return 32; } case DivSInt32: { - if (auto* const_ = binary->right->dynCast()) { + if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); if (maxBits == 32) { return 32; } - auto value = const_->value.geti32(); + auto value = c->value.geti32(); return std::max(Index(0), maxBits - (31 - Index(CountLeadingZeroes(value)))); } @@ -160,46 +154,40 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case SubInt64: case MulInt64: case RemSInt64: { - if (auto* const_ = binary->right->dynCast()) { + if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); if (maxBits == 64) { return 64; } - auto value = const_->value.geti64(); - return value <= 1 - ? Index(0) - : std::min(maxBits, - 64 - Index(CountLeadingZeroes(value - 1))); + auto value = c->value.geti64(); + return std::min(maxBits, 64 - Index(CountLeadingZeroes(value - 1))); } return 64; } case RemUInt64: { - if (auto* const_ = binary->right->dynCast()) { + if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); - auto value = const_->value.geti64(); - return value <= 1 - ? Index(0) - : std::min(maxBits, - 64 - Index(CountLeadingZeroes(value - 1))); + auto value = c->value.geti64(); + return std::min(maxBits, 64 - Index(CountLeadingZeroes(value - 1))); } return 64; } case DivUInt64: { - if (auto* const_ = binary->right->dynCast()) { + if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); - auto value = const_->value.geti64(); + auto value = c->value.geti64(); return std::max(Index(0), maxBits - (63 - Index(CountLeadingZeroes(value)))); } return 64; } case DivSInt64: { - if (auto* const_ = binary->right->dynCast()) { + if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); if (maxBits == 64) { return 64; } - auto value = const_->value.geti64(); + auto value = c->value.geti64(); return std::max(Index(0), maxBits - (63 - Index(CountLeadingZeroes(value)))); } @@ -298,8 +286,10 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case WrapInt64: case ExtendUInt32: return std::min(Index(32), getMaxBits(unary->value, localInfoProvider)); - case ExtendSInt32: - return std::min(Index(64), getMaxBits(unary->value, localInfoProvider)); + case ExtendSInt32: { + auto maxBits = getMaxBits(unary->value, localInfoProvider); + return maxBits == 32 ? Index(64) : maxBits; + } default: {} } } else if (auto* set = curr->dynCast()) { From 2dc792c5e7aba8cefd7b2c917bb02994b8e1896a Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Sat, 30 May 2020 09:10:26 +0300 Subject: [PATCH 08/73] fix missing returns for rest cases --- src/passes/OptimizeInstructions.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index aab78e7bf8f..ce428ddb10c 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -69,6 +69,7 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case AddInt32: case SubInt32: case MulInt32: + return 32; case RemSInt32: { if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); @@ -153,6 +154,7 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case AddInt64: case SubInt64: case MulInt64: + return 64; case RemSInt64: { if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); From 36f73e5e484a7f787ebdcdd661caddfecfea107d Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Tue, 2 Jun 2020 21:53:01 +0300 Subject: [PATCH 09/73] rearrange cases --- src/passes/OptimizeInstructions.cpp | 53 ++++++++++++++--------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index ce428ddb10c..3f1878f990b 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -70,22 +70,15 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case SubInt32: case MulInt32: return 32; - case RemSInt32: { + case DivSInt32: { if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); if (maxBits == 32) { return 32; } auto value = c->value.geti32(); - return std::min(maxBits, 32 - Index(CountLeadingZeroes(value - 1))); - } - return 32; - } - case RemUInt32: { - if (auto* c = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - auto value = c->value.geti32(); - return std::min(maxBits, 32 - Index(CountLeadingZeroes(value - 1))); + return std::max(Index(0), + maxBits - (31 - Index(CountLeadingZeroes(value)))); } return 32; } @@ -98,15 +91,22 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { } return 32; } - case DivSInt32: { + case RemSInt32: { if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); if (maxBits == 32) { return 32; } auto value = c->value.geti32(); - return std::max(Index(0), - maxBits - (31 - Index(CountLeadingZeroes(value)))); + return std::min(maxBits, 32 - Index(CountLeadingZeroes(value - 1))); + } + return 32; + } + case RemUInt32: { + if (auto* c = binary->right->dynCast()) { + auto maxBits = getMaxBits(binary->left, localInfoProvider); + auto value = c->value.geti32(); + return std::min(maxBits, 32 - Index(CountLeadingZeroes(value - 1))); } return 32; } @@ -148,29 +148,21 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { } return 32; } - case RotLInt64: case RotRInt64: case AddInt64: case SubInt64: case MulInt64: return 64; - case RemSInt64: { + case DivSInt64: { if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); if (maxBits == 64) { return 64; } auto value = c->value.geti64(); - return std::min(maxBits, 64 - Index(CountLeadingZeroes(value - 1))); - } - return 64; - } - case RemUInt64: { - if (auto* c = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - auto value = c->value.geti64(); - return std::min(maxBits, 64 - Index(CountLeadingZeroes(value - 1))); + return std::max(Index(0), + maxBits - (63 - Index(CountLeadingZeroes(value)))); } return 64; } @@ -183,15 +175,22 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { } return 64; } - case DivSInt64: { + case RemSInt64: { if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); if (maxBits == 64) { return 64; } auto value = c->value.geti64(); - return std::max(Index(0), - maxBits - (63 - Index(CountLeadingZeroes(value)))); + return std::min(maxBits, 64 - Index(CountLeadingZeroes(value - 1))); + } + return 64; + } + case RemUInt64: { + if (auto* c = binary->right->dynCast()) { + auto maxBits = getMaxBits(binary->left, localInfoProvider); + auto value = c->value.geti64(); + return std::min(maxBits, 64 - Index(CountLeadingZeroes(value - 1))); } return 64; } From c77d5d4e4813574182751d5f975c1fecf0739f72 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 5 Jun 2020 16:18:38 +0300 Subject: [PATCH 10/73] calc getMaxBits also for multiply --- src/passes/OptimizeInstructions.cpp | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 3f1878f990b..b8d7a43ab98 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -68,8 +68,15 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case RotRInt32: case AddInt32: case SubInt32: - case MulInt32: - return 32; + return 32; + case MulInt32: { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 32) { + return 32; + } + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + return std::min(Index(32), maxBitsLeft + maxBitsRight); + } case DivSInt32: { if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); @@ -152,8 +159,15 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case RotRInt64: case AddInt64: case SubInt64: - case MulInt64: - return 64; + return 64; + case MulInt64: { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 64) { + return 64; + } + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + return std::min(Index(64), maxBitsLeft + maxBitsRight); + } case DivSInt64: { if (auto* c = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); From 0bba5b63b0c6f2788a39af08c4900905b6ae0d40 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 5 Jun 2020 16:20:59 +0300 Subject: [PATCH 11/73] lint --- src/passes/OptimizeInstructions.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index b8d7a43ab98..ff045f796cf 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -68,7 +68,7 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case RotRInt32: case AddInt32: case SubInt32: - return 32; + return 32; case MulInt32: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); if (maxBitsLeft == 32) { @@ -159,7 +159,7 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case RotRInt64: case AddInt64: case SubInt64: - return 64; + return 64; case MulInt64: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); if (maxBitsLeft == 64) { From f43c8db0f46934b9fb5091b5ddeb6590272eb83d Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 5 Jun 2020 16:39:29 +0300 Subject: [PATCH 12/73] generalize div / rem for all type dividers --- src/passes/OptimizeInstructions.cpp | 92 +++++++++---------------- test/emcc_hello_world.fromasm.imprecise | 9 +-- 2 files changed, 35 insertions(+), 66 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index ff045f796cf..51d69251930 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -78,44 +78,30 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { return std::min(Index(32), maxBitsLeft + maxBitsRight); } case DivSInt32: { - if (auto* c = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - if (maxBits == 32) { - return 32; - } - auto value = c->value.geti32(); - return std::max(Index(0), - maxBits - (31 - Index(CountLeadingZeroes(value)))); + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 32) { + return 32; } - return 32; + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + return std::max(Index(0), maxBitsLeft - maxBitsRight + 1); } case DivUInt32: { - if (auto* c = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - auto value = c->value.geti32(); - return std::max(Index(0), - maxBits - (31 - Index(CountLeadingZeroes(value)))); - } - return 32; + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + return std::max(Index(0), maxBitsLeft - maxBitsRight + 1); } case RemSInt32: { - if (auto* c = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - if (maxBits == 32) { - return 32; - } - auto value = c->value.geti32(); - return std::min(maxBits, 32 - Index(CountLeadingZeroes(value - 1))); + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 32) { + return 32; } - return 32; + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); } case RemUInt32: { - if (auto* c = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - auto value = c->value.geti32(); - return std::min(maxBits, 32 - Index(CountLeadingZeroes(value - 1))); - } - return 32; + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); } case AndInt32: return std::min(getMaxBits(binary->left, localInfoProvider), @@ -169,44 +155,30 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { return std::min(Index(64), maxBitsLeft + maxBitsRight); } case DivSInt64: { - if (auto* c = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - if (maxBits == 64) { - return 64; - } - auto value = c->value.geti64(); - return std::max(Index(0), - maxBits - (63 - Index(CountLeadingZeroes(value)))); + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 64) { + return 64; } - return 64; + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + return std::max(Index(0), maxBitsLeft - maxBitsRight + 1); } case DivUInt64: { - if (auto* c = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - auto value = c->value.geti64(); - return std::max(Index(0), - maxBits - (63 - Index(CountLeadingZeroes(value)))); - } - return 64; + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + return std::max(Index(0), maxBitsLeft - maxBitsRight + 1); } case RemSInt64: { - if (auto* c = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - if (maxBits == 64) { - return 64; - } - auto value = c->value.geti64(); - return std::min(maxBits, 64 - Index(CountLeadingZeroes(value - 1))); + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 64) { + return 64; } - return 64; + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); } case RemUInt64: { - if (auto* c = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - auto value = c->value.geti64(); - return std::min(maxBits, 64 - Index(CountLeadingZeroes(value - 1))); - } - return 64; + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); } case AndInt64: return std::min(getMaxBits(binary->left, localInfoProvider), diff --git a/test/emcc_hello_world.fromasm.imprecise b/test/emcc_hello_world.fromasm.imprecise index 4c5d7afd213..8a34e50073c 100644 --- a/test/emcc_hello_world.fromasm.imprecise +++ b/test/emcc_hello_world.fromasm.imprecise @@ -4772,12 +4772,9 @@ (select (f64.const 9007199254740994) (f64.const 9007199254740992) - (i32.and - (i32.div_u - (local.get $23) - (local.get $8) - ) - (i32.const 1) + (i32.div_u + (local.get $23) + (local.get $8) ) ) ) From a6415e1113f058d0a06174e511e65c14d2d5e2dc Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 5 Jun 2020 16:52:23 +0300 Subject: [PATCH 13/73] add fast paths when divider or multiplier is zero --- src/passes/OptimizeInstructions.cpp | 42 ++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 51d69251930..d38014de9e2 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -70,11 +70,14 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case SubInt32: return 32; case MulInt32: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 32) { + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + if (maxBitsRight == 32) { return 32; } - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + if (maxBitsRight == 0) { + return 0; + } + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); return std::min(Index(32), maxBitsLeft + maxBitsRight); } case DivSInt32: { @@ -82,11 +85,17 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { if (maxBitsLeft == 32) { return 32; } + if (maxBitsLeft == 0) { + return 0; + } auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::max(Index(0), maxBitsLeft - maxBitsRight + 1); } case DivUInt32: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::max(Index(0), maxBitsLeft - maxBitsRight + 1); } @@ -95,11 +104,17 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { if (maxBitsLeft == 32) { return 32; } + if (maxBitsLeft == 0) { + return 0; + } auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); } case RemUInt32: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); } @@ -147,11 +162,14 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case SubInt64: return 64; case MulInt64: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 64) { + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + if (maxBitsRight == 64) { return 64; } - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + if (maxBitsRight == 0) { + return 0; + } + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); return std::min(Index(64), maxBitsLeft + maxBitsRight); } case DivSInt64: { @@ -159,11 +177,17 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { if (maxBitsLeft == 64) { return 64; } + if (maxBitsLeft == 0) { + return 0; + } auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::max(Index(0), maxBitsLeft - maxBitsRight + 1); } case DivUInt64: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::max(Index(0), maxBitsLeft - maxBitsRight + 1); } @@ -172,11 +196,17 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { if (maxBitsLeft == 64) { return 64; } + if (maxBitsLeft == 0) { + return 0; + } auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); } case RemUInt64: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); } From d979620c9d7542644697000e4e09f3f57f3b9a7d Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 5 Jun 2020 19:24:15 +0300 Subject: [PATCH 14/73] more optimizations --- src/passes/OptimizeInstructions.cpp | 60 +++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index d38014de9e2..fbfcf871933 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -118,13 +118,21 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); } - case AndInt32: - return std::min(getMaxBits(binary->left, localInfoProvider), - getMaxBits(binary->right, localInfoProvider)); + case AndInt32: { + auto maxBits = getMaxBits(binary->right, localInfoProvider); + if (maxBits == 0) { + return 0; + } + return std::min(getMaxBits(binary->left, localInfoProvider), maxBits); + } case OrInt32: - case XorInt32: - return std::max(getMaxBits(binary->left, localInfoProvider), - getMaxBits(binary->right, localInfoProvider)); + case XorInt32: { + auto maxBits = getMaxBits(binary->right, localInfoProvider); + if (maxBits == 32) { + return 32; + } + return std::max(getMaxBits(binary->left, localInfoProvider), maxBits); + } case ShlInt32: { if (auto* shifts = binary->right->dynCast()) { return std::min(Index(32), @@ -136,6 +144,9 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case ShrUInt32: { if (auto* shift = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); + if (maxBits == 0) { + return 0; + } auto shifts = std::min(Index(Bits::getEffectiveShifts(shift)), maxBits); // can ignore more shifts than zero us out @@ -149,6 +160,9 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { if (maxBits == 32) { return 32; } + if (maxBits == 0) { + return 0; + } auto shifts = std::min(Index(Bits::getEffectiveShifts(shift)), maxBits); // can ignore more shifts than zero us out @@ -210,24 +224,37 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); } - case AndInt64: - return std::min(getMaxBits(binary->left, localInfoProvider), - getMaxBits(binary->right, localInfoProvider)); + case AndInt64: { + auto maxBits = getMaxBits(binary->right, localInfoProvider); + if (maxBits == 0) { + return 0; + } + return std::min(getMaxBits(binary->left, localInfoProvider), maxBits); + } case OrInt64: - case XorInt64: - return std::max(getMaxBits(binary->left, localInfoProvider), - getMaxBits(binary->right, localInfoProvider)); + case XorInt64: { + auto maxBits = getMaxBits(binary->right, localInfoProvider); + if (maxBits == 64) { + return 64; + } + return std::max(getMaxBits(binary->left, localInfoProvider), maxBits); + } case ShlInt64: { if (auto* shifts = binary->right->dynCast()) { - return std::min(Index(64), - getMaxBits(binary->left, localInfoProvider) + - Bits::getEffectiveShifts(shifts)); + auto maxBits = getMaxBits(binary->left, localInfoProvider); + if (maxBits == 0) { + return 0; + } + return std::min(Index(64), Bits::getEffectiveShifts(shifts) + maxBits); } return 64; } case ShrUInt64: { if (auto* shift = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); + if (maxBits == 0) { + return 0; + } auto shifts = std::min(Index(Bits::getEffectiveShifts(shift)), maxBits); // can ignore more shifts than zero us out @@ -241,6 +268,9 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { if (maxBits == 64) { return 64; } + if (maxBits == 0) { + return 0; + } auto shifts = std::min(Index(Bits::getEffectiveShifts(shift)), maxBits); // can ignore more shifts than zero us out From 6685e6d61fc713aee25653b4f2bd0bd0c4c1a249 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 5 Jun 2020 19:26:45 +0300 Subject: [PATCH 15/73] lint --- src/passes/OptimizeInstructions.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index fbfcf871933..2800221815f 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -245,7 +245,8 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { if (maxBits == 0) { return 0; } - return std::min(Index(64), Bits::getEffectiveShifts(shifts) + maxBits); + return std::min(Index(64), + Bits::getEffectiveShifts(shifts) + maxBits); } return 64; } From 7726f1880b8902175be8c40065bf7f23d23622cd Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 5 Jun 2020 21:41:30 +0300 Subject: [PATCH 16/73] revert generalizations for div / rem --- src/passes/OptimizeInstructions.cpp | 136 +++++++++++++++--------- test/emcc_hello_world.fromasm.imprecise | 9 +- 2 files changed, 90 insertions(+), 55 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 2800221815f..67d59463e94 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -81,42 +81,58 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { return std::min(Index(32), maxBitsLeft + maxBitsRight); } case DivSInt32: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 32) { - return 32; - } - if (maxBitsLeft == 0) { - return 0; + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 32) { + return 32; + } + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti32(); + auto maxBitsRight = 31 - Index(CountLeadingZeroes(value)); + return std::max(Index(0), maxBitsLeft - maxBitsRight); } - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - return std::max(Index(0), maxBitsLeft - maxBitsRight + 1); + return 32; } case DivUInt32: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti32(); + auto maxBitsRight = 31 - Index(CountLeadingZeroes(value)); + return std::max(Index(0), maxBitsLeft - maxBitsRight); } - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - return std::max(Index(0), maxBitsLeft - maxBitsRight + 1); + return 32; } case RemSInt32: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 32) { - return 32; - } - if (maxBitsLeft == 0) { - return 0; + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 32) { + return 32; + } + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti32(); + auto maxBitsRight = 32 - Index(CountLeadingZeroes(value - 1)); + return std::min(maxBitsLeft, maxBitsRight); } - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); + return 32; } case RemUInt32: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti32(); + auto maxBitsRight = 32 - Index(CountLeadingZeroes(value - 1)); + return std::min(maxBitsLeft, maxBitsRight); } - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); + return 32; } case AndInt32: { auto maxBits = getMaxBits(binary->right, localInfoProvider); @@ -187,42 +203,58 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { return std::min(Index(64), maxBitsLeft + maxBitsRight); } case DivSInt64: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 64) { - return 64; - } - if (maxBitsLeft == 0) { - return 0; + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 64) { + return 64; + } + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti32(); + auto maxBitsRight = 63 - Index(CountLeadingZeroes(value)); + return std::max(Index(0), maxBitsLeft - maxBitsRight); } - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - return std::max(Index(0), maxBitsLeft - maxBitsRight + 1); + return 64; } case DivUInt64: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti32(); + auto maxBitsRight = 63 - Index(CountLeadingZeroes(value)); + return std::max(Index(0), maxBitsLeft - maxBitsRight); } - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - return std::max(Index(0), maxBitsLeft - maxBitsRight + 1); + return 64; } case RemSInt64: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 64) { - return 64; - } - if (maxBitsLeft == 0) { - return 0; + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 64) { + return 64; + } + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti32(); + auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); + return std::min(maxBitsLeft, maxBitsRight); } - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); + return 64; } case RemUInt64: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti32(); + auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); + return std::min(maxBitsLeft, maxBitsRight); } - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - return std::min(maxBitsLeft, std::max(Index(0), maxBitsRight - 1)); + return 64; } case AndInt64: { auto maxBits = getMaxBits(binary->right, localInfoProvider); diff --git a/test/emcc_hello_world.fromasm.imprecise b/test/emcc_hello_world.fromasm.imprecise index 8a34e50073c..4c5d7afd213 100644 --- a/test/emcc_hello_world.fromasm.imprecise +++ b/test/emcc_hello_world.fromasm.imprecise @@ -4772,9 +4772,12 @@ (select (f64.const 9007199254740994) (f64.const 9007199254740992) - (i32.div_u - (local.get $23) - (local.get $8) + (i32.and + (i32.div_u + (local.get $23) + (local.get $8) + ) + (i32.const 1) ) ) ) From a39091a25f7c24a7485bbcdf7f7e9528a8e3bfd8 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 5 Jun 2020 21:56:29 +0300 Subject: [PATCH 17/73] return max bits of left expr for udiv as default case --- src/passes/OptimizeInstructions.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 67d59463e94..bba2e607ded 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -96,16 +96,16 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { return 32; } case DivUInt32: { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } if (auto* c = binary->right->dynCast()) { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; - } auto value = c->value.geti32(); auto maxBitsRight = 31 - Index(CountLeadingZeroes(value)); return std::max(Index(0), maxBitsLeft - maxBitsRight); } - return 32; + return maxBitsLeft; } case RemSInt32: { if (auto* c = binary->right->dynCast()) { @@ -218,16 +218,16 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { return 64; } case DivUInt64: { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } if (auto* c = binary->right->dynCast()) { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; - } auto value = c->value.geti32(); auto maxBitsRight = 63 - Index(CountLeadingZeroes(value)); return std::max(Index(0), maxBitsLeft - maxBitsRight); } - return 64; + return maxBitsLeft; } case RemSInt64: { if (auto* c = binary->right->dynCast()) { From df767f481a5d6bd6bb92e45968b6562ec74e7d7f Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Sat, 6 Jun 2020 11:02:55 +0300 Subject: [PATCH 18/73] return zero when lhs also zero for mul --- src/passes/OptimizeInstructions.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index bba2e607ded..8e180f181f7 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -78,6 +78,9 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { return 0; } auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } return std::min(Index(32), maxBitsLeft + maxBitsRight); } case DivSInt32: { @@ -200,6 +203,9 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { return 0; } auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } return std::min(Index(64), maxBitsLeft + maxBitsRight); } case DivSInt64: { From 6b8d232d5e8308a6ad2e8fb44ce5848cd3d40bf9 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 22 Jul 2020 22:39:27 +0300 Subject: [PATCH 19/73] wip --- src/passes/OptimizeInstructions.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 3db6b7dd887..2603d9efa70 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -70,6 +70,11 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case AddInt32: case SubInt32: return 32; + // case AddInt32: { + // auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + // auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + // return std::min(Index(32), std::max(maxBitsLeft, maxBitsRight) + 1); + // } case MulInt32: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); if (maxBitsRight == 32) { @@ -195,6 +200,11 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case AddInt64: case SubInt64: return 64; + // case AddInt64: { + // auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + // auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + // return std::min(Index(64), std::max(maxBitsLeft, maxBitsRight) + 1); + // } case MulInt64: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); if (maxBitsRight == 64) { From f387148ae5fe2f7e500cab67a180b36dfac3d919 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 22 Jul 2020 23:02:21 +0300 Subject: [PATCH 20/73] fix using geti32 instead geti64 for 64-bit consts --- src/passes/OptimizeInstructions.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 2603d9efa70..2db9ef57399 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -228,7 +228,7 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { if (maxBitsLeft == 0) { return 0; } - auto value = c->value.geti32(); + auto value = c->value.geti64(); auto maxBitsRight = 63 - Index(CountLeadingZeroes(value)); return std::max(Index(0), maxBitsLeft - maxBitsRight); } @@ -240,7 +240,7 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { return 0; } if (auto* c = binary->right->dynCast()) { - auto value = c->value.geti32(); + auto value = c->value.geti64(); auto maxBitsRight = 63 - Index(CountLeadingZeroes(value)); return std::max(Index(0), maxBitsLeft - maxBitsRight); } @@ -255,7 +255,7 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { if (maxBitsLeft == 0) { return 0; } - auto value = c->value.geti32(); + auto value = c->value.geti64(); auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); return std::min(maxBitsLeft, maxBitsRight); } @@ -267,7 +267,7 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { if (maxBitsLeft == 0) { return 0; } - auto value = c->value.geti32(); + auto value = c->value.geti64(); auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); return std::min(maxBitsLeft, maxBitsRight); } From 38ee4e79f69c43ea91ce64eae6a38f31cb4c5b64 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Thu, 23 Jul 2020 00:17:33 +0300 Subject: [PATCH 21/73] cleanups --- src/passes/OptimizeInstructions.cpp | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 2db9ef57399..9e29bdacf26 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -70,11 +70,6 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case AddInt32: case SubInt32: return 32; - // case AddInt32: { - // auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - // auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - // return std::min(Index(32), std::max(maxBitsLeft, maxBitsRight) + 1); - // } case MulInt32: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); if (maxBitsRight == 32) { @@ -200,11 +195,6 @@ Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { case AddInt64: case SubInt64: return 64; - // case AddInt64: { - // auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - // auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - // return std::min(Index(64), std::max(maxBitsLeft, maxBitsRight) + 1); - // } case MulInt64: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); if (maxBitsRight == 64) { From 2e9ab7642c401420ad70a9921a074597cf1435fa Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Tue, 4 Aug 2020 23:13:43 +0300 Subject: [PATCH 22/73] resolve conflicts --- src/ir/bits.h | 257 ++++++++++++++++++-- src/passes/OptimizeInstructions.cpp | 356 ---------------------------- 2 files changed, 233 insertions(+), 380 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index e0bca8d879b..ebca0e03965 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -121,42 +121,112 @@ struct DummyLocalInfoProvider { } }; -// Returns the maximum amount of bits used in an integer expression +// returns the maximum amount of bits used in an integer expression // not extremely precise (doesn't look into add operands, etc.) // LocalInfoProvider is an optional class that can provide answers about // local.get. -template -Index getMaxBits(Expression* curr, - LocalInfoProvider* localInfoProvider = nullptr) { - if (auto* const_ = curr->dynCast()) { +template +Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { + if (auto* c = curr->dynCast()) { switch (curr->type.getSingle()) { case Type::i32: - return 32 - const_->value.countLeadingZeroes().geti32(); + return 32 - c->value.countLeadingZeroes().geti32(); case Type::i64: - return 64 - const_->value.countLeadingZeroes().geti64(); + return 64 - c->value.countLeadingZeroes().geti64(); default: WASM_UNREACHABLE("invalid type"); } } else if (auto* binary = curr->dynCast()) { switch (binary->op) { // 32-bit - case AddInt32: - case SubInt32: - case MulInt32: - case DivSInt32: - case DivUInt32: - case RemSInt32: - case RemUInt32: case RotLInt32: case RotRInt32: + case AddInt32: + case SubInt32: + return 32; + case MulInt32: { + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + if (maxBitsRight == 32) { + return 32; + } + if (maxBitsRight == 0) { + return 0; + } + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } + return std::min(Index(32), maxBitsLeft + maxBitsRight); + } + case DivSInt32: { + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 32) { + return 32; + } + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti32(); + auto maxBitsRight = 31 - Index(CountLeadingZeroes(value)); + return std::max(Index(0), maxBitsLeft - maxBitsRight); + } + return 32; + } + case DivUInt32: { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } + if (auto* c = binary->right->dynCast()) { + auto value = c->value.geti32(); + auto maxBitsRight = 31 - Index(CountLeadingZeroes(value)); + return std::max(Index(0), maxBitsLeft - maxBitsRight); + } + return maxBitsLeft; + } + case RemSInt32: { + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 32) { + return 32; + } + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti32(); + auto maxBitsRight = 32 - Index(CountLeadingZeroes(value - 1)); + return std::min(maxBitsLeft, maxBitsRight); + } + return 32; + } + case RemUInt32: { + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti32(); + auto maxBitsRight = 32 - Index(CountLeadingZeroes(value - 1)); + return std::min(maxBitsLeft, maxBitsRight); + } return 32; - case AndInt32: - return std::min(getMaxBits(binary->left, localInfoProvider), - getMaxBits(binary->right, localInfoProvider)); + } + case AndInt32: { + auto maxBits = getMaxBits(binary->right, localInfoProvider); + if (maxBits == 0) { + return 0; + } + return std::min(getMaxBits(binary->left, localInfoProvider), maxBits); + } case OrInt32: - case XorInt32: - return std::max(getMaxBits(binary->left, localInfoProvider), - getMaxBits(binary->right, localInfoProvider)); + case XorInt32: { + auto maxBits = getMaxBits(binary->right, localInfoProvider); + if (maxBits == 32) { + return 32; + } + return std::max(getMaxBits(binary->left, localInfoProvider), maxBits); + } case ShlInt32: { if (auto* shifts = binary->right->dynCast()) { return std::min(Index(32), @@ -168,6 +238,9 @@ Index getMaxBits(Expression* curr, case ShrUInt32: { if (auto* shift = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); + if (maxBits == 0) { + return 0; + } auto shifts = std::min(Index(Bits::getEffectiveShifts(shift)), maxBits); // can ignore more shifts than zero us out @@ -181,6 +254,9 @@ Index getMaxBits(Expression* curr, if (maxBits == 32) { return 32; } + if (maxBits == 0) { + return 0; + } auto shifts = std::min(Index(Bits::getEffectiveShifts(shift)), maxBits); // can ignore more shifts than zero us out @@ -188,7 +264,134 @@ Index getMaxBits(Expression* curr, } return 32; } - // 64-bit TODO + case RotLInt64: + case RotRInt64: + case AddInt64: + case SubInt64: + return 64; + case MulInt64: { + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + if (maxBitsRight == 64) { + return 64; + } + if (maxBitsRight == 0) { + return 0; + } + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } + return std::min(Index(64), maxBitsLeft + maxBitsRight); + } + case DivSInt64: { + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 64) { + return 64; + } + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti64(); + auto maxBitsRight = 63 - Index(CountLeadingZeroes(value)); + return std::max(Index(0), maxBitsLeft - maxBitsRight); + } + return 64; + } + case DivUInt64: { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } + if (auto* c = binary->right->dynCast()) { + auto value = c->value.geti64(); + auto maxBitsRight = 63 - Index(CountLeadingZeroes(value)); + return std::max(Index(0), maxBitsLeft - maxBitsRight); + } + return maxBitsLeft; + } + case RemSInt64: { + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 64) { + return 64; + } + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti64(); + auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); + return std::min(maxBitsLeft, maxBitsRight); + } + return 64; + } + case RemUInt64: { + if (auto* c = binary->right->dynCast()) { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 0) { + return 0; + } + auto value = c->value.geti64(); + auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); + return std::min(maxBitsLeft, maxBitsRight); + } + return 64; + } + case AndInt64: { + auto maxBits = getMaxBits(binary->right, localInfoProvider); + if (maxBits == 0) { + return 0; + } + return std::min(getMaxBits(binary->left, localInfoProvider), maxBits); + } + case OrInt64: + case XorInt64: { + auto maxBits = getMaxBits(binary->right, localInfoProvider); + if (maxBits == 64) { + return 64; + } + return std::max(getMaxBits(binary->left, localInfoProvider), maxBits); + } + case ShlInt64: { + if (auto* shifts = binary->right->dynCast()) { + auto maxBits = getMaxBits(binary->left, localInfoProvider); + if (maxBits == 0) { + return 0; + } + return std::min(Index(64), + Bits::getEffectiveShifts(shifts) + maxBits); + } + return 64; + } + case ShrUInt64: { + if (auto* shift = binary->right->dynCast()) { + auto maxBits = getMaxBits(binary->left, localInfoProvider); + if (maxBits == 0) { + return 0; + } + auto shifts = + std::min(Index(Bits::getEffectiveShifts(shift)), + maxBits); // can ignore more shifts than zero us out + return std::max(Index(0), maxBits - shifts); + } + return 64; + } + case ShrSInt64: { + if (auto* shift = binary->right->dynCast()) { + auto maxBits = getMaxBits(binary->left, localInfoProvider); + if (maxBits == 64) { + return 64; + } + if (maxBits == 0) { + return 0; + } + auto shifts = + std::min(Index(Bits::getEffectiveShifts(shift)), + maxBits); // can ignore more shifts than zero us out + return std::max(Index(0), maxBits - shifts); + } + return 64; + } // comparisons case EqInt32: case NeInt32: @@ -200,6 +403,7 @@ Index getMaxBits(Expression* curr, case GtUInt32: case GeSInt32: case GeUInt32: + case EqInt64: case NeInt64: case LtSInt64: @@ -210,12 +414,14 @@ Index getMaxBits(Expression* curr, case GtUInt64: case GeSInt64: case GeUInt64: + case EqFloat32: case NeFloat32: case LtFloat32: case LeFloat32: case GtFloat32: case GeFloat32: + case EqFloat64: case NeFloat64: case LtFloat64: @@ -223,8 +429,7 @@ Index getMaxBits(Expression* curr, case GtFloat64: case GeFloat64: return 1; - default: { - } + default: {} } } else if (auto* unary = curr->dynCast()) { switch (unary->op) { @@ -240,9 +445,13 @@ Index getMaxBits(Expression* curr, case EqZInt64: return 1; case WrapInt64: + case ExtendUInt32: return std::min(Index(32), getMaxBits(unary->value, localInfoProvider)); - default: { + case ExtendSInt32: { + auto maxBits = getMaxBits(unary->value, localInfoProvider); + return maxBits == 32 ? Index(64) : maxBits; } + default: {} } } else if (auto* set = curr->dynCast()) { // a tee passes through the value diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 4ffa4c5df5d..38610c312bd 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -48,362 +48,6 @@ Name ANY_EXPR = "any.expr"; // Utilities -// returns the maximum amount of bits used in an integer expression -// not extremely precise (doesn't look into add operands, etc.) -// LocalInfoProvider is an optional class that can provide answers about -// local.get. -template -Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { - if (auto* c = curr->dynCast()) { - switch (curr->type.getSingle()) { - case Type::i32: - return 32 - c->value.countLeadingZeroes().geti32(); - case Type::i64: - return 64 - c->value.countLeadingZeroes().geti64(); - default: - WASM_UNREACHABLE("invalid type"); - } - } else if (auto* binary = curr->dynCast()) { - switch (binary->op) { - // 32-bit - case RotLInt32: - case RotRInt32: - case AddInt32: - case SubInt32: - return 32; - case MulInt32: { - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - if (maxBitsRight == 32) { - return 32; - } - if (maxBitsRight == 0) { - return 0; - } - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; - } - return std::min(Index(32), maxBitsLeft + maxBitsRight); - } - case DivSInt32: { - if (auto* c = binary->right->dynCast()) { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 32) { - return 32; - } - if (maxBitsLeft == 0) { - return 0; - } - auto value = c->value.geti32(); - auto maxBitsRight = 31 - Index(CountLeadingZeroes(value)); - return std::max(Index(0), maxBitsLeft - maxBitsRight); - } - return 32; - } - case DivUInt32: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; - } - if (auto* c = binary->right->dynCast()) { - auto value = c->value.geti32(); - auto maxBitsRight = 31 - Index(CountLeadingZeroes(value)); - return std::max(Index(0), maxBitsLeft - maxBitsRight); - } - return maxBitsLeft; - } - case RemSInt32: { - if (auto* c = binary->right->dynCast()) { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 32) { - return 32; - } - if (maxBitsLeft == 0) { - return 0; - } - auto value = c->value.geti32(); - auto maxBitsRight = 32 - Index(CountLeadingZeroes(value - 1)); - return std::min(maxBitsLeft, maxBitsRight); - } - return 32; - } - case RemUInt32: { - if (auto* c = binary->right->dynCast()) { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; - } - auto value = c->value.geti32(); - auto maxBitsRight = 32 - Index(CountLeadingZeroes(value - 1)); - return std::min(maxBitsLeft, maxBitsRight); - } - return 32; - } - case AndInt32: { - auto maxBits = getMaxBits(binary->right, localInfoProvider); - if (maxBits == 0) { - return 0; - } - return std::min(getMaxBits(binary->left, localInfoProvider), maxBits); - } - case OrInt32: - case XorInt32: { - auto maxBits = getMaxBits(binary->right, localInfoProvider); - if (maxBits == 32) { - return 32; - } - return std::max(getMaxBits(binary->left, localInfoProvider), maxBits); - } - case ShlInt32: { - if (auto* shifts = binary->right->dynCast()) { - return std::min(Index(32), - getMaxBits(binary->left, localInfoProvider) + - Bits::getEffectiveShifts(shifts)); - } - return 32; - } - case ShrUInt32: { - if (auto* shift = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - if (maxBits == 0) { - return 0; - } - auto shifts = - std::min(Index(Bits::getEffectiveShifts(shift)), - maxBits); // can ignore more shifts than zero us out - return std::max(Index(0), maxBits - shifts); - } - return 32; - } - case ShrSInt32: { - if (auto* shift = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - if (maxBits == 32) { - return 32; - } - if (maxBits == 0) { - return 0; - } - auto shifts = - std::min(Index(Bits::getEffectiveShifts(shift)), - maxBits); // can ignore more shifts than zero us out - return std::max(Index(0), maxBits - shifts); - } - return 32; - } - case RotLInt64: - case RotRInt64: - case AddInt64: - case SubInt64: - return 64; - case MulInt64: { - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - if (maxBitsRight == 64) { - return 64; - } - if (maxBitsRight == 0) { - return 0; - } - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; - } - return std::min(Index(64), maxBitsLeft + maxBitsRight); - } - case DivSInt64: { - if (auto* c = binary->right->dynCast()) { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 64) { - return 64; - } - if (maxBitsLeft == 0) { - return 0; - } - auto value = c->value.geti64(); - auto maxBitsRight = 63 - Index(CountLeadingZeroes(value)); - return std::max(Index(0), maxBitsLeft - maxBitsRight); - } - return 64; - } - case DivUInt64: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; - } - if (auto* c = binary->right->dynCast()) { - auto value = c->value.geti64(); - auto maxBitsRight = 63 - Index(CountLeadingZeroes(value)); - return std::max(Index(0), maxBitsLeft - maxBitsRight); - } - return maxBitsLeft; - } - case RemSInt64: { - if (auto* c = binary->right->dynCast()) { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 64) { - return 64; - } - if (maxBitsLeft == 0) { - return 0; - } - auto value = c->value.geti64(); - auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); - return std::min(maxBitsLeft, maxBitsRight); - } - return 64; - } - case RemUInt64: { - if (auto* c = binary->right->dynCast()) { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; - } - auto value = c->value.geti64(); - auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); - return std::min(maxBitsLeft, maxBitsRight); - } - return 64; - } - case AndInt64: { - auto maxBits = getMaxBits(binary->right, localInfoProvider); - if (maxBits == 0) { - return 0; - } - return std::min(getMaxBits(binary->left, localInfoProvider), maxBits); - } - case OrInt64: - case XorInt64: { - auto maxBits = getMaxBits(binary->right, localInfoProvider); - if (maxBits == 64) { - return 64; - } - return std::max(getMaxBits(binary->left, localInfoProvider), maxBits); - } - case ShlInt64: { - if (auto* shifts = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - if (maxBits == 0) { - return 0; - } - return std::min(Index(64), - Bits::getEffectiveShifts(shifts) + maxBits); - } - return 64; - } - case ShrUInt64: { - if (auto* shift = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - if (maxBits == 0) { - return 0; - } - auto shifts = - std::min(Index(Bits::getEffectiveShifts(shift)), - maxBits); // can ignore more shifts than zero us out - return std::max(Index(0), maxBits - shifts); - } - return 64; - } - case ShrSInt64: { - if (auto* shift = binary->right->dynCast()) { - auto maxBits = getMaxBits(binary->left, localInfoProvider); - if (maxBits == 64) { - return 64; - } - if (maxBits == 0) { - return 0; - } - auto shifts = - std::min(Index(Bits::getEffectiveShifts(shift)), - maxBits); // can ignore more shifts than zero us out - return std::max(Index(0), maxBits - shifts); - } - return 64; - } - // comparisons - case EqInt32: - case NeInt32: - case LtSInt32: - case LtUInt32: - case LeSInt32: - case LeUInt32: - case GtSInt32: - case GtUInt32: - case GeSInt32: - case GeUInt32: - - case EqInt64: - case NeInt64: - case LtSInt64: - case LtUInt64: - case LeSInt64: - case LeUInt64: - case GtSInt64: - case GtUInt64: - case GeSInt64: - case GeUInt64: - - case EqFloat32: - case NeFloat32: - case LtFloat32: - case LeFloat32: - case GtFloat32: - case GeFloat32: - - case EqFloat64: - case NeFloat64: - case LtFloat64: - case LeFloat64: - case GtFloat64: - case GeFloat64: - return 1; - default: {} - } - } else if (auto* unary = curr->dynCast()) { - switch (unary->op) { - case ClzInt32: - case CtzInt32: - case PopcntInt32: - return 6; - case ClzInt64: - case CtzInt64: - case PopcntInt64: - return 7; - case EqZInt32: - case EqZInt64: - return 1; - case WrapInt64: - case ExtendUInt32: - return std::min(Index(32), getMaxBits(unary->value, localInfoProvider)); - case ExtendSInt32: { - auto maxBits = getMaxBits(unary->value, localInfoProvider); - return maxBits == 32 ? Index(64) : maxBits; - } - default: {} - } - } else if (auto* set = curr->dynCast()) { - // a tee passes through the value - return getMaxBits(set->value, localInfoProvider); - } else if (auto* get = curr->dynCast()) { - return localInfoProvider->getMaxBitsForLocal(get); - } else if (auto* load = curr->dynCast()) { - // if signed, then the sign-extension might fill all the bits - // if unsigned, then we have a limit - if (LoadUtils::isSignRelevant(load) && !load->signed_) { - return 8 * load->bytes; - } - } - switch (curr->type.getSingle()) { - case Type::i32: - return 32; - case Type::i64: - return 64; - case Type::unreachable: - return 64; // not interesting, but don't crash - default: - WASM_UNREACHABLE("invalid type"); - } -} - // Useful information about locals struct LocalInfo { static const Index kUnknown = Index(-1); From 3ea4530375d511762243c80deed4272023ee4a24 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Tue, 4 Aug 2020 23:15:30 +0300 Subject: [PATCH 23/73] cleanups --- src/passes/OptimizeInstructions.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 38610c312bd..7f66ca7eed9 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -46,8 +46,6 @@ Name F32_EXPR = "f32.expr"; Name F64_EXPR = "f64.expr"; Name ANY_EXPR = "any.expr"; -// Utilities - // Useful information about locals struct LocalInfo { static const Index kUnknown = Index(-1); From 252ce01c6bedf48d5c40acbfe0ed00c959c247f0 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Tue, 4 Aug 2020 23:59:51 +0300 Subject: [PATCH 24/73] more fixes after resolving conflicts --- src/ir/bits.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index ebca0e03965..c0194ed2e5d 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -125,8 +125,9 @@ struct DummyLocalInfoProvider { // not extremely precise (doesn't look into add operands, etc.) // LocalInfoProvider is an optional class that can provide answers about // local.get. -template -Index getMaxBits(Expression* curr, LocalInfoProvider* localInfoProvider) { +template +Index getMaxBits(Expression* curr, + LocalInfoProvider* localInfoProvider = nullptr) { if (auto* c = curr->dynCast()) { switch (curr->type.getSingle()) { case Type::i32: From fd4e8cf0360b575e38f4b4254550bd3ffd86008c Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 00:35:52 +0300 Subject: [PATCH 25/73] more fancy unit test error output --- test/example/cpp-unit.cpp | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 2ba4388d197..5627ce40aeb 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -8,9 +8,23 @@ using namespace wasm; -void compare(size_t x, size_t y) { +#define FG_RED "\x1b[31m" +#define FG_GREEN "\x1b[32m" +#define FG_BLACK "\x1b[30m" + +#define BG_RED "\x1b[41m" +#define BG_BLACK "\x1b[40m" + +#define RESET "\x1b[0m" + +template +void assert_equal(T x, U y) { if (x != y) { - std::cout << "comparison error!\n" << x << '\n' << y << '\n'; + std::cerr << '\n' + << BG_RED FG_BLACK << "î‚° ASSERTION ERROR " << RESET FG_RED << "î‚°\n" + << FG_RED << " Actual: " << x << '\n' + << FG_GREEN << " Expected: " << y << '\n' + << RESET << std::endl; abort(); } } @@ -19,17 +33,17 @@ void test_bits() { Const c; c.type = Type::i32; c.value = Literal(int32_t(1)); - compare(Bits::getMaxBits(&c), 1); + assert_equal(Bits::getMaxBits(&c), 1); c.value = Literal(int32_t(2)); - compare(Bits::getMaxBits(&c), 2); + assert_equal(Bits::getMaxBits(&c), 2); c.value = Literal(int32_t(3)); - compare(Bits::getMaxBits(&c), 2); + assert_equal(Bits::getMaxBits(&c), 2); } void test_cost() { // Some optimizations assume that the cost of a get is zero, e.g. local-cse. LocalGet get; - compare(CostAnalyzer(&get).cost, 0); + assert_equal(CostAnalyzer(&get).cost, 0); } int main() { @@ -37,6 +51,6 @@ int main() { test_cost(); - std::cout << "Success.\n"; + std::cout << "Success" << std::endl; return 0; } From 60b7b55fe739163dae6de79de1d88bf0d22b6290 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 00:38:40 +0300 Subject: [PATCH 26/73] lint --- src/ir/bits.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index c0194ed2e5d..4163e2fa8af 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -430,7 +430,8 @@ Index getMaxBits(Expression* curr, case GtFloat64: case GeFloat64: return 1; - default: {} + default: { + } } } else if (auto* unary = curr->dynCast()) { switch (unary->op) { @@ -452,7 +453,8 @@ Index getMaxBits(Expression* curr, auto maxBits = getMaxBits(unary->value, localInfoProvider); return maxBits == 32 ? Index(64) : maxBits; } - default: {} + default: { + } } } else if (auto* set = curr->dynCast()) { // a tee passes through the value From d93f65d8e7af39667f8f4cf6b095a42e047ac7a6 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 00:48:21 +0300 Subject: [PATCH 27/73] fixture refresh --- test/example/cpp-unit.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/example/cpp-unit.txt b/test/example/cpp-unit.txt index a9d787cc55c..35821117c87 100644 --- a/test/example/cpp-unit.txt +++ b/test/example/cpp-unit.txt @@ -1 +1 @@ -Success. +Success From c9fe2cbf6137a841e5c8bff50cf8aab830c6c0ec Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 01:51:26 +0300 Subject: [PATCH 28/73] add basic tests --- src/ir/bits.h | 2 +- test/example/cpp-unit.cpp | 114 +++++++++++++++++++++++++++++++++++++- 2 files changed, 113 insertions(+), 3 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index 4163e2fa8af..0529a14d81a 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -121,7 +121,7 @@ struct DummyLocalInfoProvider { } }; -// returns the maximum amount of bits used in an integer expression +// Returns the maximum amount of bits used in an integer expression // not extremely precise (doesn't look into add operands, etc.) // LocalInfoProvider is an optional class that can provide answers about // local.get. diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 5627ce40aeb..37b47359e60 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -30,14 +30,124 @@ void assert_equal(T x, U y) { } void test_bits() { - Const c; + Const c, c0, c1; + Binary b; + + // --- // + // i32 // + // --- // + + // Const: i32 + c.type = Type::i32; + c.value = Literal(int32_t(0)); + assert_equal(Bits::getMaxBits(&c), 0); c.value = Literal(int32_t(1)); assert_equal(Bits::getMaxBits(&c), 1); c.value = Literal(int32_t(2)); assert_equal(Bits::getMaxBits(&c), 2); - c.value = Literal(int32_t(3)); + c.value = Literal(int32_t(-1)); + assert_equal(Bits::getMaxBits(&c), 32); + + b.type = Type::i32; + c0.type = Type::i32; + c1.type = Type::i32; + + b.left = &c0; + b.right = &c1; + + // Binary: AddInt32 + b.op = AddInt32; + c0.value = Literal(int32_t(0xFFFF)); + c1.value = Literal(int32_t(0x11)); + assert_equal(Bits::getMaxBits(&b), 32); + c0.value = Literal(int32_t(-1)); + c1.value = Literal(int32_t(2)); + assert_equal(Bits::getMaxBits(&b), 32); + + // Binary: AddInt32 + b.op = SubInt32; + c0.value = Literal(int32_t(0xFFFF)); + c1.value = Literal(int32_t(0x11)); + assert_equal(Bits::getMaxBits(&b), 32); + c0.value = Literal(int32_t(-1)); + c1.value = Literal(int32_t(2)); + assert_equal(Bits::getMaxBits(&b), 32); + + // Binary: MulInt32 + b.op = MulInt32; + c0.value = Literal(int32_t(0xFFFF)); + c1.value = Literal(int32_t(0x11)); + assert_equal(Bits::getMaxBits(&b), 21); + c0.value = Literal(int32_t(0)); + c1.value = Literal(int32_t(1)); + assert_equal(Bits::getMaxBits(&b), 0); + c0.value = Literal(int32_t(1)); + c1.value = Literal(int32_t(0)); + assert_equal(Bits::getMaxBits(&b), 0); + c0.value = Literal(int32_t(3)); + c1.value = Literal(int32_t(3)); + assert_equal(Bits::getMaxBits(&b), 4); + c0.value = Literal(int32_t(2)); + c1.value = Literal(int32_t(-2)); + assert_equal(Bits::getMaxBits(&b), 32); + + // --- // + // i64 // + // --- // + + c.type = Type::i64; + + // Const: i64 + + c.value = Literal(int64_t(0)); + assert_equal(Bits::getMaxBits(&c), 0); + c.value = Literal(int64_t(1)); + assert_equal(Bits::getMaxBits(&c), 1); + c.value = Literal(int64_t(2)); assert_equal(Bits::getMaxBits(&c), 2); + c.value = Literal(int64_t(-1)); + assert_equal(Bits::getMaxBits(&c), 64); + + c0.type = Type::i64; + c1.type = Type::i64; + b.type = Type::i64; + + // Binary: AddInt64 + b.op = AddInt64; + c0.value = Literal(int64_t(0xFFFF)); + c1.value = Literal(int64_t(0x11)); + assert_equal(Bits::getMaxBits(&b), 64); + c0.value = Literal(int64_t(-1)); + c1.value = Literal(int64_t(2)); + assert_equal(Bits::getMaxBits(&b), 64); + + // Binary: AddInt64 + b.op = SubInt64; + c0.value = Literal(int64_t(0xFFFF)); + c1.value = Literal(int64_t(0x11)); + assert_equal(Bits::getMaxBits(&b), 64); + c0.value = Literal(int64_t(-1)); + c1.value = Literal(int64_t(2)); + assert_equal(Bits::getMaxBits(&b), 64); + + // Binary: MulInt64 + b.op = MulInt64; + c0.value = Literal(int64_t(0xFFFF)); + c1.value = Literal(int64_t(0x11)); + assert_equal(Bits::getMaxBits(&b), 21); + c0.value = Literal(int64_t(0)); + c1.value = Literal(int64_t(1)); + assert_equal(Bits::getMaxBits(&b), 0); + c0.value = Literal(int64_t(1)); + c1.value = Literal(int64_t(0)); + assert_equal(Bits::getMaxBits(&b), 0); + c0.value = Literal(int64_t(3)); + c1.value = Literal(int64_t(3)); + assert_equal(Bits::getMaxBits(&b), 4); + c0.value = Literal(int64_t(2)); + c1.value = Literal(int64_t(-2)); + assert_equal(Bits::getMaxBits(&b), 64); } void test_cost() { From 14ae90c498c6bbc900ad3de477076322cc586a05 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 02:20:48 +0300 Subject: [PATCH 29/73] print line and file for assertion errors --- test/example/cpp-unit.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 37b47359e60..082005ce115 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -8,9 +8,10 @@ using namespace wasm; -#define FG_RED "\x1b[31m" -#define FG_GREEN "\x1b[32m" -#define FG_BLACK "\x1b[30m" +#define FG_RED "\x1b[31m" +#define FG_GREEN "\x1b[32m" +#define FG_BLACK "\x1b[30m" +#define FG_YELLOW "\x1b[33m" #define BG_RED "\x1b[41m" #define BG_BLACK "\x1b[40m" @@ -18,17 +19,21 @@ using namespace wasm; #define RESET "\x1b[0m" template -void assert_equal(T x, U y) { +void assert_equal_(T x, U y, int line, const char* file) { if (x != y) { std::cerr << '\n' << BG_RED FG_BLACK << "î‚° ASSERTION ERROR " << RESET FG_RED << "î‚°\n" << FG_RED << " Actual: " << x << '\n' - << FG_GREEN << " Expected: " << y << '\n' + << FG_GREEN << " Expected: " << y << "\n\n" + << FG_YELLOW << " Line: " << line << '\n' + << FG_YELLOW << " File: " << file << '\n' << RESET << std::endl; abort(); } } +#define assert_equal(a, b) assert_equal_((a), (b), __LINE__, __FILE__) + void test_bits() { Const c, c0, c1; Binary b; @@ -41,7 +46,7 @@ void test_bits() { c.type = Type::i32; c.value = Literal(int32_t(0)); - assert_equal(Bits::getMaxBits(&c), 0); + assert_equal(Bits::getMaxBits(&c), 1); c.value = Literal(int32_t(1)); assert_equal(Bits::getMaxBits(&c), 1); c.value = Literal(int32_t(2)); From 90f39d4e3331390f67374daa002c4e1e4c31fac0 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 02:29:23 +0300 Subject: [PATCH 30/73] more --- test/example/cpp-unit.cpp | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 082005ce115..4c50de9ac3a 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -18,17 +18,19 @@ using namespace wasm; #define RESET "\x1b[0m" +static int assertFailCount = 0; + template void assert_equal_(T x, U y, int line, const char* file) { if (x != y) { std::cerr << '\n' - << BG_RED FG_BLACK << "î‚° ASSERTION ERROR " << RESET FG_RED << "î‚°\n" + << BG_RED FG_BLACK << "î‚° ASSERTION ERROR " + << ++assertFailCount << " " << RESET FG_RED << "î‚°\n" << FG_RED << " Actual: " << x << '\n' << FG_GREEN << " Expected: " << y << "\n\n" << FG_YELLOW << " Line: " << line << '\n' << FG_YELLOW << " File: " << file << '\n' << RESET << std::endl; - abort(); } } @@ -46,7 +48,7 @@ void test_bits() { c.type = Type::i32; c.value = Literal(int32_t(0)); - assert_equal(Bits::getMaxBits(&c), 1); + assert_equal(Bits::getMaxBits(&c), 0); c.value = Literal(int32_t(1)); assert_equal(Bits::getMaxBits(&c), 1); c.value = Literal(int32_t(2)); @@ -163,9 +165,12 @@ void test_cost() { int main() { test_bits(); - test_cost(); - std::cout << "Success" << std::endl; + if (assertFailCount > 0) { + abort(); + } else { + std::cout << "Success" << std::endl; + } return 0; } From 5a992141ed5eeecce1a1988f3ecd82e7b8d76437 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 02:34:23 +0300 Subject: [PATCH 31/73] refactor --- test/example/cpp-unit.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 4c50de9ac3a..2d27b2fc637 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -18,18 +18,19 @@ using namespace wasm; #define RESET "\x1b[0m" -static int assertFailCount = 0; +static int failCounts = 0; template -void assert_equal_(T x, U y, int line, const char* file) { - if (x != y) { +void assert_equal_(T a, U b, int line, const char* file) { + if (a != b) { std::cerr << '\n' << BG_RED FG_BLACK << "î‚° ASSERTION ERROR " - << ++assertFailCount << " " << RESET FG_RED << "î‚°\n" - << FG_RED << " Actual: " << x << '\n' - << FG_GREEN << " Expected: " << y << "\n\n" - << FG_YELLOW << " Line: " << line << '\n' - << FG_YELLOW << " File: " << file << '\n' + << ++failCounts << " " + << RESET FG_RED << "î‚°\n" + << FG_RED << " Actual: " << a << '\n' + << FG_GREEN << " Expected: " << b << "\n\n" + << FG_YELLOW << " Line: " << line << '\n' + << FG_YELLOW << " File: " << file << '\n' << RESET << std::endl; } } @@ -167,7 +168,7 @@ int main() { test_bits(); test_cost(); - if (assertFailCount > 0) { + if (failCounts > 0) { abort(); } else { std::cout << "Success" << std::endl; From 64aded9c81e7914893620d81d383602d46052dff Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 02:35:02 +0300 Subject: [PATCH 32/73] -> failCount --- test/example/cpp-unit.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 2d27b2fc637..c86e68a3f1b 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -18,14 +18,14 @@ using namespace wasm; #define RESET "\x1b[0m" -static int failCounts = 0; +static int failCount = 0; template void assert_equal_(T a, U b, int line, const char* file) { if (a != b) { std::cerr << '\n' << BG_RED FG_BLACK << "î‚° ASSERTION ERROR " - << ++failCounts << " " + << ++failCount << " " << RESET FG_RED << "î‚°\n" << FG_RED << " Actual: " << a << '\n' << FG_GREEN << " Expected: " << b << "\n\n" @@ -168,7 +168,7 @@ int main() { test_bits(); test_cost(); - if (failCounts > 0) { + if (failCount > 0) { abort(); } else { std::cout << "Success" << std::endl; From 4b2061a1234f965ba5118cf0e638106972bff18e Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 03:25:54 +0300 Subject: [PATCH 33/73] -> failsCount --- test/example/cpp-unit.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index c86e68a3f1b..50a08ea6b75 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -18,14 +18,14 @@ using namespace wasm; #define RESET "\x1b[0m" -static int failCount = 0; +static int failsCount = 0; template void assert_equal_(T a, U b, int line, const char* file) { if (a != b) { std::cerr << '\n' << BG_RED FG_BLACK << "î‚° ASSERTION ERROR " - << ++failCount << " " + << ++failsCount << " " << RESET FG_RED << "î‚°\n" << FG_RED << " Actual: " << a << '\n' << FG_GREEN << " Expected: " << b << "\n\n" @@ -168,7 +168,7 @@ int main() { test_bits(); test_cost(); - if (failCount > 0) { + if (failsCount > 0) { abort(); } else { std::cout << "Success" << std::endl; From 216b6fab79647eb1e582d8fea6f679e4b9e7c2e1 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 03:37:23 +0300 Subject: [PATCH 34/73] simplify output to cout as well --- test/example/cpp-unit.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 50a08ea6b75..425ea5f5b6f 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -32,6 +32,12 @@ void assert_equal_(T a, U b, int line, const char* file) { << FG_YELLOW << " Line: " << line << '\n' << FG_YELLOW << " File: " << file << '\n' << RESET << std::endl; + + std::cout << "actual: " << a + << ", expected: " << b + << ", line " << line + << ", file " << file + << std::endl; } } From c631b94bcaf750187295b6f29242889363ed7546 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 13:16:24 +0300 Subject: [PATCH 35/73] add basic tests fo divs --- test/example/cpp-unit.cpp | 90 ++++++++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 20 deletions(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 425ea5f5b6f..46fd6b710f8 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -47,13 +47,18 @@ void test_bits() { Const c, c0, c1; Binary b; + b.left = &c0; + b.right = &c1; + // --- // // i32 // // --- // - // Const: i32 + c.type = Type::i32; + c0.type = Type::i32; + c1.type = Type::i32; + b.type = Type::i32; - c.type = Type::i32; c.value = Literal(int32_t(0)); assert_equal(Bits::getMaxBits(&c), 0); c.value = Literal(int32_t(1)); @@ -63,14 +68,6 @@ void test_bits() { c.value = Literal(int32_t(-1)); assert_equal(Bits::getMaxBits(&c), 32); - b.type = Type::i32; - c0.type = Type::i32; - c1.type = Type::i32; - - b.left = &c0; - b.right = &c1; - - // Binary: AddInt32 b.op = AddInt32; c0.value = Literal(int32_t(0xFFFF)); c1.value = Literal(int32_t(0x11)); @@ -79,7 +76,6 @@ void test_bits() { c1.value = Literal(int32_t(2)); assert_equal(Bits::getMaxBits(&b), 32); - // Binary: AddInt32 b.op = SubInt32; c0.value = Literal(int32_t(0xFFFF)); c1.value = Literal(int32_t(0x11)); @@ -88,7 +84,6 @@ void test_bits() { c1.value = Literal(int32_t(2)); assert_equal(Bits::getMaxBits(&b), 32); - // Binary: MulInt32 b.op = MulInt32; c0.value = Literal(int32_t(0xFFFF)); c1.value = Literal(int32_t(0x11)); @@ -106,11 +101,44 @@ void test_bits() { c1.value = Literal(int32_t(-2)); assert_equal(Bits::getMaxBits(&b), 32); + b.op = DivSInt32; + c0.value = Literal(int32_t(0)); + c1.value = Literal(int32_t(0xF)); + assert_equal(Bits::getMaxBits(&b), 0); + c0.value = Literal(int32_t( 1)); + c1.value = Literal(int32_t( 2)); + assert_equal(Bits::getMaxBits(&b), 0); + c0.value = Literal(int32_t(0xFF)); + c1.value = Literal(int32_t(0xFF)); + assert_equal(Bits::getMaxBits(&b), 1); + c0.value = Literal(int32_t(-1)); + c1.value = Literal(int32_t( 1)); + assert_equal(Bits::getMaxBits(&b), 32); + + + b.op = DivUInt32; + c0.value = Literal(uint32_t(0)); + c1.value = Literal(uint32_t(0xF)); + assert_equal(Bits::getMaxBits(&b), 0); + c0.value = Literal(int32_t( 1)); + c1.value = Literal(int32_t( 2)); + assert_equal(Bits::getMaxBits(&b), 0); + c0.value = Literal(int32_t(0xFF)); + c1.value = Literal(int32_t(0xFF)); + assert_equal(Bits::getMaxBits(&b), 1); + c0.value = Literal(int32_t(-1)); + c1.value = Literal(int32_t( 1)); + assert_equal(Bits::getMaxBits(&b), 32); + + // --- // // i64 // // --- // - c.type = Type::i64; + c.type = Type::i64; + c0.type = Type::i64; + c1.type = Type::i64; + b.type = Type::i64; // Const: i64 @@ -123,11 +151,6 @@ void test_bits() { c.value = Literal(int64_t(-1)); assert_equal(Bits::getMaxBits(&c), 64); - c0.type = Type::i64; - c1.type = Type::i64; - b.type = Type::i64; - - // Binary: AddInt64 b.op = AddInt64; c0.value = Literal(int64_t(0xFFFF)); c1.value = Literal(int64_t(0x11)); @@ -136,7 +159,6 @@ void test_bits() { c1.value = Literal(int64_t(2)); assert_equal(Bits::getMaxBits(&b), 64); - // Binary: AddInt64 b.op = SubInt64; c0.value = Literal(int64_t(0xFFFF)); c1.value = Literal(int64_t(0x11)); @@ -145,7 +167,6 @@ void test_bits() { c1.value = Literal(int64_t(2)); assert_equal(Bits::getMaxBits(&b), 64); - // Binary: MulInt64 b.op = MulInt64; c0.value = Literal(int64_t(0xFFFF)); c1.value = Literal(int64_t(0x11)); @@ -162,6 +183,35 @@ void test_bits() { c0.value = Literal(int64_t(2)); c1.value = Literal(int64_t(-2)); assert_equal(Bits::getMaxBits(&b), 64); + + b.op = DivSInt64; + c0.value = Literal(int64_t(0)); + c1.value = Literal(int64_t(0xF)); + assert_equal(Bits::getMaxBits(&b), 0); + c0.value = Literal(int64_t( 1)); + c1.value = Literal(int64_t( 2)); + assert_equal(Bits::getMaxBits(&b), 0); + c0.value = Literal(int64_t(0xFF)); + c1.value = Literal(int64_t(0xFF)); + assert_equal(Bits::getMaxBits(&b), 1); + c0.value = Literal(int64_t(-1)); + c1.value = Literal(int64_t( 1)); + assert_equal(Bits::getMaxBits(&b), 64); + + + b.op = DivUInt64; + c0.value = Literal(uint64_t(0)); + c1.value = Literal(uint64_t(0xF)); + assert_equal(Bits::getMaxBits(&b), 0); + c0.value = Literal(uint64_t( 1)); + c1.value = Literal(uint64_t( 2)); + assert_equal(Bits::getMaxBits(&b), 0); + c0.value = Literal(uint64_t(0xFF)); + c1.value = Literal(uint64_t(0xFF)); + assert_equal(Bits::getMaxBits(&b), 1); + c0.value = Literal(uint64_t(-1)); + c1.value = Literal(uint64_t( 1)); + assert_equal(Bits::getMaxBits(&b), 64); } void test_cost() { From d0a493874991240ed482a760ad07a9b86112d644 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 13:20:38 +0300 Subject: [PATCH 36/73] finish div tests --- test/example/cpp-unit.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 46fd6b710f8..a17f3f3d4a3 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -114,21 +114,27 @@ void test_bits() { c0.value = Literal(int32_t(-1)); c1.value = Literal(int32_t( 1)); assert_equal(Bits::getMaxBits(&b), 32); + c0.value = Literal(int32_t(-1)); + c1.value = Literal(int32_t( 2)); + assert_equal(Bits::getMaxBits(&b), 32); b.op = DivUInt32; c0.value = Literal(uint32_t(0)); c1.value = Literal(uint32_t(0xF)); assert_equal(Bits::getMaxBits(&b), 0); - c0.value = Literal(int32_t( 1)); - c1.value = Literal(int32_t( 2)); + c0.value = Literal(uint32_t( 1)); + c1.value = Literal(uint32_t( 2)); assert_equal(Bits::getMaxBits(&b), 0); - c0.value = Literal(int32_t(0xFF)); - c1.value = Literal(int32_t(0xFF)); + c0.value = Literal(uint32_t(0xFF)); + c1.value = Literal(uint32_t(0xFF)); assert_equal(Bits::getMaxBits(&b), 1); - c0.value = Literal(int32_t(-1)); - c1.value = Literal(int32_t( 1)); + c0.value = Literal(uint32_t(-1)); + c1.value = Literal(uint32_t( 1)); assert_equal(Bits::getMaxBits(&b), 32); + c0.value = Literal(uint32_t(-1)); + c1.value = Literal(uint32_t( 2)); + assert_equal(Bits::getMaxBits(&b), 31); // --- // @@ -197,6 +203,9 @@ void test_bits() { c0.value = Literal(int64_t(-1)); c1.value = Literal(int64_t( 1)); assert_equal(Bits::getMaxBits(&b), 64); + c0.value = Literal(int64_t(-1)); + c1.value = Literal(int64_t( 2)); + assert_equal(Bits::getMaxBits(&b), 64); b.op = DivUInt64; @@ -212,6 +221,9 @@ void test_bits() { c0.value = Literal(uint64_t(-1)); c1.value = Literal(uint64_t( 1)); assert_equal(Bits::getMaxBits(&b), 64); + c0.value = Literal(uint64_t(-1)); + c1.value = Literal(uint64_t( 2)); + assert_equal(Bits::getMaxBits(&b), 63); } void test_cost() { From 543d2397ece42d8aefca133b4c575680196d3b10 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 13:23:17 +0300 Subject: [PATCH 37/73] more --- test/example/cpp-unit.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index a17f3f3d4a3..865a62e6d6a 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -117,6 +117,9 @@ void test_bits() { c0.value = Literal(int32_t(-1)); c1.value = Literal(int32_t( 2)); assert_equal(Bits::getMaxBits(&b), 32); + c0.value = Literal(int32_t(0x7FFFFFFF)); + c1.value = Literal(int32_t(3)); + assert_equal(Bits::getMaxBits(&b), 30); b.op = DivUInt32; @@ -135,6 +138,9 @@ void test_bits() { c0.value = Literal(uint32_t(-1)); c1.value = Literal(uint32_t( 2)); assert_equal(Bits::getMaxBits(&b), 31); + c0.value = Literal(uint32_t(0x7FFFFFFF)); + c1.value = Literal(uint32_t(3)); + assert_equal(Bits::getMaxBits(&b), 30); // --- // @@ -206,6 +212,9 @@ void test_bits() { c0.value = Literal(int64_t(-1)); c1.value = Literal(int64_t( 2)); assert_equal(Bits::getMaxBits(&b), 64); + c0.value = Literal(int64_t(0x7FFFFFFFFFFFFFFF)); + c1.value = Literal(int64_t(3)); + assert_equal(Bits::getMaxBits(&b), 62); b.op = DivUInt64; @@ -224,6 +233,9 @@ void test_bits() { c0.value = Literal(uint64_t(-1)); c1.value = Literal(uint64_t( 2)); assert_equal(Bits::getMaxBits(&b), 63); + c0.value = Literal(uint64_t(0x7FFFFFFFFFFFFFFF)); + c1.value = Literal(uint64_t(3)); + assert_equal(Bits::getMaxBits(&b), 62); } void test_cost() { From 56731016d5b41b434cd515791fcca4cf36248531 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 13:54:44 +0300 Subject: [PATCH 38/73] more --- test/example/cpp-unit.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 865a62e6d6a..960fffd83ff 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -120,6 +120,9 @@ void test_bits() { c0.value = Literal(int32_t(0x7FFFFFFF)); c1.value = Literal(int32_t(3)); assert_equal(Bits::getMaxBits(&b), 30); + c0.value = Literal(int32_t(0x80000000)); + c1.value = Literal(int32_t(-1)); + assert_equal(Bits::getMaxBits(&b), 32); b.op = DivUInt32; @@ -141,6 +144,9 @@ void test_bits() { c0.value = Literal(uint32_t(0x7FFFFFFF)); c1.value = Literal(uint32_t(3)); assert_equal(Bits::getMaxBits(&b), 30); + c0.value = Literal(uint32_t(0x80000000)); + c1.value = Literal(uint32_t(-1)); + assert_equal(Bits::getMaxBits(&b), 1); // --- // @@ -215,6 +221,9 @@ void test_bits() { c0.value = Literal(int64_t(0x7FFFFFFFFFFFFFFF)); c1.value = Literal(int64_t(3)); assert_equal(Bits::getMaxBits(&b), 62); + c0.value = Literal(int64_t(0x8000000000000000)); + c1.value = Literal(int64_t(-1)); + assert_equal(Bits::getMaxBits(&b), 64); b.op = DivUInt64; @@ -236,6 +245,9 @@ void test_bits() { c0.value = Literal(uint64_t(0x7FFFFFFFFFFFFFFF)); c1.value = Literal(uint64_t(3)); assert_equal(Bits::getMaxBits(&b), 62); + c0.value = Literal(uint64_t(0x8000000000000000)); + c1.value = Literal(uint64_t(-1)); + assert_equal(Bits::getMaxBits(&b), 1); } void test_cost() { From 85674875aa1c0ed47f89f02b4e9c910c9dfb0a72 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 14:49:52 +0300 Subject: [PATCH 39/73] reduce to two consts --- test/example/cpp-unit.cpp | 40 ++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 960fffd83ff..19f67c30293 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -44,7 +44,7 @@ void assert_equal_(T a, U b, int line, const char* file) { #define assert_equal(a, b) assert_equal_((a), (b), __LINE__, __FILE__) void test_bits() { - Const c, c0, c1; + Const c0, c1; Binary b; b.left = &c0; @@ -54,19 +54,20 @@ void test_bits() { // i32 // // --- // - c.type = Type::i32; c0.type = Type::i32; c1.type = Type::i32; b.type = Type::i32; - c.value = Literal(int32_t(0)); - assert_equal(Bits::getMaxBits(&c), 0); - c.value = Literal(int32_t(1)); - assert_equal(Bits::getMaxBits(&c), 1); - c.value = Literal(int32_t(2)); - assert_equal(Bits::getMaxBits(&c), 2); - c.value = Literal(int32_t(-1)); - assert_equal(Bits::getMaxBits(&c), 32); + c0.value = Literal(int32_t(0)); + assert_equal(Bits::getMaxBits(&c0), 0); + c0.value = Literal(int32_t(1)); + assert_equal(Bits::getMaxBits(&c0), 1); + c0.value = Literal(int32_t(2)); + assert_equal(Bits::getMaxBits(&c0), 2); + c0.value = Literal(int32_t(0x80000)); + assert_equal(Bits::getMaxBits(&c0), 20); + c0.value = Literal(int32_t(-1)); + assert_equal(Bits::getMaxBits(&c0), 32); b.op = AddInt32; c0.value = Literal(int32_t(0xFFFF)); @@ -153,21 +154,22 @@ void test_bits() { // i64 // // --- // - c.type = Type::i64; c0.type = Type::i64; c1.type = Type::i64; b.type = Type::i64; // Const: i64 - c.value = Literal(int64_t(0)); - assert_equal(Bits::getMaxBits(&c), 0); - c.value = Literal(int64_t(1)); - assert_equal(Bits::getMaxBits(&c), 1); - c.value = Literal(int64_t(2)); - assert_equal(Bits::getMaxBits(&c), 2); - c.value = Literal(int64_t(-1)); - assert_equal(Bits::getMaxBits(&c), 64); + c0.value = Literal(int64_t(0)); + assert_equal(Bits::getMaxBits(&c0), 0); + c0.value = Literal(int64_t(1)); + assert_equal(Bits::getMaxBits(&c0), 1); + c0.value = Literal(int64_t(2)); + assert_equal(Bits::getMaxBits(&c0), 2); + c0.value = Literal(int64_t(0x80000)); + assert_equal(Bits::getMaxBits(&c0), 20); + c0.value = Literal(int64_t(-1)); + assert_equal(Bits::getMaxBits(&c0), 64); b.op = AddInt64; c0.value = Literal(int64_t(0xFFFF)); From 957e945440e409605d592f07a9f33e05b0ac1a55 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 14:51:54 +0300 Subject: [PATCH 40/73] reorder color consts --- test/example/cpp-unit.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 19f67c30293..b22953581a5 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -8,15 +8,15 @@ using namespace wasm; +#define RESET "\x1b[0m" + +#define FG_BLACK "\x1b[30m" #define FG_RED "\x1b[31m" #define FG_GREEN "\x1b[32m" -#define FG_BLACK "\x1b[30m" #define FG_YELLOW "\x1b[33m" -#define BG_RED "\x1b[41m" -#define BG_BLACK "\x1b[40m" - -#define RESET "\x1b[0m" +#define BG_BLACK "\x1b[40m" +#define BG_RED "\x1b[41m" static int failsCount = 0; From d5d6d2bc20f8d4598cd662c984eb72044eefbef4 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 14:53:58 +0300 Subject: [PATCH 41/73] use Bits ns --- test/example/cpp-unit.cpp | 113 +++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 56 deletions(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index b22953581a5..06c5d4d1e52 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -7,6 +7,7 @@ #include using namespace wasm; +using namespace Bits; #define RESET "\x1b[0m" @@ -59,95 +60,95 @@ void test_bits() { b.type = Type::i32; c0.value = Literal(int32_t(0)); - assert_equal(Bits::getMaxBits(&c0), 0); + assert_equal(getMaxBits(&c0), 0); c0.value = Literal(int32_t(1)); - assert_equal(Bits::getMaxBits(&c0), 1); + assert_equal(getMaxBits(&c0), 1); c0.value = Literal(int32_t(2)); - assert_equal(Bits::getMaxBits(&c0), 2); + assert_equal(getMaxBits(&c0), 2); c0.value = Literal(int32_t(0x80000)); - assert_equal(Bits::getMaxBits(&c0), 20); + assert_equal(getMaxBits(&c0), 20); c0.value = Literal(int32_t(-1)); - assert_equal(Bits::getMaxBits(&c0), 32); + assert_equal(getMaxBits(&c0), 32); b.op = AddInt32; c0.value = Literal(int32_t(0xFFFF)); c1.value = Literal(int32_t(0x11)); - assert_equal(Bits::getMaxBits(&b), 32); + assert_equal(getMaxBits(&b), 32); c0.value = Literal(int32_t(-1)); c1.value = Literal(int32_t(2)); - assert_equal(Bits::getMaxBits(&b), 32); + assert_equal(getMaxBits(&b), 32); b.op = SubInt32; c0.value = Literal(int32_t(0xFFFF)); c1.value = Literal(int32_t(0x11)); - assert_equal(Bits::getMaxBits(&b), 32); + assert_equal(getMaxBits(&b), 32); c0.value = Literal(int32_t(-1)); c1.value = Literal(int32_t(2)); - assert_equal(Bits::getMaxBits(&b), 32); + assert_equal(getMaxBits(&b), 32); b.op = MulInt32; c0.value = Literal(int32_t(0xFFFF)); c1.value = Literal(int32_t(0x11)); - assert_equal(Bits::getMaxBits(&b), 21); + assert_equal(getMaxBits(&b), 21); c0.value = Literal(int32_t(0)); c1.value = Literal(int32_t(1)); - assert_equal(Bits::getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 0); c0.value = Literal(int32_t(1)); c1.value = Literal(int32_t(0)); - assert_equal(Bits::getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 0); c0.value = Literal(int32_t(3)); c1.value = Literal(int32_t(3)); - assert_equal(Bits::getMaxBits(&b), 4); + assert_equal(getMaxBits(&b), 4); c0.value = Literal(int32_t(2)); c1.value = Literal(int32_t(-2)); - assert_equal(Bits::getMaxBits(&b), 32); + assert_equal(getMaxBits(&b), 32); b.op = DivSInt32; c0.value = Literal(int32_t(0)); c1.value = Literal(int32_t(0xF)); - assert_equal(Bits::getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 0); c0.value = Literal(int32_t( 1)); c1.value = Literal(int32_t( 2)); - assert_equal(Bits::getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 0); c0.value = Literal(int32_t(0xFF)); c1.value = Literal(int32_t(0xFF)); - assert_equal(Bits::getMaxBits(&b), 1); + assert_equal(getMaxBits(&b), 1); c0.value = Literal(int32_t(-1)); c1.value = Literal(int32_t( 1)); - assert_equal(Bits::getMaxBits(&b), 32); + assert_equal(getMaxBits(&b), 32); c0.value = Literal(int32_t(-1)); c1.value = Literal(int32_t( 2)); - assert_equal(Bits::getMaxBits(&b), 32); + assert_equal(getMaxBits(&b), 32); c0.value = Literal(int32_t(0x7FFFFFFF)); c1.value = Literal(int32_t(3)); - assert_equal(Bits::getMaxBits(&b), 30); + assert_equal(getMaxBits(&b), 30); c0.value = Literal(int32_t(0x80000000)); c1.value = Literal(int32_t(-1)); - assert_equal(Bits::getMaxBits(&b), 32); + assert_equal(getMaxBits(&b), 32); b.op = DivUInt32; c0.value = Literal(uint32_t(0)); c1.value = Literal(uint32_t(0xF)); - assert_equal(Bits::getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 0); c0.value = Literal(uint32_t( 1)); c1.value = Literal(uint32_t( 2)); - assert_equal(Bits::getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 0); c0.value = Literal(uint32_t(0xFF)); c1.value = Literal(uint32_t(0xFF)); - assert_equal(Bits::getMaxBits(&b), 1); + assert_equal(getMaxBits(&b), 1); c0.value = Literal(uint32_t(-1)); c1.value = Literal(uint32_t( 1)); - assert_equal(Bits::getMaxBits(&b), 32); + assert_equal(getMaxBits(&b), 32); c0.value = Literal(uint32_t(-1)); c1.value = Literal(uint32_t( 2)); - assert_equal(Bits::getMaxBits(&b), 31); + assert_equal(getMaxBits(&b), 31); c0.value = Literal(uint32_t(0x7FFFFFFF)); c1.value = Literal(uint32_t(3)); - assert_equal(Bits::getMaxBits(&b), 30); + assert_equal(getMaxBits(&b), 30); c0.value = Literal(uint32_t(0x80000000)); c1.value = Literal(uint32_t(-1)); - assert_equal(Bits::getMaxBits(&b), 1); + assert_equal(getMaxBits(&b), 1); // --- // @@ -161,95 +162,95 @@ void test_bits() { // Const: i64 c0.value = Literal(int64_t(0)); - assert_equal(Bits::getMaxBits(&c0), 0); + assert_equal(getMaxBits(&c0), 0); c0.value = Literal(int64_t(1)); - assert_equal(Bits::getMaxBits(&c0), 1); + assert_equal(getMaxBits(&c0), 1); c0.value = Literal(int64_t(2)); - assert_equal(Bits::getMaxBits(&c0), 2); + assert_equal(getMaxBits(&c0), 2); c0.value = Literal(int64_t(0x80000)); - assert_equal(Bits::getMaxBits(&c0), 20); + assert_equal(getMaxBits(&c0), 20); c0.value = Literal(int64_t(-1)); - assert_equal(Bits::getMaxBits(&c0), 64); + assert_equal(getMaxBits(&c0), 64); b.op = AddInt64; c0.value = Literal(int64_t(0xFFFF)); c1.value = Literal(int64_t(0x11)); - assert_equal(Bits::getMaxBits(&b), 64); + assert_equal(getMaxBits(&b), 64); c0.value = Literal(int64_t(-1)); c1.value = Literal(int64_t(2)); - assert_equal(Bits::getMaxBits(&b), 64); + assert_equal(getMaxBits(&b), 64); b.op = SubInt64; c0.value = Literal(int64_t(0xFFFF)); c1.value = Literal(int64_t(0x11)); - assert_equal(Bits::getMaxBits(&b), 64); + assert_equal(getMaxBits(&b), 64); c0.value = Literal(int64_t(-1)); c1.value = Literal(int64_t(2)); - assert_equal(Bits::getMaxBits(&b), 64); + assert_equal(getMaxBits(&b), 64); b.op = MulInt64; c0.value = Literal(int64_t(0xFFFF)); c1.value = Literal(int64_t(0x11)); - assert_equal(Bits::getMaxBits(&b), 21); + assert_equal(getMaxBits(&b), 21); c0.value = Literal(int64_t(0)); c1.value = Literal(int64_t(1)); - assert_equal(Bits::getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 0); c0.value = Literal(int64_t(1)); c1.value = Literal(int64_t(0)); - assert_equal(Bits::getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 0); c0.value = Literal(int64_t(3)); c1.value = Literal(int64_t(3)); - assert_equal(Bits::getMaxBits(&b), 4); + assert_equal(getMaxBits(&b), 4); c0.value = Literal(int64_t(2)); c1.value = Literal(int64_t(-2)); - assert_equal(Bits::getMaxBits(&b), 64); + assert_equal(getMaxBits(&b), 64); b.op = DivSInt64; c0.value = Literal(int64_t(0)); c1.value = Literal(int64_t(0xF)); - assert_equal(Bits::getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 0); c0.value = Literal(int64_t( 1)); c1.value = Literal(int64_t( 2)); - assert_equal(Bits::getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 0); c0.value = Literal(int64_t(0xFF)); c1.value = Literal(int64_t(0xFF)); - assert_equal(Bits::getMaxBits(&b), 1); + assert_equal(getMaxBits(&b), 1); c0.value = Literal(int64_t(-1)); c1.value = Literal(int64_t( 1)); - assert_equal(Bits::getMaxBits(&b), 64); + assert_equal(getMaxBits(&b), 64); c0.value = Literal(int64_t(-1)); c1.value = Literal(int64_t( 2)); - assert_equal(Bits::getMaxBits(&b), 64); + assert_equal(getMaxBits(&b), 64); c0.value = Literal(int64_t(0x7FFFFFFFFFFFFFFF)); c1.value = Literal(int64_t(3)); - assert_equal(Bits::getMaxBits(&b), 62); + assert_equal(getMaxBits(&b), 62); c0.value = Literal(int64_t(0x8000000000000000)); c1.value = Literal(int64_t(-1)); - assert_equal(Bits::getMaxBits(&b), 64); + assert_equal(getMaxBits(&b), 64); b.op = DivUInt64; c0.value = Literal(uint64_t(0)); c1.value = Literal(uint64_t(0xF)); - assert_equal(Bits::getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 0); c0.value = Literal(uint64_t( 1)); c1.value = Literal(uint64_t( 2)); - assert_equal(Bits::getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 0); c0.value = Literal(uint64_t(0xFF)); c1.value = Literal(uint64_t(0xFF)); - assert_equal(Bits::getMaxBits(&b), 1); + assert_equal(getMaxBits(&b), 1); c0.value = Literal(uint64_t(-1)); c1.value = Literal(uint64_t( 1)); - assert_equal(Bits::getMaxBits(&b), 64); + assert_equal(getMaxBits(&b), 64); c0.value = Literal(uint64_t(-1)); c1.value = Literal(uint64_t( 2)); - assert_equal(Bits::getMaxBits(&b), 63); + assert_equal(getMaxBits(&b), 63); c0.value = Literal(uint64_t(0x7FFFFFFFFFFFFFFF)); c1.value = Literal(uint64_t(3)); - assert_equal(Bits::getMaxBits(&b), 62); + assert_equal(getMaxBits(&b), 62); c0.value = Literal(uint64_t(0x8000000000000000)); c1.value = Literal(uint64_t(-1)); - assert_equal(Bits::getMaxBits(&b), 1); + assert_equal(getMaxBits(&b), 1); } void test_cost() { From 709b8ed080d082d9f8f23227e42b7906feae0b83 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 16:54:29 +0300 Subject: [PATCH 42/73] add rem_s / rem_u tests --- test/example/cpp-unit.cpp | 81 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 06c5d4d1e52..2a09fcd085f 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -150,6 +150,46 @@ void test_bits() { c1.value = Literal(uint32_t(-1)); assert_equal(getMaxBits(&b), 1); + b.op = RemSInt32; + c0.value = Literal(int32_t(0)); + c1.value = Literal(int32_t(0xF)); + assert_equal(getMaxBits(&b), 0); + c0.value = Literal(int32_t(0)); + c1.value = Literal(int32_t(-1)); + assert_equal(getMaxBits(&b), 0); + c0.value = Literal(int32_t( 1)); + c1.value = Literal(int32_t( 2)); + assert_equal(getMaxBits(&b), 1); + c0.value = Literal(int32_t(-1)); + c1.value = Literal(int32_t( 2)); + assert_equal(getMaxBits(&b), 32); + c0.value = Literal(int32_t(3)); + c1.value = Literal(int32_t(-1)); + assert_equal(getMaxBits(&b), 2); + c0.value = Literal(int32_t(0x7FFFFFFF)); + c1.value = Literal(int32_t(0x7FFFFFFF)); + assert_equal(getMaxBits(&b), 31); + + b.op = RemUInt32; + c0.value = Literal(uint32_t(0)); + c1.value = Literal(uint32_t(0xF)); + assert_equal(getMaxBits(&b), 0); + c0.value = Literal(uint32_t(0)); + c1.value = Literal(uint32_t(-1)); + assert_equal(getMaxBits(&b), 0); + c0.value = Literal(uint32_t( 1)); + c1.value = Literal(uint32_t( 2)); + assert_equal(getMaxBits(&b), 1); + c0.value = Literal(uint32_t(-1)); + c1.value = Literal(uint32_t( 2)); + assert_equal(getMaxBits(&b), 1); + c0.value = Literal(uint32_t(3)); + c1.value = Literal(uint32_t(-1)); + assert_equal(getMaxBits(&b), 2); + c0.value = Literal(uint32_t(0x7FFFFFFF)); + c1.value = Literal(uint32_t(0x7FFFFFFF)); + assert_equal(getMaxBits(&b), 31); + // --- // // i64 // @@ -228,7 +268,6 @@ void test_bits() { c1.value = Literal(int64_t(-1)); assert_equal(getMaxBits(&b), 64); - b.op = DivUInt64; c0.value = Literal(uint64_t(0)); c1.value = Literal(uint64_t(0xF)); @@ -251,6 +290,46 @@ void test_bits() { c0.value = Literal(uint64_t(0x8000000000000000)); c1.value = Literal(uint64_t(-1)); assert_equal(getMaxBits(&b), 1); + + b.op = RemSInt64; + c0.value = Literal(int64_t(0)); + c1.value = Literal(int64_t(0xF)); + assert_equal(getMaxBits(&b), 0); + c0.value = Literal(int64_t(0)); + c1.value = Literal(int64_t(-1)); + assert_equal(getMaxBits(&b), 0); + c0.value = Literal(int64_t( 1)); + c1.value = Literal(int64_t( 2)); + assert_equal(getMaxBits(&b), 1); + c0.value = Literal(int64_t(-1)); + c1.value = Literal(int64_t( 2)); + assert_equal(getMaxBits(&b), 64); + c0.value = Literal(int64_t(3)); + c1.value = Literal(int64_t(-1)); + assert_equal(getMaxBits(&b), 2); + c0.value = Literal(int64_t(0x7FFFFFFFFFFFFFFF)); + c1.value = Literal(int64_t(0x7FFFFFFFFFFFFFFF)); + assert_equal(getMaxBits(&b), 63); + + b.op = RemUInt64; + c0.value = Literal(uint64_t(0)); + c1.value = Literal(uint64_t(0xF)); + assert_equal(getMaxBits(&b), 0); + c0.value = Literal(uint64_t(0)); + c1.value = Literal(uint64_t(-1)); + assert_equal(getMaxBits(&b), 0); + c0.value = Literal(uint64_t( 1)); + c1.value = Literal(uint64_t( 2)); + assert_equal(getMaxBits(&b), 1); + c0.value = Literal(uint64_t(-1)); + c1.value = Literal(uint64_t( 2)); + assert_equal(getMaxBits(&b), 1); + c0.value = Literal(uint64_t(3)); + c1.value = Literal(uint64_t(-1)); + assert_equal(getMaxBits(&b), 2); + c0.value = Literal(uint64_t(0x7FFFFFFFFFFFFFFF)); + c1.value = Literal(uint64_t(0x7FFFFFFFFFFFFFFF)); + assert_equal(getMaxBits(&b), 63); } void test_cost() { From 569362f38587a66bcea8c3521c46c7aed0a051b6 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 17:32:15 +0300 Subject: [PATCH 43/73] add and / or / xor tests --- test/example/cpp-unit.cpp | 101 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 2a09fcd085f..45b3e296302 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -190,6 +190,56 @@ void test_bits() { c1.value = Literal(uint32_t(0x7FFFFFFF)); assert_equal(getMaxBits(&b), 31); + b.op = AndInt32; + c0.value = Literal(int32_t(0)); + c1.value = Literal(int32_t(0xF)); + assert_equal(getMaxBits(&b), 0); + c0.value = Literal(int32_t(0xF)); + c1.value = Literal(int32_t(0)); + assert_equal(getMaxBits(&b), 0); + c0.value = Literal(int32_t(3)); + c1.value = Literal(int32_t(3)); + assert_equal(getMaxBits(&b), 2); + c0.value = Literal(int32_t(-1)); + c1.value = Literal(int32_t(3)); + assert_equal(getMaxBits(&b), 2); + c0.value = Literal(int32_t(3)); + c1.value = Literal(int32_t(-1)); + assert_equal(getMaxBits(&b), 2); + + b.op = OrInt32; + c0.value = Literal(int32_t(0)); + c1.value = Literal(int32_t(0xF)); + assert_equal(getMaxBits(&b), 4); + c0.value = Literal(int32_t(0xF)); + c1.value = Literal(int32_t(0)); + assert_equal(getMaxBits(&b), 4); + c0.value = Literal(int32_t(3)); + c1.value = Literal(int32_t(3)); + assert_equal(getMaxBits(&b), 2); + c0.value = Literal(int32_t(-1)); + c1.value = Literal(int32_t(3)); + assert_equal(getMaxBits(&b), 32); + c0.value = Literal(int32_t(3)); + c1.value = Literal(int32_t(-1)); + assert_equal(getMaxBits(&b), 32); + + b.op = XorInt32; + c0.value = Literal(int32_t(0)); + c1.value = Literal(int32_t(0xF)); + assert_equal(getMaxBits(&b), 4); + c0.value = Literal(int32_t(0xF)); + c1.value = Literal(int32_t(0)); + assert_equal(getMaxBits(&b), 4); + c0.value = Literal(int32_t(3)); + c1.value = Literal(int32_t(3)); + assert_equal(getMaxBits(&b), 2); + c0.value = Literal(int32_t(-1)); + c1.value = Literal(int32_t(3)); + assert_equal(getMaxBits(&b), 32); + c0.value = Literal(int32_t(3)); + c1.value = Literal(int32_t(-1)); + assert_equal(getMaxBits(&b), 32); // --- // // i64 // @@ -330,6 +380,57 @@ void test_bits() { c0.value = Literal(uint64_t(0x7FFFFFFFFFFFFFFF)); c1.value = Literal(uint64_t(0x7FFFFFFFFFFFFFFF)); assert_equal(getMaxBits(&b), 63); + + b.op = AndInt64; + c0.value = Literal(int64_t(0)); + c1.value = Literal(int64_t(0xF)); + assert_equal(getMaxBits(&b), 0); + c0.value = Literal(int64_t(0xF)); + c1.value = Literal(int64_t(0)); + assert_equal(getMaxBits(&b), 0); + c0.value = Literal(int64_t(3)); + c1.value = Literal(int64_t(3)); + assert_equal(getMaxBits(&b), 2); + c0.value = Literal(int64_t(-1)); + c1.value = Literal(int64_t(3)); + assert_equal(getMaxBits(&b), 2); + c0.value = Literal(int64_t(3)); + c1.value = Literal(int64_t(-1)); + assert_equal(getMaxBits(&b), 2); + + b.op = OrInt64; + c0.value = Literal(int64_t(0)); + c1.value = Literal(int64_t(0xF)); + assert_equal(getMaxBits(&b), 4); + c0.value = Literal(int64_t(0xF)); + c1.value = Literal(int64_t(0)); + assert_equal(getMaxBits(&b), 4); + c0.value = Literal(int64_t(3)); + c1.value = Literal(int64_t(3)); + assert_equal(getMaxBits(&b), 2); + c0.value = Literal(int64_t(-1)); + c1.value = Literal(int64_t(3)); + assert_equal(getMaxBits(&b), 64); + c0.value = Literal(int64_t(3)); + c1.value = Literal(int64_t(-1)); + assert_equal(getMaxBits(&b), 64); + + b.op = XorInt64; + c0.value = Literal(int64_t(0)); + c1.value = Literal(int64_t(0xF)); + assert_equal(getMaxBits(&b), 4); + c0.value = Literal(int64_t(0xF)); + c1.value = Literal(int64_t(0)); + assert_equal(getMaxBits(&b), 4); + c0.value = Literal(int64_t(3)); + c1.value = Literal(int64_t(3)); + assert_equal(getMaxBits(&b), 2); + c0.value = Literal(int64_t(-1)); + c1.value = Literal(int64_t(3)); + assert_equal(getMaxBits(&b), 64); + c0.value = Literal(int64_t(3)); + c1.value = Literal(int64_t(-1)); + assert_equal(getMaxBits(&b), 64); } void test_cost() { From 9545f9e5174e504dc62538ccf3635db41cc4483f Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 5 Aug 2020 18:02:44 +0300 Subject: [PATCH 44/73] add unary ops --- test/example/cpp-unit.cpp | 47 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 45b3e296302..c85dc225a7d 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -431,6 +431,53 @@ void test_bits() { c0.value = Literal(int64_t(3)); c1.value = Literal(int64_t(-1)); assert_equal(getMaxBits(&b), 64); + + // Unary + Unary u; + c0.type = Type::i32; + u.value = &c0; + + u.type = Type::i64; + + u.op = ExtendUInt32; + c0.value = Literal(int32_t(0)); + assert_equal(getMaxBits(&u), 0); + c0.value = Literal(int32_t(1)); + assert_equal(getMaxBits(&u), 1); + c0.value = Literal(int32_t(0xF)); + assert_equal(getMaxBits(&u), 4); + c0.value = Literal(int32_t(-1)); + assert_equal(getMaxBits(&u), 32); + + u.op = ExtendSInt32; + c0.value = Literal(int32_t(0)); + assert_equal(getMaxBits(&u), 0); + c0.value = Literal(int32_t(1)); + assert_equal(getMaxBits(&u), 1); + c0.value = Literal(int32_t(0xF)); + assert_equal(getMaxBits(&u), 4); + c0.value = Literal(int32_t(0x7FFFFFFF)); + assert_equal(getMaxBits(&u), 31); + c0.value = Literal(int32_t(0x80000000)); + assert_equal(getMaxBits(&u), 64); + c0.value = Literal(int32_t(-1)); + assert_equal(getMaxBits(&u), 64); + + u.type = Type::i32; + c0.type = Type::i64; + + u.op = WrapInt64; + c0.value = Literal(int64_t(0)); + assert_equal(getMaxBits(&u), 0); + c0.value = Literal(int64_t(0x7FFFFFFF)); + assert_equal(getMaxBits(&u), 31); + c0.value = Literal(int64_t(0xFFFFFFFF)); + assert_equal(getMaxBits(&u), 32); + c0.value = Literal(int64_t(0xFFFFFFFFFF)); + assert_equal(getMaxBits(&u), 32); + c0.value = Literal(int64_t(-1)); + assert_equal(getMaxBits(&u), 32); + } void test_cost() { From 9085d8ea0517fe89135db7bb6c3dbc22a059ec83 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Sat, 8 Aug 2020 00:53:35 +0300 Subject: [PATCH 45/73] remove check to zero for rhs consts --- src/ir/bits.h | 12 ------------ test/example/cpp-unit.cpp | 4 ++-- 2 files changed, 2 insertions(+), 14 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index 0529a14d81a..6b34de3738d 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -150,9 +150,6 @@ Index getMaxBits(Expression* curr, if (maxBitsRight == 32) { return 32; } - if (maxBitsRight == 0) { - return 0; - } auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); if (maxBitsLeft == 0) { return 0; @@ -215,9 +212,6 @@ Index getMaxBits(Expression* curr, } case AndInt32: { auto maxBits = getMaxBits(binary->right, localInfoProvider); - if (maxBits == 0) { - return 0; - } return std::min(getMaxBits(binary->left, localInfoProvider), maxBits); } case OrInt32: @@ -275,9 +269,6 @@ Index getMaxBits(Expression* curr, if (maxBitsRight == 64) { return 64; } - if (maxBitsRight == 0) { - return 0; - } auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); if (maxBitsLeft == 0) { return 0; @@ -340,9 +331,6 @@ Index getMaxBits(Expression* curr, } case AndInt64: { auto maxBits = getMaxBits(binary->right, localInfoProvider); - if (maxBits == 0) { - return 0; - } return std::min(getMaxBits(binary->left, localInfoProvider), maxBits); } case OrInt64: diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index c85dc225a7d..cdbde08a5fb 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -95,7 +95,7 @@ void test_bits() { assert_equal(getMaxBits(&b), 0); c0.value = Literal(int32_t(1)); c1.value = Literal(int32_t(0)); - assert_equal(getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 1); c0.value = Literal(int32_t(3)); c1.value = Literal(int32_t(3)); assert_equal(getMaxBits(&b), 4); @@ -287,7 +287,7 @@ void test_bits() { assert_equal(getMaxBits(&b), 0); c0.value = Literal(int64_t(1)); c1.value = Literal(int64_t(0)); - assert_equal(getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 1); c0.value = Literal(int64_t(3)); c1.value = Literal(int64_t(3)); assert_equal(getMaxBits(&b), 4); From 551a675d4c13716b9482a6411c054c0661a1b6f1 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 12 Aug 2020 00:35:41 +0300 Subject: [PATCH 46/73] changes according review --- src/ir/bits.h | 18 ++++++++++-------- test/example/cpp-unit.cpp | 14 ++++++++++---- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index 6b34de3738d..a1e91f30e31 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -142,18 +142,19 @@ Index getMaxBits(Expression* curr, // 32-bit case RotLInt32: case RotRInt32: - case AddInt32: case SubInt32: return 32; + case AddInt32: { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + return std::min(Index(32), std::max(maxBitsLeft, maxBitsRight) + 1); + } case MulInt32: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); if (maxBitsRight == 32) { return 32; } auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; - } return std::min(Index(32), maxBitsLeft + maxBitsRight); } case DivSInt32: { @@ -261,18 +262,19 @@ Index getMaxBits(Expression* curr, } case RotLInt64: case RotRInt64: - case AddInt64: case SubInt64: return 64; + case AddInt64: { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + return std::min(Index(64), std::max(maxBitsLeft, maxBitsRight) + 1); + } case MulInt64: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); if (maxBitsRight == 64) { return 64; } auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; - } return std::min(Index(64), maxBitsLeft + maxBitsRight); } case DivSInt64: { diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index cdbde08a5fb..c42b3a9b0d0 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -73,10 +73,13 @@ void test_bits() { b.op = AddInt32; c0.value = Literal(int32_t(0xFFFF)); c1.value = Literal(int32_t(0x11)); - assert_equal(getMaxBits(&b), 32); + assert_equal(getMaxBits(&b), 17); c0.value = Literal(int32_t(-1)); c1.value = Literal(int32_t(2)); assert_equal(getMaxBits(&b), 32); + c0.value = Literal(int32_t(-1)); + c1.value = Literal(int32_t(-1)); + assert_equal(getMaxBits(&b), 32); b.op = SubInt32; c0.value = Literal(int32_t(0xFFFF)); @@ -92,7 +95,7 @@ void test_bits() { assert_equal(getMaxBits(&b), 21); c0.value = Literal(int32_t(0)); c1.value = Literal(int32_t(1)); - assert_equal(getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 1); c0.value = Literal(int32_t(1)); c1.value = Literal(int32_t(0)); assert_equal(getMaxBits(&b), 1); @@ -265,10 +268,13 @@ void test_bits() { b.op = AddInt64; c0.value = Literal(int64_t(0xFFFF)); c1.value = Literal(int64_t(0x11)); - assert_equal(getMaxBits(&b), 64); + assert_equal(getMaxBits(&b), 17); c0.value = Literal(int64_t(-1)); c1.value = Literal(int64_t(2)); assert_equal(getMaxBits(&b), 64); + c0.value = Literal(int64_t(-1)); + c1.value = Literal(int64_t(-1)); + assert_equal(getMaxBits(&b), 64); b.op = SubInt64; c0.value = Literal(int64_t(0xFFFF)); @@ -284,7 +290,7 @@ void test_bits() { assert_equal(getMaxBits(&b), 21); c0.value = Literal(int64_t(0)); c1.value = Literal(int64_t(1)); - assert_equal(getMaxBits(&b), 0); + assert_equal(getMaxBits(&b), 1); c0.value = Literal(int64_t(1)); c1.value = Literal(int64_t(0)); assert_equal(getMaxBits(&b), 1); From d7335a8cd723298af5c61d3a171af8cf49b457ed Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 12 Aug 2020 11:37:38 +0300 Subject: [PATCH 47/73] also ahndling sub32/sub64 --- src/ir/bits.h | 14 ++++++++++++-- test/example/cpp-unit.cpp | 28 ++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index a1e91f30e31..daec38f4df9 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -142,13 +142,18 @@ Index getMaxBits(Expression* curr, // 32-bit case RotLInt32: case RotRInt32: - case SubInt32: return 32; case AddInt32: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::min(Index(32), std::max(maxBitsLeft, maxBitsRight) + 1); } + case SubInt32: { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + if (maxBitsLeft <= maxBitsRight) return 32; + return std::min(Index(32), std::max(maxBitsLeft, maxBitsRight)); + } case MulInt32: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); if (maxBitsRight == 32) { @@ -262,13 +267,18 @@ Index getMaxBits(Expression* curr, } case RotLInt64: case RotRInt64: - case SubInt64: return 64; case AddInt64: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::min(Index(64), std::max(maxBitsLeft, maxBitsRight) + 1); } + case SubInt64: { + auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); + if (maxBitsLeft <= maxBitsRight) return 64; + return std::min(Index(64), std::max(maxBitsLeft, maxBitsRight)); + } case MulInt64: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); if (maxBitsRight == 64) { diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index c42b3a9b0d0..dcbbae74c6b 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -84,10 +84,22 @@ void test_bits() { b.op = SubInt32; c0.value = Literal(int32_t(0xFFFF)); c1.value = Literal(int32_t(0x11)); - assert_equal(getMaxBits(&b), 32); + assert_equal(getMaxBits(&b), 16); c0.value = Literal(int32_t(-1)); c1.value = Literal(int32_t(2)); assert_equal(getMaxBits(&b), 32); + c0.value = Literal(int32_t(2)); + c1.value = Literal(int32_t(-1)); + assert_equal(getMaxBits(&b), 32); + c0.value = Literal(int32_t(0x7FFFFFF0)); + c1.value = Literal(int32_t(0x7FFFFFFF)); + assert_equal(getMaxBits(&b), 32); + c0.value = Literal(int32_t(1)); + c1.value = Literal(int32_t(1)); + assert_equal(getMaxBits(&b), 32); + c0.value = Literal(int32_t(0)); + c1.value = Literal(int32_t(0x7FFFFFFF)); + assert_equal(getMaxBits(&b), 32); b.op = MulInt32; c0.value = Literal(int32_t(0xFFFF)); @@ -279,10 +291,22 @@ void test_bits() { b.op = SubInt64; c0.value = Literal(int64_t(0xFFFF)); c1.value = Literal(int64_t(0x11)); - assert_equal(getMaxBits(&b), 64); + assert_equal(getMaxBits(&b), 16); c0.value = Literal(int64_t(-1)); c1.value = Literal(int64_t(2)); assert_equal(getMaxBits(&b), 64); + c0.value = Literal(int64_t(2)); + c1.value = Literal(int64_t(-1)); + assert_equal(getMaxBits(&b), 64); + c0.value = Literal(int64_t(0x7FFFFFFFFFFFFFF0)); + c1.value = Literal(int64_t(0x7FFFFFFFFFFFFFFF)); + assert_equal(getMaxBits(&b), 64); + c0.value = Literal(int64_t(1)); + c1.value = Literal(int64_t(1)); + assert_equal(getMaxBits(&b), 64); + c0.value = Literal(int64_t(0)); + c1.value = Literal(int64_t(0x7FFFFFFFFFFFFFFF)); + assert_equal(getMaxBits(&b), 64); b.op = MulInt64; c0.value = Literal(int64_t(0xFFFF)); From 3a27ca3910f43430f7c1c5aa5edf59ab3253eaef Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 12 Aug 2020 11:42:30 +0300 Subject: [PATCH 48/73] linter --- src/ir/bits.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index daec38f4df9..82696f4ba7b 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -151,7 +151,9 @@ Index getMaxBits(Expression* curr, case SubInt32: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - if (maxBitsLeft <= maxBitsRight) return 32; + if (maxBitsLeft <= maxBitsRight) { + return 32; + } return std::min(Index(32), std::max(maxBitsLeft, maxBitsRight)); } case MulInt32: { @@ -276,7 +278,9 @@ Index getMaxBits(Expression* curr, case SubInt64: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - if (maxBitsLeft <= maxBitsRight) return 64; + if (maxBitsLeft <= maxBitsRight) { + return 64; + } return std::min(Index(64), std::max(maxBitsLeft, maxBitsRight)); } case MulInt64: { From e0739c374c57ed06135f4c1aa04bcf9faad6f0a4 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 12 Aug 2020 14:35:13 +0300 Subject: [PATCH 49/73] add early returns for negative or zero lhs --- src/ir/bits.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/ir/bits.h b/src/ir/bits.h index 82696f4ba7b..c0b1791a424 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -150,6 +150,9 @@ Index getMaxBits(Expression* curr, } case SubInt32: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 32 || maxBitsLeft == 0) { + return 32; + } auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); if (maxBitsLeft <= maxBitsRight) { return 32; @@ -277,6 +280,9 @@ Index getMaxBits(Expression* curr, } case SubInt64: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + if (maxBitsLeft == 64 || maxBitsLeft == 0) { + return 64; + } auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); if (maxBitsLeft <= maxBitsRight) { return 64; From 74e568c1a57634473429bc44022252670d9b32cd Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 12 Aug 2020 15:55:05 +0300 Subject: [PATCH 50/73] remove redundant upper bound limit --- src/ir/bits.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index c0b1791a424..e3986d563d3 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -157,7 +157,7 @@ Index getMaxBits(Expression* curr, if (maxBitsLeft <= maxBitsRight) { return 32; } - return std::min(Index(32), std::max(maxBitsLeft, maxBitsRight)); + return std::max(maxBitsLeft, maxBitsRight); } case MulInt32: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); @@ -287,7 +287,7 @@ Index getMaxBits(Expression* curr, if (maxBitsLeft <= maxBitsRight) { return 64; } - return std::min(Index(64), std::max(maxBitsLeft, maxBitsRight)); + return std::max(maxBitsLeft, maxBitsRight); } case MulInt64: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); From 6883ce7f021608d344d287fff3ad0b6e8271b8e2 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Thu, 13 Aug 2020 19:47:36 +0300 Subject: [PATCH 51/73] cleanup tests --- test/example/cpp-unit.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index dcbbae74c6b..66c546f6c82 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -264,8 +264,6 @@ void test_bits() { c1.type = Type::i64; b.type = Type::i64; - // Const: i64 - c0.value = Literal(int64_t(0)); assert_equal(getMaxBits(&c0), 0); c0.value = Literal(int64_t(1)); @@ -462,7 +460,6 @@ void test_bits() { c1.value = Literal(int64_t(-1)); assert_equal(getMaxBits(&b), 64); - // Unary Unary u; c0.type = Type::i32; u.value = &c0; From 0cc2e855abf445cc28de4c855ca4b4212b97e600 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 14 Aug 2020 19:33:26 +0300 Subject: [PATCH 52/73] remove naeg checks for MulInt32/MulInt64 --- src/ir/bits.h | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index e3986d563d3..291fc14a915 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -161,9 +161,6 @@ Index getMaxBits(Expression* curr, } case MulInt32: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - if (maxBitsRight == 32) { - return 32; - } auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); return std::min(Index(32), maxBitsLeft + maxBitsRight); } @@ -291,9 +288,6 @@ Index getMaxBits(Expression* curr, } case MulInt64: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - if (maxBitsRight == 64) { - return 64; - } auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); return std::min(Index(64), maxBitsLeft + maxBitsRight); } From acd6518ae5a803c9829d4836ffb38c0c90f59ea8 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 14 Aug 2020 19:43:45 +0300 Subject: [PATCH 53/73] simplify SubInt32/SubInt64 --- src/ir/bits.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index 291fc14a915..b0ad709b3c3 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -157,7 +157,7 @@ Index getMaxBits(Expression* curr, if (maxBitsLeft <= maxBitsRight) { return 32; } - return std::max(maxBitsLeft, maxBitsRight); + return maxBitsLeft; } case MulInt32: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); @@ -284,7 +284,7 @@ Index getMaxBits(Expression* curr, if (maxBitsLeft <= maxBitsRight) { return 64; } - return std::max(maxBitsLeft, maxBitsRight); + return maxBitsLeft; } case MulInt64: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); From df40a08c1b160c3b1b97e3b4e4e12bcdaab613df Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 14 Aug 2020 19:46:35 +0300 Subject: [PATCH 54/73] more tests --- test/example/cpp-unit.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 66c546f6c82..3d5f5eb21b7 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -91,6 +91,9 @@ void test_bits() { c0.value = Literal(int32_t(2)); c1.value = Literal(int32_t(-1)); assert_equal(getMaxBits(&b), 32); + c0.value = Literal(int32_t(0)); + c1.value = Literal(int32_t(1)); + assert_equal(getMaxBits(&b), 32); c0.value = Literal(int32_t(0x7FFFFFF0)); c1.value = Literal(int32_t(0x7FFFFFFF)); assert_equal(getMaxBits(&b), 32); @@ -296,6 +299,9 @@ void test_bits() { c0.value = Literal(int64_t(2)); c1.value = Literal(int64_t(-1)); assert_equal(getMaxBits(&b), 64); + c0.value = Literal(int64_t(0)); + c1.value = Literal(int64_t(1)); + assert_equal(getMaxBits(&b), 64); c0.value = Literal(int64_t(0x7FFFFFFFFFFFFFF0)); c1.value = Literal(int64_t(0x7FFFFFFFFFFFFFFF)); assert_equal(getMaxBits(&b), 64); From da177ae35deb89755d347e84f068afd002f5b103 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Sun, 16 Aug 2020 18:39:13 +0300 Subject: [PATCH 55/73] add antiexample --- .../optimize-instructions_all-features.txt | 31 ++++++++++++++++++- .../optimize-instructions_all-features.wast | 18 +++++++++++ 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index c3d06f1d220..2a3144ab47e 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -3,8 +3,8 @@ (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) - (type $i32_i64_=>_none (func (param i32 i64))) (type $i32_=>_none (func (param i32))) + (type $i32_i64_=>_none (func (param i32 i64))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $none_=>_i64 (func (result i64))) (type $i64_=>_i64 (func (param i64) (result i64))) @@ -3721,6 +3721,35 @@ ) ) ) + (func $sub_with_masks (param $x i32) (param $y i32) (result i32) + (i32.sub + (i32.and + (local.get $x) + (i32.const 255) + ) + (i32.and + (local.get $y) + (i32.const 127) + ) + ) + ) + (func $test_get_maxbits_for_sub (param $x i32) + (drop + (i32.and + (call $sub_with_masks + (i32.const 0) + (i32.const 1) + ) + (i32.const 255) + ) + ) + (drop + (i32.and + (local.get $x) + (i32.const 127) + ) + ) + ) ) (module (type $none_=>_none (func)) diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast index 2790cc9eafd..6a186a2210e 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -4233,6 +4233,24 @@ ) )) ) + (func $sub_with_masks (param $x i32) (param $y i32) (result i32) + (i32.sub + (i32.and (local.get $x) (i32.const 255)) + (i32.and (local.get $y) (i32.const 127)) + ) + ) + (func $test_get_maxbits_for_sub (param $x i32) + ;; should not remove i32.and + (drop (i32.and + (call $sub_with_masks (i32.const 0) (i32.const 1)) + (i32.const 255) + )) + ;; should remove i32.and + (drop (i32.and + (i32.and (local.get $x) (i32.const 127)) + (i32.const 255) + )) + ) ) (module (import "env" "memory" (memory $0 (shared 256 256))) From d84f9babcd0fda2582f06832ade266279a266d99 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Sun, 16 Aug 2020 18:43:45 +0300 Subject: [PATCH 56/73] larger value (255 -> 1023) --- test/passes/optimize-instructions_all-features.txt | 2 +- test/passes/optimize-instructions_all-features.wast | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index 2a3144ab47e..85e066552f3 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -3740,7 +3740,7 @@ (i32.const 0) (i32.const 1) ) - (i32.const 255) + (i32.const 1023) ) ) (drop diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast index 6a186a2210e..f9764cec22b 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -4243,12 +4243,12 @@ ;; should not remove i32.and (drop (i32.and (call $sub_with_masks (i32.const 0) (i32.const 1)) - (i32.const 255) + (i32.const 1023) )) ;; should remove i32.and (drop (i32.and (i32.and (local.get $x) (i32.const 127)) - (i32.const 255) + (i32.const 1023) )) ) ) From 5c1d1c4c24da92a6eb59dd17177cf837108bb425 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Sun, 16 Aug 2020 20:28:17 +0300 Subject: [PATCH 57/73] add example with global --- test/passes/optimize-instructions_all-features.txt | 10 ++++++++++ test/passes/optimize-instructions_all-features.wast | 6 ++++++ 2 files changed, 16 insertions(+) diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index 85e066552f3..5486dbdb6b5 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -15,6 +15,7 @@ (type $none_=>_f64 (func (result f64))) (type $none_=>_externref (func (result externref))) (memory $0 0) + (global $g0 (mut i32) (i32.const 0)) (export "load-off-2" (func $load-off-2)) (func $f (param $i1 i32) (param $i2 i64) (if @@ -3743,6 +3744,15 @@ (i32.const 1023) ) ) + (drop + (i32.and + (call $sub_with_masks + (global.get $g0) + (i32.const 1) + ) + (i32.const 1023) + ) + ) (drop (i32.and (local.get $x) diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast index f9764cec22b..2172e71c5d5 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -1,6 +1,7 @@ (module (memory 0) (type $0 (func (param i32 i64))) + (global $g0 (mut i32) (i32.const 0)) (func $f (type $0) (param $i1 i32) (param $i2 i64) (if (i32.eqz @@ -4245,6 +4246,11 @@ (call $sub_with_masks (i32.const 0) (i32.const 1)) (i32.const 1023) )) + ;; should not remove i32.and + (drop (i32.and + (call $sub_with_masks (global.get $g0) (i32.const 1)) + (i32.const 1023) + )) ;; should remove i32.and (drop (i32.and (i32.and (local.get $x) (i32.const 127)) From f319270fa52d01e7d0de2365db4cfec6ce1adadc Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Sun, 16 Aug 2020 20:34:24 +0300 Subject: [PATCH 58/73] make blobal exportable --- test/passes/optimize-instructions_all-features.txt | 1 + test/passes/optimize-instructions_all-features.wast | 1 + 2 files changed, 2 insertions(+) diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index 5486dbdb6b5..a195b6a0034 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -16,6 +16,7 @@ (type $none_=>_externref (func (result externref))) (memory $0 0) (global $g0 (mut i32) (i32.const 0)) + (export "g0" (global $g0)) (export "load-off-2" (func $load-off-2)) (func $f (param $i1 i32) (param $i2 i64) (if diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast index 2172e71c5d5..82b15f74f78 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -2,6 +2,7 @@ (memory 0) (type $0 (func (param i32 i64))) (global $g0 (mut i32) (i32.const 0)) + (export "g0" (global $g0)) (func $f (type $0) (param $i1 i32) (param $i2 i64) (if (i32.eqz From 55d9824e810b17059e1c5353c4bd1452652e413b Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Sun, 16 Aug 2020 20:51:57 +0300 Subject: [PATCH 59/73] more tests --- test/passes/optimize-instructions_all-features.txt | 11 ++++++++++- test/passes/optimize-instructions_all-features.wast | 10 +++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index a195b6a0034..545eb7087d1 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -3754,10 +3754,19 @@ (i32.const 1023) ) ) + (drop + (i32.and + (i32.sub + (i32.const 0) + (i32.const 1) + ) + (i32.const 1023) + ) + ) (drop (i32.and (local.get $x) - (i32.const 127) + (i32.const 255) ) ) ) diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast index 82b15f74f78..58a072ea67d 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -4252,9 +4252,17 @@ (call $sub_with_masks (global.get $g0) (i32.const 1)) (i32.const 1023) )) + ;; should not remove i32.and + (drop (i32.and + (i32.sub + (i32.and (i32.const 0) (i32.const 255)) + (i32.and (i32.const 1) (i32.const 127)) + ) + (i32.const 1023) + )) ;; should remove i32.and (drop (i32.and - (i32.and (local.get $x) (i32.const 127)) + (i32.and (local.get $x) (i32.const 255)) (i32.const 1023) )) ) From f9240087d7fe575047fb98546b86031d7f9dc45c Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Sun, 16 Aug 2020 22:00:10 +0300 Subject: [PATCH 60/73] revert getMaxBits for subtractions + remove fixtures --- src/ir/bits.h | 24 +-------- test/example/cpp-unit.cpp | 4 +- .../optimize-instructions_all-features.txt | 51 +------------------ .../optimize-instructions_all-features.wast | 33 ------------ 4 files changed, 5 insertions(+), 107 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index b0ad709b3c3..82ae01a92c5 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -142,23 +142,13 @@ Index getMaxBits(Expression* curr, // 32-bit case RotLInt32: case RotRInt32: + case SubInt32: return 32; case AddInt32: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::min(Index(32), std::max(maxBitsLeft, maxBitsRight) + 1); } - case SubInt32: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 32 || maxBitsLeft == 0) { - return 32; - } - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - if (maxBitsLeft <= maxBitsRight) { - return 32; - } - return maxBitsLeft; - } case MulInt32: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); @@ -269,23 +259,13 @@ Index getMaxBits(Expression* curr, } case RotLInt64: case RotRInt64: + case SubInt64: return 64; case AddInt64: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); return std::min(Index(64), std::max(maxBitsLeft, maxBitsRight) + 1); } - case SubInt64: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 64 || maxBitsLeft == 0) { - return 64; - } - auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); - if (maxBitsLeft <= maxBitsRight) { - return 64; - } - return maxBitsLeft; - } case MulInt64: { auto maxBitsRight = getMaxBits(binary->right, localInfoProvider); auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 3d5f5eb21b7..efaf693a5d9 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -84,7 +84,7 @@ void test_bits() { b.op = SubInt32; c0.value = Literal(int32_t(0xFFFF)); c1.value = Literal(int32_t(0x11)); - assert_equal(getMaxBits(&b), 16); + assert_equal(getMaxBits(&b), 32); c0.value = Literal(int32_t(-1)); c1.value = Literal(int32_t(2)); assert_equal(getMaxBits(&b), 32); @@ -292,7 +292,7 @@ void test_bits() { b.op = SubInt64; c0.value = Literal(int64_t(0xFFFF)); c1.value = Literal(int64_t(0x11)); - assert_equal(getMaxBits(&b), 16); + assert_equal(getMaxBits(&b), 64); c0.value = Literal(int64_t(-1)); c1.value = Literal(int64_t(2)); assert_equal(getMaxBits(&b), 64); diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt index 545eb7087d1..c3d06f1d220 100644 --- a/test/passes/optimize-instructions_all-features.txt +++ b/test/passes/optimize-instructions_all-features.txt @@ -3,8 +3,8 @@ (type $i32_=>_i32 (func (param i32) (result i32))) (type $none_=>_i32 (func (result i32))) (type $none_=>_none (func)) - (type $i32_=>_none (func (param i32))) (type $i32_i64_=>_none (func (param i32 i64))) + (type $i32_=>_none (func (param i32))) (type $i32_i32_=>_i32 (func (param i32 i32) (result i32))) (type $none_=>_i64 (func (result i64))) (type $i64_=>_i64 (func (param i64) (result i64))) @@ -15,8 +15,6 @@ (type $none_=>_f64 (func (result f64))) (type $none_=>_externref (func (result externref))) (memory $0 0) - (global $g0 (mut i32) (i32.const 0)) - (export "g0" (global $g0)) (export "load-off-2" (func $load-off-2)) (func $f (param $i1 i32) (param $i2 i64) (if @@ -3723,53 +3721,6 @@ ) ) ) - (func $sub_with_masks (param $x i32) (param $y i32) (result i32) - (i32.sub - (i32.and - (local.get $x) - (i32.const 255) - ) - (i32.and - (local.get $y) - (i32.const 127) - ) - ) - ) - (func $test_get_maxbits_for_sub (param $x i32) - (drop - (i32.and - (call $sub_with_masks - (i32.const 0) - (i32.const 1) - ) - (i32.const 1023) - ) - ) - (drop - (i32.and - (call $sub_with_masks - (global.get $g0) - (i32.const 1) - ) - (i32.const 1023) - ) - ) - (drop - (i32.and - (i32.sub - (i32.const 0) - (i32.const 1) - ) - (i32.const 1023) - ) - ) - (drop - (i32.and - (local.get $x) - (i32.const 255) - ) - ) - ) ) (module (type $none_=>_none (func)) diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast index 58a072ea67d..2790cc9eafd 100644 --- a/test/passes/optimize-instructions_all-features.wast +++ b/test/passes/optimize-instructions_all-features.wast @@ -1,8 +1,6 @@ (module (memory 0) (type $0 (func (param i32 i64))) - (global $g0 (mut i32) (i32.const 0)) - (export "g0" (global $g0)) (func $f (type $0) (param $i1 i32) (param $i2 i64) (if (i32.eqz @@ -4235,37 +4233,6 @@ ) )) ) - (func $sub_with_masks (param $x i32) (param $y i32) (result i32) - (i32.sub - (i32.and (local.get $x) (i32.const 255)) - (i32.and (local.get $y) (i32.const 127)) - ) - ) - (func $test_get_maxbits_for_sub (param $x i32) - ;; should not remove i32.and - (drop (i32.and - (call $sub_with_masks (i32.const 0) (i32.const 1)) - (i32.const 1023) - )) - ;; should not remove i32.and - (drop (i32.and - (call $sub_with_masks (global.get $g0) (i32.const 1)) - (i32.const 1023) - )) - ;; should not remove i32.and - (drop (i32.and - (i32.sub - (i32.and (i32.const 0) (i32.const 255)) - (i32.and (i32.const 1) (i32.const 127)) - ) - (i32.const 1023) - )) - ;; should remove i32.and - (drop (i32.and - (i32.and (local.get $x) (i32.const 255)) - (i32.const 1023) - )) - ) ) (module (import "env" "memory" (memory $0 (shared 256 256))) From 30b18425ddc56c14f074c8244f18a39346a63242 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Tue, 18 Aug 2020 21:51:01 +0300 Subject: [PATCH 61/73] remove some zero checks --- src/ir/bits.h | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index 2e32af5daf2..83e3a4e9a89 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -187,9 +187,6 @@ Index getMaxBits(Expression* curr, if (maxBitsLeft == 32) { return 32; } - if (maxBitsLeft == 0) { - return 0; - } auto value = c->value.geti32(); auto maxBitsRight = 32 - Index(CountLeadingZeroes(value - 1)); return std::min(maxBitsLeft, maxBitsRight); @@ -199,9 +196,6 @@ Index getMaxBits(Expression* curr, case RemUInt32: { if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; - } auto value = c->value.geti32(); auto maxBitsRight = 32 - Index(CountLeadingZeroes(value - 1)); return std::min(maxBitsLeft, maxBitsRight); @@ -231,9 +225,6 @@ Index getMaxBits(Expression* curr, case ShrUInt32: { if (auto* shift = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); - if (maxBits == 0) { - return 0; - } auto shifts = std::min(Index(Bits::getEffectiveShifts(shift)), maxBits); // can ignore more shifts than zero us out @@ -247,9 +238,6 @@ Index getMaxBits(Expression* curr, if (maxBits == 32) { return 32; } - if (maxBits == 0) { - return 0; - } auto shifts = std::min(Index(Bits::getEffectiveShifts(shift)), maxBits); // can ignore more shifts than zero us out @@ -304,9 +292,6 @@ Index getMaxBits(Expression* curr, if (maxBitsLeft == 64) { return 64; } - if (maxBitsLeft == 0) { - return 0; - } auto value = c->value.geti64(); auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); return std::min(maxBitsLeft, maxBitsRight); @@ -316,9 +301,6 @@ Index getMaxBits(Expression* curr, case RemUInt64: { if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - if (maxBitsLeft == 0) { - return 0; - } auto value = c->value.geti64(); auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); return std::min(maxBitsLeft, maxBitsRight); @@ -340,9 +322,6 @@ Index getMaxBits(Expression* curr, case ShlInt64: { if (auto* shifts = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); - if (maxBits == 0) { - return 0; - } return std::min(Index(64), Bits::getEffectiveShifts(shifts) + maxBits); } @@ -351,9 +330,6 @@ Index getMaxBits(Expression* curr, case ShrUInt64: { if (auto* shift = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); - if (maxBits == 0) { - return 0; - } auto shifts = std::min(Index(Bits::getEffectiveShifts(shift)), maxBits); // can ignore more shifts than zero us out @@ -367,9 +343,6 @@ Index getMaxBits(Expression* curr, if (maxBits == 64) { return 64; } - if (maxBits == 0) { - return 0; - } auto shifts = std::min(Index(Bits::getEffectiveShifts(shift)), maxBits); // can ignore more shifts than zero us out From b91ee8ce19820ddd11e15f5cd9b9380f18ec416a Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Sat, 22 Aug 2020 19:39:59 +0300 Subject: [PATCH 62/73] add comments + refactorings --- src/ir/bits.h | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index 83e3a4e9a89..13a5a77cce2 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -157,39 +157,41 @@ Index getMaxBits(Expression* curr, case DivSInt32: { if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + // if maxBitsLeft is negative if (maxBitsLeft == 32) { return 32; } + // properly handle zero for divisible if (maxBitsLeft == 0) { return 0; } - auto value = c->value.geti32(); - auto maxBitsRight = 31 - Index(CountLeadingZeroes(value)); - return std::max(Index(0), maxBitsLeft - maxBitsRight); + auto bitsRight = 31 - Index(c->value.countLeadingZeroes().geti32()); + return std::max(Index(0), maxBitsLeft - bitsRight); } return 32; } case DivUInt32: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + // properly handle zero for divisible if (maxBitsLeft == 0) { return 0; } if (auto* c = binary->right->dynCast()) { - auto value = c->value.geti32(); - auto maxBitsRight = 31 - Index(CountLeadingZeroes(value)); - return std::max(Index(0), maxBitsLeft - maxBitsRight); + auto bitsRight = 31 - Index(c->value.countLeadingZeroes().geti32()); + return std::max(Index(0), maxBitsLeft - bitsRight); } return maxBitsLeft; } case RemSInt32: { if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + // if maxBitsLeft is negative if (maxBitsLeft == 32) { return 32; } auto value = c->value.geti32(); - auto maxBitsRight = 32 - Index(CountLeadingZeroes(value - 1)); - return std::min(maxBitsLeft, maxBitsRight); + auto bitsRight = 32 - Index(CountLeadingZeroes(value - 1)); + return std::min(maxBitsLeft, bitsRight); } return 32; } @@ -197,8 +199,8 @@ Index getMaxBits(Expression* curr, if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); auto value = c->value.geti32(); - auto maxBitsRight = 32 - Index(CountLeadingZeroes(value - 1)); - return std::min(maxBitsLeft, maxBitsRight); + auto bitsRight = 32 - Index(CountLeadingZeroes(value - 1)); + return std::min(maxBitsLeft, bitsRight); } return 32; } @@ -209,6 +211,7 @@ Index getMaxBits(Expression* curr, case OrInt32: case XorInt32: { auto maxBits = getMaxBits(binary->right, localInfoProvider); + // if maxBits is negative if (maxBits == 32) { return 32; } @@ -235,6 +238,7 @@ Index getMaxBits(Expression* curr, case ShrSInt32: { if (auto* shift = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); + // if maxBits is negative if (maxBits == 32) { return 32; } @@ -262,33 +266,35 @@ Index getMaxBits(Expression* curr, case DivSInt64: { if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + // if maxBitsLeft is negative if (maxBitsLeft == 64) { return 64; } + // properly handle zero for divisible if (maxBitsLeft == 0) { return 0; } - auto value = c->value.geti64(); - auto maxBitsRight = 63 - Index(CountLeadingZeroes(value)); - return std::max(Index(0), maxBitsLeft - maxBitsRight); + auto bitsRight = 63 - Index(c->value.countLeadingZeroes().geti64()); + return std::max(Index(0), maxBitsLeft - bitsRight); } return 64; } case DivUInt64: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + // properly handle zero for divisible if (maxBitsLeft == 0) { return 0; } if (auto* c = binary->right->dynCast()) { - auto value = c->value.geti64(); - auto maxBitsRight = 63 - Index(CountLeadingZeroes(value)); - return std::max(Index(0), maxBitsLeft - maxBitsRight); + auto bitsRight = 63 - Index(c->value.countLeadingZeroes().geti64()); + return std::max(Index(0), maxBitsLeft - bitsRight); } return maxBitsLeft; } case RemSInt64: { if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + // if maxBitsLeft is negative if (maxBitsLeft == 64) { return 64; } @@ -314,6 +320,7 @@ Index getMaxBits(Expression* curr, case OrInt64: case XorInt64: { auto maxBits = getMaxBits(binary->right, localInfoProvider); + // if maxBits is negative if (maxBits == 64) { return 64; } @@ -340,6 +347,7 @@ Index getMaxBits(Expression* curr, case ShrSInt64: { if (auto* shift = binary->right->dynCast()) { auto maxBits = getMaxBits(binary->left, localInfoProvider); + // if maxBits is negative if (maxBits == 64) { return 64; } From 146c966725b656d97927042a76f10edb67f1fe97 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 28 Aug 2020 17:37:52 +0300 Subject: [PATCH 63/73] refactor DivSInt32|64 / DivUInt32|64 --- src/ir/bits.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index 13a5a77cce2..ee388f1d5cd 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -165,8 +165,8 @@ Index getMaxBits(Expression* curr, if (maxBitsLeft == 0) { return 0; } - auto bitsRight = 31 - Index(c->value.countLeadingZeroes().geti32()); - return std::max(Index(0), maxBitsLeft - bitsRight); + auto bitsRight = getMaxBits(c); + return std::max(Index(0), maxBitsLeft - bitsRight + 1); } return 32; } @@ -177,8 +177,8 @@ Index getMaxBits(Expression* curr, return 0; } if (auto* c = binary->right->dynCast()) { - auto bitsRight = 31 - Index(c->value.countLeadingZeroes().geti32()); - return std::max(Index(0), maxBitsLeft - bitsRight); + auto bitsRight = getMaxBits(c); + return std::max(Index(0), maxBitsLeft - bitsRight + 1); } return maxBitsLeft; } @@ -274,8 +274,8 @@ Index getMaxBits(Expression* curr, if (maxBitsLeft == 0) { return 0; } - auto bitsRight = 63 - Index(c->value.countLeadingZeroes().geti64()); - return std::max(Index(0), maxBitsLeft - bitsRight); + auto bitsRight = getMaxBits(c); + return std::max(Index(0), maxBitsLeft - bitsRight + 1); } return 64; } @@ -286,8 +286,8 @@ Index getMaxBits(Expression* curr, return 0; } if (auto* c = binary->right->dynCast()) { - auto bitsRight = 63 - Index(c->value.countLeadingZeroes().geti64()); - return std::max(Index(0), maxBitsLeft - bitsRight); + auto bitsRight = getMaxBits(c); + return std::max(Index(0), maxBitsLeft - bitsRight + 1); } return maxBitsLeft; } From a74f10edc3ea4cec97642b1d323c3775223cf322 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 28 Aug 2020 18:34:34 +0300 Subject: [PATCH 64/73] more tests and fixes --- src/ir/bits.h | 38 ++++++++++++++++++++++---------------- test/example/cpp-unit.cpp | 12 ++++++++++++ 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index ee388f1d5cd..89ac47af35c 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -157,8 +157,8 @@ Index getMaxBits(Expression* curr, case DivSInt32: { if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - // if maxBitsLeft is negative - if (maxBitsLeft == 32) { + // if maxBitsLeft or right constant is negative + if (maxBitsLeft == 32 || c->value.geti32() < 0) { return 32; } // properly handle zero for divisible @@ -172,11 +172,14 @@ Index getMaxBits(Expression* curr, } case DivUInt32: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - // properly handle zero for divisible - if (maxBitsLeft == 0) { - return 0; - } if (auto* c = binary->right->dynCast()) { + // properly handle zero for divisible + if (maxBitsLeft == 0) { + return 0; + } + if (c->value.geti32() < 0) { + return 1; + } auto bitsRight = getMaxBits(c); return std::max(Index(0), maxBitsLeft - bitsRight + 1); } @@ -190,7 +193,7 @@ Index getMaxBits(Expression* curr, return 32; } auto value = c->value.geti32(); - auto bitsRight = 32 - Index(CountLeadingZeroes(value - 1)); + auto bitsRight = 32 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 return std::min(maxBitsLeft, bitsRight); } return 32; @@ -199,7 +202,7 @@ Index getMaxBits(Expression* curr, if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); auto value = c->value.geti32(); - auto bitsRight = 32 - Index(CountLeadingZeroes(value - 1)); + auto bitsRight = 32 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 return std::min(maxBitsLeft, bitsRight); } return 32; @@ -266,8 +269,8 @@ Index getMaxBits(Expression* curr, case DivSInt64: { if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - // if maxBitsLeft is negative - if (maxBitsLeft == 64) { + // if maxBitsLeft or right const value is negative + if (maxBitsLeft == 64 || c->value.geti64() < 0) { return 64; } // properly handle zero for divisible @@ -281,11 +284,14 @@ Index getMaxBits(Expression* curr, } case DivUInt64: { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - // properly handle zero for divisible - if (maxBitsLeft == 0) { - return 0; - } if (auto* c = binary->right->dynCast()) { + // properly handle zero for divisible + if (maxBitsLeft == 0) { + return 0; + } + if (c->value.geti64() < 0) { + return 1; + } auto bitsRight = getMaxBits(c); return std::max(Index(0), maxBitsLeft - bitsRight + 1); } @@ -299,7 +305,7 @@ Index getMaxBits(Expression* curr, return 64; } auto value = c->value.geti64(); - auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); + auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 return std::min(maxBitsLeft, maxBitsRight); } return 64; @@ -308,7 +314,7 @@ Index getMaxBits(Expression* curr, if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); auto value = c->value.geti64(); - auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); + auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 return std::min(maxBitsLeft, maxBitsRight); } return 64; diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index efaf693a5d9..d333aa75e7d 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -143,6 +143,9 @@ void test_bits() { c0.value = Literal(int32_t(0x80000000)); c1.value = Literal(int32_t(-1)); assert_equal(getMaxBits(&b), 32); + c0.value = Literal(int32_t(2)); + c1.value = Literal(int32_t(-2)); + assert_equal(getMaxBits(&b), 32); b.op = DivUInt32; @@ -167,6 +170,9 @@ void test_bits() { c0.value = Literal(uint32_t(0x80000000)); c1.value = Literal(uint32_t(-1)); assert_equal(getMaxBits(&b), 1); + c0.value = Literal(uint32_t(2)); + c1.value = Literal(uint32_t(-2)); + assert_equal(getMaxBits(&b), 1); b.op = RemSInt32; c0.value = Literal(int32_t(0)); @@ -351,6 +357,9 @@ void test_bits() { c0.value = Literal(int64_t(0x8000000000000000)); c1.value = Literal(int64_t(-1)); assert_equal(getMaxBits(&b), 64); + c0.value = Literal(int64_t(2)); + c1.value = Literal(int64_t(-2)); + assert_equal(getMaxBits(&b), 64); b.op = DivUInt64; c0.value = Literal(uint64_t(0)); @@ -374,6 +383,9 @@ void test_bits() { c0.value = Literal(uint64_t(0x8000000000000000)); c1.value = Literal(uint64_t(-1)); assert_equal(getMaxBits(&b), 1); + c0.value = Literal(uint64_t(2)); + c1.value = Literal(uint64_t(-2)); + assert_equal(getMaxBits(&b), 1); b.op = RemSInt64; c0.value = Literal(int64_t(0)); From b4d614dab957f3cf953adad827b6c2e5b62d8fc6 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 28 Aug 2020 18:58:50 +0300 Subject: [PATCH 65/73] refactor --- src/ir/bits.h | 40 ++++++++++++---------------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index 89ac47af35c..f408999bb52 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -156,32 +156,24 @@ Index getMaxBits(Expression* curr, } case DivSInt32: { if (auto* c = binary->right->dynCast()) { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + int32_t maxBitsLeft = getMaxBits(binary->left, localInfoProvider); // if maxBitsLeft or right constant is negative if (maxBitsLeft == 32 || c->value.geti32() < 0) { return 32; } - // properly handle zero for divisible - if (maxBitsLeft == 0) { - return 0; - } - auto bitsRight = getMaxBits(c); - return std::max(Index(0), maxBitsLeft - bitsRight + 1); + int32_t bitsRight = getMaxBits(c); + return std::max(0, maxBitsLeft - bitsRight + 1); } return 32; } case DivUInt32: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + int32_t maxBitsLeft = getMaxBits(binary->left, localInfoProvider); if (auto* c = binary->right->dynCast()) { - // properly handle zero for divisible - if (maxBitsLeft == 0) { - return 0; - } if (c->value.geti32() < 0) { return 1; } - auto bitsRight = getMaxBits(c); - return std::max(Index(0), maxBitsLeft - bitsRight + 1); + int32_t bitsRight = getMaxBits(c); + return std::max(0, maxBitsLeft - bitsRight + 1); } return maxBitsLeft; } @@ -268,32 +260,24 @@ Index getMaxBits(Expression* curr, } case DivSInt64: { if (auto* c = binary->right->dynCast()) { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + int32_t maxBitsLeft = getMaxBits(binary->left, localInfoProvider); // if maxBitsLeft or right const value is negative if (maxBitsLeft == 64 || c->value.geti64() < 0) { return 64; } - // properly handle zero for divisible - if (maxBitsLeft == 0) { - return 0; - } - auto bitsRight = getMaxBits(c); - return std::max(Index(0), maxBitsLeft - bitsRight + 1); + int32_t bitsRight = getMaxBits(c); + return std::max(0, maxBitsLeft - bitsRight + 1); } return 64; } case DivUInt64: { - auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); + int32_t maxBitsLeft = getMaxBits(binary->left, localInfoProvider); if (auto* c = binary->right->dynCast()) { - // properly handle zero for divisible - if (maxBitsLeft == 0) { - return 0; - } if (c->value.geti64() < 0) { return 1; } - auto bitsRight = getMaxBits(c); - return std::max(Index(0), maxBitsLeft - bitsRight + 1); + int32_t bitsRight = getMaxBits(c); + return std::max(0, maxBitsLeft - bitsRight + 1); } return maxBitsLeft; } From 9b2fe4d304eb42a0a1c8a046dd141da916ee3099 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 28 Aug 2020 19:00:13 +0300 Subject: [PATCH 66/73] lint --- src/ir/bits.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index f408999bb52..79b86101c5f 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -185,7 +185,8 @@ Index getMaxBits(Expression* curr, return 32; } auto value = c->value.geti32(); - auto bitsRight = 32 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 + auto bitsRight = + 32 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 return std::min(maxBitsLeft, bitsRight); } return 32; @@ -194,7 +195,8 @@ Index getMaxBits(Expression* curr, if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); auto value = c->value.geti32(); - auto bitsRight = 32 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 + auto bitsRight = + 32 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 return std::min(maxBitsLeft, bitsRight); } return 32; @@ -289,7 +291,8 @@ Index getMaxBits(Expression* curr, return 64; } auto value = c->value.geti64(); - auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 + auto maxBitsRight = + 64 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 return std::min(maxBitsLeft, maxBitsRight); } return 64; @@ -298,7 +301,8 @@ Index getMaxBits(Expression* curr, if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); auto value = c->value.geti64(); - auto maxBitsRight = 64 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 + auto maxBitsRight = + 64 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 return std::min(maxBitsLeft, maxBitsRight); } return 64; From 162c94d7727c48c4e103bcf5384694c13f344930 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 28 Aug 2020 19:28:47 +0300 Subject: [PATCH 67/73] more tests --- test/example/cpp-unit.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index d333aa75e7d..9fa6e2becbe 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -140,6 +140,12 @@ void test_bits() { c0.value = Literal(int32_t(0x7FFFFFFF)); c1.value = Literal(int32_t(3)); assert_equal(getMaxBits(&b), 30); + c0.value = Literal(int32_t(0x0000FFFF)); + c1.value = Literal(int32_t(0xFF)); + assert_equal(getMaxBits(&b), 9); + c0.value = Literal(int32_t(0x00001000)); + c1.value = Literal(int32_t(0x00000FFF)); + assert_equal(getMaxBits(&b), 2); c0.value = Literal(int32_t(0x80000000)); c1.value = Literal(int32_t(-1)); assert_equal(getMaxBits(&b), 32); @@ -167,6 +173,12 @@ void test_bits() { c0.value = Literal(uint32_t(0x7FFFFFFF)); c1.value = Literal(uint32_t(3)); assert_equal(getMaxBits(&b), 30); + c0.value = Literal(int32_t(0x0000FFFF)); + c1.value = Literal(int32_t(0xFF)); + assert_equal(getMaxBits(&b), 9); + c0.value = Literal(int32_t(0x00001000)); + c1.value = Literal(int32_t(0x00000FFF)); + assert_equal(getMaxBits(&b), 2); c0.value = Literal(uint32_t(0x80000000)); c1.value = Literal(uint32_t(-1)); assert_equal(getMaxBits(&b), 1); From 8404d91f133fd850e0e317d09fe5e2319971168d Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 28 Aug 2020 19:30:55 +0300 Subject: [PATCH 68/73] indent --- test/example/cpp-unit.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index 9fa6e2becbe..a0713e371c0 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -143,7 +143,7 @@ void test_bits() { c0.value = Literal(int32_t(0x0000FFFF)); c1.value = Literal(int32_t(0xFF)); assert_equal(getMaxBits(&b), 9); - c0.value = Literal(int32_t(0x00001000)); + c0.value = Literal(int32_t(0x00001000)); c1.value = Literal(int32_t(0x00000FFF)); assert_equal(getMaxBits(&b), 2); c0.value = Literal(int32_t(0x80000000)); From 4be09567a0a4de27b909a7ac4f6194d4ad4e8cc6 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Fri, 28 Aug 2020 19:38:25 +0300 Subject: [PATCH 69/73] simplify --- src/ir/bits.h | 6 ------ test/example/cpp-unit.cpp | 4 ++-- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index 79b86101c5f..40e5b98f3b0 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -169,9 +169,6 @@ Index getMaxBits(Expression* curr, case DivUInt32: { int32_t maxBitsLeft = getMaxBits(binary->left, localInfoProvider); if (auto* c = binary->right->dynCast()) { - if (c->value.geti32() < 0) { - return 1; - } int32_t bitsRight = getMaxBits(c); return std::max(0, maxBitsLeft - bitsRight + 1); } @@ -275,9 +272,6 @@ Index getMaxBits(Expression* curr, case DivUInt64: { int32_t maxBitsLeft = getMaxBits(binary->left, localInfoProvider); if (auto* c = binary->right->dynCast()) { - if (c->value.geti64() < 0) { - return 1; - } int32_t bitsRight = getMaxBits(c); return std::max(0, maxBitsLeft - bitsRight + 1); } diff --git a/test/example/cpp-unit.cpp b/test/example/cpp-unit.cpp index a0713e371c0..07c88c1c575 100644 --- a/test/example/cpp-unit.cpp +++ b/test/example/cpp-unit.cpp @@ -184,7 +184,7 @@ void test_bits() { assert_equal(getMaxBits(&b), 1); c0.value = Literal(uint32_t(2)); c1.value = Literal(uint32_t(-2)); - assert_equal(getMaxBits(&b), 1); + assert_equal(getMaxBits(&b), 0); b.op = RemSInt32; c0.value = Literal(int32_t(0)); @@ -397,7 +397,7 @@ void test_bits() { assert_equal(getMaxBits(&b), 1); c0.value = Literal(uint64_t(2)); c1.value = Literal(uint64_t(-2)); - assert_equal(getMaxBits(&b), 1); + assert_equal(getMaxBits(&b), 0); b.op = RemSInt64; c0.value = Literal(int64_t(0)); From 5fc687a1d1ff164888b09d13d6c144776429e6ce Mon Sep 17 00:00:00 2001 From: Max Graey Date: Wed, 16 Sep 2020 15:55:48 +0300 Subject: [PATCH 70/73] Update src/ir/bits.h Co-authored-by: Thomas Lively <7121787+tlively@users.noreply.github.com> --- src/ir/bits.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index 40e5b98f3b0..2d8827574e6 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -157,7 +157,7 @@ Index getMaxBits(Expression* curr, case DivSInt32: { if (auto* c = binary->right->dynCast()) { int32_t maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - // if maxBitsLeft or right constant is negative + // If either side might be negative, then the result will be negative if (maxBitsLeft == 32 || c->value.geti32() < 0) { return 32; } From 0be907632b9fb86241b5bb5abb24f6f38974718b Mon Sep 17 00:00:00 2001 From: Max Graey Date: Wed, 16 Sep 2020 15:56:04 +0300 Subject: [PATCH 71/73] Update src/ir/bits.h Co-authored-by: Thomas Lively <7121787+tlively@users.noreply.github.com> --- src/ir/bits.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index 2d8827574e6..7724cd84ce3 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -199,8 +199,8 @@ Index getMaxBits(Expression* curr, return 32; } case AndInt32: { - auto maxBits = getMaxBits(binary->right, localInfoProvider); - return std::min(getMaxBits(binary->left, localInfoProvider), maxBits); + return std::min(getMaxBits(binary->left, localInfoProvider), + getMaxBits(binary->right, localInfoProvider)); } case OrInt32: case XorInt32: { From 33c9eab1d32b829f9622483432a45feb35b1ce4d Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 16 Sep 2020 16:30:09 +0300 Subject: [PATCH 72/73] add CeilLog2 util --- src/ir/bits.h | 20 ++++++-------------- src/support/bits.cpp | 9 +++++++++ src/support/bits.h | 6 ++++++ 3 files changed, 21 insertions(+), 14 deletions(-) diff --git a/src/ir/bits.h b/src/ir/bits.h index 7724cd84ce3..132f7ec4dc8 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -181,9 +181,7 @@ Index getMaxBits(Expression* curr, if (maxBitsLeft == 32) { return 32; } - auto value = c->value.geti32(); - auto bitsRight = - 32 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 + auto bitsRight = Index(CeilLog2(c->value.geti32())); return std::min(maxBitsLeft, bitsRight); } return 32; @@ -191,9 +189,7 @@ Index getMaxBits(Expression* curr, case RemUInt32: { if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - auto value = c->value.geti32(); - auto bitsRight = - 32 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 + auto bitsRight = Index(CeilLog2(c->value.geti32())); return std::min(maxBitsLeft, bitsRight); } return 32; @@ -284,20 +280,16 @@ Index getMaxBits(Expression* curr, if (maxBitsLeft == 64) { return 64; } - auto value = c->value.geti64(); - auto maxBitsRight = - 64 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 - return std::min(maxBitsLeft, maxBitsRight); + auto bitsRight = Index(CeilLog2(c->value.geti64())); + return std::min(maxBitsLeft, bitsRight); } return 64; } case RemUInt64: { if (auto* c = binary->right->dynCast()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - auto value = c->value.geti64(); - auto maxBitsRight = - 64 - Index(CountLeadingZeroes(value - 1)); // ceiled Log2 - return std::min(maxBitsLeft, maxBitsRight); + auto bitsRight = Index(CeilLog2(c->value.geti64())); + return std::min(maxBitsLeft, bitsRight); } return 64; } diff --git a/src/support/bits.cpp b/src/support/bits.cpp index 992b979558e..87fa7208b3f 100644 --- a/src/support/bits.cpp +++ b/src/support/bits.cpp @@ -152,6 +152,15 @@ template<> int CountLeadingZeroes(uint64_t v) { #endif } + +template<> int CeilLog2(uint32_t v) { + return 32 - CountLeadingZeroes(v - 1); +} + +template<> int CeilLog2(uint64_t v) { + return 64 - CountLeadingZeroes(v - 1); +} + uint32_t Log2(uint32_t v) { switch (v) { default: diff --git a/src/support/bits.h b/src/support/bits.h index bd91fdec659..a927a28321e 100644 --- a/src/support/bits.h +++ b/src/support/bits.h @@ -40,6 +40,7 @@ template int PopCount(T); template uint32_t BitReverse(T); template int CountTrailingZeroes(T); template int CountLeadingZeroes(T); +template int CeilLog2(T); #ifndef wasm_support_bits_definitions // The template specializations are provided elsewhere. @@ -52,6 +53,8 @@ extern template int CountTrailingZeroes(uint32_t); extern template int CountTrailingZeroes(uint64_t); extern template int CountLeadingZeroes(uint32_t); extern template int CountLeadingZeroes(uint64_t); +extern template int CeilLog2(uint32_t); +extern template int CeilLog2(uint64_t); #endif // Convenience signed -> unsigned. It usually doesn't make much sense to use bit @@ -65,6 +68,9 @@ template int CountTrailingZeroes(T v) { template int CountLeadingZeroes(T v) { return CountLeadingZeroes(typename std::make_unsigned::type(v)); } +template int CeilLog2(T v) { + return CeilLog2(typename std::make_unsigned::type(v)); +} template bool IsPowerOf2(T v) { return v != 0 && (v & (v - 1)) == 0; } From 277d15944dab2d4b881fb800c70c82eba5692eb4 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 16 Sep 2020 17:24:56 +0300 Subject: [PATCH 73/73] lint --- src/support/bits.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/support/bits.cpp b/src/support/bits.cpp index 87fa7208b3f..e60f2365b90 100644 --- a/src/support/bits.cpp +++ b/src/support/bits.cpp @@ -152,7 +152,6 @@ template<> int CountLeadingZeroes(uint64_t v) { #endif } - template<> int CeilLog2(uint32_t v) { return 32 - CountLeadingZeroes(v - 1); }