summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/OptimizeInstructions.cpp30
-rw-r--r--src/support/bits.cpp14
-rw-r--r--src/support/bits.h4
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);