Skip to content

Commit

Permalink
Add optimization from x < 0 || x > POSITIVE_CONST to `x > POSITIVE_…
Browse files Browse the repository at this point in the history
…CONST` with unsigned comparison

Fixes WebAssembly#6685
  • Loading branch information
i582 committed Oct 11, 2024
1 parent a8aa660 commit 623ad09
Show file tree
Hide file tree
Showing 2 changed files with 189 additions and 0 deletions.
27 changes: 27 additions & 0 deletions src/passes/OptimizeInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,25 @@ struct OptimizeInstructions
return replaceCurrent(un);
}
}
{
// x < 0 || x > POSITIVE_CONST ==> x > POSITIVE_CONST (unsigned
// comparison)
Binary* bin;
Expression *x_left, *x_right;
Const* y;
// TODO: check if x_left === x_right
if (matches(curr,
binary(&bin,
OrInt32,
binary(LtSInt32, pure(&x_left), i32(0)),
binary(GtSInt32, pure(&x_right), constant(&y)))) &&
y->type == Type::i32 && y->value.geti32() > 0) {
bin->op = GtUInt32;
bin->left = x_left;
bin->right = y;
return;
}
}
{
// x <<>> (C & (31 | 63)) ==> x <<>> C'
// x <<>> (y & (31 | 63)) ==> x <<>> y
Expand Down Expand Up @@ -679,6 +698,14 @@ struct OptimizeInstructions
if (auto* ret = optimizeAddedConstants(curr)) {
return replaceCurrent(ret);
}
} else if (curr->op == SubInt32 || curr->op == SubInt64 ||
curr->op == AddVecI8x16 || curr->op == AddVecI16x8 ||
curr->op == SubVecI8x16 || curr->op == SubVecI16x8 ||
curr->op == AddVecI32x4 || curr->op == AddVecI64x2 ||
curr->op == SubVecI32x4 || curr->op == SubVecI64x2) {
if (auto* ret = optimizeAddedConstants(curr)) {
return replaceCurrent(ret);
}
} else if (curr->op == MulFloat32 || curr->op == MulFloat64 ||
curr->op == DivFloat32 || curr->op == DivFloat64) {
if (curr->left->type == curr->right->type) {
Expand Down
162 changes: 162 additions & 0 deletions test/lit/passes/optimize-instructions-cmps.wast
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited.
;; RUN: wasm-opt %s --optimize-instructions -S -o - | filecheck %s

;; Tests for "x < 0 || x > POSITIVE_CONST ==> x > POSITIVE_CONST (unsigned comparison)" optimization

(module
;; CHECK: (global $g (mut i32) (i32.const 0))
(global $g (mut i32) (i32.const 0))

;; CHECK: (func $cmp (param $0 i32) (result i32)
;; CHECK-NEXT: (i32.gt_u
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (i32.const 255)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $cmp (param $0 i32) (result i32)
(i32.or
(i32.lt_s
(local.get $0)
(i32.const 0)
)
(i32.gt_s
(local.get $0)
(i32.const 255)
)
)
)

;; CHECK: (func $cmp2 (param $0 i32) (result i32)
;; CHECK-NEXT: (i32.or
;; CHECK-NEXT: (i32.lt_s
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.gt_s
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (i32.const -255)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $cmp2 (param $0 i32) (result i32)
(i32.or
(i32.lt_s
(local.get $0)
(i32.const 0)
)
(i32.gt_s
(local.get $0)
(i32.const -255) ;; negative number
)
)
)

;; CHECK: (func $cmp3 (param $0 i32) (result i32)
;; CHECK-NEXT: (i32.or
;; CHECK-NEXT: (i32.lt_s
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.gt_s
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (i32.const 255)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $cmp3 (param $0 i32) (result i32)
(i32.or
(i32.lt_s
(local.get $0)
(i32.const 10) ;; note this
)
(i32.gt_s
(local.get $0)
(i32.const 255)
)
)
)

;; CHECK: (func $set_global_and_return (param $x i32) (result i32)
;; CHECK-NEXT: (global.set $g
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
;; CHECK-NEXT: (local.get $x)
;; CHECK-NEXT: )
(func $set_global_and_return (param $x i32) (result i32)
(global.set $g (local.get $x)) ;; side-effect
(local.get $x)
)

;; CHECK: (func $cmp4 (result i32)
;; CHECK-NEXT: (i32.or
;; CHECK-NEXT: (i32.lt_s
;; CHECK-NEXT: (call $set_global_and_return
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.gt_s
;; CHECK-NEXT: (call $set_global_and_return
;; CHECK-NEXT: (i32.const 10)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.const 255)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $cmp4 (result i32)
(i32.or
(i32.lt_s
(call $set_global_and_return (i32.const 10)) ;; x with side-effect
(i32.const 0)
)
(i32.gt_s
(call $set_global_and_return (i32.const 10))
(i32.const 255)
)
)
)

;; CHECK: (func $cmp5 (param $0 i32) (param $1 i32) (result i32)
;; CHECK-NEXT: (i32.gt_u
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (i32.const 255)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $cmp5 (param $0 i32) (param $1 i32) (result i32)
(i32.or
(i32.lt_s
(local.get $0)
(i32.const 0)
)
(i32.gt_s
(local.get $1) ;; note this
(i32.const 255)
)
)
)

;; CHECK: (func $cmp6 (param $0 i32) (param $1 i32) (result i32)
;; CHECK-NEXT: (i32.or
;; CHECK-NEXT: (i32.lt_s
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (i32.const 0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (i32.gt_s
;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: (local.get $1)
;; CHECK-NEXT: )
;; CHECK-NEXT: )
;; CHECK-NEXT: )
(func $cmp6 (param $0 i32) (param $1 i32) (result i32)
(i32.or
(i32.lt_s
(local.get $0)
(i32.const 0)
)
(i32.gt_s
(local.get $0)
(local.get $1) ;; non-constant
)
)
)
)

0 comments on commit 623ad09

Please sign in to comment.