| ;; 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 |
| |
| (module |
| (memory 0) |
| ;; CHECK: (type $0 (func (param i32 i64))) |
| (type $0 (func (param i32 i64))) |
| ;; CHECK: (func $and-and (param $i1 i32) (result i32) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $i1) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $and-and (param $i1 i32) (result i32) |
| (i32.and |
| (i32.and |
| (local.get $i1) |
| (i32.const 5) |
| ) |
| (i32.const 3) |
| ) |
| ) |
| ;; CHECK: (func $or-or (param $i1 i32) (result i32) |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $i1) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $or-or (param $i1 i32) (result i32) |
| (i32.or |
| (i32.or |
| (local.get $i1) |
| (i32.const 1) |
| ) |
| (i32.const 2) |
| ) |
| ) |
| ;; CHECK: (func $xor-xor (param $i1 i32) (result i32) |
| ;; CHECK-NEXT: (i32.xor |
| ;; CHECK-NEXT: (local.get $i1) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $xor-xor (param $i1 i32) (result i32) |
| (i32.xor |
| (i32.xor |
| (local.get $i1) |
| (i32.const -2) |
| ) |
| (i32.const -5) |
| ) |
| ) |
| ;; CHECK: (func $mul-mul (param $i1 i32) (result i32) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (local.get $i1) |
| ;; CHECK-NEXT: (i32.const -10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $mul-mul (param $i1 i32) (result i32) |
| (i32.mul |
| (i32.mul |
| (local.get $i1) |
| (i32.const -2) |
| ) |
| (i32.const 5) |
| ) |
| ) |
| ;; overflow also valid |
| ;; CHECK: (func $mul-mul-overflow (param $i1 i32) (result i32) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (local.get $i1) |
| ;; CHECK-NEXT: (i32.const -133169153) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $mul-mul-overflow (param $i1 i32) (result i32) |
| (i32.mul |
| (i32.mul |
| (local.get $i1) |
| (i32.const 0xfffff) |
| ) |
| (i32.const 0x8000001) |
| ) |
| ) |
| ;; CHECK: (func $if-eqz-one-arm (param $i1 i32) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $i1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-eqz-one-arm (param $i1 i32) |
| (if |
| (i32.eqz |
| (local.get $i1) |
| ) |
| (drop |
| (i32.const 10) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $if-eqz-two-arms (param $i1 i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (local.get $i1) |
| ;; CHECK-NEXT: (i32.const 12) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-eqz-two-arms (param $i1 i32) |
| (if |
| (i32.eqz |
| (local.get $i1) |
| ) |
| (drop |
| (i32.const 11) |
| ) |
| (drop |
| (i32.const 12) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $if-eqz-two-arms-i64 (param $i2 i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (local.get $i2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: (i32.const 12) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-eqz-two-arms-i64 (param $i2 i64) |
| (if |
| (i64.eqz |
| (local.get $i2) |
| ) |
| (drop |
| (i32.const 11) |
| ) |
| (drop |
| (i32.const 12) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-gt_s (result i32) |
| ;; CHECK-NEXT: (i32.le_u |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-gt_s (result i32) |
| (i32.eqz |
| (i32.gt_s |
| (i32.const 1) |
| (i32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-ge_s (result i32) |
| ;; CHECK-NEXT: (i32.lt_u |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-ge_s (result i32) |
| (i32.eqz |
| (i32.ge_s |
| (i32.const 1) |
| (i32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-lt_s (result i32) |
| ;; CHECK-NEXT: (i32.ge_u |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-lt_s (result i32) |
| (i32.eqz |
| (i32.lt_s |
| (i32.const 1) |
| (i32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-le_s (result i32) |
| ;; CHECK-NEXT: (i32.gt_u |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-le_s (result i32) |
| (i32.eqz |
| (i32.le_s |
| (i32.const 1) |
| (i32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-gt_u (result i32) |
| ;; CHECK-NEXT: (i32.le_u |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-gt_u (result i32) |
| (i32.eqz |
| (i32.gt_u |
| (i32.const 1) |
| (i32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-ge_u (result i32) |
| ;; CHECK-NEXT: (i32.lt_u |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-ge_u (result i32) |
| (i32.eqz |
| (i32.ge_u |
| (i32.const 1) |
| (i32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-lt_u (result i32) |
| ;; CHECK-NEXT: (i32.ge_u |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-lt_u (result i32) |
| (i32.eqz |
| (i32.lt_u |
| (i32.const 1) |
| (i32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-le_u (result i32) |
| ;; CHECK-NEXT: (i32.gt_u |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-le_u (result i32) |
| (i32.eqz |
| (i32.le_u |
| (i32.const 1) |
| (i32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-gt (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (f32.gt |
| ;; CHECK-NEXT: (f32.const 1) |
| ;; CHECK-NEXT: (f32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-gt (result i32) |
| (i32.eqz |
| (f32.gt |
| (f32.const 1) |
| (f32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-ge (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (f32.ge |
| ;; CHECK-NEXT: (f32.const 1) |
| ;; CHECK-NEXT: (f32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-ge (result i32) |
| (i32.eqz |
| (f32.ge |
| (f32.const 1) |
| (f32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-lt (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (f32.lt |
| ;; CHECK-NEXT: (f32.const 1) |
| ;; CHECK-NEXT: (f32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-lt (result i32) |
| (i32.eqz |
| (f32.lt |
| (f32.const 1) |
| (f32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-le (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (f32.le |
| ;; CHECK-NEXT: (f32.const 1) |
| ;; CHECK-NEXT: (f32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-le (result i32) |
| (i32.eqz |
| (f32.le |
| (f32.const 1) |
| (f32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-gt-f64 (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (f64.gt |
| ;; CHECK-NEXT: (f64.const 1) |
| ;; CHECK-NEXT: (f64.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-gt-f64 (result i32) |
| (i32.eqz |
| (f64.gt |
| (f64.const 1) |
| (f64.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-ge-f64 (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (f64.ge |
| ;; CHECK-NEXT: (f64.const 1) |
| ;; CHECK-NEXT: (f64.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-ge-f64 (result i32) |
| (i32.eqz |
| (f64.ge |
| (f64.const 1) |
| (f64.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-lt-f64 (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (f64.lt |
| ;; CHECK-NEXT: (f64.const 1) |
| ;; CHECK-NEXT: (f64.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-lt-f64 (result i32) |
| (i32.eqz |
| (f64.lt |
| (f64.const 1) |
| (f64.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-le-f64 (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (f64.le |
| ;; CHECK-NEXT: (f64.const 1) |
| ;; CHECK-NEXT: (f64.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-le-f64 (result i32) |
| (i32.eqz |
| (f64.le |
| (f64.const 1) |
| (f64.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-eq (result i32) |
| ;; CHECK-NEXT: (f32.ne |
| ;; CHECK-NEXT: (f32.const 1) |
| ;; CHECK-NEXT: (f32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-eq (result i32) |
| (i32.eqz |
| (f32.eq |
| (f32.const 1) |
| (f32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-ne (result i32) |
| ;; CHECK-NEXT: (f32.eq |
| ;; CHECK-NEXT: (f32.const 1) |
| ;; CHECK-NEXT: (f32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-ne (result i32) |
| (i32.eqz |
| (f32.ne |
| (f32.const 1) |
| (f32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-eq-f64 (result i32) |
| ;; CHECK-NEXT: (f64.ne |
| ;; CHECK-NEXT: (f64.const 1) |
| ;; CHECK-NEXT: (f64.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-eq-f64 (result i32) |
| (i32.eqz |
| (f64.eq |
| (f64.const 1) |
| (f64.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-ne-f64 (result i32) |
| ;; CHECK-NEXT: (f64.eq |
| ;; CHECK-NEXT: (f64.const 1) |
| ;; CHECK-NEXT: (f64.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eqz-ne-f64 (result i32) |
| (i32.eqz |
| (f64.ne |
| (f64.const 1) |
| (f64.const 2) |
| ) |
| ) |
| ) |
| |
| ;; we handle only 0 in the right position, as we assume a const is there, and |
| ;; don't care about whether both are consts here (precompute does that, so no |
| ;; need) |
| ;; CHECK: (func $eq-zero-rhs (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.const 100) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-zero-rhs (result i32) |
| (i32.eq |
| (i32.const 100) |
| (i32.const 0) |
| ) |
| ) |
| ;; CHECK: (func $eq-zero-lhs (result i32) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (i32.const 100) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-zero-lhs (result i32) |
| (i32.eq |
| (i32.const 0) |
| (i32.const 100) |
| ) |
| ) |
| ;; CHECK: (func $eq-zero-zero (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-zero-zero (result i32) |
| (i32.eq |
| (i32.const 0) |
| (i32.const 0) |
| ) |
| ) |
| ;; CHECK: (func $eq-zero-rhs-i64 (result i32) |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.const 100) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-zero-rhs-i64 (result i32) |
| (i64.eq |
| (i64.const 100) |
| (i64.const 0) |
| ) |
| ) |
| ;; CHECK: (func $eq-zero-lhs-i64 (result i32) |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: (i64.const 100) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-zero-lhs-i64 (result i32) |
| (i64.eq |
| (i64.const 0) |
| (i64.const 100) |
| ) |
| ) |
| ;; CHECK: (func $eq-zero-zero-i64 (result i32) |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-zero-zero-i64 (result i32) |
| (i64.eq |
| (i64.const 0) |
| (i64.const 0) |
| ) |
| ) |
| ;; CHECK: (func $if-eqz-eqz |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (i32.const 123) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-eqz-eqz |
| (if |
| (i32.eqz |
| (i32.eqz |
| (i32.const 123) |
| ) |
| ) |
| (nop) |
| ) |
| ) |
| ;; CHECK: (func $select-eqz (param $i1 i32) (result i32) |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const 102) |
| ;; CHECK-NEXT: (i32.const 101) |
| ;; CHECK-NEXT: (local.get $i1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-eqz (param $i1 i32) (result i32) |
| (select |
| (i32.const 101) |
| (i32.const 102) |
| (i32.eqz |
| (local.get $i1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-eqz-noreorder (param $i1 i32) (result i32) |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.tee $i1 |
| ;; CHECK-NEXT: (i32.const 103) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.tee $i1 |
| ;; CHECK-NEXT: (i32.const 104) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $i1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-eqz-noreorder (param $i1 i32) (result i32) |
| (select |
| (local.tee $i1 |
| (i32.const 103) |
| ) ;; these conflict |
| (local.tee $i1 |
| (i32.const 104) |
| ) |
| (i32.eqz |
| (local.get $i1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-eqz-eqz (result i32) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| (func $select-eqz-eqz (result i32) |
| (select |
| (i32.const 0) |
| (i32.const 1) |
| (i32.eqz |
| (i32.eqz |
| (i32.const 2) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-sign-32-lt (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 31) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-sign-32-lt (param $x i32) (result i32) |
| (select |
| (i32.const -1) |
| (i32.const 1) |
| (i32.lt_s |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-sign-32-ge (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 31) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-sign-32-ge (param $x i32) (result i32) |
| (select |
| (i32.const 1) |
| (i32.const -1) |
| (i32.ge_s |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-sign-64-lt (param $x i64) (result i64) |
| ;; CHECK-NEXT: (i64.or |
| ;; CHECK-NEXT: (i64.shr_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 63) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-sign-64-lt (param $x i64) (result i64) |
| (select |
| (i64.const -1) |
| (i64.const 1) |
| (i64.lt_s |
| (local.get $x) |
| (i64.const 0) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-sign-64-ge (param $x i64) (result i64) |
| ;; CHECK-NEXT: (i64.or |
| ;; CHECK-NEXT: (i64.shr_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 63) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-sign-64-ge (param $x i64) (result i64) |
| (select |
| (i64.const 1) |
| (i64.const -1) |
| (i64.ge_s |
| (local.get $x) |
| (i64.const 0) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-sign-lt-skip-1 (param $x i32) (result i64) |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-sign-lt-skip-1 (param $x i32) (result i64) |
| (select |
| (i64.const -1) |
| (i64.const 1) |
| (i32.lt_s |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-sign-lt-skip-2 (param $x i64) (result i32) |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i64.lt_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-sign-lt-skip-2 (param $x i64) (result i32) |
| (select |
| (i32.const -1) |
| (i32.const 1) |
| (i64.lt_s |
| (local.get $x) |
| (i64.const 0) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-or (param $x i32) (param $y i32) (result i32) |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-or (param $x i32) (param $y i32) (result i32) |
| (select |
| (i32.const 1) |
| (i32.eq |
| (local.get $y) |
| (i32.const 1337) |
| ) |
| (i32.and |
| (local.get $x) |
| (i32.const 1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-or-side-effects (param $x i32) (param $y i32) (result i32) |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (call $select-or-side-effects |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (call $select-or-side-effects |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-or-side-effects (param $x i32) (param $y i32) (result i32) |
| ;; When there are side effects, the order of the operations must remain |
| ;; correct. |
| (select |
| (i32.const 1) |
| (i32.eq |
| (call $select-or-side-effects |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.const 1337) |
| ) |
| (i32.and |
| (call $select-or-side-effects |
| (local.get $y) |
| (local.get $x) |
| ) |
| (i32.const 1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-or-no-bits (param $x i32) (param $y i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-or-no-bits (param $x i32) (param $y i32) |
| ;; The following cannot be optimized into an "or" operation due to maxBits |
| ;; not being known to be 1. |
| (drop |
| (select |
| ;; Too many bits in ifTrue |
| (i32.const 2) |
| (i32.eq |
| (local.get $y) |
| (i32.const 1337) |
| ) |
| (i32.eq |
| (local.get $x) |
| (i32.const 42) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 1) |
| ;; Too many bits in ifFalse |
| (local.get $y) |
| (i32.eq |
| (local.get $x) |
| (i32.const 42) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 1) |
| (i32.eq |
| (local.get $y) |
| (i32.const 1337) |
| ) |
| ;; Too many bits in condition |
| (local.get $x) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-or-no-type (param $x i32) (param $y i64) (result i64) |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-or-no-type (param $x i32) (param $y i64) (result i64) |
| ;; An i64 result cannot be optimized into an "or" of the ifTrue and the |
| ;; condition due to their types being different. |
| (select |
| (i64.const 1) |
| (i64.and |
| (local.get $y) |
| (i64.const 1) |
| ) |
| (i32.and |
| (local.get $x) |
| (i32.const 1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-or-no-const (param $x i32) (param $y i32) (result i32) |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-or-no-const (param $x i32) (param $y i32) (result i32) |
| (select |
| ;; The wrong const (should be 1). |
| (i32.const 0) |
| (i32.eq |
| (local.get $y) |
| (i32.const 1337) |
| ) |
| (i32.and |
| (local.get $x) |
| (i32.const 1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-and (param $x i32) (param $y i32) (result i32) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-and (param $x i32) (param $y i32) (result i32) |
| (select |
| (i32.eq |
| (local.get $y) |
| (i32.const 1337) |
| ) |
| (i32.const 0) |
| (i32.eq |
| (local.get $x) |
| (i32.const 42) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-and-no-const (param $x i32) (param $y i32) (result i32) |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-and-no-const (param $x i32) (param $y i32) (result i32) |
| (select |
| (i32.eq |
| (local.get $y) |
| (i32.const 1337) |
| ) |
| ;; The wrong constant (should be 0). |
| (i32.const 1) |
| (i32.eq |
| (local.get $x) |
| (i32.const 42) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $load8_s-and-255 (result i32) |
| ;; CHECK-NEXT: (i32.load8_u |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $load8_s-and-255 (result i32) |
| (i32.and (i32.load8_s (i32.const 0)) (i32.const 255)) |
| ) |
| ;; CHECK: (func $load8_u-and-255 (result i32) |
| ;; CHECK-NEXT: (i32.load8_u |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $load8_u-and-255 (result i32) |
| (i32.and (i32.load8_u (i32.const 1)) (i32.const 255)) |
| ) |
| ;; CHECK: (func $load8_s-and-254 (result i32) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.load8_s |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 254) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $load8_s-and-254 (result i32) |
| (i32.and (i32.load8_s (i32.const 2)) (i32.const 254)) |
| ) |
| ;; CHECK: (func $load8_u-and-1 (result i32) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.load8_u |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $load8_u-and-1 (result i32) |
| (i32.and (i32.load8_u (i32.const 3)) (i32.const 1)) |
| ) |
| ;; CHECK: (func $load16_s-and-65535 (result i32) |
| ;; CHECK-NEXT: (i32.load16_u |
| ;; CHECK-NEXT: (i32.const 4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $load16_s-and-65535 (result i32) |
| (i32.and (i32.load16_s (i32.const 4)) (i32.const 65535)) |
| ) |
| ;; CHECK: (func $load16_u-and-65535 (result i32) |
| ;; CHECK-NEXT: (i32.load16_u |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $load16_u-and-65535 (result i32) |
| (i32.and (i32.load16_u (i32.const 5)) (i32.const 65535)) |
| ) |
| ;; CHECK: (func $load16_s-and-65534 (result i32) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.load16_s |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 65534) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $load16_s-and-65534 (result i32) |
| (i32.and (i32.load16_s (i32.const 6)) (i32.const 65534)) |
| ) |
| ;; CHECK: (func $load16_u-and-1 (result i32) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.load16_u |
| ;; CHECK-NEXT: (i32.const 7) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $load16_u-and-1 (result i32) |
| (i32.and (i32.load16_u (i32.const 7)) (i32.const 1)) |
| ) |
| ;; CHECK: (func $store8-and-255 |
| ;; CHECK-NEXT: (i32.store8 |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store8-and-255 |
| (i32.store8 (i32.const 8) (i32.and (i32.const -1) (i32.const 255))) |
| ) |
| ;; CHECK: (func $store8-and-254 |
| ;; CHECK-NEXT: (i32.store8 |
| ;; CHECK-NEXT: (i32.const 9) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.const -2) |
| ;; CHECK-NEXT: (i32.const 254) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store8-and-254 |
| (i32.store8 (i32.const 9) (i32.and (i32.const -2) (i32.const 254))) |
| ) |
| ;; CHECK: (func $store16-and-65535 |
| ;; CHECK-NEXT: (i32.store16 |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: (i32.const -3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store16-and-65535 |
| (i32.store16 (i32.const 10) (i32.and (i32.const -3) (i32.const 65535))) |
| ) |
| ;; CHECK: (func $store16-and-65534 |
| ;; CHECK-NEXT: (i32.store16 |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.const -4) |
| ;; CHECK-NEXT: (i32.const 65534) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store16-and-65534 |
| (i32.store16 (i32.const 11) (i32.and (i32.const -4) (i32.const 65534))) |
| ) |
| ;; CHECK: (func $store8-wrap |
| ;; CHECK-NEXT: (i64.store8 |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store8-wrap |
| (i32.store8 (i32.const 11) (i32.wrap_i64 (i64.const 1))) |
| ) |
| ;; CHECK: (func $store16-wrap |
| ;; CHECK-NEXT: (i64.store16 |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: (i64.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store16-wrap |
| (i32.store16 (i32.const 11) (i32.wrap_i64 (i64.const 2))) |
| ) |
| ;; CHECK: (func $store-wrap |
| ;; CHECK-NEXT: (i64.store32 |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: (i64.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store-wrap |
| (i32.store (i32.const 11) (i32.wrap_i64 (i64.const 3))) |
| ) |
| ;; CHECK: (func $store8-neg1 |
| ;; CHECK-NEXT: (i32.store8 |
| ;; CHECK-NEXT: (i32.const 7) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store8-neg1 |
| (i32.store8 (i32.const 7) (i32.const -1)) ;; 255 |
| ) |
| ;; CHECK: (func $store8-255 |
| ;; CHECK-NEXT: (i32.store8 |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store8-255 |
| (i32.store8 (i32.const 8) (i32.const 255)) |
| ) |
| ;; CHECK: (func $store8-256 |
| ;; CHECK-NEXT: (i32.store8 |
| ;; CHECK-NEXT: (i32.const 9) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store8-256 |
| (i32.store8 (i32.const 9) (i32.const 256)) ;; 0 |
| ) |
| ;; CHECK: (func $store16-neg1 |
| ;; CHECK-NEXT: (i32.store16 |
| ;; CHECK-NEXT: (i32.const 13) |
| ;; CHECK-NEXT: (i32.const 65535) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store16-neg1 |
| (i32.store16 (i32.const 13) (i32.const -1)) ;; 65535 |
| ) |
| ;; CHECK: (func $store16-65535 |
| ;; CHECK-NEXT: (i32.store16 |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: (i32.const 65535) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store16-65535 |
| (i32.store16 (i32.const 10) (i32.const 65535)) |
| ) |
| ;; CHECK: (func $store16-65536 |
| ;; CHECK-NEXT: (i32.store16 |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store16-65536 |
| (i32.store16 (i32.const 11) (i32.const 65536)) ;; 0 |
| ) |
| ;; CHECK: (func $store-65536 |
| ;; CHECK-NEXT: (i32.store |
| ;; CHECK-NEXT: (i32.const 14) |
| ;; CHECK-NEXT: (i32.const 65536) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store-65536 |
| (i32.store (i32.const 14) (i32.const 65536)) |
| ) |
| ;; CHECK: (func $store8-255-i64 |
| ;; CHECK-NEXT: (i64.store8 |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: (i64.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store8-255-i64 |
| (i64.store8 (i32.const 8) (i64.const 255)) |
| ) |
| ;; CHECK: (func $store8-256-i64 |
| ;; CHECK-NEXT: (i64.store8 |
| ;; CHECK-NEXT: (i32.const 9) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store8-256-i64 |
| (i64.store8 (i32.const 9) (i64.const 256)) ;; 0 |
| ) |
| ;; CHECK: (func $store16-65535-i64 |
| ;; CHECK-NEXT: (i64.store16 |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: (i64.const 65535) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store16-65535-i64 |
| (i64.store16 (i32.const 10) (i64.const 65535)) |
| ) |
| ;; CHECK: (func $store16-65536-i64 |
| ;; CHECK-NEXT: (i64.store16 |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store16-65536-i64 |
| (i64.store16 (i32.const 11) (i64.const 65536)) ;; 0 |
| ) |
| ;; CHECK: (func $store32-4294967295 |
| ;; CHECK-NEXT: (i64.store32 |
| ;; CHECK-NEXT: (i32.const 12) |
| ;; CHECK-NEXT: (i64.const 4294967295) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store32-4294967295 |
| (i64.store32 (i32.const 12) (i64.const 4294967295)) |
| ) |
| ;; CHECK: (func $store32-4294967296 |
| ;; CHECK-NEXT: (i64.store32 |
| ;; CHECK-NEXT: (i32.const 13) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store32-4294967296 |
| (i64.store32 (i32.const 13) (i64.const 4294967296)) ;; 0 |
| ) |
| ;; CHECK: (func $store-4294967296 |
| ;; CHECK-NEXT: (i64.store |
| ;; CHECK-NEXT: (i32.const 14) |
| ;; CHECK-NEXT: (i64.const 4294967296) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store-4294967296 |
| (i64.store (i32.const 14) (i64.const 4294967296)) |
| ) |
| ;; CHECK: (func $and-neg1 |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 100) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.const 100) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $and-neg1 |
| (drop (i32.and (i32.const 100) (i32.const -1))) |
| (drop (i32.and (i32.const 100) (i32.const 1))) |
| ) |
| ;; CHECK: (func $and-pos1 |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.const 1000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.const 1000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.const 100) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.lt_u |
| ;; CHECK-NEXT: (i32.const 2000) |
| ;; CHECK-NEXT: (i32.const 3000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $and-pos1 |
| (drop (i32.and (i32.eqz (i32.const 1000)) (i32.const 1))) |
| (drop (i32.and (i32.const 1) (i32.eqz (i32.const 1000)))) |
| (drop (i32.and (i32.const 100) (i32.const 1))) |
| (drop (i32.and (i32.lt_s (i32.const 2000) (i32.const 3000)) (i32.const 1))) |
| ) |
| ;; CHECK: (func $canonicalize-unreachable |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.div_s |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.div_s |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $canonicalize-unreachable |
| (drop (i32.and (unreachable) (i32.const 1))) ;; ok to reorder |
| (drop (i32.and (i32.const 1) (unreachable))) |
| (drop (i32.div_s (unreachable) (i32.const 1))) ;; not ok |
| (drop (i32.div_s (i32.const 1) (unreachable))) |
| ) |
| ;; CHECK: (func $canonicalize-consts-vars (param $x i32) (param $y i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (i32.const -4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $canonicalize-consts-vars (param $x i32) (param $y i32) |
| (drop (i32.and (i32.const 1) (i32.const 2))) |
| (drop (i32.and (local.get $x) (i32.const 3))) |
| (drop (i32.and (i32.const 4) (local.get $x))) |
| (drop (i32.and (local.get $x) (local.get $y))) |
| (drop (i32.and (local.get $y) (local.get $x))) |
| (drop (i32.and (local.get $y) (local.tee $x (i32.const -4)))) |
| ) |
| ;; CHECK: (func $canonicalize-block-var (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (i32.const -5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (i32.const -6) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $canonicalize-block-var (param $x i32) |
| (drop (i32.and |
| (block (result i32) |
| (i32.const -5) |
| ) |
| (local.get $x) |
| )) |
| (drop (i32.and |
| (local.get $x) |
| (block (result i32) |
| (i32.const -6) |
| ) |
| )) |
| ) |
| ;; CHECK: (func $canonicalize-block-loop |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (loop $loop-in (result i32) |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (loop $loop-in1 (result i32) |
| ;; CHECK-NEXT: (i32.const 7) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (loop $loop-in3 (result i32) |
| ;; CHECK-NEXT: (call $and-pos1) |
| ;; CHECK-NEXT: (i32.const 9) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (call $and-pos1) |
| ;; CHECK-NEXT: (i32.const 12) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (loop $loop-in5 (result i32) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (loop $loop-in7 (result i32) |
| ;; CHECK-NEXT: (call $and-pos1) |
| ;; CHECK-NEXT: (i32.const 13) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (call $and-pos1) |
| ;; CHECK-NEXT: (i32.const 14) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (call $and-pos1) |
| ;; CHECK-NEXT: (i32.const 14) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (loop $loop-in10 (result i32) |
| ;; CHECK-NEXT: (call $and-pos1) |
| ;; CHECK-NEXT: (i32.const 13) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $canonicalize-block-loop |
| (drop (i32.and |
| (block (result i32) |
| (i32.const 5) |
| ) |
| (loop (result i32) |
| (i32.const 6) |
| ) |
| )) |
| (drop (i32.and |
| (loop (result i32) |
| (i32.const 7) |
| ) |
| (block (result i32) |
| (i32.const 8) |
| ) |
| )) |
| (drop (i32.and |
| (loop (result i32) |
| (call $and-pos1) |
| (i32.const 9) |
| ) |
| (block (result i32) |
| (i32.const 10) |
| ) |
| )) |
| (drop (i32.and |
| (loop (result i32) |
| (i32.const 11) |
| ) |
| (block (result i32) |
| (call $and-pos1) |
| (i32.const 12) |
| ) |
| )) |
| (drop (i32.and |
| (loop (result i32) |
| (call $and-pos1) |
| (i32.const 13) |
| ) |
| (block (result i32) |
| (call $and-pos1) |
| (i32.const 14) |
| ) |
| )) |
| (drop (i32.and |
| (block (result i32) |
| (call $and-pos1) |
| (i32.const 14) |
| ) |
| (loop (result i32) |
| (call $and-pos1) |
| (i32.const 13) |
| ) |
| )) |
| ) |
| ;; CHECK: (func $canonicalize-gt_s-gt-u |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.gt_u |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: (i32.const 17) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.gt_u |
| ;; CHECK-NEXT: (i32.const 18) |
| ;; CHECK-NEXT: (i32.const 19) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.gt_u |
| ;; CHECK-NEXT: (i32.const 20) |
| ;; CHECK-NEXT: (i32.const 21) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.gt_u |
| ;; CHECK-NEXT: (i32.const 22) |
| ;; CHECK-NEXT: (i32.const 23) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $canonicalize-gt_s-gt-u |
| (drop (i32.and |
| (i32.gt_s |
| (i32.const 16) |
| (i32.const 17) |
| ) |
| (i32.gt_u |
| (i32.const 18) |
| (i32.const 19) |
| ) |
| )) |
| (drop (i32.and |
| (i32.gt_u |
| (i32.const 20) |
| (i32.const 21) |
| ) |
| (i32.gt_s |
| (i32.const 22) |
| (i32.const 23) |
| ) |
| )) |
| ) |
| ;; CHECK: (func $canonicalize-cmp-near-zero (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.le_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.gt_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $canonicalize-cmp-near-zero (param $x i32) |
| ;; i32(x) > -1 ==> x >= 0 |
| (drop (i32.gt_s |
| (local.get $x) |
| (i32.const -1) |
| )) |
| ;; i32(x) <= -1 ==> x < 0 |
| (drop (i32.le_s |
| (local.get $x) |
| (i32.const -1) |
| )) |
| ;; -1 < i32(x) ==> x >= 0 |
| (drop (i32.lt_s |
| (i32.const -1) |
| (local.get $x) |
| )) |
| ;; -1 >= i32(x) ==> x < 0 |
| (drop (i32.ge_s |
| (i32.const -1) |
| (local.get $x) |
| )) |
| ;; i32(x) < 1 ==> x <= 0 |
| (drop (i32.lt_s |
| (local.get $x) |
| (i32.const 1) |
| )) |
| ;; (signed)x >= 1 ==> x > 0 |
| (drop (i32.ge_s |
| (local.get $x) |
| (i32.const 1) |
| )) |
| ;; u32(x) < 1 ==> x == 0 |
| (drop (i32.lt_u |
| (local.get $x) |
| (i32.const 1) |
| )) |
| ;; u32(x) >= 1 ==> x != 0 |
| (drop (i32.ge_u |
| (local.get $x) |
| (i32.const 1) |
| )) |
| ) |
| ;; CHECK: (func $canonicalize-cmp-const (param $x i32) (param $fx f64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.le_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.ne |
| ;; CHECK-NEXT: (local.get $fx) |
| ;; CHECK-NEXT: (f64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.gt |
| ;; CHECK-NEXT: (local.get $fx) |
| ;; CHECK-NEXT: (f64.const -2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.le |
| ;; CHECK-NEXT: (local.get $fx) |
| ;; CHECK-NEXT: (f64.const inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.ge |
| ;; CHECK-NEXT: (local.get $fx) |
| ;; CHECK-NEXT: (f64.const nan:0x8000000000000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.ge |
| ;; CHECK-NEXT: (f64.const 1) |
| ;; CHECK-NEXT: (f64.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $canonicalize-cmp-const (param $x i32) (param $fx f64) |
| (drop (i32.gt_s |
| (i32.const 1) |
| (local.get $x) |
| )) |
| (drop (i32.gt_u |
| (i32.const 0) |
| (local.get $x) |
| )) |
| (drop (i32.ne |
| (i32.const -1) |
| (local.get $x) |
| )) |
| (drop (f64.ne |
| (f64.const -1) |
| (local.get $fx) |
| )) |
| (drop (f64.lt |
| (f64.const -2) |
| (local.get $fx) |
| )) |
| (drop (f64.ge |
| (f64.const inf) |
| (local.get $fx) |
| )) |
| (drop (f64.le |
| (f64.const nan) |
| (local.get $fx) |
| )) |
| ;; skip |
| (drop (f64.ge |
| (f64.const 1) |
| (f64.const 2) |
| )) |
| ) |
| ;; CHECK: (func $canonicalize-nested-vars (param $x i32) (param $y i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.ctz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.ctz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.ctz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.ctz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $canonicalize-nested-vars (param $x i32) (param $y i32) |
| (drop (i32.add (i32.ctz (local.get $x)) (i32.ctz (local.get $y)))) |
| (drop (i32.add (i32.ctz (local.get $y)) (i32.ctz (local.get $x)))) |
| ) |
| ;; CHECK: (func $canonicalize-ctz-eqz (param $x i32) (param $y i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.ctz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.ctz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $canonicalize-ctz-eqz (param $x i32) (param $y i32) |
| (drop (i32.add (i32.ctz (local.get $x)) (i32.eqz (local.get $y)))) |
| (drop (i32.add (i32.eqz (local.get $x)) (i32.ctz (local.get $y)))) |
| ) |
| ;; CHECK: (func $ne0 (result i32) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| (func $ne0 (result i32) |
| (if (i32.ne (call $ne0) (i32.const 0)) |
| (nop) |
| ) |
| (if (i32.ne (i32.const 0) (call $ne0)) |
| (nop) |
| ) |
| ;; through an or |
| (if |
| (i32.or |
| (i32.ne (i32.const 0) (call $ne0)) |
| (i32.ne (i32.const 0) (call $ne0)) |
| ) |
| (nop) |
| ) |
| ;; but not an and |
| (if |
| (i32.and |
| (i32.ne (i32.const 0) (call $ne0)) |
| (i32.ne (i32.const 0) (call $ne0)) |
| ) |
| (nop) |
| ) |
| (i32.const 1) |
| ) |
| ;; CHECK: (func $recurse-bool |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (call $ne1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $recurse-bool |
| (if |
| (if (result i32) |
| (i32.const 1) |
| (i32.ne (call $ne0) (i32.const 0)) |
| (i32.ne (call $ne1) (i32.const 0)) |
| ) |
| (nop) |
| ) |
| (if |
| (block (result i32) |
| (nop) |
| (i32.ne (call $ne0) (i32.const 0)) |
| ) |
| (nop) |
| ) |
| ) |
| ;; CHECK: (func $ne1 (result i32) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $ne1 (result i32) |
| (unreachable) |
| ) |
| ;; CHECK: (func $store-off-2-add-consts (param $0 i32) |
| ;; CHECK-NEXT: (i32.store |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store-off-2-add-consts (param $0 i32) |
| (i32.store offset=2 |
| (i32.add |
| (i32.const 1) |
| (i32.const 3) |
| ) |
| (local.get $0) |
| ) |
| (i32.store offset=2 |
| (i32.add |
| (i32.const 3) |
| (i32.const 1) |
| ) |
| (local.get $0) |
| ) |
| ) |
| ;; CHECK: (func $store-off-2-add-var-const (param $0 i32) |
| ;; CHECK-NEXT: (i32.store offset=2 |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store offset=2 |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 7) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store-off-2-add-var-const (param $0 i32) |
| (i32.store offset=2 |
| (i32.add |
| (local.get $0) |
| (i32.const 5) |
| ) |
| (local.get $0) |
| ) |
| (i32.store offset=2 |
| (i32.add |
| (i32.const 7) |
| (local.get $0) |
| ) |
| (local.get $0) |
| ) |
| ) |
| ;; CHECK: (func $store-off-2-add-var-negative-const (param $0 i32) |
| ;; CHECK-NEXT: (i32.store offset=2 |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store offset=2 |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 13) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store-off-2-add-var-negative-const (param $0 i32) |
| (i32.store offset=2 |
| (i32.add |
| (i32.const -11) ;; do not fold this! |
| (local.get $0) |
| ) |
| (local.get $0) |
| ) |
| (i32.store offset=2 |
| (i32.add |
| (local.get $0) |
| (i32.const -13) ;; do not fold this! |
| ) |
| (local.get $0) |
| ) |
| ) |
| ;; CHECK: (func $store-off-2-negative-const (param $0 i32) |
| ;; CHECK-NEXT: (i32.store |
| ;; CHECK-NEXT: (i32.const 4) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store offset=2 |
| ;; CHECK-NEXT: (i32.const -2) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store-off-2-negative-const (param $0 i32) |
| (i32.store offset=2 |
| (i32.add |
| (i32.const -15) |
| (i32.const 17) |
| ) |
| (local.get $0) |
| ) |
| (i32.store offset=2 |
| (i32.add |
| (i32.const -21) |
| (i32.const 19) |
| ) |
| (local.get $0) |
| ) |
| ) |
| ;; CHECK: (func $store-off-2-const (param $0 i32) |
| ;; CHECK-NEXT: (i32.store |
| ;; CHECK-NEXT: (i32.const 25) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store offset=2 |
| ;; CHECK-NEXT: (i32.const -25) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store-off-2-const (param $0 i32) |
| (i32.store offset=2 |
| (i32.const 23) |
| (local.get $0) |
| ) |
| (i32.store offset=2 |
| (i32.const -25) |
| (local.get $0) |
| ) |
| ) |
| ;; CHECK: (func $load-off-2 (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.load offset=2 |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.load offset=2 |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $load-off-2 (param $0 i32) (result i32) |
| (drop |
| (i32.load offset=2 |
| (i32.add |
| (i32.const 2) |
| (i32.const 4) |
| ) |
| ) |
| ) |
| (drop |
| (i32.load offset=2 |
| (i32.add |
| (i32.const 4) |
| (i32.const 2) |
| ) |
| ) |
| ) |
| (drop |
| (i32.load offset=2 |
| (i32.add |
| (local.get $0) |
| (i32.const 6) |
| ) |
| ) |
| ) |
| (drop |
| (i32.load offset=2 |
| (i32.const 8) |
| ) |
| ) |
| (i32.load offset=2 |
| (i32.add |
| (i32.const 10) |
| (local.get $0) |
| ) |
| ) |
| ) |
| ;; eq of sign-ext to const, can be a zext |
| ;; CHECK: (func $eq-sext-24-zero (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-sext-24-zero (param $0 i32) (result i32) |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| ;; CHECK: (func $eq-sext-16-zero (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 65535) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-sext-16-zero (param $0 i32) (result i32) |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 16) |
| ) |
| (i32.const 16) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| ;; CHECK: (func $eq-sext-5-zero (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 134217727) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-sext-5-zero (param $0 i32) (result i32) |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 5) ;; weird size, but still valid |
| ) |
| (i32.const 5) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| ;; CHECK: (func $eq-sext-24-const (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 100) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-sext-24-const (param $0 i32) (result i32) |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 100) ;; non-zero |
| ) |
| ) |
| ;; CHECK: (func $eq-sext-24-big-positive-const (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| (func $eq-sext-24-big-positive-const (param $0 i32) (result i32) |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 32767) ;; non-zero and bigger than the mask, with sign bit |
| ) |
| ) |
| ;; CHECK: (func $eq-sext-24-negative-const (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| (func $eq-sext-24-negative-const (param $0 i32) (result i32) |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const -149) ;; non-zero and bigger than the mask, without sign bit |
| ) |
| ) |
| ;; eq of two sign-ext, can both be a zext |
| ;; CHECK: (func $eq-sext-sext-24 (param $0 i32) (param $1 i32) (result i32) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-sext-sext-24 (param $0 i32) (param $1 i32) (result i32) |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.shr_s |
| (i32.shl |
| (local.get $1) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eq-sext-sext-16 (param $0 i32) (param $1 i32) (result i32) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 65535) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 65535) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-sext-sext-16 (param $0 i32) (param $1 i32) (result i32) |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 16) |
| ) |
| (i32.const 16) |
| ) |
| (i32.shr_s |
| (i32.shl |
| (local.get $1) |
| (i32.const 16) |
| ) |
| (i32.const 16) |
| ) |
| ) |
| ) |
| ;; corner cases we should not opt |
| ;; CHECK: (func $eq-sext-smaller-shr (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 23) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-sext-smaller-shr (param $0 i32) (result i32) |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 23) ;; different shift, smaller |
| ) |
| (i32.const 0) |
| ) |
| ) |
| ;; CHECK: (func $eq-sext-unsigned-shr (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-sext-unsigned-shr (param $0 i32) (result i32) |
| (i32.eq |
| (i32.shr_u ;; unsigned |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| ;; CHECK: (func $lt_s-sext-zero (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $lt_s-sext-zero (param $0 i32) (result i32) |
| (i32.lt_s ;; non-eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| ;; CHECK: (func $if-sext-unreachable (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 111) |
| ;; CHECK-NEXT: (i32.const 222) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-sext-unreachable (param $0 i32) (result i32) |
| (if (result i32) |
| (i32.shr_s |
| (i32.shl |
| (unreachable) ;; ignore an unreachable value |
| (i32.const 16) |
| ) |
| (i32.const 16) |
| ) |
| (i32.const 111) |
| (i32.const 222) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-100 (result i32) |
| ;; CHECK-NEXT: (i32.const 100) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-100 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.const 100) ;; small! |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-127 (result i32) |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-127 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.const 127) ;; just small enough |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-128 (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-128 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.const 128) ;; just too big |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-var (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-var (param $0 i32) (result i32) |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) ;; who knows... |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-unreachable (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-unreachable (result i32) |
| (i32.shr_s |
| (i32.shl |
| (unreachable) ;; ignore |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-div (result i32) |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-div (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.div_s ;; this could be optimizable in theory, but currently we don't look into adds etc. |
| (i32.const 1) |
| (i32.const 2) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-and-127-128 (result i32) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-and-127-128 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.and ;; takes the min, here it is ok |
| (i32.const 127) |
| (i32.const 128) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-and-128-129 (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: (i32.const 129) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-and-128-129 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.and ;; takes the min, here it is not |
| (i32.const 128) |
| (i32.const 129) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-xor-127-126 (result i32) |
| ;; CHECK-NEXT: (i32.xor |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: (i32.const 126) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-xor-127-126 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.xor ;; takes the max, here it is ok |
| (i32.const 127) |
| (i32.const 126) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-xor-127-128 (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.xor |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-xor-127-128 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.xor ;; takes the max, here it is not |
| (i32.const 127) |
| (i32.const 128) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-or-127-126 (result i32) |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: (i32.const 126) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-or-127-126 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.or ;; takes the max, here it is ok |
| (i32.const 127) |
| (i32.const 126) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-or-127-128 (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-or-127-128 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.or ;; takes the max, here it is not |
| (i32.const 127) |
| (i32.const 128) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shl-32-2 (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.const 32) |
| ;; CHECK-NEXT: (i32.const 26) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shl-32-2 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shl ;; adds, here it is too much |
| (i32.const 32) |
| (i32.const 2) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shl-32-1 (result i32) |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.const 32) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shl-32-1 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shl ;; adds, here it is ok |
| (i32.const 32) |
| (i32.const 1) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shl-32-35 (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.const 32) |
| ;; CHECK-NEXT: (i32.const 27) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shl-32-35 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shl ;; adds, here it is too much and "overflows" |
| (i32.const 32) |
| (i32.const 35) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shr_u-256-1 (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.const 256) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shr_u-256-1 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_u ;; subtracts, here it is still too much |
| (i32.const 256) |
| (i32.const 1) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shr_u-256-2 (result i32) |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.const 256) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shr_u-256-2 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_u ;; subtracts, here it is ok |
| (i32.const 256) |
| (i32.const 2) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shr_u-128-35 (result i32) |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shr_u-128-35 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_u ;; subtracts, here it "overflows" |
| (i32.const 128) |
| (i32.const 35) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shr_s-256-1 (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.const 256) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shr_s-256-1 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_s ;; subtracts, here it is still too much |
| (i32.const 256) |
| (i32.const 1) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shr_s-256-2 (result i32) |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.const 256) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shr_s-256-2 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_s ;; subtracts, here it is ok |
| (i32.const 256) |
| (i32.const 2) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shr_s-128-35 (result i32) |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shr_s-128-35 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_s ;; subtracts, here it "overflows" |
| (i32.const 128) |
| (i32.const 35) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shr_s-neg1-32 (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shr_s-neg1-32 (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_s ;; subtracts, here there is a sign bit, so it stays 32 bits no matter how much we shift |
| (i32.const -1) |
| (i32.const 32) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shr_s-and-masked-sign (result i32) |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 31) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shr_s-and-masked-sign (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_s ;; subtracts, here we mask out that sign bit |
| (i32.and |
| (i32.const -1) |
| (i32.const 2147483647) |
| ) |
| (i32.const 31) ;; adjusted after we fixed shift computation to just look at lower 5 bits |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-ne (result i32) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-ne (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.ne ;; 1 bit |
| (i32.const -1) |
| (i32.const -1) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-le (result i32) |
| ;; CHECK-NEXT: (f32.le |
| ;; CHECK-NEXT: (f32.const -1) |
| ;; CHECK-NEXT: (f32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-le (result i32) |
| (i32.shr_s |
| (i32.shl |
| (f32.le |
| (f32.const -1) |
| (f32.const -1) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-clz (result i32) |
| ;; CHECK-NEXT: (i32.clz |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-clz (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.clz ;; assumed 5 bits |
| (i32.const 0) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shl-clz (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.clz |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 26) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shl-clz (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shl |
| (i32.clz ;; assumed 5 bits |
| (i32.const 0) |
| ) |
| (i32.const 2) ;; + 2, so 7 |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shl-clz-too-big (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.clz |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 27) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shl-clz-too-big (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shl |
| (i32.clz ;; assumed 5 bits |
| (i32.const 0) |
| ) |
| (i32.const 3) ;; + 3, so 8, too much |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-wrap-clz (result i32) |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.clz |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-wrap-clz (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.wrap_i64 ;; preserves 6 |
| (i64.clz ;; assumed 6 bits |
| (i64.const 0) |
| ) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shl-wrap-clz (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.clz |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 25) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shl-wrap-clz (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shl |
| (i32.wrap_i64 ;; preserves 6 |
| (i64.clz ;; assumed 6 bits |
| (i64.const 0) |
| ) |
| ) |
| (i32.const 1) ;; + 1, so 7 |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shl-wrap-clz-too-big (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.clz |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 26) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shl-wrap-clz-too-big (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shl |
| (i32.wrap_i64 ;; preserves 6 |
| (i64.clz ;; assumed 6 bits |
| (i64.const 0) |
| ) |
| ) |
| (i32.const 2) ;; + 2, so 8, too much |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-eqz (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-eqz (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.eqz ;; 1 bit |
| (i32.const -1) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shr_u-wrap-too-big (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shr_u-wrap-too-big (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_u |
| (i32.wrap_i64 ;; down to 32 |
| (i64.const -1) ;; 64 |
| ) |
| (i32.const 24) ;; 32 - 24 = 8 |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shr_u-wrap (result i32) |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 25) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shr_u-wrap (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_u |
| (i32.wrap_i64 ;; down to 32 |
| (i64.const -1) ;; 64 |
| ) |
| (i32.const 25) ;; 32 - 25 = 7, ok |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shr_u-wrap-extend-too-big (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shr_u-wrap-extend-too-big (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_u |
| (i32.wrap_i64 ;; stay 32 |
| (i64.extend_i32_s |
| (i32.const -1) |
| ) |
| ) |
| (i32.const 24) ;; 32 - 24 = 8 |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-shr_u-wrap-extend (result i32) |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (i32.const 25) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-shr_u-wrap-extend (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_u |
| (i32.wrap_i64 ;; stay 32 |
| (i64.extend_i32_s |
| (i32.const -1) |
| ) |
| ) |
| (i32.const 25) ;; 32 - 25 = 7, ok |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $sext-24-xor (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.xor |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.le_u |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sext-24-xor (param $0 i32) (result i32) ;; fuzz testcase |
| (i32.shr_s |
| (i32.shl |
| (i32.xor ;; should be 32 bits |
| (i32.le_u ;; 1 bit |
| (local.get $0) |
| (i32.const 2) |
| ) |
| (local.get $0) ;; unknown, so 32 bits |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ;; CHECK: (func $linear-sums (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 12) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 18) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const -4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 26) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const -20) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 22) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 14) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 66) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 44) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 14) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 34) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $linear-sums (param $0 i32) (param $1 i32) |
| (drop |
| (i32.add |
| (i32.add |
| (local.get $1) |
| (i32.const 16) |
| ) |
| (i32.shl |
| (i32.add |
| (local.get $0) |
| (i32.const -1) ;; -16, so cancels out! |
| ) |
| (i32.const 4) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.add |
| (local.get $1) |
| (i32.const 20) |
| ) |
| (i32.shl |
| (i32.add |
| (local.get $0) |
| (i32.const -1) ;; -8, so sum is +12 |
| ) |
| (i32.const 3) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add ;; simple sum |
| (i32.const 1) |
| (i32.const 3) |
| ) |
| ) |
| (drop |
| (i32.add ;; nested sum |
| (i32.add |
| (i32.const 1) |
| (i32.const 3) |
| ) |
| (i32.add |
| (i32.const 5) |
| (i32.const 9) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.add |
| (i32.const 1) |
| (i32.const 3) |
| ) |
| (i32.sub ;; internal sub |
| (i32.const 5) |
| (i32.const 3) |
| ) |
| ) |
| ) |
| (drop |
| (i32.sub ;; external sub |
| (i32.add |
| (i32.const 1) |
| (i32.const 3) |
| ) |
| (i32.add |
| (i32.const 5) |
| (i32.const 3) |
| ) |
| ) |
| ) |
| (drop |
| (i32.sub ;; external sub |
| (i32.add |
| (i32.const 1) |
| (i32.const 3) |
| ) |
| (i32.sub ;; and also internal sub |
| (i32.const 5) |
| (i32.const 3) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.add |
| (i32.const 1) |
| (i32.const 3) |
| ) |
| (i32.sub ;; negating sub |
| (i32.const 0) |
| (i32.const 3) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.sub |
| (i32.const 0) |
| (i32.sub ;; two negating subs |
| (i32.const 0) |
| (i32.add |
| (i32.const 3) |
| (i32.const 20) |
| ) |
| ) |
| ) |
| (i32.add |
| (i32.const 1) |
| (i32.const 2) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.add |
| (i32.const 0) |
| (i32.sub ;; one negating sub |
| (i32.const 0) |
| (i32.add |
| (i32.const 3) |
| (i32.const 20) |
| ) |
| ) |
| ) |
| (i32.add |
| (i32.const 1) |
| (i32.const 2) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.shl ;; shifted value |
| (i32.const 1) |
| (i32.const 3) |
| ) |
| (i32.add |
| (i32.const 5) |
| (i32.const 9) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.shl ;; shifted value |
| (i32.const 1) |
| (local.get $0) ;; but not by const |
| ) |
| (i32.add |
| (i32.const 5) |
| (i32.const 9) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.shl ;; shifted nested value |
| (i32.sub |
| (local.get $1) |
| (i32.const 10) |
| ) |
| (i32.const 3) |
| ) |
| (i32.add |
| (i32.const 5) |
| (i32.const 9) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.mul ;; multiplied |
| (i32.const 10) |
| (i32.const 3) |
| ) |
| (i32.add |
| (i32.const 5) |
| (i32.const 9) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.mul ;; multiplied by nonconstant - can't recurse |
| (i32.const 10) |
| (local.get $0) |
| ) |
| (i32.add |
| (i32.const 5) |
| (i32.const 9) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.mul ;; nested mul |
| (i32.add |
| (i32.const 10) |
| (local.get $0) |
| ) |
| (i32.const 2) |
| ) |
| (i32.add |
| (i32.const 5) |
| (i32.const 9) |
| ) |
| ) |
| ) |
| (drop |
| (i32.add |
| (i32.add |
| (local.get $0) |
| (i32.const 10) ;; cancelled out with the below |
| ) |
| (i32.sub |
| (i32.const -5) |
| (i32.const 5) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $almost-sign-ext (param $0 i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.const 100) |
| ;; CHECK-NEXT: (i32.const 25) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.const 50) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $almost-sign-ext (param $0 i32) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (i32.const 100) ;; too big, there is a sign bit, due to the extra shift |
| (i32.const 25) |
| ) |
| (i32.const 24) ;; different shift, but larger, so ok to opt if we leave a shift, in theory |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (i32.const 50) ;; small enough, no sign bit |
| (i32.const 25) |
| ) |
| (i32.const 24) ;; different shift, but larger, so ok to opt if we leave a shift |
| ) |
| ) |
| ) |
| ;; CHECK: (func $squaring (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 203) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 19) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 19) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 19) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $squaring (param $0 i32) (param $1 i32) |
| (drop |
| (i32.and |
| (i32.and |
| (local.get $0) |
| (i32.const 11) |
| ) |
| (i32.const 200) |
| ) |
| ) |
| (drop |
| (i32.and |
| (i32.and |
| (local.get $0) |
| (i32.const 11) |
| ) |
| (local.get $0) ;; non-const, cannot optimize this! |
| ) |
| ) |
| (drop |
| (i32.and |
| (i32.and |
| (i32.const 11) ;; flipped order |
| (local.get $0) |
| ) |
| (i32.const 200) |
| ) |
| ) |
| (drop |
| (i32.or |
| (i32.or |
| (local.get $0) |
| (i32.const 11) |
| ) |
| (i32.const 200) |
| ) |
| ) |
| (drop |
| (i32.shl |
| (i32.shl |
| (local.get $0) |
| (i32.const 11) |
| ) |
| (i32.const 200) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shr_s |
| (local.get $0) |
| (i32.const 11) |
| ) |
| (i32.const 200) |
| ) |
| ) |
| (drop |
| (i32.shr_u |
| (i32.shr_u |
| (local.get $0) |
| (i32.const 11) |
| ) |
| (i32.const 200) |
| ) |
| ) |
| (drop |
| (i32.shr_u |
| (i32.shr_s ;; but do not optimize a mixture or different shifts! |
| (local.get $0) |
| (i32.const 11) |
| ) |
| (i32.const 200) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $sign-ext-ne (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 111) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sign-ext-ne (param $0 i32) (param $1 i32) |
| ;; ne of sign-ext to const, can be a zext |
| (drop |
| (i32.ne |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 65000) |
| ) |
| ) |
| (drop |
| (i32.ne |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 64872) ;; no sign bit |
| ) |
| ) |
| (drop |
| (i32.ne |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const -149) ;; no sign bit, not all ones |
| ) |
| ) |
| (drop |
| (i32.ne |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 111) |
| ) |
| ) |
| (drop |
| (i32.ne |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.shr_s |
| (i32.shl |
| (local.get $1) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $sign-ext-eqz (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sign-ext-eqz (param $0 i32) (param $1 i32) |
| (drop |
| (i32.eqz |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $sign-ext-boolean (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 100) |
| ;; CHECK-NEXT: (i32.const 200) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sign-ext-boolean (param $0 i32) (param $1 i32) |
| (drop |
| (if (result i32) |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 100) |
| (i32.const 200) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $add-sub-zero (param $0 i32) (param $1 i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $add-sub-zero (param $0 i32) (param $1 i64) |
| (drop |
| (i32.add |
| (local.get $0) |
| (i32.const 0) |
| ) |
| ) |
| (drop |
| (i32.sub |
| (local.get $0) |
| (i32.const 0) |
| ) |
| ) |
| (drop |
| (i64.add |
| (local.get $1) |
| (i64.const 0) |
| ) |
| ) |
| (drop |
| (i64.sub |
| (local.get $1) |
| (i64.const 0) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $store-signext (param $0 i32) |
| ;; CHECK-NEXT: (i32.store8 |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store8 |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 25) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 25) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store8 |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store16 |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store16 |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 17) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 17) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store16 |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store-signext (param $0 i32) |
| (i32.store8 |
| (i32.const 8) |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) ;; exact size we store, sign-ext of 8 bits |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (i32.store8 |
| (i32.const 8) |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 25) ;; 7 bits. so the ext can alter a bit we store, do not optimize |
| ) |
| (i32.const 25) |
| ) |
| ) |
| (i32.store8 |
| (i32.const 8) |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 23) ;; 9 bits, this is good to optimize |
| ) |
| (i32.const 23) |
| ) |
| ) |
| (i32.store16 |
| (i32.const 8) |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 16) ;; exact size we store, sign-ext of 16 bits |
| ) |
| (i32.const 16) |
| ) |
| ) |
| (i32.store16 |
| (i32.const 8) |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 17) ;; 15 bits. so the ext can alter a bit we store, do not optimize |
| ) |
| (i32.const 17) |
| ) |
| ) |
| (i32.store16 |
| (i32.const 8) |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 14) ;; 17 bits, this is good to optimize |
| ) |
| (i32.const 14) |
| ) |
| ) |
| (i32.store |
| (i32.const 8) |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 16) ;; 4 bytes stored, do nothing |
| ) |
| (i32.const 16) |
| ) |
| ) |
| (i32.store |
| (i32.const 8) |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 8) ;; 4 bytes stored, do nothing |
| ) |
| (i32.const 8) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $sign-ext-tee (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sign-ext-tee (param $0 i32) (param $1 i32) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.tee $0 |
| (i32.const 128) ;; too big |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.tee $0 |
| (i32.const 127) ;; just right |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $sign-ext-load (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.load8_s |
| ;; CHECK-NEXT: (i32.const 256) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.load8_s |
| ;; CHECK-NEXT: (i32.const 256) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.load8_u |
| ;; CHECK-NEXT: (i32.const 256) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.load16_s |
| ;; CHECK-NEXT: (i32.const 256) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (i32.load8_s |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (i32.load8_u |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (i32.load8_s |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $1 |
| ;; CHECK-NEXT: (i32.load8_u |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sign-ext-load (param $0 i32) (param $1 i32) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (i32.load8_s ;; one byte, so perfect |
| (i32.const 256) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_u |
| (i32.load8_s ;; one byte, but sexted to 32 |
| (i32.const 256) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (i32.shr_u |
| (i32.load8_u ;; one byte, but reduced to 7 |
| (i32.const 256) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (i32.load16_s ;; two, so perfect |
| (i32.const 256) |
| ) |
| (i32.const 16) |
| ) |
| (i32.const 16) |
| ) |
| ) |
| ;; through tees, we cannot alter the load sign |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.tee $1 |
| (i32.load8_s |
| (i32.const 1) |
| ) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.tee $1 |
| (i32.load8_u |
| (i32.const 1) |
| ) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (drop |
| (i32.and |
| (local.tee $1 |
| (i32.load8_s |
| (i32.const 1) |
| ) |
| ) |
| (i32.const 255) |
| ) |
| ) |
| (drop |
| (i32.and |
| (local.tee $1 |
| (i32.load8_u |
| (i32.const 1) |
| ) |
| ) |
| (i32.const 255) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $mask-bits (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 254) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1279) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1290) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $mask-bits (param $0 i32) (param $1 i32) |
| (drop |
| (i32.and |
| (local.tee $0 |
| (i32.const 127) ;; 7 bits |
| ) |
| (i32.const 255) ;; mask 8, so we don't need this |
| ) |
| ) |
| (drop |
| (i32.and |
| (local.tee $0 |
| (i32.const 128) ;; 8 bits |
| ) |
| (i32.const 255) ;; mask 8, so we don't need this |
| ) |
| ) |
| (drop |
| (i32.and |
| (local.tee $0 |
| (i32.const 128) |
| ) |
| (i32.const 254) ;; improper mask, small |
| ) |
| ) |
| (drop |
| (i32.and |
| (local.tee $0 |
| (i32.const 128) |
| ) |
| (i32.const 1279) ;; improper mask, large |
| ) |
| ) |
| (drop |
| (i32.and |
| (local.tee $0 |
| (i32.const 128) |
| ) |
| (i32.const 1290) ;; improper mask, large |
| ) |
| ) |
| (drop |
| (i32.and |
| (local.tee $0 |
| (i32.const 128) |
| ) |
| (i32.const 4095) ;; proper mask, huge |
| ) |
| ) |
| (drop |
| (i32.and |
| (local.tee $0 |
| (i32.const 128) |
| ) |
| (i32.const 511) ;; proper mask, large |
| ) |
| ) |
| (drop |
| (i32.and |
| (local.tee $0 |
| (i32.const 128) |
| ) |
| (i32.const 127) ;; proper mask, just too small |
| ) |
| ) |
| ) |
| ;; CHECK: (func $local-info-zero-ext (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (local $x i32) |
| ;; CHECK-NEXT: (local $y i32) |
| ;; CHECK-NEXT: (local $z i32) |
| ;; CHECK-NEXT: (local $w i32) |
| ;; CHECK-NEXT: (local.set $x |
| ;; CHECK-NEXT: (i32.const 212) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $y |
| ;; CHECK-NEXT: (i32.const 500) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (i32.const 212) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $z |
| ;; CHECK-NEXT: (i32.const 212) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $z |
| ;; CHECK-NEXT: (i32.const 220) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $w |
| ;; CHECK-NEXT: (i32.const 212) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $w |
| ;; CHECK-NEXT: (i32.const 1000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $local-info-zero-ext (param $0 i32) (param $1 i32) |
| (local $x i32) |
| (local $y i32) |
| (local $z i32) |
| (local $w i32) |
| (local.set $x |
| (i32.const 212) ;; mask is unneeded, we are small |
| ) |
| (drop |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| ) |
| (local.set $y |
| (i32.const 500) ;; mask is needed, we are too big |
| ) |
| (drop |
| (i32.and |
| (local.get $y) |
| (i32.const 255) |
| ) |
| ) |
| (local.set $0 |
| (i32.const 212) ;; mask is unneeded, but we are a param, not a var, so no |
| ) |
| (drop |
| (i32.and |
| (local.get $0) |
| (i32.const 255) |
| ) |
| ) |
| (local.set $z |
| (i32.const 212) ;; mask is unneeded, we are small |
| ) |
| (local.set $z |
| (i32.const 220) ;; mask is still unneeded even with 2 uses |
| ) |
| (drop |
| (i32.and |
| (local.get $z) |
| (i32.const 255) |
| ) |
| ) |
| (local.set $w |
| (i32.const 212) ;; mask is unneeded, we are small |
| ) |
| (local.set $w |
| (i32.const 1000) ;; mask is needed, one use is too big |
| ) |
| (drop |
| (i32.and |
| (local.get $w) |
| (i32.const 255) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $local-info-sign-ext-bitsize (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (local $x i32) |
| ;; CHECK-NEXT: (local $y i32) |
| ;; CHECK-NEXT: (local $z i32) |
| ;; CHECK-NEXT: (local $w i32) |
| ;; CHECK-NEXT: (local.set $x |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $y |
| ;; CHECK-NEXT: (i32.const 128) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $z |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $z |
| ;; CHECK-NEXT: (i32.const 100) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $w |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $w |
| ;; CHECK-NEXT: (i32.const 150) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $local-info-sign-ext-bitsize (param $0 i32) (param $1 i32) |
| (local $x i32) |
| (local $y i32) |
| (local $z i32) |
| (local $w i32) |
| (local.set $x |
| (i32.const 127) ;; mask is unneeded, we are small |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $x) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (local.set $y |
| (i32.const 128) ;; mask is needed, we are too big |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $y) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (local.set $0 |
| (i32.const 127) ;; mask is unneeded, but we are a param, not a var, so no |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (local.set $z |
| (i32.const 127) ;; mask is unneeded, we are small |
| ) |
| (local.set $z |
| (i32.const 100) ;; mask is still unneeded even with 2 uses |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $z) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (local.set $w |
| (i32.const 127) ;; mask is unneeded, we are small |
| ) |
| (local.set $w |
| (i32.const 150) ;; mask is needed, one use is too big |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $w) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $local-info-sign-ext-already-exted (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (local $x i32) |
| ;; CHECK-NEXT: (local $y i32) |
| ;; CHECK-NEXT: (local $z i32) |
| ;; CHECK-NEXT: (local $w i32) |
| ;; CHECK-NEXT: (local.set $x |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $y |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $0 |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $z |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $z |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $w |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $w |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 23) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 23) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $local-info-sign-ext-already-exted (param $0 i32) (param $1 i32) |
| (local $x i32) |
| (local $y i32) |
| (local $z i32) |
| (local $w i32) |
| (local.set $x |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) ;; already sign-exted here, so no need later |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $x) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (local.set $y |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) ;; already sign-exted here, but wrong bit size |
| (i32.const 16) |
| ) |
| (i32.const 16) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $y) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (local.set $0 |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) ;; already sign-exted here, so no need later, but we are a param |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (local.set $z |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) ;; already sign-exted here, so no need later |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (local.set $z |
| (i32.shr_s |
| (i32.shl |
| (local.get $1) ;; already sign-exted here, so no need later |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $z) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (local.set $w |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) ;; already sign-exted here, so no need later |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (local.set $w |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) ;; not quite a sign-ext |
| (i32.const 23) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $w) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (drop ;; odd corner case |
| (i32.shr_s |
| (i32.shl |
| (local.get $0) ;; param, so we should know nothing |
| (i32.const 24) |
| ) |
| (i32.const 23) ;; different shift, smaller |
| ) |
| ) |
| ) |
| ;; CHECK: (func $signed-loads-fill-the-bits (param $$e i32) (result i32) |
| ;; CHECK-NEXT: (local $$0 i32) |
| ;; CHECK-NEXT: (local $$conv i32) |
| ;; CHECK-NEXT: (local.set $$0 |
| ;; CHECK-NEXT: (i32.load8_s |
| ;; CHECK-NEXT: (i32.const 1024) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $$conv |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $$0) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (return |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $$e) |
| ;; CHECK-NEXT: (local.get $$conv) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $signed-loads-fill-the-bits (param $$e i32) (result i32) |
| (local $$0 i32) |
| (local $$conv i32) |
| (local.set $$0 |
| (i32.load8_s ;; one byte, but 32 bits due to sign-extend |
| (i32.const 1024) |
| ) |
| ) |
| (local.set $$conv |
| (i32.and |
| (local.get $$0) |
| (i32.const 255) ;; so we need this zexting! |
| ) |
| ) |
| (return |
| (i32.eq |
| (local.get $$conv) |
| (local.get $$e) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $local-info-sign-ext-already-exted-by-load (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (local $x i32) |
| ;; CHECK-NEXT: (local $y i32) |
| ;; CHECK-NEXT: (local $z i32) |
| ;; CHECK-NEXT: (local $w i32) |
| ;; CHECK-NEXT: (local.set $x |
| ;; CHECK-NEXT: (i32.load8_s |
| ;; CHECK-NEXT: (i32.const 1024) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $y |
| ;; CHECK-NEXT: (i32.load8_u |
| ;; CHECK-NEXT: (i32.const 1024) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $z |
| ;; CHECK-NEXT: (i32.load16_s |
| ;; CHECK-NEXT: (i32.const 1024) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $local-info-sign-ext-already-exted-by-load (param $0 i32) (param $1 i32) |
| (local $x i32) |
| (local $y i32) |
| (local $z i32) |
| (local $w i32) |
| (local.set $x |
| (i32.load8_s (i32.const 1024)) ;; 8 bits, sign extended, no need to do it again |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $x) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (local.set $y |
| (i32.load8_u (i32.const 1024)) ;; 8 bits, zext, so bad |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $y) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| (local.set $z |
| (i32.load16_s (i32.const 1024)) ;; 16 bits sign-extended, wrong size |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $z) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $compare-load-s-sign-extend (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.load8_u |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.load8_u |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.load8_u |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.load8_s |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.load8_u |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.load8_s |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $compare-load-s-sign-extend (param $0 i32) (param $1 i32) |
| (drop |
| (i32.eq |
| (i32.load8_s |
| (local.get $0) |
| ) |
| (i32.shr_s |
| (i32.shl |
| (local.get $1) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $1) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.load8_s |
| (local.get $0) ;; flip order, we should canonicalize |
| ) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.load8_u ;; unsigned, bad |
| (local.get $0) |
| ) |
| (i32.shr_s |
| (i32.shl |
| (local.get $1) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.load8_s |
| (local.get $0) |
| ) |
| (i32.shr_s |
| (i32.shl |
| (local.get $1) |
| (i32.const 16) ;; wrong size |
| ) |
| (i32.const 16) |
| ) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $1) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.load8_u ;; unsigned, bad |
| (local.get $0) |
| ) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $1) |
| (i32.const 16) ;; wrong size |
| ) |
| (i32.const 16) |
| ) |
| (i32.load8_s |
| (local.get $0) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $unsign-diff-sizes (param $x i32) (param $y i32) (result i32) |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (call $unsign-diff-sizes |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (call $unsign-diff-sizes |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2006) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $unsign-diff-sizes (param $x i32) (param $y i32) (result i32) |
| (i32.ne |
| (i32.shr_s |
| (i32.shl |
| (call $unsign-diff-sizes |
| (i32.const -1) |
| (i32.const 5) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.shr_s |
| (i32.shl |
| (call $unsign-diff-sizes |
| (i32.const 1) |
| (i32.const 2006) |
| ) |
| (i32.const 16) |
| ) |
| (i32.const 16) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $unsign-same-sizes (param $x i32) (param $y i32) (result i32) |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (call $unsign-same-sizes |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (call $unsign-same-sizes |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2006) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $unsign-same-sizes (param $x i32) (param $y i32) (result i32) |
| (i32.ne |
| (i32.shr_s |
| (i32.shl |
| (call $unsign-same-sizes |
| (i32.const -1) |
| (i32.const 5) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.shr_s |
| (i32.shl |
| (call $unsign-same-sizes |
| (i32.const 1) |
| (i32.const 2006) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $fuzz-almost-sign-ext |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.load16_u |
| ;; CHECK-NEXT: (i32.const 2278) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 17) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.load16_u |
| ;; CHECK-NEXT: (i32.const 2278) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 17) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $fuzz-almost-sign-ext |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (i32.load16_u |
| (i32.const 2278) |
| ) |
| (i32.const 17) |
| ) |
| (i32.const 16) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (i32.shl |
| (i32.load16_u |
| (i32.const 2278) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const 16) |
| ) |
| (i32.const 16) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $fuzz-comp-impossible (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 127) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 252) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $fuzz-comp-impossible (param $x i32) |
| (drop |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $x) |
| (i32.const 16) |
| ) |
| (i32.const 16) |
| ) |
| (i32.const 65535) ;; impossible to be equal, the effective sign bit is set, but not the higher bits, which the sign-ext will set on the non-const value |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $x) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 255) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $x) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 127) ;; safe |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $x) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 128) ;; unsafe again |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $x) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 4223) ;; more big bits, so sign bit though |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $x) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const 4224) ;; more big bits |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.shr_s |
| (i32.shl |
| (local.get $x) |
| (i32.const 24) |
| ) |
| (i32.const 24) |
| ) |
| (i32.const -4) ;; safe even with more big bits, as they are all 1s |
| ) |
| ) |
| ) |
| ;; CHECK: (func $if-parallel (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-parallel (param $0 i32) (param $1 i32) |
| (drop |
| (if (result i32) |
| (local.get $0) |
| (i32.add (local.get $1) (i32.const 1)) |
| (i32.add (local.get $1) (i32.const 1)) |
| ) |
| ) |
| (drop |
| (if (result i32) |
| (local.tee $0 (local.get $1)) ;; side effects! |
| (i32.add (local.get $1) (i32.const 1)) |
| (i32.add (local.get $1) (i32.const 1)) |
| ) |
| ) |
| (drop |
| (if (result i32) |
| (local.get $0) |
| (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if |
| (i32.add (local.get $1) (unreachable)) |
| ) |
| ) |
| (drop |
| (if (result i32) |
| (local.tee $0 (local.get $1)) ;; side effects! |
| (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if |
| (i32.add (local.get $1) (unreachable)) |
| ) |
| ) |
| (drop |
| (if (result i32) |
| (unreachable) ;; !!! |
| (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if |
| (i32.add (local.get $1) (unreachable)) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-parallel (param $0 i32) (param $1 i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.tee $0 |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-parallel (param $0 i32) (param $1 i32) |
| (drop |
| (select |
| (i32.add (local.get $1) (i32.const 1)) |
| (i32.add (local.get $1) (i32.const 1)) |
| (local.get $0) |
| ) |
| ) |
| (drop |
| (select |
| (local.tee $0 (local.get $1)) ;; side effects! |
| (local.tee $0 (local.get $1)) ;; side effects! |
| (local.get $0) |
| ) |
| ) |
| (drop |
| (select |
| (i32.add (local.get $1) (i32.const 1)) |
| (i32.add (local.get $1) (i32.const 1)) |
| (local.tee $0 (local.get $1)) ;; side effects! (but no interference with values) |
| ) |
| ) |
| (drop |
| (select |
| (local.tee $0 (local.get $1)) ;; side effects! interference! |
| (local.tee $0 (local.get $1)) ;; side effects! interference! |
| (local.tee $0 (local.get $1)) ;; side effects! interference! |
| ) |
| ) |
| (drop |
| (select |
| (local.tee $0 (local.get $1)) ;; side effects! |
| (local.tee $0 (local.get $1)) ;; side effects! |
| (unreachable) ;; side effects! (but no interference with values) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $zero-shifts-is-not-sign-ext |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.load16_s align=1 |
| ;; CHECK-NEXT: (i32.const 790656516) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -5431187) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.load16_s align=1 |
| ;; CHECK-NEXT: (i32.const 790656516) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -5431187) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $zero-shifts-is-not-sign-ext |
| (drop |
| (i32.eq |
| (i32.const -5431187) |
| (i32.add |
| (i32.const 0) |
| (i32.shr_s |
| (i32.shl |
| (i32.load16_s align=1 |
| (i32.const 790656516) |
| ) |
| (i32.const 0) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.const -5431187) |
| (i32.add |
| (i32.const 0) |
| (i32.shr_s |
| (i32.shl |
| (i32.load16_s align=1 |
| (i32.const 790656516) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $zero-ops (result i32) |
| ;; CHECK-NEXT: (return |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.load16_s align=1 |
| ;; CHECK-NEXT: (i32.const 790656516) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $zero-ops (result i32) |
| (return |
| (i32.eq |
| (i32.const -1337) |
| (i32.shr_u |
| (i32.add |
| (i32.const 0) |
| (i32.shr_s |
| (i32.shl |
| (i32.load16_s align=1 |
| (i32.const 790656516) |
| ) |
| (i32.const 0) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $zero-ops-64 (result i32) |
| ;; CHECK-NEXT: (return |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (i64.load16_s align=1 |
| ;; CHECK-NEXT: (i32.const 790656516) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const -1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $zero-ops-64 (result i32) |
| (return |
| (i64.eq |
| (i64.const -1337) |
| (i64.shr_u |
| (i64.add |
| (i64.const 0) |
| (i64.shr_s |
| (i64.shl |
| (i64.load16_s align=1 |
| (i32.const 790656516) |
| ) |
| (i64.const 0) |
| ) |
| (i64.const 0) |
| ) |
| ) |
| (i64.const 0) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $zero-ops-64-special (result i32) |
| ;; CHECK-NEXT: (return |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.popcnt |
| ;; CHECK-NEXT: (i64.const 7377) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $zero-ops-64-special (result i32) |
| (return |
| (i32.wrap_i64 |
| (i64.popcnt |
| (i64.sub |
| (i64.shl |
| (i64.const 4294783828) |
| (i64.const 17179869183) |
| ) |
| (i64.const -7377) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $sign-ext-1-and-ne (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $sign-ext-1-and-ne) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| (func $sign-ext-1-and-ne (result i32) |
| (select |
| (i32.ne |
| (i32.const 1333788672) |
| (i32.shr_s |
| (i32.shl |
| (call $sign-ext-1-and-ne) |
| (i32.const 1) |
| ) |
| (i32.const 1) |
| ) |
| ) |
| (i32.const 2) |
| (i32.const 1) |
| ) |
| ) |
| ;; CHECK: (func $neg-shifts-and-255 (result i32) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.const -99) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $neg-shifts-and-255 (result i32) |
| (i32.and |
| (i32.shr_u |
| (i32.const -99) |
| (i32.const -32) ;; this shift does nothing |
| ) |
| (i32.const 255) |
| ) |
| ) |
| ;; CHECK: (func $neg-shifts-and-255-b (result i32) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.const -2349025) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $neg-shifts-and-255-b (result i32) |
| (i32.and |
| (i32.shl |
| (i32.const -2349025) |
| (i32.const -32) ;; this shift does nothing |
| ) |
| (i32.const 255) |
| ) |
| ) |
| ;; CHECK: (func $left-shifts-square-overflow (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| (func $left-shifts-square-overflow (param $x i32) (result i32) |
| (i32.shl |
| (i32.shl |
| (local.get $x) |
| (i32.const 31) |
| ) |
| (i32.const 1) |
| ) |
| ) |
| ;; CHECK: (func $left-shifts-square-overflow-with-side-effect (param $x i32) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| (func $left-shifts-square-overflow-with-side-effect (param $x i32) (result i32) |
| (i32.shl |
| (i32.shl |
| (call $ne0) ;; side effect |
| (i32.const 31) |
| ) |
| (i32.const 5) |
| ) |
| ) |
| ;; CHECK: (func $right-shifts-square-overflow-unsigned (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| (func $right-shifts-square-overflow-unsigned (param $x i32) (result i32) |
| (i32.shr_u |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 65535) ;; 31 bits effectively |
| ) |
| (i32.const 32767) ;; also 31 bits, so two shifts that force the value into nothing for sure |
| ) |
| ) |
| ;; CHECK: (func $shifts-square-overflow-signed (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 31) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $shifts-square-overflow-signed (param $x i32) (result i32) |
| (i32.shr_s |
| (i32.shr_s |
| (local.get $x) |
| (i32.const 65535) ;; 31 bits effectively |
| ) |
| (i32.const 32767) ;; also 31 bits, so two shifts that force the value into nothing for sure |
| ) |
| ) |
| ;; CHECK: (func $shifts-square-no-overflow-small (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 9) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $shifts-square-no-overflow-small (param $x i32) (result i32) |
| (i32.shr_u |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1031) ;; 7 bits effectively |
| ) |
| (i32.const 4098) ;; 2 bits effectively |
| ) |
| ) |
| ;; CHECK: (func $left-shifts-square-overflow-unsigned-64 (param $x i64) (result i64) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| (func $left-shifts-square-overflow-unsigned-64 (param $x i64) (result i64) |
| (i64.shl |
| (i64.shl |
| (local.get $x) |
| (i64.const 2) |
| ) |
| (i64.const 63) |
| ) |
| ) |
| ;; CHECK: (func $right-shifts-square-overflow-unsigned-64 (param $x i64) (result i64) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| (func $right-shifts-square-overflow-unsigned-64 (param $x i64) (result i64) |
| (i64.shr_u |
| (i64.shr_u |
| (local.get $x) |
| (i64.const 65535) ;; 63 bits effectively |
| ) |
| (i64.const 64767) ;; also 63 bits, so two shifts that force the value into nothing for sure |
| ) |
| ) |
| ;; CHECK: (func $right-shifts-square-overflow-signed-64 (param $x i64) (result i64) |
| ;; CHECK-NEXT: (i64.shr_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 63) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $right-shifts-square-overflow-signed-64 (param $x i64) (result i64) |
| (i64.shr_s |
| (i64.shr_s |
| (local.get $x) |
| (i64.const 65535) ;; 63 bits effectively |
| ) |
| (i64.const 64767) ;; also 63 bits, so two shifts that force the value into nothing for sure |
| ) |
| ) |
| ;; CHECK: (func $shifts-square-no-overflow-small-64 (param $x i64) (result i64) |
| ;; CHECK-NEXT: (i64.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 9) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $shifts-square-no-overflow-small-64 (param $x i64) (result i64) |
| (i64.shr_u |
| (i64.shr_u |
| (local.get $x) |
| (i64.const 1031) ;; 7 bits effectively |
| ) |
| (i64.const 4098) ;; 2 bits effectively |
| ) |
| ) |
| ;; CHECK: (func $shifts-square-unreachable (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (i32.const 1031) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 4098) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $shifts-square-unreachable (param $x i32) (result i32) |
| (i32.shr_u |
| (i32.shr_u |
| (unreachable) |
| (i32.const 1031) ;; 7 bits effectively |
| ) |
| (i32.const 4098) ;; 2 bits effectively |
| ) |
| ) |
| ;; CHECK: (func $mix-shifts (result i32) |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.const 23) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $mix-shifts (result i32) |
| (i32.shr_s |
| (i32.shl |
| (i32.const 23) |
| (i32.const -61) |
| ) |
| (i32.const 168) |
| ) |
| ) |
| ;; CHECK: (func $actually-no-shifts (result i32) |
| ;; CHECK-NEXT: (i32.const 33) |
| ;; CHECK-NEXT: ) |
| (func $actually-no-shifts (result i32) |
| (i32.add |
| (i32.shl |
| (i32.const 23) |
| (i32.const 32) ;; really 0 |
| ) |
| (i32.const 10) |
| ) |
| ) |
| ;; CHECK: (func $less-shifts-than-it-seems (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.const 4800) |
| ;; CHECK-NEXT: ) |
| (func $less-shifts-than-it-seems (param $x i32) (result i32) |
| (i32.add |
| (i32.shl |
| (i32.const 200) |
| (i32.const 36) ;; really 4 |
| ) |
| (i32.shl |
| (i32.const 100) |
| (i32.const 4) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $rotate-left-square-no-overflow-small (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.rotl |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 7) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $rotate-left-square-no-overflow-small (param $x i32) (result i32) |
| (i32.rotl |
| (i32.rotl |
| (local.get $x) |
| (i32.const 3) |
| ) |
| (i32.const 4) |
| ) |
| ) |
| ;; CHECK: (func $rotate-right-square-no-overflow-small (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.rotr |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 7) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $rotate-right-square-no-overflow-small (param $x i32) (result i32) |
| (i32.rotr |
| (i32.rotr |
| (local.get $x) |
| (i32.const 3) |
| ) |
| (i32.const 4) |
| ) |
| ) |
| ;; CHECK: (func $rotate-left-square-no-shifts (param $x i32) (result i32) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| (func $rotate-left-square-no-shifts (param $x i32) (result i32) |
| (i32.rotl |
| (i32.rotl |
| (local.get $x) |
| (i32.const 12) |
| ) |
| (i32.const 20) |
| ) |
| ) |
| ;; CHECK: (func $rotate-right-square-no-shifts (param $x i32) (result i32) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| (func $rotate-right-square-no-shifts (param $x i32) (result i32) |
| (i32.rotr |
| (i32.rotr |
| (local.get $x) |
| (i32.const 30) |
| ) |
| (i32.const 2) |
| ) |
| ) |
| ;; CHECK: (func $rotate-right-left-pos (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.rotl |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 23) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $rotate-right-left-pos (param $x i32) (result i32) |
| (i32.rotr |
| (i32.rotl |
| (local.get $x) |
| (i32.const 27) |
| ) |
| (i32.const 4) |
| ) |
| ) |
| ;; CHECK: (func $rotate-left-right-pos (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.rotr |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 7) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $rotate-left-right-pos (param $x i32) (result i32) |
| (i32.rotl |
| (i32.rotr |
| (local.get $x) |
| (i32.const 12) |
| ) |
| (i32.const 5) |
| ) |
| ) |
| ;; CHECK: (func $rotate-right-left-neg (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.rotl |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 27) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $rotate-right-left-neg (param $x i32) (result i32) |
| (i32.rotr |
| (i32.rotl |
| (local.get $x) |
| (i32.const 5) |
| ) |
| (i32.const 10) |
| ) |
| ) |
| ;; CHECK: (func $rotate-left-right-neg (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.rotr |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 27) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $rotate-left-right-neg (param $x i32) (result i32) |
| (i32.rotl |
| (i32.rotr |
| (local.get $x) |
| (i32.const 5) |
| ) |
| (i32.const 10) |
| ) |
| ) |
| ;; CHECK: (func $rotate-right-left-none (param $x i32) (result i32) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| (func $rotate-right-left-none (param $x i32) (result i32) |
| (i32.rotr |
| (i32.rotl |
| (local.get $x) |
| (i32.const 16) |
| ) |
| (i32.const 16) |
| ) |
| ) |
| ;; CHECK: (func $rotate-left-right-none (param $x i32) (result i32) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| (func $rotate-left-right-none (param $x i32) (result i32) |
| (i32.rotl |
| (i32.rotr |
| (local.get $x) |
| (i32.const 16) |
| ) |
| (i32.const 16) |
| ) |
| ) |
| ;; CHECK: (func $rotate-right-left-overflow (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.rotl |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 27) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $rotate-right-left-overflow (param $x i32) (result i32) |
| (i32.rotr |
| (i32.rotl |
| (local.get $x) |
| (i32.const 18) |
| ) |
| (i32.const 23) |
| ) |
| ) |
| ;; CHECK: (func $rotate-left-right-overflow (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.rotr |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 27) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $rotate-left-right-overflow (param $x i32) (result i32) |
| (i32.rotl |
| (i32.rotr |
| (local.get $x) |
| (i32.const 18) |
| ) |
| (i32.const 23) |
| ) |
| ) |
| ;; CHECK: (func $and-popcount32 (result i32) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.popcnt |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 31) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $and-popcount32 (result i32) |
| (i32.and |
| (i32.popcnt |
| (i32.const -1) |
| ) |
| (i32.const 31) |
| ) |
| ) |
| ;; CHECK: (func $and-popcount32-big (result i32) |
| ;; CHECK-NEXT: (i32.popcnt |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $and-popcount32-big (result i32) |
| (i32.and |
| (i32.popcnt |
| (i32.const -1) |
| ) |
| (i32.const 63) |
| ) |
| ) |
| ;; CHECK: (func $and-popcount64 (result i64) |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (i64.popcnt |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 63) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $and-popcount64 (result i64) ;; these are TODOs |
| (i64.and |
| (i64.popcnt |
| (i64.const -1) |
| ) |
| (i64.const 63) |
| ) |
| ) |
| ;; CHECK: (func $and-popcount64-big (result i64) |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (i64.popcnt |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 127) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $and-popcount64-big (result i64) |
| (i64.and |
| (i64.popcnt |
| (i64.const -1) |
| ) |
| (i64.const 127) |
| ) |
| ) |
| ;; CHECK: (func $and-popcount64-bigger (result i64) |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (i64.popcnt |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $and-popcount64-bigger (result i64) |
| (i64.and |
| (i64.popcnt |
| (i64.const -1) |
| ) |
| (i64.const 255) |
| ) |
| ) |
| ;; CHECK: (func $optimizeAddedConstants-filters-through-nonzero (result i32) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.const -536870912) |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 31744) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimizeAddedConstants-filters-through-nonzero (result i32) |
| (i32.sub |
| (i32.add |
| (i32.shl |
| (i32.const -536870912) |
| (i32.wrap_i64 |
| (i64.const 0) |
| ) |
| ) |
| (i32.const -32768) |
| ) |
| (i32.const -1024) |
| ) |
| ) |
| ;; CHECK: (func $optimizeAddedConstants-filters-through-nonzero-b (result i32) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.const -536870912) |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 31744) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimizeAddedConstants-filters-through-nonzero-b (result i32) |
| (i32.sub |
| (i32.add |
| (i32.shl |
| (i32.const -536870912) |
| (i32.wrap_i64 |
| (i64.const -1) |
| ) |
| ) |
| (i32.const -32768) |
| ) |
| (i32.const -1024) |
| ) |
| ) |
| ;; CHECK: (func $optimizeAddedConstants-mul-lshift-32 (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 12) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimizeAddedConstants-mul-lshift-32 (param $x i32) (result i32) |
| (i32.shl |
| (i32.mul |
| (local.get $x) |
| (i32.const 3) |
| ) |
| (i32.const 2) |
| ) |
| ) |
| ;; CHECK: (func $optimizeAddedConstants-mul-lshift-64 (param $x i64) (result i64) |
| ;; CHECK-NEXT: (i64.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 12) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimizeAddedConstants-mul-lshift-64 (param $x i64) (result i64) |
| (i64.shl |
| (i64.mul |
| (local.get $x) |
| (i64.const 3) |
| ) |
| (i64.const 2) |
| ) |
| ) |
| ;; CHECK: (func $optimizeAddedConstants-lshift-mul-32 (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 12) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimizeAddedConstants-lshift-mul-32 (param $x i32) (result i32) |
| (i32.mul |
| (i32.shl |
| (local.get $x) |
| (i32.const 2) |
| ) |
| (i32.const 3) |
| ) |
| ) |
| ;; CHECK: (func $optimizeAddedConstants-lshift-mul-64 (param $x i64) (result i64) |
| ;; CHECK-NEXT: (i64.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 12) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimizeAddedConstants-lshift-mul-64 (param $x i64) (result i64) |
| (i64.mul |
| (i64.shl |
| (local.get $x) |
| (i64.const 2) |
| ) |
| (i64.const 3) |
| ) |
| ) |
| ;; CHECK: (func $return-proper-value-from-shift-left-by-zero (result i32) |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (loop $label$0 (result i32) |
| ;; CHECK-NEXT: (block $label$1 |
| ;; CHECK-NEXT: (br_if $label$1 |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -62) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 40) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $return-proper-value-from-shift-left-by-zero (result i32) |
| (if (result i32) |
| (i32.sub |
| (i32.add |
| (loop $label$0 (result i32) |
| (block $label$1 |
| (br_if $label$1 |
| (i32.shl |
| (i32.load |
| (i32.const 0) |
| ) |
| (i32.const -31904) ;; really 0 shifts |
| ) |
| ) |
| ) |
| (i32.const -62) |
| ) |
| (i32.const 38) |
| ) |
| (i32.const -2) |
| ) |
| (i32.const 1) |
| (i32.const 0) |
| ) |
| ) |
| ;; CHECK: (func $de-morgan-2 (param $x i32) (param $y i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.xor |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $de-morgan-2 (param $x i32) (param $y i32) |
| (drop |
| (i32.and (i32.eqz (local.get $x)) (i32.eqz (local.get $y))) |
| ) |
| (drop |
| (i32.or (i32.eqz (local.get $x)) (i32.eqz (local.get $y))) |
| ) |
| (drop |
| (i32.xor (i32.eqz (local.get $x)) (i32.eqz (local.get $y))) |
| ) |
| (drop |
| (i32.and (i32.eqz (local.get $x)) (local.get $y)) |
| ) |
| (drop |
| (i32.and (local.get $x) (i32.eqz (local.get $y))) |
| ) |
| (drop |
| (i32.and (i32.eqz (local.get $x)) (i32.wrap_i64 (i64.const 2))) |
| ) |
| (drop |
| (i32.and (i32.wrap_i64 (i64.const 1)) (i32.eqz (local.get $y))) |
| ) |
| ) |
| ;; CHECK: (func $subzero1 (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 32) |
| ;; CHECK-NEXT: (i32.clz |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $subzero1 (param $0 i32) (result i32) |
| (i32.add |
| (i32.sub |
| (i32.const 1) |
| (i32.clz |
| (local.get $0) |
| ) |
| ) |
| (i32.const 31) |
| ) |
| ) |
| ;; CHECK: (func $subzero2 (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 32) |
| ;; CHECK-NEXT: (i32.clz |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $subzero2 (param $0 i32) (result i32) |
| (i32.add |
| (i32.const 31) |
| (i32.sub |
| (i32.const 1) |
| (i32.clz |
| (local.get $0) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $subzero3 (param $0 i32) (param $1 i32) (result i32) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (i32.clz |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $subzero3 (param $0 i32) (param $1 i32) (result i32) |
| (i32.add |
| (i32.sub |
| (i32.const 0) |
| (i32.clz |
| (local.get $0) |
| ) |
| ) |
| (local.get $1) |
| ) |
| ) |
| ;; CHECK: (func $subzero4 (param $0 i32) (param $1 i32) (result i32) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.clz |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $subzero4 (param $0 i32) (param $1 i32) (result i32) |
| (i32.add |
| (local.get $0) |
| (i32.sub |
| (i32.const 0) |
| (i32.clz |
| (local.get $1) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $remove-signs-for-mul-i32 (param $0 i32) (param $1 i32) (result i32) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $remove-signs-for-mul-i32 (param $0 i32) (param $1 i32) (result i32) |
| (i32.mul |
| (i32.sub |
| (i32.const 0) |
| (local.get $0) |
| ) |
| (i32.sub |
| (i32.const 0) |
| (local.get $1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $remove-signs-for-mul-i64 (param $0 i64) (param $1 i64) (result i64) |
| ;; CHECK-NEXT: (i64.mul |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $remove-signs-for-mul-i64 (param $0 i64) (param $1 i64) (result i64) |
| (i64.mul |
| (i64.sub |
| (i64.const 0) |
| (local.get $0) |
| ) |
| (i64.sub |
| (i64.const 0) |
| (local.get $1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $propagate-sign-for-i32-lhs (param $0 i32) (param $1 i32) (result i32) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $propagate-sign-for-i32-lhs (param $0 i32) (param $1 i32) (result i32) |
| (i32.mul |
| (i32.sub |
| (i32.const 0) |
| (local.get $0) |
| ) |
| (local.get $1) |
| ) |
| ) |
| ;; CHECK: (func $propagate-sign-for-i32-rhs (param $0 i32) (param $1 i32) (result i32) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $propagate-sign-for-i32-rhs (param $0 i32) (param $1 i32) (result i32) |
| (i32.mul |
| (local.get $0) |
| (i32.sub |
| (i32.const 0) |
| (local.get $1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $propagate-sign-for-i64-lhs (param $0 i64) (param $1 i64) (result i64) |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: (i64.mul |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $propagate-sign-for-i64-lhs (param $0 i64) (param $1 i64) (result i64) |
| (i64.mul |
| (i64.sub |
| (i64.const 0) |
| (local.get $0) |
| ) |
| (local.get $1) |
| ) |
| ) |
| ;; CHECK: (func $propagate-sign-for-i64-rhs (param $0 i64) (param $1 i64) (result i64) |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: (i64.mul |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $propagate-sign-for-i64-rhs (param $0 i64) (param $1 i64) (result i64) |
| (i64.mul |
| (local.get $0) |
| (i64.sub |
| (i64.const 0) |
| (local.get $1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $propagate-sign-for-i32-rhs-side (param $0 i32) (param $1 i32) (result i32) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (call $subzero4 |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $propagate-sign-for-i32-rhs-side (param $0 i32) (param $1 i32) (result i32) |
| (i32.mul |
| (call $subzero4 |
| (local.get $0) |
| (local.get $1) |
| ) |
| (i32.sub |
| (i32.const 0) |
| (local.get $1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $propagate-sign-for-mul-i32-lhs-const (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const -3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $propagate-sign-for-mul-i32-lhs-const (param $0 i32) (result i32) |
| (i32.mul |
| (i32.const 3) |
| (i32.sub |
| (i32.const 0) |
| (local.get $0) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $propagate-sign-for-mul-i32-lhs-const-pot (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $propagate-sign-for-mul-i32-lhs-const-pot (param $0 i32) (result i32) |
| (i32.mul |
| (i32.const 2) |
| (i32.sub |
| (i32.const 0) |
| (local.get $0) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $propagate-sign-for-mul-i32-rhs-const (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $propagate-sign-for-mul-i32-rhs-const (param $0 i32) (result i32) |
| (i32.mul |
| (i32.sub |
| (i32.const 0) |
| (local.get $0) |
| ) |
| (i32.const -5) |
| ) |
| ) |
| ;; CHECK: (func $propagate-sign-for-i32-both-sign-consts (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $propagate-sign-for-i32-both-sign-consts (param $0 i32) (result i32) |
| (i32.mul |
| (i32.const -5) |
| (i32.sub |
| (i32.const 0) |
| (i32.const 2) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $propagate-sign-for-mul-i32-smin (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 31) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $propagate-sign-for-mul-i32-smin (param $0 i32) (result i32) |
| (i32.mul |
| (i32.sub |
| (i32.const 0) |
| (local.get $0) |
| ) |
| (i32.const 0x80000000) |
| ) |
| ) |
| ;; CHECK: (func $propagate-sign-for-mul-i32-skip-2 (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $propagate-sign-for-mul-i32-skip-2 (param $0 i32) (result i32) |
| (i32.mul |
| (local.get $0) |
| (i32.sub |
| (i32.const 0) |
| (i32.const 3) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $mul-32-power-2 (param $x i32) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-32-power-2 |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-32-power-2 |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-32-power-2 |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-32-power-2 |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-32-power-2 |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (call $mul-32-power-2 |
| ;; CHECK-NEXT: (i32.const 123) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-32-power-2 |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-32-power-2 |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 31) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $mul-32-power-2 (param $x i32) (result i32) |
| (drop |
| (call $mul-32-power-2 |
| (i32.mul |
| (local.get $x) |
| (i32.const 4) |
| ) |
| ) |
| ) |
| (drop |
| (call $mul-32-power-2 |
| (i32.mul |
| (local.get $x) |
| (i32.const 5) |
| ) |
| ) |
| ) |
| (drop |
| (call $mul-32-power-2 |
| (i32.mul |
| (local.get $x) |
| (i32.const 1) |
| ) |
| ) |
| ) |
| (drop |
| (call $mul-32-power-2 |
| (i32.mul |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (call $mul-32-power-2 |
| (i32.mul |
| (call $mul-32-power-2 (i32.const 123)) ;; side effects |
| (i32.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (call $mul-32-power-2 |
| (i32.mul |
| (local.get $x) |
| (i32.const 0xffffffff) |
| ) |
| ) |
| ) |
| (drop |
| (call $mul-32-power-2 |
| (i32.mul |
| (local.get $x) |
| (i32.const 0x80000000) |
| ) |
| ) |
| ) |
| (unreachable) |
| ) |
| ;; CHECK: (func $mul-64-power-2 (param $x i64) (result i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-64-power-2 |
| ;; CHECK-NEXT: (i64.shl |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-64-power-2 |
| ;; CHECK-NEXT: (i64.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-64-power-2 |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-64-power-2 |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-64-power-2 |
| ;; CHECK-NEXT: (i64.mul |
| ;; CHECK-NEXT: (call $mul-64-power-2 |
| ;; CHECK-NEXT: (i64.const 123) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-64-power-2 |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $mul-64-power-2 |
| ;; CHECK-NEXT: (i64.shl |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 63) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $mul-64-power-2 (param $x i64) (result i64) |
| (drop |
| (call $mul-64-power-2 |
| (i64.mul |
| (local.get $x) |
| (i64.const 4) |
| ) |
| ) |
| ) |
| (drop |
| (call $mul-64-power-2 |
| (i64.mul |
| (local.get $x) |
| (i64.const 5) |
| ) |
| ) |
| ) |
| (drop |
| (call $mul-64-power-2 |
| (i64.mul |
| (local.get $x) |
| (i64.const 1) |
| ) |
| ) |
| ) |
| (drop |
| (call $mul-64-power-2 |
| (i64.mul |
| (local.get $x) |
| (i64.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (call $mul-64-power-2 |
| (i64.mul |
| (call $mul-64-power-2 (i64.const 123)) ;; side effects |
| (i64.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (call $mul-64-power-2 |
| (i64.mul |
| (local.get $x) |
| (i64.const 0xffffffffffffffff) |
| ) |
| ) |
| ) |
| (drop |
| (call $mul-64-power-2 |
| (i64.mul |
| (local.get $x) |
| (i64.const 0x8000000000000000) |
| ) |
| ) |
| ) |
| (unreachable) |
| ) |
| ;; CHECK: (func $div-32-power-2 (param $x i32) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $div-32-power-2 |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $div-32-power-2 |
| ;; CHECK-NEXT: (i32.div_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $div-32-power-2 |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $div-32-power-2 |
| ;; CHECK-NEXT: (i32.div_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $div-32-power-2 |
| ;; CHECK-NEXT: (i32.div_u |
| ;; CHECK-NEXT: (call $div-32-power-2 |
| ;; CHECK-NEXT: (i32.const 123) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $div-32-power-2 |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $div-32-power-2 |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 31) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $div-32-power-2 (param $x i32) (result i32) |
| (drop |
| (call $div-32-power-2 |
| (i32.div_u |
| (local.get $x) |
| (i32.const 4) |
| ) |
| ) |
| ) |
| (drop |
| (call $div-32-power-2 |
| (i32.div_u |
| (local.get $x) |
| (i32.const 5) |
| ) |
| ) |
| ) |
| (drop |
| (call $div-32-power-2 |
| (i32.div_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| ) |
| ) |
| (drop |
| (call $div-32-power-2 |
| (i32.div_u |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (call $div-32-power-2 |
| (i32.div_u |
| (call $div-32-power-2 (i32.const 123)) ;; side effects |
| (i32.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (call $div-32-power-2 |
| (i32.div_u |
| (local.get $x) |
| (i32.const 0xffffffff) |
| ) |
| ) |
| ) |
| (drop |
| (call $div-32-power-2 |
| (i32.div_u |
| (local.get $x) |
| (i32.const 0x80000000) |
| ) |
| ) |
| ) |
| (unreachable) |
| ) |
| ;; CHECK: (func $urem-32-power-2 (param $x i32) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $urem-32-power-2 |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $urem-32-power-2 |
| ;; CHECK-NEXT: (i32.rem_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $urem-32-power-2 |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $urem-32-power-2 |
| ;; CHECK-NEXT: (i32.rem_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $urem-32-power-2 |
| ;; CHECK-NEXT: (i32.rem_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $urem-32-power-2 |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (call $urem-32-power-2 |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $urem-32-power-2 (param $x i32) (result i32) |
| (drop |
| (call $urem-32-power-2 |
| (i32.rem_u |
| (local.get $x) |
| (i32.const 4) |
| ) |
| ) |
| ) |
| (drop |
| (call $urem-32-power-2 |
| (i32.rem_u |
| (local.get $x) |
| (i32.const 5) |
| ) |
| ) |
| ) |
| (drop |
| (call $urem-32-power-2 |
| (i32.rem_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| ) |
| ) |
| (drop |
| (call $urem-32-power-2 |
| (i32.rem_u |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (call $urem-32-power-2 |
| (i32.rem_u |
| (local.get $x) |
| (i32.const 0xffffffff) |
| ) |
| ) |
| ) |
| (drop |
| (call $urem-32-power-2 |
| (i32.rem_u |
| (local.get $x) |
| (i32.const 0x80000000) |
| ) |
| ) |
| ) |
| ;; (unsigned)x % 1 |
| (drop |
| (call $urem-32-power-2 |
| (i32.rem_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| ) |
| ) |
| (unreachable) |
| ) |
| ;; CHECK: (func $fdiv-32-power-2 (param $x f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const 0.5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const -0.5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const 2.3283064365386963e-10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const 5.421010862427522e-20) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const 8507059173023461586584365e13) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const 1.1754943508222875e-38) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const -8507059173023461586584365e13) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const -1.1754943508222875e-38) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.div |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const 5.877471754111438e-39) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.div |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const 5.877471754111438e-39) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.div |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.div |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.div |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.div |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const -inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $fdiv-32-power-2 (param $x f32) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const 2) |
| )) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const -2) |
| )) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const 4294967296) |
| )) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const 18446744073709551616) |
| )) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const 0x1p-126) |
| )) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const 0x1p+126) |
| )) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const -0x1p-126) |
| )) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const -0x1p+126) |
| )) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const 0x1p-127) ;; skip |
| )) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const 0x1p-127) ;; skip |
| )) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const 0) ;; skip |
| )) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const nan) ;; skip |
| )) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const inf) ;; skip |
| )) |
| (drop (f32.div |
| (local.get $x) |
| (f32.const -inf) ;; skip |
| )) |
| ) |
| ;; CHECK: (func $fdiv-64-power-2 (param $x f64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const 0.5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const -0.5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const 2.3283064365386963e-10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const 5.421010862427522e-20) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const 4494232837155789769323262e283) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const 2.2250738585072014e-308) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const -4494232837155789769323262e283) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const -2.2250738585072014e-308) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const 1.1125369292536007e-308) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const 8988465674311579538646525e283) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const nan:0x8000000000000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const -inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $fdiv-64-power-2 (param $x f64) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const 2) |
| )) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const -2) |
| )) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const 4294967296) |
| )) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const 18446744073709551616) |
| )) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const 0x1p-1022) |
| )) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const 0x1p+1022) |
| )) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const -0x1p-1022) |
| )) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const -0x1p+1022) |
| )) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const 0x1p-1023) ;; skip |
| )) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const 0x1p+1023) ;; skip |
| )) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const 0) ;; skip |
| )) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const nan) ;; skip |
| )) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const inf) ;; skip |
| )) |
| (drop (f64.div |
| (local.get $x) |
| (f64.const -inf) ;; skip |
| )) |
| ) |
| ;; CHECK: (func $srem-by-const (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.rem_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.rem_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -9223372036854775808) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $srem-by-const (param $x i32) (param $y i64) |
| ;; (signed)x % 1 |
| (drop (i32.rem_s |
| (local.get $x) |
| (i32.const 1) |
| )) |
| (drop (i64.rem_s |
| (local.get $y) |
| (i64.const 1) |
| )) |
| ;; (signed)x % 0x80000000 -> x & 0x7FFFFFFF |
| (drop (i32.rem_s |
| (local.get $x) |
| (i32.const 0x80000000) |
| )) |
| ;; (signed)x % 0x8000000000000000 -> x & 0x7FFFFFFFFFFFFFFF |
| (drop (i64.rem_s |
| (local.get $y) |
| (i64.const 0x8000000000000000) |
| )) |
| ) |
| ;; CHECK: (func $srem-by-pot-eq-ne-zero (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 9223372036854775807) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.ne |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 9223372036854775807) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.rem_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.rem_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $srem-by-pot-eq-ne-zero (param $x i32) (param $y i64) |
| ;; eqz((signed)x % 4) |
| (drop (i32.eqz |
| (i32.rem_s |
| (local.get $x) |
| (i32.const 4) |
| ) |
| )) |
| (drop (i64.eqz |
| (i64.rem_s |
| (local.get $y) |
| (i64.const 4) |
| ) |
| )) |
| ;; eqz((signed)x % -4) |
| (drop (i32.eqz |
| (i32.rem_s |
| (local.get $x) |
| (i32.const -4) |
| ) |
| )) |
| (drop (i64.eqz |
| (i64.rem_s |
| (local.get $y) |
| (i64.const -4) |
| ) |
| )) |
| ;; (signed)x % 4 == 0 |
| (drop (i32.eq |
| (i32.rem_s |
| (local.get $x) |
| (i32.const 4) |
| ) |
| (i32.const 0) |
| )) |
| (drop (i64.eq |
| (i64.rem_s |
| (local.get $y) |
| (i64.const 2) |
| ) |
| (i64.const 0) |
| )) |
| ;; (signed)x % -4 == 0 |
| (drop (i32.eq |
| (i32.rem_s |
| (local.get $x) |
| (i32.const -4) |
| ) |
| (i32.const 0) |
| )) |
| (drop (i64.eq |
| (i64.rem_s |
| (local.get $y) |
| (i64.const -4) |
| ) |
| (i64.const 0) |
| )) |
| ;; (signed)x % 2 != 0 |
| (drop (i32.ne |
| (i32.rem_s |
| (local.get $x) |
| (i32.const 2) |
| ) |
| (i32.const 0) |
| )) |
| (drop (i64.ne |
| (i64.rem_s |
| (local.get $y) |
| (i64.const 2) |
| ) |
| (i64.const 0) |
| )) |
| ;; (signed)x % -1 == 0 -> 0 == 0 |
| (drop (i32.eq |
| (i32.rem_s |
| (local.get $x) |
| (i32.const -1) |
| ) |
| (i32.const 0) |
| )) |
| ;; (signed)x % 0x80000000 == 0 |
| (drop (i32.eq |
| (i32.rem_s |
| (local.get $x) |
| (i32.const 0x80000000) |
| ) |
| (i32.const 0) |
| )) |
| ;; (signed)x % 0x80000000 != 0 |
| (drop (i32.ne |
| (i32.rem_s |
| (local.get $x) |
| (i32.const 0x80000000) |
| ) |
| (i32.const 0) |
| )) |
| ;; (signed)x % 0x8000000000000000 == 0 |
| (drop (i64.eq |
| (i64.rem_s |
| (local.get $y) |
| (i64.const 0x8000000000000000) |
| ) |
| (i64.const 0) |
| )) |
| ;; (signed)x % 0x8000000000000000 != 0 |
| (drop (i64.ne |
| (i64.rem_s |
| (local.get $y) |
| (i64.const 0x8000000000000000) |
| ) |
| (i64.const 0) |
| )) |
| ;; |
| (drop (i32.eq |
| (i32.rem_s |
| (local.get $x) |
| (i32.const 3) ;; skip |
| ) |
| (i32.const 0) |
| )) |
| (drop (i64.eq |
| (i64.rem_s |
| (local.get $y) |
| (i64.const 3) ;; skip |
| ) |
| (i64.const 0) |
| )) |
| ) |
| ;; CHECK: (func $orZero (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| (func $orZero (param $0 i32) (result i32) |
| (i32.or |
| (local.get $0) |
| (i32.const 0) |
| ) |
| ) |
| ;; CHECK: (func $andZero (param $0 i32) (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (call $andZero |
| ;; CHECK-NEXT: (i32.const 1234) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| (func $andZero (param $0 i32) (result i32) |
| (drop |
| (i32.and |
| (local.get $0) |
| (i32.const 0) |
| ) |
| ) |
| (drop |
| (i32.and |
| (call $andZero (i32.const 1234)) ;; side effects |
| (i32.const 0) |
| ) |
| ) |
| (unreachable) |
| ) |
| ;; CHECK: (func $abstract-additions (param $x32 i32) (param $x64 i64) (param $y32 f32) (param $y64 f64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $y32) |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $y64) |
| ;; CHECK-NEXT: (f64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $y32) |
| ;; CHECK-NEXT: (f32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $y64) |
| ;; CHECK-NEXT: (f64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $y32) |
| ;; CHECK-NEXT: (f32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $y64) |
| ;; CHECK-NEXT: (f64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.div |
| ;; CHECK-NEXT: (local.get $y32) |
| ;; CHECK-NEXT: (f32.const 1.2000000476837158) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: (local.get $x64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const -0) |
| ;; CHECK-NEXT: (local.get $y32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.sub |
| ;; CHECK-NEXT: (f64.const -0) |
| ;; CHECK-NEXT: (local.get $y64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.le_u |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 20) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: (i32.const 30) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (local.get $x64) |
| ;; CHECK-NEXT: (i64.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: (i32.const 30) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: (i32.const 30) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: (i32.const 30) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $abstract-additions (param $x32 i32) (param $x64 i64) (param $y32 f32) (param $y64 f64) |
| (drop |
| (i32.or |
| (i32.const 0) |
| (local.get $x32) |
| ) |
| ) |
| (drop |
| (i32.shl |
| (local.get $x32) |
| (i32.const 0) |
| ) |
| ) |
| (drop |
| (i32.shr_u |
| (local.get $x32) |
| (i32.const 0) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (local.get $x32) |
| (i32.const 0) |
| ) |
| ) |
| (drop |
| (i64.or |
| (i64.const 0) |
| (local.get $x64) |
| ) |
| ) |
| (drop |
| (i64.shl |
| (local.get $x64) |
| (i64.const 0) |
| ) |
| ) |
| (drop |
| (i64.shr_u |
| (local.get $x64) |
| (i64.const 0) |
| ) |
| ) |
| (drop |
| (i64.shr_s |
| (local.get $x64) |
| (i64.const 0) |
| ) |
| ) |
| (drop |
| (i32.mul |
| (local.get $x32) |
| (i32.const 0) |
| ) |
| ) |
| (drop |
| (i64.mul |
| (local.get $x64) |
| (i64.const 0) |
| ) |
| ) |
| (drop |
| (f32.mul |
| (local.get $y32) |
| (f32.const 0) |
| ) |
| ) |
| (drop |
| (f64.mul |
| (local.get $y64) |
| (f64.const 0) |
| ) |
| ) |
| (drop |
| (i32.mul |
| (local.get $x32) |
| (i32.const 1) |
| ) |
| ) |
| (drop |
| (i64.mul |
| (local.get $x64) |
| (i64.const 1) |
| ) |
| ) |
| (drop |
| (f32.mul |
| (local.get $y32) |
| (f32.const 1) |
| ) |
| ) |
| (drop |
| (f64.mul |
| (local.get $y64) |
| (f64.const 1) |
| ) |
| ) |
| (drop |
| (i32.and |
| (local.get $x32) |
| (i32.const 0) |
| ) |
| ) |
| (drop |
| (i64.and |
| (local.get $x64) |
| (i64.const 0) |
| ) |
| ) |
| (drop |
| (i32.and |
| (unreachable) |
| (i32.const 0) |
| ) |
| ) |
| (drop |
| (i64.and |
| (unreachable) |
| (i64.const 0) |
| ) |
| ) |
| (drop |
| (i32.div_s |
| (local.get $x32) |
| (i32.const 1) |
| ) |
| ) |
| (drop |
| (i32.div_u |
| (local.get $x32) |
| (i32.const 1) |
| ) |
| ) |
| (drop |
| (i64.div_s |
| (local.get $x64) |
| (i64.const 1) |
| ) |
| ) |
| (drop |
| (i64.div_u |
| (local.get $x64) |
| (i64.const 1) |
| ) |
| ) |
| (drop |
| (f32.div |
| (local.get $y32) |
| (f32.const 1) |
| ) |
| ) |
| (drop |
| (f64.div |
| (local.get $y64) |
| (f64.const 1) |
| ) |
| ) |
| (drop |
| (f32.div |
| (local.get $y32) |
| (f32.const 1.2) |
| ) |
| ) |
| (drop |
| (i32.mul |
| (local.get $x32) |
| (i32.const -1) |
| ) |
| ) |
| (drop |
| (i64.mul |
| (local.get $x64) |
| (i64.const -1) |
| ) |
| ) |
| (drop |
| (f32.mul |
| (local.get $y32) |
| (f32.const -1) |
| ) |
| ) |
| (drop |
| (f64.mul |
| (local.get $y64) |
| (f64.const -1) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.add |
| (local.get $x32) |
| (i32.const 10) |
| ) |
| (i32.const 20) |
| ) |
| ) |
| (drop |
| (i32.le_u |
| (i32.add |
| (local.get $x32) |
| (i32.const 10) |
| ) |
| (i32.const 20) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.sub |
| (local.get $x32) |
| (i32.const 10) |
| ) |
| (i32.const 20) |
| ) |
| ) |
| (drop |
| (i64.eq |
| (i64.add |
| (local.get $x64) |
| (i64.const 10) |
| ) |
| (i64.const 20) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.const 20) |
| (i32.add |
| (local.get $x32) |
| (i32.const 10) |
| ) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.add |
| (local.get $x32) |
| (i32.const 10) |
| ) |
| (i32.add |
| (local.get $x32) |
| (i32.const 20) |
| ) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.sub |
| (local.get $x32) |
| (i32.const 10) |
| ) |
| (i32.const 20) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.add |
| (local.get $x32) |
| (i32.const 10) |
| ) |
| (i32.sub |
| (local.get $x32) |
| (i32.const 20) |
| ) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.sub |
| (local.get $x32) |
| (i32.const 10) |
| ) |
| (i32.add |
| (local.get $x32) |
| (i32.const 20) |
| ) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (i32.sub |
| (local.get $x32) |
| (i32.const 10) |
| ) |
| (i32.sub |
| (local.get $x32) |
| (i32.const 20) |
| ) |
| ) |
| ) |
| (drop |
| (i64.le_s |
| (i64.sub |
| (local.get $x64) |
| (i64.const 288230376151711744) |
| ) |
| (i64.const 9223372036854775807) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $negatives-are-sometimes-better (param $x i32) (param $y i64) (param $z f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -8192) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -1048576) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -134217728) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.add |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -8192) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -1048576) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -134217728) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -17179869184) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -2199023255552) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -281474976710656) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -36028797018963968) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -4611686018427387904) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (f32.const 64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $negatives-are-sometimes-better (param $x i32) (param $y i64) (param $z f32) |
| (drop (i32.add (local.get $x) (i32.const 0x40))) |
| (drop (i32.sub (local.get $x) (i32.const 0x40))) |
| (drop (i32.add (local.get $x) (i32.const 0x2000))) |
| (drop (i32.add (local.get $x) (i32.const 0x100000))) |
| (drop (i32.add (local.get $x) (i32.const 0x8000000))) |
| |
| (drop (i64.add (local.get $y) (i64.const 0x40))) |
| (drop (i64.sub (local.get $y) (i64.const 0x40))) |
| (drop (i64.add (local.get $y) (i64.const 0x2000))) |
| (drop (i64.add (local.get $y) (i64.const 0x100000))) |
| (drop (i64.add (local.get $y) (i64.const 0x8000000))) |
| |
| (drop (i64.add (local.get $y) (i64.const 0x400000000))) |
| (drop (i64.add (local.get $y) (i64.const 0x20000000000))) |
| (drop (i64.add (local.get $y) (i64.const 0x1000000000000))) |
| (drop (i64.add (local.get $y) (i64.const 0x80000000000000))) |
| (drop (i64.add (local.get $y) (i64.const 0x4000000000000000))) |
| |
| (drop (f32.add (local.get $z) (f32.const 0x40))) |
| ) |
| ;; CHECK: (func $shift-a-zero (param $x i32) (param $y i64) (param $z f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $shift-a-zero (param $x i32) (param $y i64) (param $z f32) |
| (drop |
| (i32.shl |
| (i32.const 0) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.shr_u |
| (i32.const 0) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.const 0) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i64.shl |
| (i64.const 0) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (i32.shl |
| (i32.const 0) |
| (unreachable) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $identical-siblings (param $x i32) (param $y i64) (param $z f64) (param $xx i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.sub |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $xx) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $identical-siblings (param $x i32) (param $y i64) (param $z f64) (param $xx i32) |
| (drop |
| (i32.sub |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i64.sub |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (f64.sub |
| (local.get $z) |
| (local.get $z) |
| ) |
| ) |
| (drop |
| (i32.sub |
| (local.get $x) |
| (local.get $xx) |
| ) |
| ) |
| (drop |
| (i32.sub |
| (unreachable) |
| (unreachable) |
| ) |
| ) |
| (drop |
| (i32.add |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| ;; more ops |
| (drop |
| (i32.xor |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.ne |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.lt_s |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.lt_u |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.gt_s |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.gt_u |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.and |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.or |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.eq |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.le_s |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.le_u |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.ge_s |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i32.ge_u |
| (local.get $x) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (i64.xor |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (i64.ne |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (i64.lt_s |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (i64.lt_u |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (i64.gt_s |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (i64.gt_u |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (i64.and |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (i64.or |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (i64.eq |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (i64.le_s |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (i64.le_u |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (i64.ge_s |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| (drop |
| (i64.ge_u |
| (local.get $y) |
| (local.get $y) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $all_ones (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $all_ones (param $x i32) (param $y i64) |
| (drop |
| (i32.and |
| (local.get $x) |
| (i32.const -1) |
| ) |
| ) |
| (drop |
| (i32.or |
| (local.get $x) |
| (i32.const -1) |
| ) |
| ) |
| (drop |
| (i32.or |
| (local.tee $x |
| (i32.const 1337) |
| ) |
| (i32.const -1) |
| ) |
| ) |
| (drop |
| (i64.and |
| (local.get $y) |
| (i64.const -1) |
| ) |
| ) |
| (drop |
| (i64.or |
| (local.get $y) |
| (i64.const -1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $xor (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $xor (param $x i32) (param $y i64) |
| (drop |
| (i32.xor |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-on-const (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 7) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const 4) |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.gt_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.le_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i64.ge_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i64.lt_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i64.lt_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i64.ge_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 2) |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-on-const (param $x i32) (param $y i64) |
| (drop |
| (select |
| (i32.const 2) |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 3) |
| (local.get $x) |
| (i32.const 1) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 4) |
| (local.tee $x |
| (i32.const 5) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| (drop |
| (select |
| (local.tee $x |
| (i32.const 6) |
| ) |
| (i32.const 7) |
| (i32.const 0) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 4) |
| (local.tee $x |
| (i32.const 5) |
| ) |
| (i32.const 1) |
| ) |
| ) |
| (drop |
| (select |
| (local.tee $x |
| (i32.const 6) |
| ) |
| (i32.const 7) |
| (i32.const 1) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 1) |
| (i32.const 0) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 0) |
| (i32.const 1) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 0) |
| (i32.const 1) |
| (i32.lt_s |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 1) |
| (i32.const 0) |
| (i32.lt_s |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 0) |
| (i32.const 1) |
| (i32.ge_s |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 1) |
| (i32.const 0) |
| (i32.gt_s |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 0) |
| (i32.const 1) |
| (i32.gt_s |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 1) |
| (i32.const 0) |
| (i32.ge_s |
| (local.get $x) |
| (i32.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (i64.const 1) |
| (i64.const 0) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (select |
| (i64.const 0) |
| (i64.const 1) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (select |
| (i64.const 1) |
| (i64.const 0) |
| (i64.eqz |
| (local.get $y) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (i64.const 0) |
| (i64.const 1) |
| (i64.eqz |
| (local.get $y) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (i64.const 0) |
| (i64.const 1) |
| (i64.lt_s |
| (local.get $y) |
| (i64.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (i64.const 1) |
| (i64.const 0) |
| (i64.lt_s |
| (local.get $y) |
| (i64.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (i64.const 0) |
| (i64.const 1) |
| (i64.ge_s |
| (local.get $y) |
| (i64.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (i64.const 1) |
| (i64.const 0) |
| (i64.ge_s |
| (local.get $y) |
| (i64.const 0) |
| ) |
| ) |
| ) |
| ;; optimize boolean |
| (drop |
| (select |
| (local.get $x) |
| (i32.const 0) |
| (i32.eqz |
| (i32.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (local.get $x) |
| (i32.const 2) |
| (i32.eqz |
| (i32.const 2) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (local.get $x) |
| (i32.const 2) |
| (i32.eqz |
| (i32.eqz |
| (local.get $x) |
| ) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (local.get $y) |
| (i64.const 0) |
| (i64.eqz |
| (i64.const 0) |
| ) |
| ) |
| ) |
| (drop |
| (select |
| (local.get $y) |
| (i64.const 2) |
| (i64.eqz |
| (i64.const 2) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $optimize-boolean (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.shr_u |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 63) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 31) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.shr_u |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 63) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.shr_u |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 63) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.ne |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-boolean (param $x i32) (param $y i64) |
| ;; bool(-x) -> bool(x) |
| (drop |
| (select |
| (i32.const 1) |
| (i32.const 2) |
| (i32.sub |
| (i32.const 0) |
| (local.get $x) |
| ) |
| ) |
| ) |
| ;; i32(bool(expr)) == 1 -> bool(expr) |
| (drop (i32.eq |
| (i32.and |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 1) |
| )) |
| ;; i32(bool(expr)) != 1 -> !bool(expr) |
| (drop (i32.ne |
| (i32.and |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 1) |
| )) |
| ;; i32(bool(expr)) ^ 1 -> !bool(expr) |
| (drop (i32.xor |
| (i32.and |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 1) |
| )) |
| ;; i64(bool(expr)) ^ 1 -> extend(!bool(expr)) |
| (drop (i64.xor |
| (i64.and |
| (local.get $y) |
| (i64.const 1) |
| ) |
| (i64.const 1) |
| )) |
| ;; i64(bool(expr)) != 0 -> i32(bool(expr)) |
| (drop (i64.ne |
| (i64.shr_u |
| (local.get $y) |
| (i64.const 63) |
| ) |
| (i64.const 0) |
| )) |
| ;; eqz((i32(bool(expr)) != 0) != 0) |
| (drop (i32.eqz |
| (i32.ne |
| (i32.ne |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 31) |
| ) |
| (i32.const 0) |
| ) |
| (i32.const 0) |
| ) |
| )) |
| ;; i32.eqz(wrap(i64(x))) |
| (drop (i32.eqz |
| (i32.wrap_i64 |
| (i64.shr_u |
| (local.get $y) |
| (i64.const 63) |
| ) |
| ) |
| )) |
| ;; eqz((i64(bool(expr)) != 0) != 0) |
| (drop (i32.eqz |
| (i32.ne |
| (i64.ne |
| (i64.shr_u |
| (local.get $y) |
| (i64.const 63) |
| ) |
| (i64.const 0) |
| ) |
| (i32.const 0) |
| ) |
| )) |
| ;; eqz((i64(bool(expr)) != 0) != 0) |
| (drop (i32.eqz |
| (i32.ne |
| (i64.ne |
| (local.get $y) |
| (i64.const 0) |
| ) |
| (i32.const 0) |
| ) |
| )) |
| ;; i32.eqz(wrap(i64(x))) -> skip |
| (drop (i32.eqz |
| (i32.wrap_i64 |
| (local.get $y) |
| ) |
| )) |
| ;; i64(bool(expr)) == 1 -> i32(bool(expr)) |
| (drop (i64.eq |
| (i64.and |
| (local.get $y) |
| (i64.const 1) |
| ) |
| (i64.const 1) |
| )) |
| ;; i64(bool(expr)) != 1 -> !i64(bool(expr)) |
| (drop (i64.ne |
| (i64.and |
| (local.get $y) |
| (i64.const 1) |
| ) |
| (i64.const 1) |
| )) |
| ;; i32(bool(expr)) & 1 -> bool(expr) |
| (drop (i32.and |
| (i32.and |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 1) |
| )) |
| ;; i32(bool(expr)) | 1 -> 1 |
| (drop (i32.or |
| (i32.and |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 1) |
| )) |
| ;; i64(bool(expr)) & 1 -> i64(bool(expr)) |
| (drop (i64.and |
| (i64.and |
| (local.get $y) |
| (i64.const 1) |
| ) |
| (i64.const 1) |
| )) |
| ;; i64(bool(expr)) | 1 -> 1 |
| (drop (i64.or |
| (i64.and |
| (local.get $y) |
| (i64.const 1) |
| ) |
| (i64.const 1) |
| )) |
| ;; i32(bool(expr)) != 0 -> i32(bool(expr)) |
| (drop (i32.ne |
| (i32.and |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 0) |
| )) |
| ;; i32(bool(expr)) != 0 -> i32(bool(expr)) |
| (drop (i32.ne |
| (i64.ne |
| (local.get $y) |
| (i64.const 0) |
| ) |
| (i32.const 0) |
| )) |
| ;; (i32(expr) != 0) != 0 -> (expr != 0) |
| (drop (i32.ne |
| (i32.ne |
| (local.get $x) |
| (i32.const 0) |
| ) |
| (i32.const 0) |
| )) |
| ;; (signed)x % 4 ? 1 : 0 |
| (drop (if (result i32) |
| (i32.rem_s |
| (local.get $x) |
| (i32.const 4) |
| ) |
| (i32.const 1) |
| (i32.const 0) |
| )) |
| ;; (signed)x % min_s ? 1 : 0 |
| (drop (if (result i32) |
| (i32.rem_s |
| (local.get $x) |
| (i32.const 0x80000000) |
| ) |
| (i32.const 1) |
| (i32.const 0) |
| )) |
| ) |
| ;; CHECK: (func $fold-eqz-eqz (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.ne |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $fold-eqz-eqz (param $x i32) (param $y i64) |
| ;; i32.eqz(i32.eqz(x)) -> x != 0 |
| (drop (i32.eqz (i32.eqz (local.get $x)))) |
| ;; i32.eqz(i64.eqz(y)) -> y != 0 |
| (drop (i32.eqz (i64.eqz (local.get $y)))) |
| ) |
| ;; CHECK: (func $optimize-bitwise-oprations (param $x i32) (param $y i32) (param $z i64) (param $w i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.rotl |
| ;; CHECK-NEXT: (i32.const -2) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.rotl |
| ;; CHECK-NEXT: (i64.const -2) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-bitwise-oprations (param $x i32) (param $y i32) (param $z i64) (param $w i64) |
| ;; ~(1 << x) -> rotl(-2, x) |
| (drop (i32.xor |
| (i32.shl |
| (i32.const 1) |
| (local.get $x) |
| ) |
| (i32.const -1) |
| )) |
| (drop (i64.xor |
| (i64.shl |
| (i64.const 1) |
| (local.get $z) |
| ) |
| (i64.const -1) |
| )) |
| ) |
| ;; CHECK: (func $getFallthrough |
| ;; CHECK-NEXT: (local $x0 i32) |
| ;; CHECK-NEXT: (local $x1 i32) |
| ;; CHECK-NEXT: (local $x2 i32) |
| ;; CHECK-NEXT: (local $x3 i32) |
| ;; CHECK-NEXT: (local $x4 i32) |
| ;; CHECK-NEXT: (local $x5 i32) |
| ;; CHECK-NEXT: (local $x6 i32) |
| ;; CHECK-NEXT: (local $x7 i32) |
| ;; CHECK-NEXT: (local.set $x0 |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $x1 |
| ;; CHECK-NEXT: (local.tee $x2 |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $x3 |
| ;; CHECK-NEXT: (loop $loop-in (result i32) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $x4 |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x4) |
| ;; CHECK-NEXT: (i32.const 7) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $x5 |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.set $x6 |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x6) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block $out (result i32) |
| ;; CHECK-NEXT: (local.set $x7 |
| ;; CHECK-NEXT: (br_if $out |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x7) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $getFallthrough ;; unit tests for Properties::getFallthrough |
| (local $x0 i32) |
| (local $x1 i32) |
| (local $x2 i32) |
| (local $x3 i32) |
| (local $x4 i32) |
| (local $x5 i32) |
| (local $x6 i32) |
| (local $x7 i32) |
| ;; the trivial case |
| (local.set $x0 (i32.const 1)) |
| (drop (i32.and (local.get $x0) (i32.const 7))) |
| ;; tees |
| (local.set $x1 (local.tee $x2 (i32.const 1))) |
| (drop (i32.and (local.get $x1) (i32.const 7))) |
| ;; loop |
| (local.set $x3 (loop (result i32) (i32.const 1))) |
| (drop (i32.and (local.get $x3) (i32.const 7))) |
| ;; if - two sides, can't |
| (local.set $x4 (if (result i32) (i32.const 1) (i32.const 2) (i32.const 3))) |
| (drop (i32.and (local.get $x4) (i32.const 7))) |
| ;; if - one side, can |
| (local.set $x5 (if (result i32) (i32.const 1) (unreachable) (i32.const 3))) |
| (drop (i32.and (local.get $x5) (i32.const 7))) |
| ;; if - one side, can |
| (local.set $x6 (if (result i32) (i32.const 1) (i32.const 3) (unreachable))) |
| (drop (i32.and (local.get $x6) (i32.const 7))) |
| ;; br_if with value |
| (drop |
| (block $out (result i32) |
| (local.set $x7 (br_if $out (i32.const 1) (i32.const 1))) |
| (drop (i32.and (local.get $x7) (i32.const 7))) |
| (unreachable) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $tee-with-unreachable-value (result f64) |
| ;; CHECK-NEXT: (local $var$0 i32) |
| ;; CHECK-NEXT: (block $label$1 (result f64) |
| ;; CHECK-NEXT: (local.tee $var$0 |
| ;; CHECK-NEXT: (br_if $label$1 |
| ;; CHECK-NEXT: (f64.const 1) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $tee-with-unreachable-value (result f64) |
| (local $var$0 i32) |
| (block $label$1 (result f64) |
| (local.tee $var$0 |
| (br_if $label$1 ;; the f64 does not actually flow through this, it's unreachable (and the type is wrong - but unchecked) |
| (f64.const 1) |
| (unreachable) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $add-sub-zero-reorder-1 (param $temp i32) (result i32) |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (local.get $temp) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.tee $temp |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $add-sub-zero-reorder-1 (param $temp i32) (result i32) |
| (i32.add |
| (i32.add |
| (i32.sub |
| (i32.const 0) ;; this zero looks like we could remove it by subtracting the get of $temp from the parent, but that would reorder it *after* the tee :( |
| (local.get $temp) |
| ) |
| (local.tee $temp ;; cannot move this tee before the get |
| (i32.const 1) |
| ) |
| ) |
| (i32.const 2) |
| ) |
| ) |
| ;; CHECK: (func $add-sub-zero-reorder-2 (param $temp i32) (result i32) |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.tee $temp |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $temp) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $add-sub-zero-reorder-2 (param $temp i32) (result i32) |
| (i32.add |
| (i32.add |
| (local.tee $temp ;; in this order, the tee already comes first, so all is good for the optimization |
| (i32.const 1) |
| ) |
| (i32.sub |
| (i32.const 0) |
| (local.get $temp) |
| ) |
| ) |
| (i32.const 2) |
| ) |
| ) |
| ;; CHECK: (func $const-float-zero (param $fx f32) (param $fy f64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (local.get $fx) |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.sub |
| ;; CHECK-NEXT: (local.get $fy) |
| ;; CHECK-NEXT: (f64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $fx) |
| ;; CHECK-NEXT: (f32.const -0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $fy) |
| ;; CHECK-NEXT: (f64.const -0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $fx) |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $fy) |
| ;; CHECK-NEXT: (f64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: (local.get $fx) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.sub |
| ;; CHECK-NEXT: (f64.const 0) |
| ;; CHECK-NEXT: (local.get $fy) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $fx) |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $fy) |
| ;; CHECK-NEXT: (f64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const -nan:0x34546d) |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $const-float-zero (param $fx f32) (param $fy f64) |
| ;; x - 0.0 ==> x |
| (drop (f32.sub |
| (local.get $fx) |
| (f32.const 0) |
| )) |
| (drop (f64.sub |
| (local.get $fy) |
| (f64.const 0) |
| )) |
| ;; x + (-0.0) ==> x |
| (drop (f32.add |
| (local.get $fx) |
| (f32.const -0) |
| )) |
| (drop (f64.add |
| (local.get $fy) |
| (f64.const -0) |
| )) |
| ;; x - (-0.0) ==> x + 0.0 |
| (drop (f32.sub |
| (local.get $fx) |
| (f32.const -0) ;; skip |
| )) |
| (drop (f64.sub |
| (local.get $fy) |
| (f64.const -0) ;; skip |
| )) |
| ;; 0.0 - x ==> 0.0 - x |
| (drop (f32.sub |
| (f32.const 0) |
| (local.get $fx) ;; skip |
| )) |
| (drop (f64.sub |
| (f64.const 0) |
| (local.get $fy) ;; skip |
| )) |
| ;; x + 0.0 ==> x + 0.0 |
| (drop (f32.add |
| (local.get $fx) ;; skip |
| (f32.const 0) |
| )) |
| (drop (f64.add |
| (local.get $fy) ;; skip |
| (f64.const 0) |
| )) |
| (drop (f32.sub |
| (f32.const -nan:0x34546d) ;; skip |
| (f32.const 0) |
| )) |
| ) |
| ;; CHECK: (func $rhs-is-neg-one (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.add |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.ge_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_s |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.lt_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.ne |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const -0) |
| ;; CHECK-NEXT: (local.get $fx) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.sub |
| ;; CHECK-NEXT: (f64.const -0) |
| ;; CHECK-NEXT: (local.get $fy) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $rhs-is-neg-one (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) |
| (drop (i32.sub |
| (local.get $x) |
| (i32.const -1) |
| )) |
| (drop (i64.sub |
| (local.get $y) |
| (i64.const -1) |
| )) |
| ;; (unsigned)x > -1 ==> 0 |
| (drop (i32.gt_u |
| (local.get $x) |
| (i32.const -1) |
| )) |
| (drop (i64.gt_u |
| (local.get $y) |
| (i64.const -1) |
| )) |
| (drop (i32.gt_s |
| (local.get $x) |
| (i32.const -1) |
| )) |
| (drop (i64.gt_s |
| (local.get $y) |
| (i64.const -1) |
| )) |
| (drop (i64.extend_i32_s |
| (i64.gt_u |
| (i64.const 0) |
| (i64.const -1) |
| ) |
| )) |
| ;; (unsigned)x <= -1 ==> 1 |
| (drop (i32.le_u |
| (local.get $x) |
| (i32.const -1) |
| )) |
| (drop (i64.le_u |
| (local.get $y) |
| (i64.const -1) |
| )) |
| (drop (i32.le_s |
| (local.get $x) |
| (i32.const -1) |
| )) |
| (drop (i64.le_s |
| (local.get $y) |
| (i64.const -1) |
| )) |
| ;; (unsigned)x >= -1 ==> x == -1 |
| (drop (i32.ge_u |
| (local.get $x) |
| (i32.const -1) |
| )) |
| (drop (i64.ge_u |
| (local.get $y) |
| (i64.const -1) |
| )) |
| ;; (unsigned)x < -1 ==> x != -1 |
| (drop (i32.lt_u |
| (local.get $x) |
| (i32.const -1) |
| )) |
| (drop (i64.lt_u |
| (local.get $y) |
| (i64.const -1) |
| )) |
| ;; x * -1 |
| (drop (i32.mul |
| (local.get $x) |
| (i32.const -1) |
| )) |
| (drop (i64.mul |
| (local.get $y) |
| (i64.const -1) |
| )) |
| (drop (f32.mul ;; skip |
| (local.get $fx) |
| (f32.const -1) |
| )) |
| (drop (f64.mul ;; skip |
| (local.get $fy) |
| (f64.const -1) |
| )) |
| ;; (unsigned)x / -1 |
| (drop (i32.div_u |
| (local.get $x) |
| (i32.const -1) |
| )) |
| (drop (i64.div_u |
| (local.get $y) |
| (i64.const -1) |
| )) |
| ) |
| ;; CHECK: (func $rhs-is-const (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -9223372036854775808) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.div_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 31) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.shr_u |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 63) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.ne |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.ne |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 9223372036854775807) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.ne |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -9223372036854775808) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -9223372036854775808) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 9223372036854775807) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const -0) |
| ;; CHECK-NEXT: (local.get $fx) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $fy) |
| ;; CHECK-NEXT: (f64.const 2.1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $fy) |
| ;; CHECK-NEXT: (f64.const -2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.div |
| ;; CHECK-NEXT: (local.get $fx) |
| ;; CHECK-NEXT: (f32.const -inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (local.get $fy) |
| ;; CHECK-NEXT: (f64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (local.get $fy) |
| ;; CHECK-NEXT: (f64.const -nan:0x8000000000000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (f64.const -5) |
| ;; CHECK-NEXT: (local.get $fy) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $rhs-is-const (param $x i32) (param $y i64) (param $fx f32) (param $fy f64) |
| ;; signed divs |
| ;; i32(x) / -2147483648 -> x == -2147483648 |
| (drop (i32.div_s |
| (local.get $x) |
| (i32.const -2147483648) |
| )) |
| ;; i64(x) / -9223372036854775808 -> x == -9223372036854775808 |
| (drop (i64.div_s |
| (local.get $y) |
| (i64.const -9223372036854775808) |
| )) |
| ;; skip |
| (drop (i64.div_s |
| (local.get $y) |
| (i64.const -2147483648) |
| )) |
| |
| ;; unsigned divs |
| ;; u32(x) / -2 => x >= -2 |
| (drop (i32.div_u |
| (local.get $x) |
| (i32.const -2) |
| )) |
| ;; u32(x) / -1 => x == -1 |
| (drop (i32.div_u |
| (local.get $x) |
| (i32.const -1) |
| )) |
| ;; u32(x) / (i32.min + 1) |
| (drop (i32.div_u |
| (local.get $x) |
| (i32.const -2147483647) |
| )) |
| ;; u32(x) / i32.min => x >>> 31 |
| (drop (i32.div_u |
| (local.get $x) |
| (i32.const -2147483648) |
| )) |
| ;; u64(x) / -1 => u64(x == -1) |
| (drop (i64.div_u |
| (local.get $y) |
| (i64.const -1) |
| )) |
| ;; u64(x) / i64.min => x >>> 63 |
| (drop (i64.div_u |
| (local.get $y) |
| (i64.const -9223372036854775808) |
| )) |
| |
| ;; (unsigned)x >= 0 => i32(1) |
| (drop (i32.ge_u |
| (local.get $x) |
| (i32.const 0) |
| )) |
| (drop (i64.ge_u |
| (local.get $y) |
| (i64.const 0) |
| )) |
| |
| ;; (unsigned)x < 0 => i32(0) |
| (drop (i32.lt_u |
| (local.get $x) |
| (i32.const 0) |
| )) |
| (drop (i64.lt_u |
| (local.get $y) |
| (i64.const 0) |
| )) |
| |
| ;; (unsigned)x > 0 => x != 0 |
| (drop (i32.gt_u |
| (local.get $x) |
| (i32.const 0) |
| )) |
| (drop (i64.gt_u |
| (local.get $y) |
| (i64.const 0) |
| )) |
| |
| ;; (unsigned)x <= 0 => x == 0 |
| (drop (i32.le_u |
| (local.get $x) |
| (i32.const 0) |
| )) |
| (drop (i64.le_u |
| (local.get $y) |
| (i64.const 0) |
| )) |
| |
| ;; i32(x) <= 0x7fffffff => i32(1) |
| (drop (i32.le_s |
| (local.get $x) |
| (i32.const 0x7fffffff) |
| )) |
| ;; i64(x) <= 0x7fffffffffffffff => i32(1) |
| (drop (i64.le_s |
| (local.get $y) |
| (i64.const 0x7fffffffffffffff) |
| )) |
| |
| ;; i32(x) >= 0x80000000 => i32(1) |
| (drop (i32.ge_s |
| (local.get $x) |
| (i32.const 0x80000000) |
| )) |
| ;; i64(x) >= 0x8000000000000000 => i32(1) |
| (drop (i64.ge_s |
| (local.get $y) |
| (i64.const 0x8000000000000000) |
| )) |
| |
| ;; i32(x) < 0x80000000 => 0 |
| (drop (i32.lt_s |
| (local.get $x) |
| (i32.const 0x80000000) |
| )) |
| ;; i64(x) < 0x8000000000000000 => 0 |
| (drop (i64.lt_s |
| (local.get $y) |
| (i64.const 0x8000000000000000) |
| )) |
| |
| ;; i32(x) > 0x7fffffff => 0 |
| (drop (i32.gt_s |
| (local.get $x) |
| (i32.const 0x7fffffff) |
| )) |
| ;; i64(x) > 0x7fffffffffffffff => 0 |
| (drop (i64.gt_s |
| (local.get $y) |
| (i64.const 0x7fffffffffffffff) |
| )) |
| |
| ;; i32(x) < 0x7fffffff => x != 0x7fffffff |
| (drop (i32.lt_s |
| (local.get $x) |
| (i32.const 0x7fffffff) |
| )) |
| ;; i64(x) < 0x7fffffffffffffff => x != 0x7fffffffffffffff |
| (drop (i64.lt_s |
| (local.get $y) |
| (i64.const 0x7fffffffffffffff) |
| )) |
| |
| ;; i32(x) > 0x80000000 => x != 0x80000000 |
| (drop (i32.gt_s |
| (local.get $x) |
| (i32.const 0x80000000) |
| )) |
| ;; i64(x) > 0x8000000000000000 => x != 0x8000000000000000 |
| (drop (i64.gt_s |
| (local.get $y) |
| (i64.const 0x8000000000000000) |
| )) |
| |
| ;; i32(x) <= 0x80000000 => x == 0x80000000 |
| (drop (i32.le_s |
| (local.get $x) |
| (i32.const 0x80000000) |
| )) |
| ;; i64(x) <= 0x8000000000000000 => x == 0x8000000000000000 |
| (drop (i64.le_s |
| (local.get $y) |
| (i64.const 0x8000000000000000) |
| )) |
| |
| ;; i32(x) >= 0x7fffffff => x == 0x7fffffff |
| (drop (i32.ge_s |
| (local.get $x) |
| (i32.const 0x7fffffff) |
| )) |
| ;; i64(x) >= 0x7fffffffffffffff => x == 0x7fffffffffffffff |
| (drop (i64.ge_s |
| (local.get $y) |
| (i64.const 0x7fffffffffffffff) |
| )) |
| |
| ;; -x * 1 => x * -1 |
| (drop (f32.mul |
| (f32.neg |
| (local.get $fx) |
| ) |
| (f32.const 1) |
| )) |
| ;; -x * -2.1 => x * 2.1 |
| (drop (f64.mul |
| (f64.neg |
| (local.get $fy) |
| ) |
| (f64.const -2.1) |
| )) |
| ;; 2 * -x => x * -2 |
| (drop (f64.mul |
| (f64.const 2) |
| (f64.neg |
| (local.get $fy) |
| ) |
| )) |
| ;; -x / inf => x / -inf |
| (drop (f32.div |
| (f32.neg |
| (local.get $fx) |
| ) |
| (f32.const inf) |
| )) |
| ;; -x / -0.0 => x / 0.0 |
| (drop (f64.div |
| (f64.neg |
| (local.get $fy) |
| ) |
| (f64.const -0.0) |
| )) |
| ;; -x / nan => x / -nan |
| (drop (f64.div |
| (f64.neg |
| (local.get $fy) |
| ) |
| (f64.const nan) |
| )) |
| ;; 5.0 / -x => -5 / x |
| (drop (f64.div |
| (f64.const 5) |
| (f64.neg |
| (local.get $fy) |
| ) |
| )) |
| ) |
| ;; CHECK: (func $lhs-is-neg-one (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $lhs-is-neg-one (param $x i32) (param $y i64) |
| ;; -1 >> x ==> -1 |
| (drop (i32.shr_s |
| (i32.const -1) |
| (local.get $x) |
| )) |
| (drop (i64.shr_s |
| (i64.const -1) |
| (local.get $y) |
| )) |
| ;; rotl(-1, x) ==> -1 |
| (drop (i32.rotl |
| (i32.const -1) |
| (local.get $x) |
| )) |
| (drop (i64.rotl |
| (i64.const -1) |
| (local.get $y) |
| )) |
| ;; rotr(-1, x) ==> -1 |
| (drop (i32.rotr |
| (i32.const -1) |
| (local.get $x) |
| )) |
| (drop (i64.rotr |
| (i64.const -1) |
| (local.get $y) |
| )) |
| ;; skip |
| (drop (i32.shr_s |
| (i32.const -1) |
| (call $ne0) ;; side effect |
| )) |
| ;; skip |
| (drop (i32.shr_u |
| (i32.const -1) |
| (local.get $x) |
| )) |
| ) |
| ;; CHECK: (func $lhs-is-const (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const -2) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (i64.const -2) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.sub |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (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) |
| ) |
| )) |
| ) |
| ;; CHECK: (func $pre-combine-or (param $x i32) (param $y i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.gt_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.gt_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.gt_s |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $pre-combine-or (param $x i32) (param $y i32) |
| (drop (i32.or |
| (i32.gt_s |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.eq |
| (local.get $y) ;; ordering should not stop us |
| (local.get $x) |
| ) |
| )) |
| (drop (i32.or |
| (i32.eq ;; ordering should not stop us |
| (local.get $y) |
| (local.get $x) |
| ) |
| (i32.gt_s |
| (local.get $x) |
| (local.get $y) |
| ) |
| )) |
| (drop (i32.or |
| (i32.gt_s |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.eq |
| (local.get $x) |
| (i32.const 1) ;; not equal |
| ) |
| )) |
| (drop (i32.or |
| (i32.gt_s |
| (local.get $x) |
| (i32.const 1) ;; not equal |
| ) |
| (i32.eq |
| (local.get $x) |
| (local.get $y) |
| ) |
| )) |
| (drop (i32.or |
| (i32.gt_s |
| (call $ne0) ;; side effects |
| (local.get $y) |
| ) |
| (i32.eq |
| (call $ne0) |
| (local.get $y) |
| ) |
| )) |
| (drop (i32.or |
| (i32.gt_s |
| (local.get $y) |
| (call $ne0) ;; side effects |
| ) |
| (i32.eq |
| (local.get $y) |
| (call $ne0) |
| ) |
| )) |
| ) |
| ;; CHECK: (func $combine-or (param $x i32) (param $y i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $combine-or (param $x i32) (param $y i32) |
| (drop (i32.or |
| (i32.gt_s |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.eq |
| (local.get $x) |
| (local.get $y) |
| ) |
| )) |
| ;; TODO: more stuff here |
| ) |
| ;; CHECK: (func $select-into-arms (param $x i32) (param $y i32) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-into-arms (param $x i32) (param $y i32) |
| (if |
| (select |
| (i32.eqz (i32.eqz (local.get $x))) |
| (i32.eqz (i32.eqz (local.get $y))) |
| (local.get $y) |
| ) |
| (unreachable) |
| ) |
| ) |
| ;; CHECK: (func $select-with-same-arm-and-cond-32 (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-with-same-arm-and-cond-32 (param $x i32) |
| ;; i32(x) ? i32(x) : 0 ==> x |
| (drop (select |
| (local.get $x) |
| (i32.const 0) |
| (local.get $x) |
| )) |
| ;; i32(x) ? 0 : i32(x) ==> {x, 0} |
| (drop (select |
| (i32.const 0) |
| (local.get $x) |
| (local.get $x) |
| )) |
| ;; i32(x) == 0 ? i32(x) : 0 ==> {x, 0} |
| (drop (select |
| (local.get $x) |
| (i32.const 0) |
| (i32.eqz (local.get $x)) |
| )) |
| ) |
| |
| ;; CHECK: (func $select-with-same-arm-and-cond-64 (param $x i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (block (result i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-with-same-arm-and-cond-64 (param $x i64) |
| ;; i64(x) != 0 ? i64(x) : 0 ==> x |
| (drop (select |
| (local.get $x) |
| (i64.const 0) |
| (i64.ne |
| (local.get $x) |
| (i64.const 0) |
| ) |
| )) |
| ;; i64(x) == 0 ? 0 : i64(x) ==> x |
| (drop (select |
| (i64.const 0) |
| (local.get $x) |
| (i64.eqz |
| (local.get $x) |
| ) |
| )) |
| ;; i64(x) != 0 ? 0 : i64(x) ==> 0 |
| (drop (select |
| (i64.const 0) |
| (local.get $x) |
| (i64.ne |
| (local.get $x) |
| (i64.const 0) |
| ) |
| )) |
| ;; i64(x) == 0 ? i64(x) : 0 ==> {x, 0} |
| (drop (select |
| (local.get $x) |
| (i64.const 0) |
| (i64.eqz |
| (local.get $x) |
| ) |
| )) |
| (drop (select |
| (local.get $x) |
| (i64.const 0) |
| (i64.eq |
| (local.get $x) |
| (i64.const 0) |
| ) |
| )) |
| ) |
| |
| ;; CHECK: (func $select-with-same-arm-and-cond-skips (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.ne |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.ne |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-with-same-arm-and-cond-skips (param $x i32) (param $y i64) |
| ;; skip not equals |
| (drop (select |
| (local.get $x) |
| (i32.const 0) |
| (i32.wrap_i64 (local.get $y)) |
| )) |
| (drop (select |
| (i32.const 0) |
| (i32.sub (i32.const 0) (local.get $x)) |
| (local.get $x) |
| )) |
| |
| ;; skip not zero |
| (drop (select |
| (local.get $x) |
| (i32.const -1) |
| (local.get $x) |
| )) |
| (drop (select |
| (i32.const -1) |
| (local.get $x) |
| (local.get $x) |
| )) |
| (drop (select |
| (i64.const -1) |
| (local.get $y) |
| (i64.ne |
| (local.get $y) |
| (i64.const 0) |
| ) |
| )) |
| (drop (select |
| (i64.const 0) |
| (local.get $y) |
| (i64.ne |
| (local.get $y) |
| (i64.const 1) |
| ) |
| )) |
| ) |
| |
| ;; CHECK: (func $select-with-same-arm-and-cond-skips-side-effects (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.div_u |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (i32.div_u |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (call $select-sign-64-lt |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (call $select-sign-64-lt |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: (call $select-sign-64-lt |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (call $select-sign-64-lt |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-with-same-arm-and-cond-skips-side-effects (param $x i32) (param $y i64) |
| ;; skip with side effects |
| (drop (select |
| (i32.div_u (i32.const 10) (local.get $x)) |
| (i32.const 0) |
| (i32.div_u (i32.const 10) (local.get $x)) |
| )) |
| (drop (select |
| (i32.const 0) |
| (call $ne0) |
| (call $ne0) |
| )) |
| (drop (select |
| (call $select-sign-64-lt (local.get $y)) |
| (i64.const 0) |
| (i64.eqz |
| (call $select-sign-64-lt (local.get $y)) |
| ) |
| )) |
| (drop (select |
| (i64.const 0) |
| (call $select-sign-64-lt (local.get $y)) |
| (i64.eqz |
| (call $select-sign-64-lt (local.get $y)) |
| ) |
| )) |
| ) |
| ;; CHECK: (func $optimize-boolean-context (param $x i32) (param $y i32) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-boolean-context (param $x i32) (param $y i32) |
| ;; 0 - x ==> x |
| (if |
| (i32.sub |
| (i32.const 0) |
| (local.get $x) |
| ) |
| (unreachable) |
| ) |
| (drop (select |
| (local.get $x) |
| (local.get $y) |
| (i32.sub |
| (i32.const 0) |
| (local.get $x) |
| ) |
| )) |
| ) |
| |
| ;; CHECK: (func $optimize-combined-by-and-equals-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.or |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-combined-by-and-equals-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; (i32(x) == 0) & (i32(y) == 0) ==> i32(x | y) == 0 |
| (drop (i32.and |
| (i32.eq (local.get $x) (i32.const 0)) |
| (i32.eq (local.get $y) (i32.const 0)) |
| )) |
| ;; (i64(x) == 0) & (i64(y) == 0) ==> i64(x | y) == 0 |
| (drop (i32.and |
| (i64.eq (local.get $a) (i64.const 0)) |
| (i64.eq (local.get $b) (i64.const 0)) |
| )) |
| ) |
| ;; CHECK: (func $optimize-combined-by-or-noequal-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.ne |
| ;; CHECK-NEXT: (i64.or |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-combined-by-or-noequal-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; (i32(x) != 0) | (i32(y) != 0) ==> i32(x | y) != 0 |
| (drop (i32.or |
| (i32.ne (local.get $x) (i32.const 0)) |
| (i32.ne (local.get $y) (i32.const 0)) |
| )) |
| ;; (i64(x) != 0) | (i64(y) != 0) ==> i64(x | y) != 0 |
| (drop (i32.or |
| (i64.ne (local.get $a) (i64.const 0)) |
| (i64.ne (local.get $b) (i64.const 0)) |
| )) |
| ) |
| ;; CHECK: (func $optimize-combined-by-or-gt-or-eq-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.ge_s |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.ge_s |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-combined-by-or-gt-or-eq-to-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; (i32(x) >= 0) | (i32(y) >= 0) ==> i32(x & y) >= 0 |
| (drop (i32.or |
| (i32.ge_s (local.get $x) (i32.const 0)) |
| (i32.ge_s (local.get $y) (i32.const 0)) |
| )) |
| ;; (i64(x) >= 0) | (i64(y) >= 0) ==> i64(x & y) >= 0 |
| (drop (i32.or |
| (i64.ge_s (local.get $a) (i64.const 0)) |
| (i64.ge_s (local.get $b) (i64.const 0)) |
| )) |
| |
| ;; skips |
| ;; (i32(x) >= 0) | (i64(y) >= 0) ==> skip |
| (drop (i32.or |
| (i32.ge_s (local.get $x) (i32.const 0)) |
| (i64.ge_s (local.get $a) (i64.const 0)) |
| )) |
| ) |
| ;; CHECK: (func $optimize-combined-by-or-ne-to-minus-one (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.ne |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.ne |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-combined-by-or-ne-to-minus-one (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; (i32(x) != -1) | (i32(y) != -1) ==> i32(x & y) != -1 |
| (drop (i32.or |
| (i32.ne (local.get $x) (i32.const -1)) |
| (i32.ne (local.get $y) (i32.const -1)) |
| )) |
| ;; (i64(x) != -1) | (i64(y) == -1) ==> i64(x & y) != -1 |
| (drop (i32.or |
| (i64.ne (local.get $a) (i64.const -1)) |
| (i64.ne (local.get $b) (i64.const -1)) |
| )) |
| |
| ;; skips |
| ;; (i32(x) != -1) | (i64(y) != -1) ==> skip |
| (drop (i32.or |
| (i32.ne (local.get $x) (i32.const -1)) |
| (i64.ne (local.get $a) (i64.const -1)) |
| )) |
| ) |
| ;; CHECK: (func $optimize-combined-by-or-lessthan-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.lt_s |
| ;; CHECK-NEXT: (i64.or |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.lt_s |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.le_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.le_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-combined-by-or-lessthan-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; (i32(x) < 0) | (i32(y) < 0) ==> i32(x | y) < 0 |
| (drop (i32.or |
| (i32.lt_s (local.get $x) (i32.const 0)) |
| (i32.lt_s (local.get $y) (i32.const 0)) |
| )) |
| ;; (i64(x) < 0) | (i64(y) < 0) ==> i64(x | y) < 0 |
| (drop (i32.or |
| (i64.lt_s (local.get $a) (i64.const 0)) |
| (i64.lt_s (local.get $b) (i64.const 0)) |
| )) |
| |
| ;; skips |
| ;; (i32(x) < 0) | (i64(a) < 0) ==> skip |
| (drop (i32.or |
| (i32.lt_s (local.get $x) (i32.const 0)) |
| (i64.lt_s (local.get $a) (i64.const 0)) |
| )) |
| ;; (i32(x) <= 0) | (i32(y) < 0) ==> skip |
| (drop (i32.or |
| (i32.le_s (local.get $x) (i32.const 0)) |
| (i32.lt_s (local.get $y) (i32.const 0)) |
| )) |
| ;; (i32(x) < 1) | (i32(y) < 0) ==> skip |
| (drop (i32.or |
| (i32.lt_s (local.get $x) (i32.const 1)) |
| (i32.lt_s (local.get $y) (i32.const 0)) |
| )) |
| ) |
| ;; CHECK: (func $optimize-combined-by-and-lessthan-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.lt_s |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-combined-by-and-lessthan-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; (i32(x) < 0) & (i32(y) < 0) ==> i32(x & y) < 0 |
| (drop (i32.and |
| (i32.lt_s (local.get $x) (i32.const 0)) |
| (i32.lt_s (local.get $y) (i32.const 0)) |
| )) |
| ;; (i64(x) < 0) & (i64(y) < 0) ==> i64(x & y) < 0 |
| (drop (i32.and |
| (i64.lt_s (local.get $a) (i64.const 0)) |
| (i64.lt_s (local.get $b) (i64.const 0)) |
| )) |
| ) |
| ;; CHECK: (func $optimize-combined-by-and-greatequal-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.ge_s |
| ;; CHECK-NEXT: (i64.or |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.ge_s |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-combined-by-and-greatequal-zero (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; (i32(x) >= 0) & (i32(y) >= 0) ==> i32(x | y) >= 0 |
| (drop (i32.and |
| (i32.ge_s (local.get $x) (i32.const 0)) |
| (i32.ge_s (local.get $y) (i32.const 0)) |
| )) |
| ;; (i64(x) >= 0) & (i64(y) >= 0) ==> i64(x | y) >= 0 |
| (drop (i32.and |
| (i64.ge_s (local.get $a) (i64.const 0)) |
| (i64.ge_s (local.get $b) (i64.const 0)) |
| )) |
| |
| ;; skips |
| ;; (i32(x) >= 0) & (i64(y) >= 0) ==> skip |
| (drop (i32.and |
| (i32.ge_s (local.get $x) (i32.const 0)) |
| (i64.ge_s (local.get $a) (i64.const 0)) |
| )) |
| ) |
| ;; CHECK: (func $optimize-combined-by-and-equal-neg-one (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-combined-by-and-equal-neg-one (param $x i32) (param $y i32) (param $a i64) (param $b i64) |
| ;; (i32(x) == -1) & (i32(y) == -1) ==> i32(x & y) == -1 |
| (drop (i32.and |
| (i32.eq (local.get $x) (i32.const -1)) |
| (i32.eq (local.get $y) (i32.const -1)) |
| )) |
| ;; (i64(x) == -1) & (i64(y) == -1) ==> i64(x & y) == -1 |
| (drop (i32.and |
| (i64.eq (local.get $a) (i64.const -1)) |
| (i64.eq (local.get $b) (i64.const -1)) |
| )) |
| |
| ;; skips |
| ;; (i32(x) == -1) & (i64(y) == -1) ==> skip |
| (drop (i32.and |
| (i32.eq (local.get $x) (i32.const -1)) |
| (i64.eq (local.get $a) (i64.const -1)) |
| )) |
| ) |
| ;; CHECK: (func $optimize-relationals (param $x i32) (param $y i32) (param $X i64) (param $Y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (local.get $X) |
| ;; CHECK-NEXT: (local.get $Y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (local.get $X) |
| ;; CHECK-NEXT: (local.get $Y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.ne |
| ;; CHECK-NEXT: (local.get $X) |
| ;; CHECK-NEXT: (local.get $Y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.gt_s |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.le_s |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.gt_s |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.gt_s |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-relationals (param $x i32) (param $y i32) (param $X i64) (param $Y i64) |
| ;; eqz(x + 0x7FFFFFFF) -> x == -2147483647 |
| (drop (i32.eqz |
| (i32.add |
| (local.get $x) |
| (i32.const 0x7FFFFFFF) |
| ) |
| )) |
| ;; eqz(x + 0x80000000) -> x == -2147483648 |
| (drop (i32.eqz |
| (i32.add |
| (local.get $x) |
| (i32.const 0x80000000) |
| ) |
| )) |
| ;; eqz(x + 0x80000001) -> x == 2147483647 |
| (drop (i32.eqz |
| (i32.add |
| (local.get $x) |
| (i32.const 0x80000001) |
| ) |
| )) |
| ;; eqz(x - y) |
| (drop (i32.eqz |
| (i32.sub |
| (local.get $x) |
| (local.get $y) |
| ) |
| )) |
| (drop (i64.eqz |
| (i64.sub |
| (local.get $X) |
| (local.get $Y) |
| ) |
| )) |
| ;; x - y == 0 |
| (drop (i32.eq |
| (i32.sub |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.const 0) |
| )) |
| (drop (i64.eq |
| (i64.sub |
| (local.get $X) |
| (local.get $Y) |
| ) |
| (i64.const 0) |
| )) |
| ;; x - y != 0 |
| (drop (i32.ne |
| (i32.sub |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.const 0) |
| )) |
| (drop (i64.ne |
| (i64.sub |
| (local.get $X) |
| (local.get $Y) |
| ) |
| (i64.const 0) |
| )) |
| ;; i32(x - y) > 0 -> x > y |
| (drop (i32.gt_s |
| (i32.sub |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.const 0) |
| )) |
| ;; i32(x - y) >= 0 -> x >= y |
| (drop (i32.ge_s |
| (i32.sub |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.const 0) |
| )) |
| ;; u32(x - y) > 0 -> x != y |
| (drop (i32.gt_u |
| (i32.sub |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.const 0) |
| )) |
| ;; u32(x - y) >= 0 -> 1 |
| (drop (i32.ge_u |
| (i32.sub |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.const 0) |
| )) |
| ;; u64(x - y) >= 0 -> i32(1) |
| (drop (i64.ge_u |
| (i64.sub |
| (local.get $X) |
| (local.get $Y) |
| ) |
| (i64.const 0) |
| )) |
| ;; i32(x - y) < 0 -> x < y |
| (drop (i32.lt_s |
| (i32.sub |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.const 0) |
| )) |
| ;; i32(x - y) <= 0 -> x <= y |
| (drop (i32.le_s |
| (i32.sub |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.const 0) |
| )) |
| ;; u32(x - y) < 0 -> 0 |
| (drop (i32.lt_u |
| (i32.sub |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.const 0) |
| )) |
| ;; u64(x - y) < 0 -> i32(0) |
| (drop (i64.lt_u |
| (i64.sub |
| (local.get $X) |
| (local.get $Y) |
| ) |
| (i64.const 0) |
| )) |
| ;; u32(x - y) <= 0 -> x == y |
| (drop (i32.le_u |
| (i32.sub |
| (local.get $x) |
| (local.get $y) |
| ) |
| (i32.const 0) |
| )) |
| ;; i32(x - 0x80000000) == 0 -> x == 0x80000000 |
| (drop (i32.eq |
| (i32.sub |
| (local.get $x) |
| (i32.const 0x80000000) |
| ) |
| (i32.const 0) |
| )) |
| ;; i32(x - 0x80000000) != 0 -> x == 0x80000000 |
| (drop (i32.ne |
| (i32.sub |
| (local.get $x) |
| (i32.const 0x80000000) |
| ) |
| (i32.const 0) |
| )) |
| ;; i32(x - { 0x80000000 }) < 0 -> skip |
| (drop (i32.lt_s |
| (i32.sub |
| (local.get $x) |
| (i32.const 0x80000000) |
| ) |
| (i32.const 0) |
| )) |
| ;; i32(x - { 0x80000000 }) >= 0 -> skip |
| (drop (i32.ge_s |
| (i32.sub |
| (local.get $x) |
| (i32.const 0x80000000) |
| ) |
| (i32.const 0) |
| )) |
| ;; i32(x - { 0x80000000 }) > 0 -> skip |
| (drop (i32.gt_s |
| (i32.sub |
| (local.get $x) |
| (block (result i32) |
| (i32.const 0x80000000) |
| ) |
| ) |
| (i32.const 0) |
| )) |
| ;; i32(x - { 0x80000000 }) <= 0 -> skip |
| (drop (i32.gt_s |
| (i32.sub |
| (local.get $x) |
| (block (result i32) |
| (i32.const 0x80000000) |
| ) |
| ) |
| (i32.const 0) |
| )) |
| ) |
| ;; CHECK: (func $unsigned-context (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.div_u |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.div_s |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.shr_u |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 9223372036854775807) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.div_s |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 9223372036854775807) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.rem_u |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 7) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_u |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 7) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -7) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $unsigned-context (param $x i32) (param $y i64) |
| (drop (i32.div_s |
| (i32.and |
| (local.get $x) |
| (i32.const 0x7fffffff) |
| ) |
| (i32.const 3) |
| )) |
| (drop (i32.div_s |
| (i32.and |
| (local.get $x) |
| (i32.const 0x7fffffff) |
| ) |
| (i32.const -3) ;; skip |
| )) |
| (drop (i32.div_s |
| (i32.and |
| (local.get $x) |
| (i32.const 0x7fffffff) |
| ) |
| (i32.const 0x80000000) ;; skip |
| )) |
| (drop (i64.div_s |
| (i64.and |
| (local.get $y) |
| (i64.const 0x7fffffffffffffff) |
| ) |
| (i64.const 2) |
| )) |
| (drop (i64.div_s |
| (i64.and |
| (local.get $y) |
| (i64.const 0x7fffffffffffffff) |
| ) |
| (i64.const -1) ;; skip |
| )) |
| (drop (i32.rem_s |
| (i32.and |
| (local.get $x) |
| (i32.const 0x7fffffff) |
| ) |
| (i32.const 3) |
| )) |
| (drop (i32.shr_s |
| (i32.and |
| (local.get $x) |
| (i32.const 0x7fffffff) |
| ) |
| (i32.const 7) |
| )) |
| (drop (i32.ge_s |
| (i32.and |
| (local.get $x) |
| (i32.const 0x7fffffff) |
| ) |
| (i32.const 7) |
| )) |
| (drop (i32.ge_s |
| (i32.and |
| (local.get $x) |
| (i32.const 0x7fffffff) |
| ) |
| (i32.const -7) ;; skip |
| )) |
| ) |
| ;; CHECK: (func $optimize-float-mul-by-two (param $0 f64) (param $1 f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (call $tee-with-unreachable-value) |
| ;; CHECK-NEXT: (f64.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (f64.const -2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-float-mul-by-two (param $0 f64) (param $1 f32) |
| (drop (f64.mul |
| (local.get $0) |
| (f64.const 2) |
| )) |
| (drop (f32.mul |
| (local.get $1) |
| (f32.const 2) |
| )) |
| |
| (drop (f64.mul |
| (call $tee-with-unreachable-value) ;; side effect |
| (f64.const 2) |
| )) |
| (drop (f64.mul |
| (f64.neg (local.get $0)) ;; complex expression |
| (f64.const 2) |
| )) |
| ) |
| ;; CHECK: (func $duplicate-elimination (param $x i32) (param $y i32) (param $z i32) (param $w f64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.abs |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.ceil |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.floor |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.trunc |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.nearest |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.nearest |
| ;; CHECK-NEXT: (f64.trunc |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.trunc |
| ;; CHECK-NEXT: (f64.nearest |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.neg |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.rem_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.rem_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.rem_s |
| ;; CHECK-NEXT: (i32.rem_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.rem_u |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.rem_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.xor |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.xor |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.xor |
| ;; CHECK-NEXT: (i32.xor |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $duplicate-elimination (param $x i32) (param $y i32) (param $z i32) (param $w f64) |
| ;; unary |
| (drop (f64.abs (f64.abs (local.get $w)))) |
| (drop (f64.ceil (f64.ceil (local.get $w)))) |
| (drop (f64.floor (f64.floor (local.get $w)))) |
| (drop (f64.trunc (f64.trunc (local.get $w)))) |
| (drop (f64.nearest (f64.nearest (local.get $w)))) |
| |
| (drop (f64.nearest (f64.trunc (local.get $w)))) ;; skip |
| (drop (f64.trunc (f64.nearest (local.get $w)))) ;; skip |
| |
| (drop (f64.neg (f64.neg (local.get $w)))) |
| (drop (f64.neg (f64.neg (f64.neg (local.get $w))))) |
| (drop (f64.neg (f64.neg (f64.neg (f64.neg (local.get $w)))))) |
| |
| (drop (i32.eqz (i32.eqz (local.get $x)))) ;; skip |
| (drop (i32.eqz (i32.eqz (i32.eqz (local.get $x))))) |
| (drop (i32.eqz (i32.eqz (i64.eqz (i64.const 1))))) |
| (drop (i32.eqz (i32.eqz (i32.ne (local.get $x) (i32.const 2))))) |
| |
| (drop (i32.eqz |
| (i32.eqz |
| (i32.and |
| (local.get $x) |
| (i32.const 1) |
| ) |
| ) |
| )) |
| |
| ;; binary |
| ;; ((signed)x % y) % y |
| (drop (i32.rem_s |
| (i32.rem_s |
| (local.get $x) |
| (local.get $y) |
| ) |
| (local.get $y) |
| )) |
| ;; ((unsigned)x % y) % y |
| (drop (i32.rem_u |
| (i32.rem_u |
| (local.get $x) |
| (local.get $y) |
| ) |
| (local.get $y) |
| )) |
| ;; 0 - (0 - y) |
| (drop (i32.sub |
| (i32.const 0) |
| (i32.sub |
| (i32.const 0) |
| (local.get $y) |
| ) |
| )) |
| ;; x - (x - y) |
| (drop (i32.sub |
| (local.get $x) |
| (i32.sub |
| (local.get $x) |
| (local.get $y) |
| ) |
| )) |
| ;; y - (x - y) - skip |
| (drop (i32.sub |
| (local.get $y) |
| (i32.sub |
| (local.get $x) |
| (local.get $y) |
| ) |
| )) |
| ;; x ^ (x ^ y) |
| (drop (i32.xor |
| (local.get $x) |
| (i32.xor |
| (local.get $x) |
| (local.get $y) |
| ) |
| )) |
| ;; x ^ (y ^ x) |
| (drop (i32.xor |
| (local.get $x) |
| (i32.xor |
| (local.get $y) |
| (local.get $x) |
| ) |
| )) |
| ;; (x ^ y) ^ x |
| (drop (i32.xor |
| (i32.xor |
| (local.get $x) |
| (local.get $y) |
| ) |
| (local.get $x) |
| )) |
| ;; (y ^ x) ^ x |
| (drop (i32.xor |
| (i32.xor |
| (local.get $y) |
| (local.get $x) |
| ) |
| (local.get $x) |
| )) |
| ;; x ^ (x ^ x) |
| (drop (i32.xor |
| (local.get $x) |
| (i32.xor |
| (local.get $x) |
| (local.get $x) |
| ) |
| )) |
| ;; x & (x & y) |
| (drop (i32.and |
| (local.get $x) |
| (i32.and |
| (local.get $x) |
| (local.get $y) |
| ) |
| )) |
| ;; x & (y & x) |
| (drop (i32.and |
| (local.get $x) |
| (i32.and |
| (local.get $y) |
| (local.get $x) |
| ) |
| )) |
| ;; (x & y) & x |
| (drop (i32.and |
| (i32.and |
| (local.get $x) |
| (local.get $y) |
| ) |
| (local.get $x) |
| )) |
| ;; (y & x) & x |
| (drop (i32.and |
| (i32.and |
| (local.get $y) |
| (local.get $x) |
| ) |
| (local.get $x) |
| )) |
| ;; x | (x | y) |
| (drop (i32.or |
| (local.get $x) |
| (i32.or |
| (local.get $x) |
| (local.get $y) |
| ) |
| )) |
| ;; x | (y | x) |
| (drop (i32.or |
| (local.get $x) |
| (i32.or |
| (local.get $y) |
| (local.get $x) |
| ) |
| )) |
| ;; (x | y) | x |
| (drop (i32.or |
| (i32.or |
| (local.get $x) |
| (local.get $y) |
| ) |
| (local.get $x) |
| )) |
| ;; (y | x) | x |
| (drop (i32.or |
| (i32.or |
| (local.get $y) |
| (local.get $x) |
| ) |
| (local.get $x) |
| )) |
| ;; (y | x) | z - skip |
| (drop (i32.or |
| (i32.or |
| (local.get $y) |
| (local.get $x) |
| ) |
| (local.get $z) |
| )) |
| ;; (z | x) | y - skip |
| (drop (i32.or |
| (i32.or |
| (local.get $z) |
| (local.get $x) |
| ) |
| (local.get $y) |
| )) |
| ;; (SE() | x) | x |
| (drop (i32.or |
| (i32.or |
| (call $ne0) ;; side effect |
| (local.get $x) |
| ) |
| (local.get $x) |
| )) |
| ;; (x | SE()) | SE() - skip |
| (drop (i32.or |
| (i32.or |
| (local.get $x) |
| (call $ne0) ;; side effect |
| ) |
| (call $ne0) ;; side effect |
| )) |
| ;; x | (SE() | x) |
| (drop (i32.or |
| (local.get $x) |
| (i32.or |
| (local.get $x) |
| (call $ne0) ;; side effect |
| ) |
| )) |
| ;; SE() | (x | SE()) - skip |
| (drop (i32.or |
| (call $ne0) ;; side effect |
| (i32.or |
| (call $ne0) ;; side effect |
| (local.get $x) |
| ) |
| )) |
| ;; (y % x) % y - skip |
| (drop (i32.rem_s |
| (i32.rem_s |
| (local.get $y) |
| (local.get $x) |
| ) |
| (local.get $y) |
| )) |
| ;; y % (x % y) - skip |
| (drop (i32.rem_u |
| (local.get $y) |
| (i32.rem_u |
| (local.get $x) |
| (local.get $y) |
| ) |
| )) |
| ;; x | (y | x) where x and y cannot be reordered - skip |
| (drop |
| (i32.or |
| (local.get $x) |
| (i32.or |
| (local.tee $x |
| (i32.const 1) |
| ) |
| (local.get $x) |
| ) |
| ) |
| ) |
| (drop |
| (i32.or |
| (i32.or |
| (local.get $x) |
| (local.tee $x |
| (i32.const 1) |
| ) |
| ) |
| (local.get $x) |
| ) |
| ) |
| ;; x ^ (y ^ x) where x and y cannot be reordered - skip |
| (drop |
| (i32.xor |
| (local.get $x) |
| (i32.xor |
| (local.tee $x |
| (i32.const 1) |
| ) |
| (local.get $x) |
| ) |
| ) |
| ) |
| (drop |
| (i32.xor |
| (i32.xor |
| (local.get $x) |
| (local.tee $x |
| (i32.const 1) |
| ) |
| ) |
| (local.get $x) |
| ) |
| ) |
| ) |
| |
| ;; i32.wrap_i64(i64.extend_i32_s(x)) ==> x |
| ;; i32.wrap_i64(i64.extend_i32_u(x)) ==> x |
| |
| ;; CHECK: (func $sign-and-zero-extention-elimination-1 (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sign-and-zero-extention-elimination-1 (param $x i32) |
| (drop (i32.wrap_i64 (i64.extend_i32_s (local.get $x)))) |
| (drop (i32.wrap_i64 (i64.extend_i32_u (local.get $x)))) |
| ) |
| ;; i64.extend_i32_u(i32.wrap_i64(x)) => x, where maxBits(x) <= 32 |
| ;; i64.extend_i32_s(i32.wrap_i64(x)) => x, where maxBits(x) <= 31 |
| |
| ;; CHECK: (func $sign-and-zero-extention-elimination-2 (param $x i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 4294967295) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_s |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_s |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 4294967295) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $sign-and-zero-extention-elimination-2 (param $x i64) |
| (drop (i64.extend_i32_u (i32.wrap_i64 (i64.and (local.get $x) (i64.const 0x00000000FFFFFFFF))))) |
| (drop (i64.extend_i32_s (i32.wrap_i64 (i64.and (local.get $x) (i64.const 0x000000007FFFFFFF))))) |
| |
| (drop (i64.extend_i32_u (i32.wrap_i64 (local.get $x)))) ;; skip |
| (drop (i64.extend_i32_s (i32.wrap_i64 (local.get $x)))) ;; skip |
| (drop (i64.extend_i32_s (i32.wrap_i64 (i64.and (local.get $x) (i64.const 0x00000000FFFFFFFF))))) ;; skip |
| ) |
| ;; CHECK: (func $optimize-shifts (param $x i32) (param $y i32) (param $z i64) (param $w i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.shl |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.shl |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.shr_s |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.shr_u |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.shl |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: (i64.const 32) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.shr_u |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: (i64.const 31) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-shifts (param $x i32) (param $y i32) (param $z i64) (param $w i64) |
| ;; i32 |
| (drop (i32.shl |
| (local.get $x) |
| (i32.const 32) |
| )) |
| (drop (i32.shr_s |
| (local.get $x) |
| (i32.const 32) |
| )) |
| (drop (i32.shr_u |
| (local.get $x) |
| (i32.const 64) |
| )) |
| (drop (i32.rotl |
| (local.get $x) |
| (i32.const 64) |
| )) |
| (drop (i32.rotr |
| (local.get $x) |
| (i32.const 64) |
| )) |
| ;; i64 |
| (drop (i64.shl |
| (local.get $z) |
| (i64.const 64) |
| )) |
| (drop (i64.shr_s |
| (local.get $z) |
| (i64.const 64) |
| )) |
| (drop (i64.shr_u |
| (local.get $z) |
| (i64.const 128) |
| )) |
| (drop (i64.rotl |
| (local.get $z) |
| (i64.const 128) |
| )) |
| (drop (i64.rotr |
| (local.get $z) |
| (i64.const 128) |
| )) |
| |
| ;; i32 |
| (drop (i32.shl |
| (local.get $x) |
| (i32.and |
| (local.get $y) |
| (i32.const 31) |
| ) |
| )) |
| (drop (i32.shl |
| (local.get $x) |
| (i32.and |
| (local.get $y) |
| (i32.const 63) |
| ) |
| )) |
| (drop (i32.shr_s |
| (local.get $x) |
| (i32.and |
| (local.get $y) |
| (i32.const 31) |
| ) |
| )) |
| (drop (i32.shr_u |
| (local.get $x) |
| (i32.and |
| (local.get $y) |
| (i32.const 31) |
| ) |
| )) |
| ;; i64 |
| (drop (i64.shl |
| (local.get $z) |
| (i64.and |
| (local.get $w) |
| (i64.const 63) |
| ) |
| )) |
| (drop (i64.shl |
| (local.get $z) |
| (i64.and |
| (local.get $w) |
| (i64.const 127) |
| ) |
| )) |
| (drop (i64.shr_s |
| (local.get $z) |
| (i64.and |
| (local.get $w) |
| (i64.const 63) |
| ) |
| )) |
| (drop (i64.shr_u |
| (local.get $z) |
| (i64.and |
| (local.get $w) |
| (i64.const 63) |
| ) |
| )) |
| ;; i32(x) >> (y & 32) -> x |
| (drop (i32.shr_u |
| (local.get $x) |
| (i32.and |
| (local.get $y) |
| (i32.const 32) |
| ) |
| )) |
| ;; i64(x) >> (y & 64) -> x |
| (drop (i64.shr_u |
| (local.get $z) |
| (i64.and |
| (local.get $w) |
| (i64.const 128) |
| ) |
| )) |
| |
| ;; skip |
| (drop (i64.shl |
| (local.get $z) |
| (i64.and |
| (local.get $w) |
| (i64.const 32) |
| ) |
| )) |
| ;; skip |
| (drop (i64.shr_u |
| (local.get $z) |
| (i64.and |
| (local.get $w) |
| (i64.const 31) |
| ) |
| )) |
| ) |
| ;; CHECK: (func $optimize-float-points (param $x0 f64) (param $x1 f64) (param $y0 f32) (param $y1 f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.abs |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.abs |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $y1) |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.abs |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (f64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.abs |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.abs |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.abs |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.abs |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.abs |
| ;; CHECK-NEXT: (f64.sub |
| ;; CHECK-NEXT: (f64.const 0) |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.abs |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.div |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.abs |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.abs |
| ;; CHECK-NEXT: (f32.div |
| ;; CHECK-NEXT: (local.get $y1) |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.div |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.abs |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (f64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.abs |
| ;; CHECK-NEXT: (f32.div |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: (local.get $y0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.abs |
| ;; CHECK-NEXT: (f64.div |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: (local.get $x0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-float-points (param $x0 f64) (param $x1 f64) (param $y0 f32) (param $y1 f32) |
| ;; abs(x) * abs(x) ==> x * x |
| (drop (f64.mul |
| (f64.abs (local.get $x0)) |
| (f64.abs (local.get $x0)) |
| )) |
| (drop (f32.mul |
| (f32.abs (local.get $y0)) |
| (f32.abs (local.get $y0)) |
| )) |
| (drop (f64.mul |
| (f64.abs (f64.add (local.get $x0) (local.get $x1))) |
| (f64.abs (f64.add (local.get $x0) (local.get $x1))) |
| )) |
| |
| ;; abs(x) * abs(y) ==> abs(x * y) |
| (drop (f64.mul |
| (f64.abs (local.get $x0)) |
| (f64.abs (local.get $x1)) |
| )) |
| (drop (f32.mul |
| (f32.abs (local.get $y1)) |
| (f32.abs (local.get $y0)) |
| )) |
| |
| (drop (f64.mul |
| (f64.abs (local.get $x0)) |
| (f64.abs (f64.const 0)) ;; skip |
| )) |
| (drop (f32.mul |
| (f32.abs (f32.const 0)) ;; skip |
| (f32.abs (local.get $y0)) |
| )) |
| (drop (f64.mul |
| (f64.abs (f64.add (local.get $x0) (local.get $x1))) |
| (f64.abs (f64.add (local.get $x0) (local.get $x0))) |
| )) |
| |
| |
| ;; abs(-x) ==> abs(x) |
| (drop (f64.abs |
| (f64.neg (local.get $x0)) |
| )) |
| (drop (f32.abs |
| (f32.neg (local.get $y0)) |
| )) |
| |
| ;; abs(0 - x) ==> skip for non-fast math |
| (drop (f64.abs |
| (f64.sub |
| (f64.const 0) |
| (local.get $x0) |
| ) |
| )) |
| (drop (f32.abs |
| (f32.sub |
| (f32.const 0) |
| (local.get $y0) |
| ) |
| )) |
| |
| ;; abs(x) / abs(x) ==> x / x |
| (drop (f64.div |
| (f64.abs (local.get $x0)) |
| (f64.abs (local.get $x0)) |
| )) |
| (drop (f32.div |
| (f32.abs (local.get $y0)) |
| (f32.abs (local.get $y0)) |
| )) |
| (drop (f64.div |
| (f64.abs (f64.add (local.get $x0) (local.get $x1))) |
| (f64.abs (f64.add (local.get $x0) (local.get $x1))) |
| )) |
| |
| ;; abs(x) / abs(y) ==> abs(x / y) |
| (drop (f64.div |
| (f64.abs (local.get $x0)) |
| (f64.abs (local.get $x1)) |
| )) |
| (drop (f32.div |
| (f32.abs (local.get $y1)) |
| (f32.abs (local.get $y0)) |
| )) |
| |
| ;; abs(x * x) ==> x * x |
| (drop (f64.abs |
| (f64.mul |
| (local.get $x0) |
| (local.get $x0) |
| ) |
| )) |
| (drop (f32.abs |
| (f32.mul |
| (local.get $y0) |
| (local.get $y0) |
| ) |
| )) |
| |
| ;; abs(x / x) ==> x / x |
| (drop (f64.abs |
| (f64.div |
| (local.get $x0) |
| (local.get $x0) |
| ) |
| )) |
| (drop (f32.abs |
| (f32.div |
| (local.get $y0) |
| (local.get $y0) |
| ) |
| )) |
| |
| (drop (f64.div |
| (f64.abs (local.get $x0)) |
| (f64.abs (f64.const 0)) ;; skip |
| )) |
| (drop (f32.div |
| (f32.abs (f32.const 0)) ;; skip |
| (f32.abs (local.get $y0)) |
| )) |
| (drop (f64.div |
| (f64.abs (f64.add (local.get $x0) (local.get $x1))) |
| (f64.abs (f64.add (local.get $x0) (local.get $x0))) |
| )) |
| ) |
| ;; CHECK: (func $ternary (param $x i32) (param $y i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary (param $x i32) (param $y i32) |
| (drop |
| (select |
| (i32.const 0) |
| (i32.eqz |
| (local.get $y) |
| ) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (select |
| (i32.const 1) |
| (i32.eqz |
| (local.get $y) |
| ) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (select |
| (i32.eqz |
| (local.get $y) |
| ) |
| (i32.const 0) |
| (local.get $x) |
| ) |
| ) |
| (drop |
| (select |
| (i32.eqz |
| (local.get $y) |
| ) |
| (i32.const 1) |
| (local.get $x) |
| ) |
| ) |
| ;; if works too |
| (drop |
| (if (result i32) |
| (local.get $x) |
| (i32.eqz |
| (local.get $y) |
| ) |
| (i32.const 1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-i64-0 (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (if (result i64) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-i64-0 (param $x i32) (param $y i64) |
| (drop |
| (if (result i32) |
| (local.get $x) |
| (i32.const 0) |
| (i64.eqz |
| (local.get $y) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-i64-1 (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (if (result i64) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-i64-1 (param $x i32) (param $y i64) |
| (drop |
| (if (result i32) |
| (local.get $x) |
| (i64.eqz |
| (local.get $y) |
| ) |
| (i32.const 1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-no (param $x i32) (param $y i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-no (param $x i32) (param $y i32) |
| (drop |
| (select |
| (i32.const 2) ;; only 0 and 1 work |
| (i32.eqz |
| (local.get $y) |
| ) |
| (local.get $x) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-no-unreachable-1 (param $x i32) (result i32) |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-no-unreachable-1 (param $x i32) (result i32) |
| (if (result i32) |
| (local.get $x) |
| ;; one arm is an eqz, the other is 0 or 1, so we can put an eqz on the |
| ;; outside in theory, but we'd need to be careful with the unreachable |
| ;; type here. ignore this case, as DCE is the proper optimization anyhow. |
| (i32.eqz |
| (unreachable) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| ;; CHECK: (func $ternary-no-unreachable-2 (param $x i32) (result i32) |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-no-unreachable-2 (param $x i32) (result i32) |
| (if (result i32) |
| (local.get $x) |
| ;; as before, but flipped |
| (i32.const 0) |
| (i32.eqz |
| (unreachable) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-identical-arms (param $x i32) (param $y i32) (param $z i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms (param $x i32) (param $y i32) (param $z i32) |
| (drop |
| (select |
| (i32.eqz (local.get $x)) |
| (i32.eqz (local.get $y)) |
| (local.get $z) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-identical-arms-if (param $x i32) (param $y i32) (param $z i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-if (param $x i32) (param $y i32) (param $z i32) |
| (drop |
| (if (result i32) |
| (local.get $z) |
| (i32.eqz (local.get $x)) |
| (i32.eqz (local.get $y)) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-identical-arms-type-change (param $x f64) (param $y f64) (param $z i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.demote_f64 |
| ;; CHECK-NEXT: (f64.floor |
| ;; CHECK-NEXT: (if (result f64) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-type-change (param $x f64) (param $y f64) (param $z i32) |
| (drop |
| ;; the if's type begins as f32, but after moving code out it will be |
| ;; f64 |
| (if (result f32) |
| (local.get $z) |
| (f32.demote_f64 (f64.floor (local.get $x))) |
| (f32.demote_f64 (f64.floor (local.get $y))) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-identical-arms-more (param $x f32) (param $y f32) (param $z i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.floor |
| ;; CHECK-NEXT: (f32.neg |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-more (param $x f32) (param $y f32) (param $z i32) |
| (drop |
| (select |
| (f32.floor (f32.neg (local.get $x))) |
| (f32.floor (f32.neg (local.get $y))) |
| (local.get $z) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-identical-arms-morer (param $x f32) (param $y f32) (param $z i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.abs |
| ;; CHECK-NEXT: (f32.floor |
| ;; CHECK-NEXT: (f32.neg |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-morer (param $x f32) (param $y f32) (param $z i32) |
| (drop |
| (select |
| (f32.abs (f32.floor (f32.neg (local.get $x)))) |
| (f32.abs (f32.floor (f32.neg (local.get $y)))) |
| (local.get $z) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-identical-arms-and-type-is-none (param $x i32) (param $y i32) (param $z i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-and-type-is-none (param $x i32) (param $y i32) (param $z i32) |
| (if |
| (local.get $z) |
| (drop (i32.eqz (local.get $x))) |
| (drop (i32.eqz (local.get $y))) |
| ) |
| ) |
| ;; CHECK: (func $ternary-identical-arms-and-type-is-none-child-types-mismatch (param $x i32) (param $y i32) (param $z i32) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.const 2.34) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-and-type-is-none-child-types-mismatch (param $x i32) (param $y i32) (param $z i32) |
| (if |
| (local.get $z) |
| ;; the drop cannot be hoisted out, since the children's type mismatch |
| ;; would not allow us to give a proper type to the if. |
| (drop (i32.const 1)) |
| (drop (f64.const 2.34)) |
| ) |
| ) |
| ;; CHECK: (func $ternary-identical-arms-but-block (param $x i32) (param $y i32) (param $z i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-but-block (param $x i32) (param $y i32) (param $z i32) |
| (drop |
| (select |
| ;; identical arms, but they are control flow structures |
| (block (result i32) |
| (i32.eqz (local.get $x)) |
| ) |
| (block (result i32) |
| (i32.eqz (local.get $y)) |
| ) |
| (local.get $z) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-identical-arms-but-binary (param $x i32) (param $y i32) (param $z i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-but-binary (param $x i32) (param $y i32) (param $z i32) |
| (drop |
| (select |
| ;; identical arms, but they are binaries, not unaries |
| (i32.add |
| (local.get $x) |
| (local.get $x) |
| ) |
| (i32.add |
| (local.get $y) |
| (local.get $y) |
| ) |
| (local.get $z) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-identical-arms-br_if-same (param $x i32) (param $y i32) (param $z i32) |
| ;; CHECK-NEXT: (block $block |
| ;; CHECK-NEXT: (br_if $block |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-br_if-same (param $x i32) (param $y i32) (param $z i32) |
| (block $block |
| (if |
| (local.get $z) |
| ;; two br_ifs with the same target are shallowly identical |
| (br_if $block |
| (local.get $x) |
| ) |
| (br_if $block |
| (local.get $y) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-identical-arms-br_if-different (param $x i32) (param $y i32) (param $z i32) |
| ;; CHECK-NEXT: (block $block1 |
| ;; CHECK-NEXT: (block $block2 |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (br_if $block1 |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (br_if $block2 |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-br_if-different (param $x i32) (param $y i32) (param $z i32) |
| (block $block1 |
| (block $block2 |
| (if |
| (local.get $z) |
| ;; two br_ifs with different targets are not shallowly identical |
| (br_if $block1 |
| (local.get $x) |
| ) |
| (br_if $block2 |
| (local.get $y) |
| ) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-identical-arms-return (param $x i32) (param $y i32) (param $z i32) (result i32) |
| ;; CHECK-NEXT: (block $block |
| ;; CHECK-NEXT: (return |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-return (param $x i32) (param $y i32) (param $z i32) (result i32) |
| (block $block |
| (if |
| (local.get $z) |
| (return |
| (local.get $x) |
| ) |
| (return |
| (local.get $y) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $ternary-identical-arms-return-select (param $x i32) (param $y i32) (param $z i32) (result i32) |
| ;; CHECK-NEXT: (block $block |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (return |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (return |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-return-select (param $x i32) (param $y i32) (param $z i32) (result i32) |
| (block $block |
| ;; we cannot optimize a select currently as the return has side effects |
| (select |
| (return |
| (local.get $x) |
| ) |
| (return |
| (local.get $y) |
| ) |
| (local.get $z) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $send-i32 (param $0 i32) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| (func $send-i32 (param i32)) |
| ;; CHECK: (func $ternary-identical-arms-call (param $x i32) (param $y i32) (param $z i32) |
| ;; CHECK-NEXT: (call $send-i32 |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-call (param $x i32) (param $y i32) (param $z i32) |
| (if |
| (local.get $z) |
| (call $send-i32 |
| (local.get $x) |
| ) |
| (call $send-i32 |
| (local.get $y) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $if-dont-change-to-unreachable (param $x i32) (param $y i32) (param $z i32) (result i32) |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (return |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (return |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-dont-change-to-unreachable (param $x i32) (param $y i32) (param $z i32) (result i32) |
| ;; if we move the returns outside, we'd become unreachable; avoid that. |
| (if (result i32) |
| (local.get $x) |
| (return |
| (local.get $y) |
| ) |
| (return |
| (local.get $z) |
| ) |
| ) |
| ) |
| |
| ;; f32.reinterpret_i32(i32.load(x)) => f32.load(x) |
| ;; f64.reinterpret_i64(i64.load(x)) => f64.load(x) |
| ;; i32.reinterpret_f32(f32.load(x)) => i32.load(x) |
| ;; i64.reinterpret_f64(f64.load(x)) => i64.load(x) |
| |
| ;; CHECK: (func $simplify_reinterpret_and_load (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.load |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.load |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.load |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.reinterpret_i32 |
| ;; CHECK-NEXT: (i32.load8_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.reinterpret_i64 |
| ;; CHECK-NEXT: (i64.load32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $simplify_reinterpret_and_load (param $x i32) |
| (drop (f32.reinterpret_i32 (i32.load (local.get $x)))) |
| (drop (f64.reinterpret_i64 (i64.load (local.get $x)))) |
| (drop (i32.reinterpret_f32 (f32.load (local.get $x)))) |
| (drop (i64.reinterpret_f64 (f64.load (local.get $x)))) |
| (drop (f32.reinterpret_i32 (i32.load8_s (local.get $x)))) ;; skip |
| (drop (f64.reinterpret_i64 (i64.load32_u (local.get $x)))) ;; skip |
| ) |
| |
| ;; f32.store(y, f32.reinterpret_i32(x)) => i32.store(y, x) |
| ;; f64.store(y, f64.reinterpret_i64(x)) => i64.store(y, x) |
| ;; i32.store(y, i32.reinterpret_f32(x)) => f32.store(y, x) |
| ;; i64.store(y, i64.reinterpret_f64(x)) => f64.store(y, x) |
| |
| ;; CHECK: (func $simplify_store_and_reinterpret (param $x i32) (param $y i64) (param $z f32) (param $w f64) |
| ;; CHECK-NEXT: (i32.store |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.store |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (f32.store |
| ;; CHECK-NEXT: (i32.const 24) |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (f64.store |
| ;; CHECK-NEXT: (i32.const 32) |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.store8 |
| ;; CHECK-NEXT: (i32.const 40) |
| ;; CHECK-NEXT: (i32.reinterpret_f32 |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.store32 |
| ;; CHECK-NEXT: (i32.const 44) |
| ;; CHECK-NEXT: (i64.reinterpret_f64 |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $simplify_store_and_reinterpret (param $x i32) (param $y i64) (param $z f32) (param $w f64) |
| (f32.store (i32.const 8) (f32.reinterpret_i32 (local.get $x))) |
| (f64.store (i32.const 16) (f64.reinterpret_i64 (local.get $y))) |
| (i32.store (i32.const 24) (i32.reinterpret_f32 (local.get $z))) |
| (i64.store (i32.const 32) (i64.reinterpret_f64 (local.get $w))) |
| (i32.store8 (i32.const 40) (i32.reinterpret_f32 (local.get $z))) ;; skip |
| (i64.store32 (i32.const 44) (i64.reinterpret_f64 (local.get $w))) ;; skip |
| ) |
| |
| ;; i32.reinterpret_f32(f32.reinterpret_i32(x)) => x |
| ;; i64.reinterpret_f64(f64.reinterpret_i64(x)) => x |
| ;; f32.reinterpret_i32(i32.reinterpret_f32(x)) => x |
| ;; f64.reinterpret_i64(i64.reinterpret_f64(x)) => x |
| |
| ;; CHECK: (func $eliminate_reinterpret_reinterpret (param $x i32) (param $y i64) (param $z f32) (param $w f64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $w) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eliminate_reinterpret_reinterpret (param $x i32) (param $y i64) (param $z f32) (param $w f64) |
| (drop (i32.reinterpret_f32 (f32.reinterpret_i32 (local.get $x)))) |
| (drop (i64.reinterpret_f64 (f64.reinterpret_i64 (local.get $y)))) |
| (drop (f32.reinterpret_i32 (i32.reinterpret_f32 (local.get $z)))) |
| (drop (f64.reinterpret_i64 (i64.reinterpret_f64 (local.get $w)))) |
| ) |
| |
| ;; CHECK: (func $simplify_int_float_conversion_roundtrips (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.trunc_f64_u |
| ;; CHECK-NEXT: (f64.convert_i32_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.trunc_f64_s |
| ;; CHECK-NEXT: (f64.convert_i32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.trunc_f32_u |
| ;; CHECK-NEXT: (f32.convert_i32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.trunc_f64_u |
| ;; CHECK-NEXT: (f64.convert_i64_u |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.trunc_f64_s |
| ;; CHECK-NEXT: (f64.convert_i64_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.trunc_f32_u |
| ;; CHECK-NEXT: (f32.convert_i32_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.trunc_f32_s |
| ;; CHECK-NEXT: (f32.convert_i64_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $simplify_int_float_conversion_roundtrips (param $x i32) (param $y i64) |
| (drop (i32.trunc_f64_u (f64.convert_i32_u (local.get $x)))) |
| (drop (i32.trunc_f64_s (f64.convert_i32_s (local.get $x)))) |
| |
| ;; skips |
| (drop (i32.trunc_f64_u (f64.convert_i32_s (local.get $x)))) |
| (drop (i32.trunc_f64_s (f64.convert_i32_u (local.get $x)))) |
| (drop (i32.trunc_f32_u (f32.convert_i32_u (local.get $x)))) |
| (drop (i32.trunc_f64_u (f64.convert_i64_u (local.get $y)))) |
| (drop (i64.trunc_f64_s (f64.convert_i64_s (local.get $y)))) |
| (drop (i64.trunc_f32_u (f32.convert_i32_s (local.get $x)))) |
| (drop (i64.trunc_f32_s (f32.convert_i64_s (local.get $y)))) |
| ) |
| |
| ;; CHECK: (func $simplify_rounding_after_conversions_i32_to_f64 (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i32_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i32_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i32_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i32_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $simplify_rounding_after_conversions_i32_to_f64 (param $x i32) |
| (drop (f64.ceil (f64.convert_i32_u (local.get $x)))) |
| (drop (f64.ceil (f64.convert_i32_s (local.get $x)))) |
| |
| (drop (f64.floor (f64.convert_i32_u (local.get $x)))) |
| (drop (f64.floor (f64.convert_i32_s (local.get $x)))) |
| |
| (drop (f64.trunc (f64.convert_i32_u (local.get $x)))) |
| (drop (f64.trunc (f64.convert_i32_s (local.get $x)))) |
| |
| (drop (f64.nearest (f64.convert_i32_u (local.get $x)))) |
| (drop (f64.nearest (f64.convert_i32_s (local.get $x)))) |
| ) |
| |
| ;; CHECK: (func $simplify_rounding_after_conversions_i32_to_f32 (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i32_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i32_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i32_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i32_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $simplify_rounding_after_conversions_i32_to_f32 (param $x i32) |
| (drop (f32.ceil (f32.convert_i32_u (local.get $x)))) |
| (drop (f32.ceil (f32.convert_i32_s (local.get $x)))) |
| |
| (drop (f32.floor (f32.convert_i32_u (local.get $x)))) |
| (drop (f32.floor (f32.convert_i32_s (local.get $x)))) |
| |
| (drop (f32.trunc (f32.convert_i32_u (local.get $x)))) |
| (drop (f32.trunc (f32.convert_i32_s (local.get $x)))) |
| |
| (drop (f32.nearest (f32.convert_i32_u (local.get $x)))) |
| (drop (f32.nearest (f32.convert_i32_s (local.get $x)))) |
| ) |
| |
| ;; CHECK: (func $simplify_rounding_after_conversions_i64_to_f64 (param $x i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i64_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i64_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i64_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i64_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i64_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i64_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i64_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.convert_i64_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $simplify_rounding_after_conversions_i64_to_f64 (param $x i64) |
| (drop (f64.ceil (f64.convert_i64_u (local.get $x)))) |
| (drop (f64.ceil (f64.convert_i64_s (local.get $x)))) |
| |
| (drop (f64.floor (f64.convert_i64_u (local.get $x)))) |
| (drop (f64.floor (f64.convert_i64_s (local.get $x)))) |
| |
| (drop (f64.trunc (f64.convert_i64_u (local.get $x)))) |
| (drop (f64.trunc (f64.convert_i64_s (local.get $x)))) |
| |
| (drop (f64.nearest (f64.convert_i64_u (local.get $x)))) |
| (drop (f64.nearest (f64.convert_i64_s (local.get $x)))) |
| ) |
| |
| ;; CHECK: (func $simplify_rounding_after_conversions_i64_to_f32 (param $x i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i64_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i64_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i64_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i64_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i64_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i64_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i64_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.convert_i64_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $simplify_rounding_after_conversions_i64_to_f32 (param $x i64) |
| (drop (f32.ceil (f32.convert_i64_u (local.get $x)))) |
| (drop (f32.ceil (f32.convert_i64_s (local.get $x)))) |
| |
| (drop (f32.floor (f32.convert_i64_u (local.get $x)))) |
| (drop (f32.floor (f32.convert_i64_s (local.get $x)))) |
| |
| (drop (f32.trunc (f32.convert_i64_u (local.get $x)))) |
| (drop (f32.trunc (f32.convert_i64_s (local.get $x)))) |
| |
| (drop (f32.nearest (f32.convert_i64_u (local.get $x)))) |
| (drop (f32.nearest (f32.convert_i64_s (local.get $x)))) |
| ) |
| |
| ;; u64(i32.load(_8|_16)(_u|_s)(x)) => i64.load(_8|_16|_32)(_u|_s)(x) |
| ;; except: |
| ;; i64.extend_i32_u(i32.load8_s(x)) and |
| ;; i64.extend_i32_u(i32.load16_s(x)) |
| |
| ;; CHECK: (func $combine_load_and_extend_u (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.load8_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.load16_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.load32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i32.load8_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (i32.load16_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $combine_load_and_extend_u (param $x i32) |
| (drop (i64.extend_i32_u (i32.load8_u (local.get $x)))) |
| (drop (i64.extend_i32_u (i32.load16_u (local.get $x)))) |
| (drop (i64.extend_i32_u (i32.load (local.get $x)))) |
| |
| ;; skips |
| (drop (i64.extend_i32_u (i32.load8_s (local.get $x)))) |
| (drop (i64.extend_i32_u (i32.load16_s (local.get $x)))) |
| ) |
| |
| ;; i64(i32.load(_8|_16)(_u|_s)(x)) => i64.load(_8|_16|_32)(_u|_s)(x) |
| |
| ;; CHECK: (func $combine_load_and_extend_s (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.load8_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.load16_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.load8_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.load16_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.load32_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $combine_load_and_extend_s (param $x i32) |
| (drop (i64.extend_i32_s (i32.load8_u (local.get $x)))) |
| (drop (i64.extend_i32_s (i32.load16_u (local.get $x)))) |
| (drop (i64.extend_i32_s (i32.load8_s (local.get $x)))) |
| (drop (i64.extend_i32_s (i32.load16_s (local.get $x)))) |
| (drop (i64.extend_i32_s (i32.load (local.get $x)))) |
| ) |
| ) |