summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Graey <maxgraey@gmail.com>2020-10-30 08:08:48 +0200
committerGitHub <noreply@github.com>2020-10-29 23:08:48 -0700
commit5fc27e20479edfef0674c89e9bb7888ee25cb054 (patch)
treea748191c55e48d91bbc3d01ed64e6d3de0762c66
parent25e47f2c3e7ca8151377075432b34c95073acaca (diff)
downloadbinaryen-5fc27e20479edfef0674c89e9bb7888ee25cb054.tar.gz
binaryen-5fc27e20479edfef0674c89e9bb7888ee25cb054.tar.bz2
binaryen-5fc27e20479edfef0674c89e9bb7888ee25cb054.zip
Fold subtraction of sums or differences from constants (#3295)
`C1 - (x + C2)` -> `(C1 - C2) - x` `C1 - (x - C2)` -> `(C1 + C2) - x` `C1 - (C2 - x)` -> `x + (C1 - C2)`
-rw-r--r--src/literal.h12
-rw-r--r--src/passes/OptimizeInstructions.cpp33
-rw-r--r--test/passes/optimize-instructions_all-features.txt44
-rw-r--r--test/passes/optimize-instructions_all-features.wast55
4 files changed, 144 insertions, 0 deletions
diff --git a/src/literal.h b/src/literal.h
index d94d1a6d0..625b3eb43 100644
--- a/src/literal.h
+++ b/src/literal.h
@@ -114,6 +114,18 @@ public:
WASM_UNREACHABLE("unexpected type");
}
}
+ bool isNegative() const {
+ switch (type.getBasic()) {
+ case Type::i32:
+ case Type::f32:
+ return i32 < 0;
+ case Type::i64:
+ case Type::f64:
+ return i64 < 0;
+ default:
+ WASM_UNREACHABLE("unexpected type");
+ }
+ }
bool isSignedMin() const {
switch (type.getBasic()) {
case Type::i32:
diff --git a/src/passes/OptimizeInstructions.cpp b/src/passes/OptimizeInstructions.cpp
index 57ef42913..20cdeee19 100644
--- a/src/passes/OptimizeInstructions.cpp
+++ b/src/passes/OptimizeInstructions.cpp
@@ -1734,6 +1734,39 @@ private:
return curr->left;
}
{
+ // C1 - (x + C2) ==> (C1 - C2) - x
+ Const *c1, *c2;
+ Expression* x;
+ if (matches(curr,
+ binary(Sub, ival(&c1), binary(Add, any(&x), ival(&c2))))) {
+ left->value = c1->value.sub(c2->value);
+ curr->right = x;
+ return curr;
+ }
+ // C1 - (x - C2) ==> (C1 + C2) - x
+ if (matches(curr,
+ binary(Sub, ival(&c1), binary(Sub, any(&x), ival(&c2))))) {
+ left->value = c1->value.add(c2->value);
+ curr->right = x;
+ return curr;
+ }
+ // C1 - (C2 - x) ==> x + (C1 - C2)
+ if (matches(curr,
+ binary(Sub, ival(&c1), binary(Sub, ival(&c2), any(&x))))) {
+ left->value = c1->value.sub(c2->value);
+ if (left->value.isNegative()) {
+ // -C1 - (C2 - x) ==> x - (C1 - C2)
+ left->value = left->value.neg();
+ curr->op = Abstract::getBinary(type, Sub);
+ } else {
+ curr->op = Abstract::getBinary(type, Add);
+ }
+ curr->right = x;
+ std::swap(curr->left, curr->right);
+ return curr;
+ }
+ }
+ {
// fval(C) / -x ==> -C / x
Expression* right;
if (matches(curr, binary(DivS, fval(), unary(Neg, any(&right))))) {
diff --git a/test/passes/optimize-instructions_all-features.txt b/test/passes/optimize-instructions_all-features.txt
index 96346ed22..522bd6fe8 100644
--- a/test/passes/optimize-instructions_all-features.txt
+++ b/test/passes/optimize-instructions_all-features.txt
@@ -4391,6 +4391,50 @@
)
)
)
+ (func $lhs-is-const (param $x i32) (param $y i64)
+ (drop
+ (i32.sub
+ (i32.const 1)
+ (local.get $x)
+ )
+ )
+ (drop
+ (i64.sub
+ (i64.const 1)
+ (local.get $y)
+ )
+ )
+ (drop
+ (i32.sub
+ (i32.const -2)
+ (local.get $x)
+ )
+ )
+ (drop
+ (i64.sub
+ (i64.const -2)
+ (local.get $y)
+ )
+ )
+ (drop
+ (i32.sub
+ (local.get $x)
+ (i32.const 1)
+ )
+ )
+ (drop
+ (i64.sub
+ (local.get $y)
+ (i64.const 1)
+ )
+ )
+ (drop
+ (i32.sub
+ (local.get $x)
+ (i32.const -2147483648)
+ )
+ )
+ )
(func $pre-combine-or (param $x i32) (param $y i32)
(drop
(i32.ge_s
diff --git a/test/passes/optimize-instructions_all-features.wast b/test/passes/optimize-instructions_all-features.wast
index cdb3c56f2..9b172e4bd 100644
--- a/test/passes/optimize-instructions_all-features.wast
+++ b/test/passes/optimize-instructions_all-features.wast
@@ -4842,6 +4842,61 @@
(local.get $x)
))
)
+ (func $lhs-is-const (param $x i32) (param $y i64)
+ ;; 0 - (x - 1)
+ (drop (i32.sub
+ (i32.const 0)
+ (i32.sub
+ (local.get $x)
+ (i32.const 1)
+ )
+ ))
+ (drop (i64.sub
+ (i64.const 0)
+ (i64.sub
+ (local.get $y)
+ (i64.const 1)
+ )
+ ))
+ ;; -1 - (x + 1)
+ (drop (i32.sub
+ (i32.const -1)
+ (i32.add
+ (local.get $x)
+ (i32.const 1)
+ )
+ ))
+ (drop (i64.sub
+ (i64.const -1)
+ (i64.add
+ (local.get $y)
+ (i64.const 1)
+ )
+ ))
+ ;; 1 - (2 - x)
+ (drop (i32.sub
+ (i32.const 1)
+ (i32.sub
+ (i32.const 2)
+ (local.get $x)
+ )
+ ))
+ (drop (i64.sub
+ (i64.const 1)
+ (i64.sub
+ (i64.const 2)
+ (local.get $y)
+ )
+ ))
+ ;; 0 - (0x80000000 - x)
+ (drop (i32.sub
+ (i32.const 0)
+ (i32.sub
+ (i32.const 0x80000000)
+ (local.get $x)
+ )
+ ))
+ )
(func $pre-combine-or (param $x i32) (param $y i32)
(drop (i32.or
(i32.gt_s