diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/bits.h | 10 | ||||
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 18 | ||||
-rw-r--r-- | src/support/bits.cpp | 47 | ||||
-rw-r--r-- | src/support/bits.h | 82 | ||||
-rw-r--r-- | src/support/utilities.h | 2 | ||||
-rw-r--r-- | src/wasm/literal.cpp | 20 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 2 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 2 |
8 files changed, 93 insertions, 90 deletions
diff --git a/src/ir/bits.h b/src/ir/bits.h index 40bd8e545..95481eeab 100644 --- a/src/ir/bits.h +++ b/src/ir/bits.h @@ -51,7 +51,7 @@ inline uint32_t getMaskedBits(uint32_t mask) { return 0; } // this is indeed a mask - return 32 - CountLeadingZeroes(mask); + return 32 - countLeadingZeroes(mask); } // gets the number of effective shifts a shift operation does. In @@ -180,7 +180,7 @@ Index getMaxBits(Expression* curr, if (maxBitsLeft == 32) { return 32; } - auto bitsRight = Index(CeilLog2(c->value.geti32())); + auto bitsRight = Index(ceilLog2(c->value.geti32())); return std::min(maxBitsLeft, bitsRight); } return 32; @@ -188,7 +188,7 @@ Index getMaxBits(Expression* curr, case RemUInt32: { if (auto* c = binary->right->dynCast<Const>()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - auto bitsRight = Index(CeilLog2(c->value.geti32())); + auto bitsRight = Index(ceilLog2(c->value.geti32())); return std::min(maxBitsLeft, bitsRight); } return 32; @@ -275,7 +275,7 @@ Index getMaxBits(Expression* curr, if (maxBitsLeft == 64) { return 64; } - auto bitsRight = Index(CeilLog2(c->value.geti64())); + auto bitsRight = Index(ceilLog2(c->value.geti64())); return std::min(maxBitsLeft, bitsRight); } return 64; @@ -283,7 +283,7 @@ Index getMaxBits(Expression* curr, case RemUInt64: { if (auto* c = binary->right->dynCast<Const>()) { auto maxBitsLeft = getMaxBits(binary->left, localInfoProvider); - auto bitsRight = Index(CeilLog2(c->value.geti64())); + auto bitsRight = Index(ceilLog2(c->value.geti64())); return std::min(maxBitsLeft, bitsRight); } return 64; diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 55af9a34d..dc38933a6 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -304,7 +304,7 @@ struct OptimizeInstructions if (matches(curr, unary(Abstract::EqZ, binary(&inner, Abstract::RemS, any(), ival(&c)))) && - IsPowerOf2((uint64_t)c->value.getInteger())) { + Bits::isPowerOf2((uint64_t)c->value.getInteger())) { inner->op = Abstract::getBinary(c->type, Abstract::And); c->value = c->value.sub(Literal::makeFromInt32(1, c->type)); return curr; @@ -407,7 +407,7 @@ struct OptimizeInstructions // forcing them to zero like we do in the zero-extend. int32_t constValue = c->value.geti32(); auto upperConstValue = constValue & ~Bits::lowBitMask(bits); - uint32_t count = PopCount(upperConstValue); + uint32_t count = Bits::popCount(upperConstValue); auto constSignBit = constValue & (1 << (bits - 1)); if ((count > 0 && count < 32 - bits) || (constSignBit && count == 0)) { @@ -529,7 +529,7 @@ struct OptimizeInstructions Bits::getMaxBits(binary->left, this) <= 31) { binary->op = op; } - if (IsPowerOf2((uint32_t)c)) { + if (Bits::isPowerOf2((uint32_t)c)) { switch (binary->op) { case MulInt32: return optimizePowerOf2Mul(binary, (uint32_t)c); @@ -550,7 +550,7 @@ struct OptimizeInstructions Bits::getMaxBits(binary->left, this) <= 63) { binary->op = op; } - if (IsPowerOf2((uint64_t)c)) { + if (Bits::isPowerOf2((uint64_t)c)) { switch (binary->op) { case MulInt64: return optimizePowerOf2Mul(binary, (uint64_t)c); @@ -976,8 +976,8 @@ private: continue; } else if (binary->op == ShlInt32) { if (auto* c = binary->right->dynCast<Const>()) { - seekStack.emplace_back(binary->left, - mul * Pow2(Bits::getEffectiveShifts(c))); + seekStack.emplace_back( + binary->left, mul * Bits::pow2(Bits::getEffectiveShifts(c))); continue; } } else if (binary->op == MulInt32) { @@ -1206,7 +1206,7 @@ private: static_assert(std::is_same<T, uint32_t>::value || std::is_same<T, uint64_t>::value, "type mismatch"); - auto shifts = CountTrailingZeroes<T>(c); + auto shifts = Bits::countTrailingZeroes(c); binary->op = std::is_same<T, uint32_t>::value ? ShlInt32 : ShlInt64; binary->right->cast<Const>()->value = Literal(static_cast<T>(shifts)); return binary; @@ -1221,7 +1221,7 @@ private: static_assert(std::is_same<T, uint32_t>::value || std::is_same<T, uint64_t>::value, "type mismatch"); - auto shifts = CountTrailingZeroes<T>(c); + auto shifts = Bits::countTrailingZeroes(c); binary->op = std::is_same<T, uint32_t>::value ? ShrUInt32 : ShrUInt64; binary->right->cast<Const>()->value = Literal(static_cast<T>(shifts)); return binary; @@ -1310,7 +1310,7 @@ private: binary(Abstract::Ne, binary(&inner, Abstract::RemS, any(), ival(&c)), ival(0))) && - IsPowerOf2((uint64_t)c->value.getInteger())) { + Bits::isPowerOf2((uint64_t)c->value.getInteger())) { inner->op = Abstract::getBinary(c->type, Abstract::And); c->value = c->value.sub(Literal::makeFromInt32(1, c->type)); return curr; diff --git a/src/support/bits.cpp b/src/support/bits.cpp index e60f2365b..7e22466d8 100644 --- a/src/support/bits.cpp +++ b/src/support/bits.cpp @@ -14,7 +14,6 @@ * limitations under the License. */ -#define wasm_support_bits_definitions #include "support/bits.h" #include "../compiler-support.h" #include "support/utilities.h" @@ -25,7 +24,9 @@ namespace wasm { -template<> int PopCount<uint8_t>(uint8_t v) { +namespace Bits { + +int popCount(uint8_t v) { // Small table lookup. static const uint8_t tbl[32] = {0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, @@ -33,15 +34,15 @@ template<> int PopCount<uint8_t>(uint8_t v) { return tbl[v & 0xf] + tbl[v >> 4]; } -template<> int PopCount<uint16_t>(uint16_t v) { +int popCount(uint16_t v) { #if __has_builtin(__builtin_popcount) || defined(__GNUC__) return __builtin_popcount(v); #else - return PopCount((uint8_t)(v & 0xFF)) + PopCount((uint8_t)(v >> 8)); + return popCount((uint8_t)(v & 0xFF)) + popCount((uint8_t)(v >> 8)); #endif } -template<> int PopCount<uint32_t>(uint32_t v) { +int popCount(uint32_t v) { #if __has_builtin(__builtin_popcount) || defined(__GNUC__) return __builtin_popcount(v); #else @@ -53,15 +54,15 @@ template<> int PopCount<uint32_t>(uint32_t v) { #endif } -template<> int PopCount<uint64_t>(uint64_t v) { +int popCount(uint64_t v) { #if __has_builtin(__builtin_popcount) || defined(__GNUC__) return __builtin_popcountll(v); #else - return PopCount((uint32_t)v) + PopCount((uint32_t)(v >> 32)); + return popCount((uint32_t)v) + popCount((uint32_t)(v >> 32)); #endif } -template<> uint32_t BitReverse<uint32_t>(uint32_t v) { +uint32_t bitReverse(uint32_t v) { // See Hacker's Delight, first edition, figure 7-1. v = ((v & 0x55555555) << 1) | ((v >> 1) & 0x55555555); v = ((v & 0x33333333) << 2) | ((v >> 2) & 0x33333333); @@ -70,7 +71,7 @@ template<> uint32_t BitReverse<uint32_t>(uint32_t v) { return v; } -template<> int CountTrailingZeroes<uint32_t>(uint32_t v) { +int countTrailingZeroes(uint32_t v) { if (v == 0) { return 32; } @@ -91,7 +92,7 @@ template<> int CountTrailingZeroes<uint32_t>(uint32_t v) { #endif } -template<> int CountTrailingZeroes<uint64_t>(uint64_t v) { +int countTrailingZeroes(uint64_t v) { if (v == 0) { return 64; } @@ -102,12 +103,12 @@ template<> int CountTrailingZeroes<uint64_t>(uint64_t v) { _BitScanForward64(&count, v); return (int)count; #else - return (uint32_t)v ? CountTrailingZeroes((uint32_t)v) - : 32 + CountTrailingZeroes((uint32_t)(v >> 32)); + return (uint32_t)v ? countTrailingZeroes((uint32_t)v) + : 32 + countTrailingZeroes((uint32_t)(v >> 32)); #endif } -template<> int CountLeadingZeroes<uint32_t>(uint32_t v) { +int countLeadingZeroes(uint32_t v) { if (v == 0) { return 32; } @@ -136,7 +137,7 @@ template<> int CountLeadingZeroes<uint32_t>(uint32_t v) { #endif } -template<> int CountLeadingZeroes<uint64_t>(uint64_t v) { +int countLeadingZeroes(uint64_t v) { if (v == 0) { return 64; } @@ -147,20 +148,16 @@ template<> int CountLeadingZeroes<uint64_t>(uint64_t v) { _BitScanReverse64(&count, v); return 63 - int(count); #else - return v >> 32 ? CountLeadingZeroes((uint32_t)(v >> 32)) - : 32 + CountLeadingZeroes((uint32_t)v); + return v >> 32 ? countLeadingZeroes((uint32_t)(v >> 32)) + : 32 + countLeadingZeroes((uint32_t)v); #endif } -template<> int CeilLog2<uint32_t>(uint32_t v) { - return 32 - CountLeadingZeroes(v - 1); -} +int ceilLog2(uint32_t v) { return 32 - countLeadingZeroes(v - 1); } -template<> int CeilLog2<uint64_t>(uint64_t v) { - return 64 - CountLeadingZeroes(v - 1); -} +int ceilLog2(uint64_t v) { return 64 - countLeadingZeroes(v - 1); } -uint32_t Log2(uint32_t v) { +uint32_t log2(uint32_t v) { switch (v) { default: WASM_UNREACHABLE("invalid value"); @@ -179,6 +176,8 @@ uint32_t Log2(uint32_t v) { } } -uint32_t Pow2(uint32_t v) { return 1 << v; } +uint32_t pow2(uint32_t v) { return 1 << v; } + +} // namespace Bits } // namespace wasm diff --git a/src/support/bits.h b/src/support/bits.h index a927a2832..3231e1c96 100644 --- a/src/support/bits.h +++ b/src/support/bits.h @@ -29,67 +29,71 @@ * * We instead use portable and reasonably-fast implementations, while * avoiding implementations with large lookup tables. - * - * TODO: The convention here should be changed PopCount => popCount, - * initial lowercase, to match the rest of the codebase. */ namespace wasm { -template<typename T> int PopCount(T); -template<typename T> uint32_t BitReverse(T); -template<typename T> int CountTrailingZeroes(T); -template<typename T> int CountLeadingZeroes(T); -template<typename T> int CeilLog2(T); - -#ifndef wasm_support_bits_definitions -// The template specializations are provided elsewhere. -extern template int PopCount(uint8_t); -extern template int PopCount(uint16_t); -extern template int PopCount(uint32_t); -extern template int PopCount(uint64_t); -extern template uint32_t BitReverse(uint32_t); -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 -// functions on signed types. -template<typename T> int PopCount(T v) { - return PopCount(typename std::make_unsigned<T>::type(v)); +namespace Bits { + +int popCount(uint8_t); +int popCount(uint16_t); +int popCount(uint32_t); +int popCount(uint64_t); + +inline int popCount(int8_t v) { return popCount(uint8_t(v)); } +inline int popCount(int16_t v) { return popCount(uint16_t(v)); } +inline int popCount(int32_t v) { return popCount(uint32_t(v)); } +inline int popCount(int64_t v) { return popCount(uint64_t(v)); } + +uint32_t bitReverse(uint32_t); + +int countTrailingZeroes(uint32_t); +int countTrailingZeroes(uint64_t); + +inline int countTrailingZeroes(int32_t v) { + return countTrailingZeroes(uint32_t(v)); } -template<typename T> int CountTrailingZeroes(T v) { - return CountTrailingZeroes(typename std::make_unsigned<T>::type(v)); +inline int countTrailingZeroes(int64_t v) { + return countTrailingZeroes(uint64_t(v)); } -template<typename T> int CountLeadingZeroes(T v) { - return CountLeadingZeroes(typename std::make_unsigned<T>::type(v)); + +int countLeadingZeroes(uint32_t); +int countLeadingZeroes(uint64_t); + +inline int countLeadingZeroes(int32_t v) { + return countLeadingZeroes(uint32_t(v)); } -template<typename T> int CeilLog2(T v) { - return CeilLog2(typename std::make_unsigned<T>::type(v)); +inline int countLeadingZeroes(int64_t v) { + return countLeadingZeroes(uint64_t(v)); } -template<typename T> bool IsPowerOf2(T v) { + +int ceilLog2(uint32_t); +int ceilLog2(uint64_t); + +inline int ceilLog2(int32_t v) { return ceilLog2(uint32_t(v)); } +inline int ceilLog2(int64_t v) { return ceilLog2(uint64_t(v)); } + +template<typename T> bool isPowerOf2(T v) { return v != 0 && (v & (v - 1)) == 0; } -template<typename T, typename U> inline static T RotateLeft(T val, U count) { +template<typename T, typename U> inline static T rotateLeft(T val, U count) { auto value = typename std::make_unsigned<T>::type(val); U mask = sizeof(T) * CHAR_BIT - 1; count &= mask; return (value << count) | (value >> (-count & mask)); } -template<typename T, typename U> inline static T RotateRight(T val, U count) { +template<typename T, typename U> inline static T rotateRight(T val, U count) { auto value = typename std::make_unsigned<T>::type(val); U mask = sizeof(T) * CHAR_BIT - 1; count &= mask; return (value >> count) | (value << (-count & mask)); } -extern uint32_t Log2(uint32_t v); -extern uint32_t Pow2(uint32_t v); +uint32_t log2(uint32_t v); +uint32_t pow2(uint32_t v); + +} // namespace Bits } // namespace wasm diff --git a/src/support/utilities.h b/src/support/utilities.h index 5280fcb3b..38fe6fd73 100644 --- a/src/support/utilities.h +++ b/src/support/utilities.h @@ -44,7 +44,7 @@ inline Destination bit_cast(const Source& source) { } inline size_t alignAddr(size_t address, size_t alignment) { - assert(alignment && IsPowerOf2((uint32_t)alignment) && + assert(alignment && Bits::isPowerOf2((uint32_t)alignment) && "Alignment is not a power of two!"); assert(address + alignment - 1 >= address); diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 54453b356..f42727aeb 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -472,30 +472,30 @@ std::ostream& operator<<(std::ostream& o, const ExceptionPackage& exn) { Literal Literal::countLeadingZeroes() const { if (type == Type::i32) { - return Literal((int32_t)CountLeadingZeroes(i32)); + return Literal((int32_t)Bits::countLeadingZeroes(i32)); } if (type == Type::i64) { - return Literal((int64_t)CountLeadingZeroes(i64)); + return Literal((int64_t)Bits::countLeadingZeroes(i64)); } WASM_UNREACHABLE("invalid type"); } Literal Literal::countTrailingZeroes() const { if (type == Type::i32) { - return Literal((int32_t)CountTrailingZeroes(i32)); + return Literal((int32_t)Bits::countTrailingZeroes(i32)); } if (type == Type::i64) { - return Literal((int64_t)CountTrailingZeroes(i64)); + return Literal((int64_t)Bits::countTrailingZeroes(i64)); } WASM_UNREACHABLE("invalid type"); } Literal Literal::popCount() const { if (type == Type::i32) { - return Literal((int32_t)PopCount(i32)); + return Literal((int32_t)Bits::popCount(i32)); } if (type == Type::i64) { - return Literal((int64_t)PopCount(i64)); + return Literal((int64_t)Bits::popCount(i64)); } WASM_UNREACHABLE("invalid type"); } @@ -1149,9 +1149,9 @@ Literal Literal::shrU(const Literal& other) const { Literal Literal::rotL(const Literal& other) const { switch (type.getBasic()) { case Type::i32: - return Literal(RotateLeft(uint32_t(i32), uint32_t(other.i32))); + return Literal(Bits::rotateLeft(uint32_t(i32), uint32_t(other.i32))); case Type::i64: - return Literal(RotateLeft(uint64_t(i64), uint64_t(other.i64))); + return Literal(Bits::rotateLeft(uint64_t(i64), uint64_t(other.i64))); default: WASM_UNREACHABLE("unexpected type"); } @@ -1160,9 +1160,9 @@ Literal Literal::rotL(const Literal& other) const { Literal Literal::rotR(const Literal& other) const { switch (type.getBasic()) { case Type::i32: - return Literal(RotateRight(uint32_t(i32), uint32_t(other.i32))); + return Literal(Bits::rotateRight(uint32_t(i32), uint32_t(other.i32))); case Type::i64: - return Literal(RotateRight(uint64_t(i64), uint64_t(other.i64))); + return Literal(Bits::rotateRight(uint64_t(i64), uint64_t(other.i64))); default: WASM_UNREACHABLE("unexpected type"); } diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 38a85bd1b..8ebddc8e8 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -3145,7 +3145,7 @@ void WasmBinaryBuilder::readMemoryAccess(Address& alignment, Address& offset) { if (rawAlignment > 4) { throwError("Alignment must be of a reasonable size"); } - alignment = Pow2(rawAlignment); + alignment = Bits::pow2(rawAlignment); offset = getU32LEB(); } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 1ca8869c7..fcf9e4b8a 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -1935,7 +1935,7 @@ void BinaryInstWriter::setScratchLocals() { void BinaryInstWriter::emitMemoryAccess(size_t alignment, size_t bytes, uint32_t offset) { - o << U32LEB(Log2(alignment ? alignment : bytes)); + o << U32LEB(Bits::log2(alignment ? alignment : bytes)); o << U32LEB(offset); } |