summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/bits.h10
-rw-r--r--src/passes/OptimizeInstructions.cpp18
-rw-r--r--src/support/bits.cpp47
-rw-r--r--src/support/bits.h82
-rw-r--r--src/support/utilities.h2
-rw-r--r--src/wasm/literal.cpp20
-rw-r--r--src/wasm/wasm-binary.cpp2
-rw-r--r--src/wasm/wasm-stack.cpp2
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);
}