summaryrefslogtreecommitdiff
path: root/src/passes/OptimizeInstructions.cpp
diff options
context:
space:
mode:
authorMax Graey <maxgraey@gmail.com>2020-10-24 04:38:51 +0300
committerGitHub <noreply@github.com>2020-10-23 18:38:51 -0700
commitb8b457ddad939a316cb833a8beb8987ca04fa865 (patch)
tree6ea6462578fb730ffd2545aea2086fdf2f0689b0 /src/passes/OptimizeInstructions.cpp
parent2dc156d1d3af7f3eb40bdce7c20aa84c98d50c15 (diff)
downloadbinaryen-b8b457ddad939a316cb833a8beb8987ca04fa865.tar.gz
binaryen-b8b457ddad939a316cb833a8beb8987ca04fa865.tar.bz2
binaryen-b8b457ddad939a316cb833a8beb8987ca04fa865.zip
OptimizeInstructions: More 64-bit integer patterns (#3015)
Extend ZeroRemover and optimizeAddedConstants to handle 64-bit integers as well. Use Literal.makeFromInt64 to make this easier.
Diffstat (limited to 'src/passes/OptimizeInstructions.cpp')
-rw-r--r--src/passes/OptimizeInstructions.cpp98
1 files changed, 56 insertions, 42 deletions
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index ad7cc8f8a..66c5269ff 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -225,15 +225,15 @@ struct OptimizeInstructions
{
// try to get rid of (0 - ..), that is, a zero only used to negate an
// int. an add of a subtract can be flipped in order to remove it:
- // (i32.add
- // (i32.sub
- // (i32.const 0)
+ // (ival.add
+ // (ival.sub
+ // (ival.const 0)
// X
// )
// Y
// )
// =>
- // (i32.sub
+ // (ival.sub
// Y
// X
// )
@@ -241,8 +241,8 @@ struct OptimizeInstructions
Expression *x, *y;
Binary* sub;
if (matches(curr,
- binary(AddInt32,
- binary(&sub, SubInt32, i32(0), any(&x)),
+ binary(Abstract::Add,
+ binary(&sub, Abstract::Sub, ival(0), any(&x)),
any(&y))) &&
canReorder(x, y)) {
sub->left = y;
@@ -252,24 +252,24 @@ struct OptimizeInstructions
}
{
// The flip case is even easier, as no reordering occurs:
- // (i32.add
+ // (ival.add
// Y
- // (i32.sub
- // (i32.const 0)
+ // (ival.sub
+ // (ival.const 0)
// X
// )
// )
// =>
- // (i32.sub
+ // (ival.sub
// Y
// X
// )
Expression* y;
Binary* sub;
if (matches(curr,
- binary(AddInt32,
+ binary(Abstract::Add,
any(&y),
- binary(&sub, SubInt32, i32(0), any())))) {
+ binary(&sub, Abstract::Sub, ival(0), any())))) {
sub->left = y;
return sub;
}
@@ -476,11 +476,11 @@ struct OptimizeInstructions
}
// note that both left and right may be consts, but then we let
// precompute compute the constant result
- } else if (binary->op == AddInt32) {
+ } else if (binary->op == AddInt32 || binary->op == AddInt64) {
if (auto* ret = optimizeAddedConstants(binary)) {
return ret;
}
- } else if (binary->op == SubInt32) {
+ } else if (binary->op == SubInt32 || binary->op == SubInt64) {
if (auto* ret = optimizeAddedConstants(binary)) {
return ret;
}
@@ -1052,13 +1052,15 @@ private:
// and combine them note that we ignore division/shift-right, as rounding
// makes this nonlinear, so not a valid opt
Expression* optimizeAddedConstants(Binary* binary) {
- uint32_t constant = 0;
+ assert(binary->type.isInteger());
+
+ uint64_t constant = 0;
std::vector<Const*> constants;
struct SeekState {
Expression* curr;
- int mul;
- SeekState(Expression* curr, int mul) : curr(curr), mul(mul) {}
+ int64_t mul;
+ SeekState(Expression* curr, int64_t mul) : curr(curr), mul(mul) {}
};
std::vector<SeekState> seekStack;
seekStack.emplace_back(binary, 1);
@@ -1068,37 +1070,40 @@ private:
auto curr = state.curr;
auto mul = state.mul;
if (auto* c = curr->dynCast<Const>()) {
- uint32_t value = c->value.geti32();
- if (value != 0) {
+ int64_t value = c->value.getInteger();
+ if (value != 0LL) {
constant += value * mul;
constants.push_back(c);
}
continue;
} else if (auto* binary = curr->dynCast<Binary>()) {
- if (binary->op == AddInt32) {
+ if (binary->op == Abstract::getBinary(binary->type, Abstract::Add)) {
seekStack.emplace_back(binary->right, mul);
seekStack.emplace_back(binary->left, mul);
continue;
- } else if (binary->op == SubInt32) {
+ } else if (binary->op ==
+ Abstract::getBinary(binary->type, Abstract::Sub)) {
// if the left is a zero, ignore it, it's how we negate ints
auto* left = binary->left->dynCast<Const>();
seekStack.emplace_back(binary->right, -mul);
- if (!left || left->value.geti32() != 0) {
+ if (!left || !left->value.isZero()) {
seekStack.emplace_back(binary->left, mul);
}
continue;
- } else if (binary->op == ShlInt32) {
+ } else if (binary->op ==
+ Abstract::getBinary(binary->type, Abstract::Shl)) {
if (auto* c = binary->right->dynCast<Const>()) {
seekStack.emplace_back(
binary->left, mul * Bits::pow2(Bits::getEffectiveShifts(c)));
continue;
}
- } else if (binary->op == MulInt32) {
+ } else if (binary->op ==
+ Abstract::getBinary(binary->type, Abstract::Mul)) {
if (auto* c = binary->left->dynCast<Const>()) {
- seekStack.emplace_back(binary->right, mul * c->value.geti32());
+ seekStack.emplace_back(binary->right, mul * c->value.getInteger());
continue;
} else if (auto* c = binary->right->dynCast<Const>()) {
- seekStack.emplace_back(binary->left, mul * c->value.geti32());
+ seekStack.emplace_back(binary->left, mul * c->value.getInteger());
continue;
}
}
@@ -1109,7 +1114,7 @@ private:
// nothing much to do, except for the trivial case of adding/subbing a
// zero
if (auto* c = binary->right->dynCast<Const>()) {
- if (c->value.geti32() == 0) {
+ if (c->value.isZero()) {
return binary->left;
}
}
@@ -1117,7 +1122,7 @@ private:
}
// wipe out all constants, we'll replace with a single added one
for (auto* c : constants) {
- c->value = Literal(int32_t(0));
+ c->value = Literal::makeZero(c->type);
}
// remove added/subbed zeros
struct ZeroRemover : public PostWalker<ZeroRemover> {
@@ -1128,44 +1133,48 @@ private:
ZeroRemover(PassOptions& passOptions) : passOptions(passOptions) {}
void visitBinary(Binary* curr) {
+ if (!curr->type.isInteger()) {
+ return;
+ }
FeatureSet features = getModule()->features;
+ auto type = curr->type;
auto* left = curr->left->dynCast<Const>();
auto* right = curr->right->dynCast<Const>();
- if (curr->op == AddInt32) {
- if (left && left->value.geti32() == 0) {
+ if (curr->op == Abstract::getBinary(type, Abstract::Add)) {
+ if (left && left->value.isZero()) {
replaceCurrent(curr->right);
return;
}
- if (right && right->value.geti32() == 0) {
+ if (right && right->value.isZero()) {
replaceCurrent(curr->left);
return;
}
- } else if (curr->op == SubInt32) {
+ } else if (curr->op == Abstract::getBinary(type, Abstract::Sub)) {
// we must leave a left zero, as it is how we negate ints
- if (right && right->value.geti32() == 0) {
+ if (right && right->value.isZero()) {
replaceCurrent(curr->left);
return;
}
- } else if (curr->op == ShlInt32) {
+ } else if (curr->op == Abstract::getBinary(type, Abstract::Shl)) {
// shifting a 0 is a 0, or anything by 0 has no effect, all unless the
// shift has side effects
- if (((left && left->value.geti32() == 0) ||
+ if (((left && left->value.isZero()) ||
(right && Bits::getEffectiveShifts(right) == 0)) &&
!EffectAnalyzer(passOptions, features, curr->right)
.hasSideEffects()) {
replaceCurrent(curr->left);
return;
}
- } else if (curr->op == MulInt32) {
+ } else if (curr->op == Abstract::getBinary(type, Abstract::Mul)) {
// multiplying by zero is a zero, unless the other side has side
// effects
- if (left && left->value.geti32() == 0 &&
+ if (left && left->value.isZero() &&
!EffectAnalyzer(passOptions, features, curr->right)
.hasSideEffects()) {
replaceCurrent(left);
return;
}
- if (right && right->value.geti32() == 0 &&
+ if (right && right->value.isZero() &&
!EffectAnalyzer(passOptions, features, curr->left)
.hasSideEffects()) {
replaceCurrent(right);
@@ -1178,17 +1187,22 @@ private:
ZeroRemover remover(getPassOptions());
remover.setModule(getModule());
remover.walk(walked);
- if (constant == 0) {
+ if (constant == 0ULL) {
return walked; // nothing more to do
}
if (auto* c = walked->dynCast<Const>()) {
- assert(c->value.geti32() == 0);
- c->value = Literal(constant);
+ assert(c->value.isZero());
+ // Accumulated 64-bit constant value in 32-bit context will be wrapped
+ // during downcasting. So it's valid unification for 32-bit and 64-bit
+ // values.
+ c->value = Literal::makeFromInt64(constant, c->type);
return c;
}
Builder builder(*getModule());
return builder.makeBinary(
- AddInt32, walked, builder.makeConst(Literal(constant)));
+ Abstract::getBinary(walked->type, Abstract::Add),
+ walked,
+ builder.makeConst(Literal::makeFromInt64(constant, walked->type)));
}
// expensive1 | expensive2 can be turned into expensive1 ? 1 : expensive2,