summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r--src/passes/OptimizeInstructions.cpp69
1 files changed, 59 insertions, 10 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 1c2445d5d..d77db8093 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -501,30 +501,42 @@ struct OptimizeInstructions
}
// math operations on a constant power of 2 right side can be optimized
if (right->type == Type::i32) {
- uint32_t c = right->value.geti32();
- if (IsPowerOf2(c)) {
+ BinaryOp op;
+ int32_t c = right->value.geti32();
+ if (c >= 0 &&
+ (op = makeUnsignedBinaryOp(binary->op)) != InvalidBinary &&
+ Bits::getMaxBits(binary->left, this) <= 31) {
+ binary->op = op;
+ }
+ if (IsPowerOf2((uint32_t)c)) {
switch (binary->op) {
case MulInt32:
- return optimizePowerOf2Mul(binary, c);
+ return optimizePowerOf2Mul(binary, (uint32_t)c);
case RemUInt32:
- return optimizePowerOf2URem(binary, c);
+ return optimizePowerOf2URem(binary, (uint32_t)c);
case DivUInt32:
- return optimizePowerOf2UDiv(binary, c);
+ return optimizePowerOf2UDiv(binary, (uint32_t)c);
default:
break;
}
}
}
if (right->type == Type::i64) {
- uint64_t c = right->value.geti64();
- if (IsPowerOf2(c)) {
+ BinaryOp op;
+ int64_t c = right->value.geti64();
+ if (c >= 0 &&
+ (op = makeUnsignedBinaryOp(binary->op)) != InvalidBinary &&
+ Bits::getMaxBits(binary->left, this) <= 63) {
+ binary->op = op;
+ }
+ if (IsPowerOf2((uint64_t)c)) {
switch (binary->op) {
case MulInt64:
- return optimizePowerOf2Mul(binary, c);
+ return optimizePowerOf2Mul(binary, (uint64_t)c);
case RemUInt64:
- return optimizePowerOf2URem(binary, c);
+ return optimizePowerOf2URem(binary, (uint64_t)c);
case DivUInt64:
- return optimizePowerOf2UDiv(binary, c);
+ return optimizePowerOf2UDiv(binary, (uint64_t)c);
default:
break;
}
@@ -1773,6 +1785,43 @@ private:
}
}
+ BinaryOp makeUnsignedBinaryOp(BinaryOp op) {
+ switch (op) {
+ case DivSInt32:
+ return DivUInt32;
+ case RemSInt32:
+ return RemUInt32;
+ case ShrSInt32:
+ return ShrUInt32;
+ case LtSInt32:
+ return LtUInt32;
+ case LeSInt32:
+ return LeUInt32;
+ case GtSInt32:
+ return GtUInt32;
+ case GeSInt32:
+ return GeUInt32;
+
+ case DivSInt64:
+ return DivUInt64;
+ case RemSInt64:
+ return RemUInt64;
+ case ShrSInt64:
+ return ShrUInt64;
+ case LtSInt64:
+ return LtUInt64;
+ case LeSInt64:
+ return LeUInt64;
+ case GtSInt64:
+ return GtUInt64;
+ case GeSInt64:
+ return GeUInt64;
+
+ default:
+ return InvalidBinary;
+ }
+ }
+
bool isSymmetric(Binary* binary) {
if (Properties::isSymmetric(binary)) {
return true;