diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/passes/OptimizeInstructions.cpp | 30 | ||||
-rw-r--r-- | src/support/bits.cpp | 14 | ||||
-rw-r--r-- | src/support/bits.h | 4 |
3 files changed, 28 insertions, 20 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp index 1790623eb..2736c8984 100644 --- a/src/passes/OptimizeInstructions.cpp +++ b/src/passes/OptimizeInstructions.cpp @@ -617,13 +617,13 @@ struct OptimizeInstructions } if (binary->op == DivFloat32) { float c = right->value.getf32(); - if (Bits::isPowerOf2Float(c)) { + if (Bits::isPowerOf2InvertibleFloat(c)) { return optimizePowerOf2FDiv(binary, c); } } if (binary->op == DivFloat64) { double c = right->value.getf64(); - if (Bits::isPowerOf2Float(c)) { + if (Bits::isPowerOf2InvertibleFloat(c)) { return optimizePowerOf2FDiv(binary, c); } } @@ -1412,18 +1412,13 @@ private: return curr; } } - // bool(x) | 1 ==> 1 - if (matches(curr, binary(Abstract::Or, pure(&left), ival(1))) && - Bits::getMaxBits(left, this) == 1) { - return right; - } - // bool(x) & 1 ==> bool(x) - if (matches(curr, binary(Abstract::And, any(&left), ival(1))) && - Bits::getMaxBits(left, this) == 1) { - return left; - } - // bool(x) == 1 ==> bool(x) - if (matches(curr, binary(EqInt32, any(&left), i32(1))) && + // i32(bool(x)) == 1 ==> i32(bool(x)) + // i32(bool(x)) != 0 ==> i32(bool(x)) + // i32(bool(x)) & 1 ==> i32(bool(x)) + // i64(bool(x)) & 1 ==> i64(bool(x)) + if ((matches(curr, binary(EqInt32, any(&left), i32(1))) || + matches(curr, binary(NeInt32, any(&left), i32(0))) || + matches(curr, binary(Abstract::And, any(&left), ival(1)))) && Bits::getMaxBits(left, this) == 1) { return left; } @@ -1436,9 +1431,14 @@ private: } // bool(x) != 1 ==> !bool(x) if (matches(curr, binary(Abstract::Ne, any(&left), ival(1))) && - Bits::getMaxBits(curr->left, this) == 1) { + Bits::getMaxBits(left, this) == 1) { return builder.makeUnary(Abstract::getUnary(type, Abstract::EqZ), left); } + // bool(x) | 1 ==> 1 + if (matches(curr, binary(Abstract::Or, pure(&left), ival(1))) && + Bits::getMaxBits(left, this) == 1) { + return right; + } // Operations on all 1s // x & -1 ==> x diff --git a/src/support/bits.cpp b/src/support/bits.cpp index 8a81a7e83..1de9a0f3b 100644 --- a/src/support/bits.cpp +++ b/src/support/bits.cpp @@ -157,12 +157,20 @@ int ceilLog2(uint32_t v) { return 32 - countLeadingZeroes(v - 1); } int ceilLog2(uint64_t v) { return 64 - countLeadingZeroes(v - 1); } -bool isPowerOf2Float(float v) { +bool isPowerOf2InvertibleFloat(float v) { // Power of two floating points should have zero as their significands, // so here we just mask the exponent range of "v" and compare it with the // unmasked input value. If they are equal, our value is a power of // two. Also, we reject all values which are less than the minimal possible // power of two or greater than the maximum possible power of two. + // We check values only with exponent in more limited ranges + // [-126..+126] for floats and [-1022..+1022] for doubles for avoiding + // overflows and reject NaNs, infinity and denormals. We also reject + // "asymmetric exponents", like +1023, because the range of + // (non-NaN, non-infinity) values is -1022..+1023, and it is convenient in + // optimizations to depend on being able to invert a power of two without + // losing precision. + // This function used in OptimizeInstruction pass. const uint32_t MIN_POT = 0x01U << 23; // 0x1p-126 const uint32_t MAX_POT = 0xFDU << 23; // 0x1p+126 const uint32_t EXP_MASK = 0xFFU << 23; // mask only exponent @@ -171,8 +179,8 @@ bool isPowerOf2Float(float v) { return u >= MIN_POT && u <= MAX_POT && (u & EXP_MASK) == u; } -bool isPowerOf2Float(double v) { - // See isPowerOf2Float(float) +bool isPowerOf2InvertibleFloat(double v) { + // See isPowerOf2InvertibleFloat(float) const uint64_t MIN_POT = 0x001ULL << 52; // 0x1p-1022 const uint64_t MAX_POT = 0x7FDULL << 52; // 0x1p+1022 const uint64_t EXP_MASK = 0x7FFULL << 52; // mask only exponent diff --git a/src/support/bits.h b/src/support/bits.h index 333eb5cc2..a34bc5067 100644 --- a/src/support/bits.h +++ b/src/support/bits.h @@ -77,8 +77,8 @@ template<typename T> bool isPowerOf2(T v) { return v != 0 && (v & (v - 1)) == 0; } -bool isPowerOf2Float(float); -bool isPowerOf2Float(double); +bool isPowerOf2InvertibleFloat(float); +bool isPowerOf2InvertibleFloat(double); template<typename T, typename U> inline static T rotateLeft(T val, U count) { auto value = typename std::make_unsigned<T>::type(val); |