| ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. |
| ;; RUN: wasm-opt %s --optimize-instructions --mvp-features -S -o - | filecheck %s |
| |
| (module |
| ;; CHECK: (type $0 (func (param i32 i64))) |
| (type $0 (func (param i32 i64))) |
| |
| ;; CHECK: (import "a" "b" (func $get-f64 (result f64))) |
| (import "a" "b" (func $get-f64 (result f64))) |
| |
| ;; CHECK: (import "a" "c" (func $set-i32 (param i32))) |
| (import "a" "c" (func $set-i32 (param i32))) |
| |
| (memory 0) |
| |
| ;; 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: (then |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-eqz-one-arm (param $i1 i32) |
| (if |
| (i32.eqz |
| (local.get $i1) |
| ) |
| (then |
| (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: (then |
| ;; CHECK-NEXT: (i32.const 12) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-eqz-two-arms (param $i1 i32) |
| (if |
| (i32.eqz |
| (local.get $i1) |
| ) |
| (then |
| (drop |
| (i32.const 11) |
| ) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i32.const 12) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-eqz-two-arms-i64 (param $i2 i64) |
| (if |
| (i64.eqz |
| (local.get $i2) |
| ) |
| (then |
| (drop |
| (i32.const 11) |
| ) |
| ) |
| (else |
| (drop |
| (i32.const 12) |
| ) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $eqz-gt_s (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; 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.eqz |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; 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.eqz |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; 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.eqz |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; 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.eqz |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; 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.eqz |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; 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.eqz |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; 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.eqz |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; 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.const 0) |
| ;; 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: (i32.const 0) |
| ;; 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: (then |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-eqz-eqz |
| (if |
| (i32.eqz |
| (i32.eqz |
| (i32.const 123) |
| ) |
| ) |
| (then |
| (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-and-eqz (param $x i32) (param $y i32) (result i32) |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-and-eqz (param $x i32) (param $y i32) (result i32) |
| (select |
| (i32.eqz |
| (local.get $x) |
| ) |
| (i32.const 0) |
| (i32.eqz |
| (local.get $y) |
| ) |
| ) |
| ) |
| ;; 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-negation (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.ge_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 20) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-or-negation (param $x i32) (param $y i32) (result i32) |
| (select |
| ;; We can turn this select into an and by negating the condition. |
| (i32.const 0) |
| (i32.eq |
| (local.get $y) |
| (i32.const 1337) |
| ) |
| (i32.lt_u |
| (local.get $x) |
| (i32.const 20) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-or-no-const (param $x i32) (param $y i32) (result i32) |
| ;; 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.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 0 or 1). |
| (i32.const 2) |
| (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-negation (param $x i32) (param $y i32) (result i32) |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-and-negation (param $x i32) (param $y i32) (result i32) |
| (select |
| (i32.eq |
| (local.get $y) |
| (i32.const 1337) |
| ) |
| ;; With a 1 here, we negate the condition. |
| (i32.const 1) |
| (i32.eq |
| (local.get $x) |
| (i32.const 42) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-and-negation-impossible (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.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 31) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-and-negation-impossible (param $x i32) (param $y i32) (result i32) |
| (select |
| (i32.eq |
| (local.get $y) |
| (i32.const 1337) |
| ) |
| ;; With a 1 here, we must negate the condition, but the condition here |
| ;; cannot be negated in a simple way, so skip. |
| (i32.const 1) |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 31) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-and-negation-impossible-float (param $x f64) (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: (f64.le |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f64.const 3.14159) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $select-and-negation-impossible-float (param $x f64) (param $y i32) (result i32) |
| (select |
| (i32.eq |
| (local.get $y) |
| (i32.const 1337) |
| ) |
| ;; With a 1 here, we must negate the condition, but the condition here |
| ;; cannot be negated due to it operating on floats (where NaNs cause |
| ;; difficulties), so we skip. |
| (i32.const 1) |
| (f64.le |
| (local.get $x) |
| (f64.const 3.14159) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $select-and-no-const (param $x i32) (param $y i32) (result i32) |
| ;; 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.ne |
| ;; 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 or 1). |
| (i32.const 2) |
| (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 (param $x i64) |
| ;; CHECK-NEXT: (i64.store8 |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store8-wrap (param $x i64) |
| (i32.store8 (i32.const 11) (i32.wrap_i64 (local.get $x))) |
| ) |
| ;; CHECK: (func $store16-wrap (param $x i64) |
| ;; CHECK-NEXT: (i64.store16 |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store16-wrap (param $x i64) |
| (i32.store16 (i32.const 11) (i32.wrap_i64 (local.get $x))) |
| ) |
| ;; CHECK: (func $store-wrap (param $x i64) |
| ;; CHECK-NEXT: (i64.store32 |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $store-wrap (param $x i64) |
| (i32.store (i32.const 11) (i32.wrap_i64 (local.get $x))) |
| ) |
| ;; 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.const 1) |
| ;; 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 (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 (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 (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 (result i32) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (loop (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 (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-near-min-max (param $x i32) (param $y i64) |
| ;; 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.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 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: (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 -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.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: ) |
| (func $canonicalize-cmp-near-min-max (param $x i32) (param $y i64) |
| ;; (signed)x < s_min + 1 ==> x == s_min |
| (drop (i32.lt_s |
| (local.get $x) |
| (i32.const -2147483647) |
| )) |
| (drop (i64.lt_s |
| (local.get $y) |
| (i64.const -9223372036854775807) |
| )) |
| ;; (signed)x >= s_min + 1 ==> x != s_min |
| (drop (i32.ge_s |
| (local.get $x) |
| (i32.const -2147483647) |
| )) |
| (drop (i64.ge_s |
| (local.get $y) |
| (i64.const -9223372036854775807) |
| )) |
| ;; (signed)x > s_max - 1 ==> x == s_max |
| (drop (i32.gt_s |
| (local.get $x) |
| (i32.const 2147483646) |
| )) |
| (drop (i64.gt_s |
| (local.get $y) |
| (i64.const 9223372036854775806) |
| )) |
| ;; (signed)x <= s_max - 1 ==> x != s_max |
| (drop (i32.le_s |
| (local.get $x) |
| (i32.const 2147483646) |
| )) |
| (drop (i64.le_s |
| (local.get $y) |
| (i64.const 9223372036854775806) |
| )) |
| ;; (unsigned)x <= u_max - 1 ==> x != u_max |
| (drop (i32.le_u |
| (local.get $x) |
| (i32.const -2) |
| )) |
| (drop (i64.le_u |
| (local.get $y) |
| (i64.const -2) |
| )) |
| ;; (unsigned)x > u_max - 1 ==> x == u_max |
| (drop (i32.gt_u |
| (local.get $x) |
| (i32.const -2) |
| )) |
| (drop (i64.gt_u |
| (local.get $y) |
| (i64.const -2) |
| )) |
| ) |
| ;; 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: (i32.const 0) |
| ;; 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 $canonicalize-consts-floats (param $x f32) (param $y f64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (f64.const -1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const 3.4000000953674316) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (f64.const 3.4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.min |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const 3.4000000953674316) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.min |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (f64.const 3.4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.max |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const 3.4000000953674316) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.max |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (f64.const 3.4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.const nan:0x8000000000000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.const nan:0x8000000000000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.copysign |
| ;; CHECK-NEXT: (f32.const 1) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.copysign |
| ;; CHECK-NEXT: (f64.const 1) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $canonicalize-consts-floats (param $x f32) (param $y f64) |
| (drop (f32.sub (local.get $x) (f32.const 1.0))) |
| (drop (f64.sub (local.get $y) (f64.const 1.0))) |
| |
| (drop (f32.mul (f32.const 3.4) (local.get $x))) |
| (drop (f64.mul (f64.const 3.4) (local.get $y))) |
| |
| (drop (f32.min (f32.const 3.4) (local.get $x))) |
| (drop (f64.min (f64.const 3.4) (local.get $y))) |
| |
| (drop (f32.max (f32.const 3.4) (local.get $x))) |
| (drop (f64.max (f64.const 3.4) (local.get $y))) |
| |
| (drop (f32.min (f32.const nan) (local.get $x))) |
| (drop (f64.min (f64.const nan) (local.get $y))) |
| |
| (drop (f32.max (f32.const nan) (local.get $x))) |
| (drop (f64.max (f64.const nan) (local.get $y))) |
| |
| ;; skips |
| (drop (f32.copysign (f32.const 1.0) (local.get $x))) |
| (drop (f64.copysign (f64.const 1.0) (local.get $y))) |
| ) |
| ;; CHECK: (func $ne0 (result i32) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (i32.or |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; 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: (then |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| (func $ne0 (result i32) |
| (if (i32.ne (call $ne0) (i32.const 0)) |
| (then |
| (nop) |
| ) |
| ) |
| (if (i32.ne (i32.const 0) (call $ne0)) |
| (then |
| (nop) |
| ) |
| ) |
| ;; through an or |
| (if |
| (i32.or |
| (i32.ne (i32.const 0) (call $ne0)) |
| (i32.ne (i32.const 0) (call $ne0)) |
| ) |
| (then |
| (nop) |
| ) |
| ) |
| ;; but not an and |
| (if |
| (i32.and |
| (i32.ne (i32.const 0) (call $ne0)) |
| (i32.ne (i32.const 0) (call $ne0)) |
| ) |
| (then |
| (nop) |
| ) |
| ) |
| (i32.const 1) |
| ) |
| ;; CHECK: (func $recurse-bool |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (if (result i32) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (call $ne1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (if |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: (call $ne0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (then |
| ;; CHECK-NEXT: (nop) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $recurse-bool |
| (if |
| (if (result i32) |
| (i32.const 1) |
| (then |
| (i32.ne (call $ne0) (i32.const 0)) |
| ) |
| (else |
| (i32.ne (call $ne1) (i32.const 0)) |
| ) |
| ) |
| (then |
| (nop) |
| ) |
| ) |
| (if |
| (block (result i32) |
| (nop) |
| (i32.ne (call $ne0) (i32.const 0)) |
| ) |
| (then |
| (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.and |
| ;; CHECK-NEXT: (local.get $0) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; 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: (then |
| ;; CHECK-NEXT: (i32.const 111) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i32.const 222) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| ) |
| (then |
| (i32.const 111) |
| ) |
| (else |
| (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.and |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (i32.const -16777216) |
| ;; 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.const -1) |
| ;; 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.and |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (i32.const -16777216) |
| ;; 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: (then |
| ;; CHECK-NEXT: (i32.const 100) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i32.const 200) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| ) |
| (then |
| (i32.const 100) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $1) |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $if-parallel (param $0 i32) (param $1 i32) |
| (drop |
| (if (result i32) |
| (local.get $0) |
| (then |
| (i32.add (local.get $1) (i32.const 1)) |
| ) |
| (else |
| (i32.add (local.get $1) (i32.const 1)) |
| ) |
| ) |
| ) |
| (drop |
| (if (result i32) |
| (local.tee $0 (local.get $1)) ;; side effects! |
| (then |
| (i32.add (local.get $1) (i32.const 1)) |
| ) |
| (else |
| (i32.add (local.get $1) (i32.const 1)) |
| ) |
| ) |
| ) |
| (drop |
| (if (result i32) |
| (local.get $0) |
| (then |
| (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if |
| ) |
| (else |
| (i32.add (local.get $1) (unreachable)) |
| ) |
| ) |
| ) |
| (drop |
| (if (result i32) |
| (local.tee $0 (local.get $1)) ;; side effects! |
| (then |
| (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if |
| ) |
| (else |
| (i32.add (local.get $1) (unreachable)) |
| ) |
| ) |
| ) |
| (drop |
| (if (result i32) |
| (unreachable) ;; !!! |
| (then |
| (i32.add (local.get $1) (unreachable)) ;; folding them would change the type of the if |
| ) |
| (else |
| (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 $mix-shifts-with-same-const-signed (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -9223372036854775808) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.shl |
| ;; CHECK-NEXT: (i64.shr_s |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 63) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $mix-shifts-with-same-const-signed (param $x i32) (param $y i64) |
| (drop |
| (i32.shl |
| (i32.shr_s |
| (local.get $x) |
| (i32.const 4) |
| ) |
| (i32.const 4) |
| ) |
| ) |
| (drop |
| (i64.shl |
| (i64.shr_s |
| (local.get $y) |
| (i64.const 63) |
| ) |
| (i64.const 127) ;; effective shift is 63 |
| ) |
| ) |
| |
| ;; skips |
| (drop |
| (i32.shl |
| (i32.shr_s |
| (local.get $x) |
| (i32.const 4) |
| ) |
| (i32.const 5) |
| ) |
| ) |
| (drop |
| (i64.shl |
| (i64.shr_s |
| (local.get $y) |
| (i64.const 63) |
| ) |
| (i64.const 1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $mix-shifts-with-same-const-unsigned (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const -16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const -9223372036854775808) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.shl |
| ;; CHECK-NEXT: (i64.shr_u |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 63) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $mix-shifts-with-same-const-unsigned (param $x i32) (param $y i64) |
| (drop |
| (i32.shl |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 4) |
| ) |
| (i32.const 4) |
| ) |
| ) |
| (drop |
| (i64.shl |
| (i64.shr_u |
| (local.get $y) |
| (i64.const 63) |
| ) |
| (i64.const 127) ;; effective shift is 63 |
| ) |
| ) |
| |
| ;; skips |
| (drop |
| (i32.shl |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 4) |
| ) |
| (i32.const 5) |
| ) |
| ) |
| (drop |
| (i64.shl |
| (i64.shr_u |
| (local.get $y) |
| (i64.const 63) |
| ) |
| (i64.const 1) |
| ) |
| ) |
| ) |
| ;; CHECK: (func $reversed-mix-shifts-with-same-const (param $x i32) (param $y i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 268435455) |
| ;; 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: (i64.and |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.shr_u |
| ;; CHECK-NEXT: (i64.shl |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 4) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 8) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_s |
| ;; CHECK-NEXT: (i32.shl |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $reversed-mix-shifts-with-same-const (param $x i32) (param $y i64) |
| (drop |
| (i32.shr_u |
| (i32.shl |
| (local.get $x) |
| (i32.const 4) |
| ) |
| (i32.const 4) |
| ) |
| ) |
| (drop |
| (i32.shr_u |
| (i32.shl |
| (local.get $x) |
| (i32.const 31) |
| ) |
| (i32.const 31) |
| ) |
| ) |
| (drop |
| (i64.shr_u |
| (i64.shl |
| (local.get $y) |
| (i64.const 127) ;; effective shift is 63 |
| ) |
| (i64.const 63) ;; effective shift is 63 |
| ) |
| ) |
| |
| ;; skips |
| (drop |
| (i32.shr_u |
| (i32.shl |
| (local.get $x) |
| (i32.const 5) |
| ) |
| (i32.const 4) |
| ) |
| ) |
| (drop |
| (i64.shr_u |
| (i64.shl |
| (local.get $y) |
| (i64.const 4) |
| ) |
| (i64.const 8) |
| ) |
| ) |
| (drop |
| (i32.shr_s |
| (i32.shl |
| (local.get $x) |
| (i32.const 6) |
| ) |
| (i32.const 6) |
| ) |
| ) |
| ) |
| ;; 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.const -536902656) |
| ;; 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.const -31744) |
| ;; 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: (then |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| ) |
| (then |
| (i32.const 1) |
| ) |
| (else |
| (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.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (local.get $y) |
| ;; 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.const nan:0x400000) |
| ;; 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.const nan:0x8000000000000) |
| ;; 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: (then |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; 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: (then |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| ) |
| (then |
| (i32.const 1) |
| ) |
| (else |
| (i32.const 0) |
| ) |
| )) |
| ;; (signed)x % min_s ? 1 : 0 |
| (drop (if (result i32) |
| (i32.rem_s |
| (local.get $x) |
| (i32.const 0x80000000) |
| ) |
| (then |
| (i32.const 1) |
| ) |
| (else |
| (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 (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: (then |
| ;; CHECK-NEXT: (i32.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; 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: (then |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; 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: (then |
| ;; CHECK-NEXT: (i32.const 3) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; 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) (then (i32.const 2) )(else (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) (then (unreachable) )(else (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) (then (i32.const 3) )(else (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.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.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.add |
| ;; 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 $simplify-add-sub-with-neg-float (param $a f32) (param $b f32) (param $x f64) (param $y f64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.sub |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.sub |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.add |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.neg |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.sub |
| ;; CHECK-NEXT: (f64.neg |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (f32.neg |
| ;; CHECK-NEXT: (local.tee $a |
| ;; CHECK-NEXT: (f32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $simplify-add-sub-with-neg-float (param $a f32) (param $b f32) (param $x f64) (param $y f64) |
| ;; -x + y ==> y - x |
| (drop (f32.add (f32.neg (local.get $a)) (local.get $b))) |
| (drop (f64.add (f64.neg (local.get $x)) (local.get $y))) |
| |
| ;; x + (-y) ==> x - y |
| (drop (f32.add (local.get $a) (f32.neg (local.get $b)))) |
| (drop (f64.add (local.get $x) (f64.neg (local.get $y)))) |
| |
| ;; x - (-y) ==> x + y |
| (drop (f32.sub (local.get $a) (f32.neg (local.get $b)))) |
| (drop (f64.sub (local.get $x) (f64.neg (local.get $y)))) |
| |
| ;; skips |
| ;; -x - y -> skip |
| (drop (f32.sub (f32.neg (local.get $a)) (local.get $b))) |
| (drop (f64.sub (f64.neg (local.get $x)) (local.get $y))) |
| ;; -x + y -> skip, iff can't reorder |
| (drop (f32.add (f32.neg (local.tee $a (f32.const 1.0))) (local.get $a))) |
| ) |
| ;; CHECK: (func $simplify-add-sub-with-neg-float-zeros (param $a f32) (param $b f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (f32.const -0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const -0) |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (f32.const -0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const -0) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (f32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (f32.const -0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (f32.const -0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $simplify-add-sub-with-neg-float-zeros (param $a f32) (param $b f32) |
| ;; edge cases for -x + y |
| (drop (f32.add (f32.neg (f32.const 0)) (local.get $b))) |
| (drop (f32.add (f32.neg (local.get $a)) (f32.const 0))) |
| (drop (f32.add (f32.neg (f32.const -0)) (local.get $b))) |
| (drop (f32.add (f32.neg (local.get $a)) (f32.const -0))) |
| ;; edge cases for x + (-y) |
| (drop (f32.add (f32.const 0) (f32.neg (local.get $b)))) |
| (drop (f32.add (local.get $a) (f32.neg (f32.const 0)))) |
| (drop (f32.add (f32.const -0) (f32.neg (local.get $b)))) |
| (drop (f32.add (local.get $a) (f32.neg (f32.const -0)))) |
| ;; edge cases for x - (-y) |
| (drop (f32.sub (f32.const 0) (f32.neg (local.get $b)))) |
| (drop (f32.sub (local.get $a) (f32.neg (f32.const 0)))) |
| (drop (f32.sub (f32.const -0) (f32.neg (local.get $b)))) |
| (drop (f32.sub (local.get $a) (f32.neg (f32.const -0)))) |
| ) |
| ;; CHECK: (func $simplify-add-sub-with-neg-float-nans (param $a f32) (param $b f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const -nan:0x400000) |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const -nan:0x400000) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (f32.const -nan:0x400000) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $simplify-add-sub-with-neg-float-nans (param $a f32) (param $b f32) |
| ;; edge cases for -x + y |
| (drop (f32.add (f32.neg (f32.const nan)) (local.get $b))) |
| (drop (f32.add (f32.neg (local.get $a)) (f32.const nan))) |
| (drop (f32.add (f32.neg (f32.const -nan)) (local.get $b))) |
| (drop (f32.add (f32.neg (local.get $a)) (f32.const -nan))) |
| ;; edge cases for x + (-y) |
| (drop (f32.add (f32.const nan) (f32.neg (local.get $b)))) |
| (drop (f32.add (local.get $a) (f32.neg (f32.const nan)))) |
| (drop (f32.add (f32.const -nan) (f32.neg (local.get $b)))) |
| (drop (f32.add (local.get $a) (f32.neg (f32.const -nan)))) |
| ;; edge cases for x - (-y) |
| (drop (f32.sub (f32.const nan) (f32.neg (local.get $b)))) |
| (drop (f32.sub (local.get $a) (f32.neg (f32.const nan)))) |
| (drop (f32.sub (f32.const -nan) (f32.neg (local.get $b)))) |
| (drop (f32.sub (local.get $a) (f32.neg (f32.const -nan)))) |
| ) |
| ;; CHECK: (func $simplify-add-sub-with-neg-float-infs (param $a f32) (param $b f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (f32.const -inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const inf) |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (f32.const inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const -inf) |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const inf) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (f32.const -inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const -inf) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (f32.const inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (f32.const inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (f32.const inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (f32.const -inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (f32.const -inf) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $simplify-add-sub-with-neg-float-infs (param $a f32) (param $b f32) |
| ;; edge cases for -x + y |
| (drop (f32.add (f32.neg (f32.const inf)) (local.get $b))) |
| (drop (f32.add (f32.neg (local.get $a)) (f32.const inf))) |
| (drop (f32.add (f32.neg (f32.const -inf)) (local.get $b))) |
| (drop (f32.add (f32.neg (local.get $a)) (f32.const -inf))) |
| ;; edge cases for x + (-y) |
| (drop (f32.add (f32.const inf) (f32.neg (local.get $b)))) |
| (drop (f32.add (local.get $a) (f32.neg (f32.const inf)))) |
| (drop (f32.add (f32.const -inf) (f32.neg (local.get $b)))) |
| (drop (f32.add (local.get $a) (f32.neg (f32.const -inf)))) |
| ;; edge cases for x - (-y) |
| (drop (f32.sub (f32.const inf) (f32.neg (local.get $b)))) |
| (drop (f32.sub (local.get $a) (f32.neg (f32.const inf)))) |
| (drop (f32.sub (f32.const -inf) (f32.neg (local.get $b)))) |
| (drop (f32.sub (local.get $a) (f32.neg (f32.const -inf)))) |
| ) |
| ;; CHECK: (func $simplify-add-sub-with-neg-float-mins (param $a f32) (param $b f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (f32.const -1.401298464324817e-45) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const 1.401298464324817e-45) |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (f32.const 1.401298464324817e-45) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const -1.401298464324817e-45) |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const 1.401298464324817e-45) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (f32.const -1.401298464324817e-45) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const -1.401298464324817e-45) |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (f32.const 1.401298464324817e-45) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (f32.const 1.401298464324817e-45) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (f32.const 1.401298464324817e-45) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $b) |
| ;; CHECK-NEXT: (f32.const -1.401298464324817e-45) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.add |
| ;; CHECK-NEXT: (local.get $a) |
| ;; CHECK-NEXT: (f32.const -1.401298464324817e-45) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $simplify-add-sub-with-neg-float-mins (param $a f32) (param $b f32) |
| ;; edge cases for -x + y |
| (drop (f32.add (f32.neg (f32.const 1.401298464324817e-45)) (local.get $b))) ;; +min value |
| (drop (f32.add (f32.neg (local.get $a)) (f32.const 1.401298464324817e-45))) ;; +min value |
| (drop (f32.add (f32.neg (f32.const -1.401298464324817e-45)) (local.get $b))) ;; -min value |
| (drop (f32.add (f32.neg (local.get $a)) (f32.const -1.401298464324817e-45))) ;; -min value |
| ;; edge cases for x + (-y) |
| (drop (f32.add (f32.const 1.401298464324817e-45) (f32.neg (local.get $b)))) |
| (drop (f32.add (local.get $a) (f32.neg (f32.const 1.401298464324817e-45)))) |
| (drop (f32.add (f32.const -1.401298464324817e-45) (f32.neg (local.get $b)))) |
| (drop (f32.add (local.get $a) (f32.neg (f32.const -1.401298464324817e-45)))) |
| ;; edge cases for x - (-y) |
| (drop (f32.sub (f32.const 1.401298464324817e-45) (f32.neg (local.get $b)))) |
| (drop (f32.sub (local.get $a) (f32.neg (f32.const 1.401298464324817e-45)))) |
| (drop (f32.sub (f32.const -1.401298464324817e-45) (f32.neg (local.get $b)))) |
| (drop (f32.sub (local.get $a) (f32.neg (f32.const -1.401298464324817e-45)))) |
| ) |
| ;; 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.const nan:0x8000000000000) |
| ;; 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: (drop |
| ;; CHECK-NEXT: (f32.sub |
| ;; CHECK-NEXT: (f32.const 3.5) |
| ;; CHECK-NEXT: (local.get $fx) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.sub |
| ;; 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) |
| ) |
| )) |
| |
| ;; -x + C -> C - x |
| (drop (f32.add |
| (f32.neg |
| (local.get $fx) |
| ) |
| (f32.const 3.5) |
| )) |
| (drop (f64.sub |
| (f64.neg |
| (local.get $fy) |
| ) |
| (f64.const -5) |
| )) |
| ) |
| ;; CHECK: (func $rhs-is-const-nan (param $x f32) (param $y f64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.const nan:0x8000000000000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.const nan:0x8000000000000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.const nan:0x8000000000000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.const nan:0x8000000000000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.const nan:0x8000000000000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.const nan:0x8000000000000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.copysign |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const nan:0x400000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.copysign |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (f32.const nan:0x200000) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.copysign |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: (f64.const -nan:0x8000000000000) |
| ;; 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 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: (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: (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: ) |
| (func $rhs-is-const-nan (param $x f32) (param $y f64) |
| |
| ;; arithmetic ops |
| |
| ;; x + nan' => nan' |
| (drop (f32.add (local.get $x) (f32.const nan))) |
| (drop (f32.add (local.get $x) (f32.const nan:0x200000))) |
| (drop (f64.add (local.get $y) (f64.const -nan))) |
| ;; x - nan' => nan' |
| (drop (f32.sub (local.get $x) (f32.const nan))) |
| (drop (f32.sub (local.get $x) (f32.const nan:0x200000))) |
| (drop (f64.sub (local.get $y) (f64.const -nan))) |
| ;; x * nan' => nan' |
| (drop (f32.mul (local.get $x) (f32.const nan))) |
| (drop (f32.mul (local.get $x) (f32.const nan:0x200000))) |
| (drop (f64.mul (local.get $y) (f64.const -nan))) |
| ;; x / nan' => nan' |
| (drop (f32.div (local.get $x) (f32.const nan))) |
| (drop (f32.div (local.get $x) (f32.const nan:0x200000))) |
| (drop (f64.div (local.get $y) (f64.const -nan))) |
| |
| ;; min / max ops |
| |
| ;; min(x, nan') => nan' |
| (drop (f32.min (local.get $x) (f32.const nan))) |
| (drop (f32.min (local.get $x) (f32.const nan:0x200000))) |
| (drop (f64.min (local.get $y) (f64.const -nan))) |
| ;; max(x, nan') => nan' |
| (drop (f32.max (local.get $x) (f32.const nan))) |
| (drop (f32.max (local.get $x) (f32.const nan:0x200000))) |
| (drop (f64.max (local.get $y) (f64.const -nan))) |
| |
| ;; copysign ops (should be skipped) |
| |
| ;; copysign(x, nan) => skip |
| (drop (f32.copysign (local.get $x) (f32.const nan))) |
| (drop (f32.copysign (local.get $x) (f32.const nan:0x200000))) |
| (drop (f64.copysign (local.get $y) (f64.const -nan))) |
| |
| ;; relational ops |
| |
| ;; x != nan => 1 |
| (drop (f32.ne (local.get $x) (f32.const nan))) |
| (drop (f32.ne (local.get $x) (f32.const nan:0x200000))) |
| (drop (f64.ne (local.get $y) (f64.const -nan))) |
| ;; x == nan => 0 |
| (drop (f32.eq (local.get $x) (f32.const nan))) |
| (drop (f32.eq (local.get $x) (f32.const nan:0x200000))) |
| (drop (f64.eq (local.get $y) (f64.const -nan))) |
| ;; x > nan => 0 |
| (drop (f32.gt (local.get $x) (f32.const nan))) |
| (drop (f32.gt (local.get $x) (f32.const nan:0x200000))) |
| (drop (f64.gt (local.get $y) (f64.const -nan))) |
| ;; x >= nan => 0 |
| (drop (f32.ge (local.get $x) (f32.const nan))) |
| (drop (f32.ge (local.get $x) (f32.const nan:0x200000))) |
| (drop (f64.ge (local.get $y) (f64.const -nan))) |
| ;; x < nan => 0 |
| (drop (f32.lt (local.get $x) (f32.const nan))) |
| (drop (f32.lt (local.get $x) (f32.const nan:0x200000))) |
| (drop (f64.lt (local.get $y) (f64.const -nan))) |
| ;; x <= nan => 0 |
| (drop (f32.le (local.get $x) (f32.const nan))) |
| (drop (f32.le (local.get $x) (f32.const nan:0x200000))) |
| (drop (f64.le (local.get $y) (f64.const -nan))) |
| ) |
| ;; 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: (then |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| ) |
| (then |
| (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: (local.get $y) |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: (i64.eq |
| ;; 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: (then |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| ) |
| (then |
| (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.const 0) |
| ;; 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.const 1) |
| ;; 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: (i32.eqz |
| ;; CHECK-NEXT: (i32.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.abs |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (call $get-f64) |
| ;; CHECK-NEXT: (call $get-f64) |
| ;; 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.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) |
| ) |
| )) |
| ;; This one cannot be optimized as the runtime values may differ: the calls |
| ;; are "generative" in that identical syntactic calls may emit different |
| ;; results. |
| (drop (f64.abs |
| (f64.mul |
| (call $get-f64) |
| (call $get-f64) |
| ) |
| )) |
| |
| ;; 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 $optimize-float-points-fallthrough (param $x f64) (param $xb f64) (param $y f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f32.mul |
| ;; CHECK-NEXT: (block (result f32) |
| ;; CHECK-NEXT: (call $set-i32 |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block (result f32) |
| ;; CHECK-NEXT: (call $set-i32 |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-float-points-fallthrough (param $x f64) (param $xb f64) (param $y f32) |
| ;; abs(x * x) ==> x * x , as in the previous function. |
| ;; |
| ;; The fallthrough values here are identical, so we can optimize away the |
| ;; f32.abs despite the effects in both (and even different-looking effects). |
| (drop (f32.abs |
| (f32.mul |
| (block (result f32) |
| (call $set-i32 |
| (i32.const 42) |
| ) |
| (local.get $y) |
| ) |
| (block (result f32) |
| (call $set-i32 |
| (i32.const 1337) |
| ) |
| (local.get $y) |
| ) |
| ) |
| )) |
| ) |
| ;; CHECK: (func $optimize-float-points-fallthrough-b (param $x f64) (param $xb f64) (param $y f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.abs |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (block (result f64) |
| ;; CHECK-NEXT: (call $set-i32 |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (call $get-f64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block (result f64) |
| ;; CHECK-NEXT: (call $set-i32 |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (call $get-f64) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-float-points-fallthrough-b (param $x f64) (param $xb f64) (param $y f32) |
| ;; But generative effects in the fallthrough values themselves block us. |
| (drop (f64.abs |
| (f64.mul |
| (block (result f64) |
| (call $set-i32 |
| (i32.const 42) |
| ) |
| (call $get-f64) ;; this changed |
| ) |
| (block (result f64) |
| (call $set-i32 |
| (i32.const 1337) |
| ) |
| (call $get-f64) ;; this changed |
| ) |
| ) |
| )) |
| ) |
| ;; CHECK: (func $optimize-float-points-fallthrough-c (param $x f64) (param $xb f64) (param $y f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.abs |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (block (result f64) |
| ;; CHECK-NEXT: (call $set-i32 |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (f64.const 12.34) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block (result f64) |
| ;; CHECK-NEXT: (call $set-i32 |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-float-points-fallthrough-c (param $x f64) (param $xb f64) (param $y f32) |
| ;; local.tee/get pairs are ok, but atm we don't look at the fallthrough of |
| ;; the right side (we'd need to consider effects). TODO |
| (drop (f64.abs |
| (f64.mul |
| (block (result f64) |
| (call $set-i32 |
| (i32.const 42) |
| ) |
| (local.tee $x ;; this changed |
| (f64.const 12.34) |
| ) |
| ) |
| (block (result f64) |
| (call $set-i32 |
| (i32.const 1337) |
| ) |
| (local.get $x) ;; this changed |
| ) |
| ) |
| )) |
| ) |
| ;; CHECK: (func $optimize-float-points-fallthrough-cb (param $x f64) (param $xb f64) (param $y f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.abs |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (block (result f64) |
| ;; CHECK-NEXT: (call $set-i32 |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (f64.const 12.34) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block (result f64) |
| ;; CHECK-NEXT: (local.set $x |
| ;; CHECK-NEXT: (f64.const 13.37) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-float-points-fallthrough-cb (param $x f64) (param $xb f64) (param $y f32) |
| ;; A conflicting set in the middle is a problem: here we cannot optimize. |
| (drop (f64.abs |
| (f64.mul |
| (block (result f64) |
| (call $set-i32 |
| (i32.const 42) |
| ) |
| (local.tee $x |
| (f64.const 12.34) |
| ) |
| ) |
| (block (result f64) |
| (local.set $x ;; this changed |
| (f64.const 13.37) |
| ) |
| (local.get $x) |
| ) |
| ) |
| )) |
| ) |
| ;; CHECK: (func $optimize-float-points-fallthrough-cc (param $x f64) (param $xb f64) (param $y f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (block (result f64) |
| ;; CHECK-NEXT: (call $set-i32 |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (f64.const 12.34) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-float-points-fallthrough-cc (param $x f64) (param $xb f64) (param $y f32) |
| ;; Removing the local.set and the block on the right lets us optimize using |
| ;; the tee/get pair. |
| (drop (f64.abs |
| (f64.mul |
| (block (result f64) |
| (call $set-i32 |
| (i32.const 42) |
| ) |
| (local.tee $x |
| (f64.const 12.34) |
| ) |
| ) |
| (local.get $x) ;; this moved out |
| ) |
| )) |
| ) |
| ;; CHECK: (func $optimize-float-points-fallthrough-d (param $x f64) (param $xb f64) (param $y f32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.abs |
| ;; CHECK-NEXT: (f64.mul |
| ;; CHECK-NEXT: (block (result f64) |
| ;; CHECK-NEXT: (call $set-i32 |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (f64.const 12.34) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (block (result f64) |
| ;; CHECK-NEXT: (call $set-i32 |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $xb) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $optimize-float-points-fallthrough-d (param $x f64) (param $xb f64) (param $y f32) |
| ;; The wrong local index means we fail again. |
| (drop (f64.abs |
| (f64.mul |
| (block (result f64) |
| (call $set-i32 |
| (i32.const 42) |
| ) |
| (local.tee $x |
| (f64.const 12.34) |
| ) |
| ) |
| (block (result f64) |
| (call $set-i32 |
| (i32.const 1337) |
| ) |
| (local.get $xb) ;; this changed |
| ) |
| ) |
| )) |
| ) |
| ;; 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: (then |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| (then |
| (i32.eqz |
| (local.get $y) |
| ) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| (then |
| (i32.const 0) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| (then |
| (i64.eqz |
| (local.get $y) |
| ) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; 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. |
| (then |
| (i32.eqz |
| (unreachable) |
| ) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (i32.eqz |
| ;; CHECK-NEXT: (unreachable) |
| ;; CHECK-NEXT: ) |
| ;; 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 |
| (then |
| (i32.const 0) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| (then |
| (i32.eqz (local.get $x)) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| (then |
| (f32.demote_f64 (f64.floor (local.get $x))) |
| ) |
| (else |
| (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-tee (param $param i32) |
| ;; CHECK-NEXT: (local $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (local.get $param) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (call $send-i32 |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (select |
| ;; CHECK-NEXT: (block (result i32) |
| ;; CHECK-NEXT: (call $send-i32 |
| ;; CHECK-NEXT: (i32.const 1337) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (local.get $param) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (local.tee $x |
| ;; CHECK-NEXT: (local.get $param) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-tee (param $param i32) |
| (local $x i32) |
| ;; The select's ifTrue and condition are equal (as a tee/get pair with |
| ;; only a const in between), but there is a side effect too, that prevents |
| ;; optimization atm TODO |
| (drop |
| (select |
| (local.tee $x |
| (local.get $param) |
| ) |
| (i32.const 0) |
| (block (result i32) |
| (call $send-i32 |
| (i32.const 42) |
| ) |
| (local.get $x) |
| ) |
| ) |
| ) |
| ;; Side effect on the ifTrue - same outcome, we cannot optimize yet. |
| (drop |
| (select |
| (block (result i32) |
| (call $send-i32 |
| (i32.const 1337) |
| ) |
| (local.tee $x |
| (local.get $param) |
| ) |
| ) |
| (i32.const 0) |
| (local.get $x) |
| ) |
| ) |
| ;; When there are no blocks or things and just a local.tee/get, we can |
| ;; optimize. |
| (drop |
| (select |
| (local.tee $x |
| (local.get $param) |
| ) |
| (i32.const 0) |
| (local.get $x) |
| ) |
| ) |
| ) |
| ;; 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: (then |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| (then |
| (drop (i32.eqz (local.get $x))) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (f64.const 2.34) |
| ;; CHECK-NEXT: ) |
| ;; 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. |
| (then |
| (drop (i32.const 1)) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; 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 |
| (then |
| (br_if $block |
| (local.get $x) |
| ) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (br_if $block1 |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (br_if $block2 |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; 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 |
| (then |
| (br_if $block1 |
| (local.get $x) |
| ) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| (then |
| (return |
| (local.get $x) |
| ) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ternary-identical-arms-call (param $x i32) (param $y i32) (param $z i32) |
| (if |
| (local.get $z) |
| (then |
| (call $send-i32 |
| (local.get $x) |
| ) |
| ) |
| (else |
| (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: (then |
| ;; CHECK-NEXT: (return |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (else |
| ;; CHECK-NEXT: (return |
| ;; CHECK-NEXT: (local.get $z) |
| ;; CHECK-NEXT: ) |
| ;; 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) |
| (then |
| (return |
| (local.get $y) |
| ) |
| ) |
| (else |
| (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)))) |
| ) |
| |
| ;; CHECK: (func $wrap-i64-to-i32-add (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $wrap-i64-to-i32-add (param $x i32) (result i32) |
| ;; Rather than extend to 64 and add there, we can do all of this in i32. |
| (i32.wrap_i64 |
| (i64.add |
| (i64.extend_i32_u |
| (local.get $x) |
| ) |
| (i64.const 8) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $wrap-i64-to-i32-sub (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const 8) |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $wrap-i64-to-i32-sub (param $x i32) (result i32) |
| (i32.wrap_i64 |
| (i64.sub |
| (i64.const 8) |
| (i64.extend_i32_u |
| (local.get $x) |
| ) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $wrap-i64-to-i32-mul (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $wrap-i64-to-i32-mul (param $x i32) (result i32) |
| (i32.wrap_i64 |
| (i64.mul |
| (i64.extend_i32_u |
| (local.get $x) |
| ) |
| (i64.const 42) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $wrap-i64-to-i32-many (param $x i32) (param $y i32) (result i32) |
| ;; CHECK-NEXT: (i32.mul |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.const -1) |
| ;; CHECK-NEXT: (local.get $y) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $wrap-i64-to-i32-many (param $x i32) (param $y i32) (result i32) |
| ;; Multiple operations that all together can be turned into i32. |
| (i32.wrap_i64 |
| (i64.mul |
| (i64.add |
| (i64.extend_i32_u |
| (local.get $x) |
| ) |
| (i64.sub |
| (i64.const -1) |
| (i64.extend_i32_u |
| (local.get $y) |
| ) |
| ) |
| ) |
| (i64.const 42) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $wrap-i64-to-i32-div-no (param $x i32) (result i32) |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.div_u |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $wrap-i64-to-i32-div-no (param $x i32) (result i32) |
| ;; We *cannot* optimize here, as division cares about i32/i64 differences. |
| (i32.wrap_i64 |
| (i64.div_s |
| (i64.extend_i32_u |
| (local.get $x) |
| ) |
| (i64.const 42) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $wrap-i64-to-i32-tee-no (param $x i32) (result i32) |
| ;; CHECK-NEXT: (local $y i64) |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.add |
| ;; CHECK-NEXT: (local.tee $y |
| ;; CHECK-NEXT: (i64.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.extend_i32_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $wrap-i64-to-i32-tee-no (param $x i32) (result i32) |
| ;; The local.tee stops us from optimizing atm. TODO |
| (local $y i64) |
| (i32.wrap_i64 |
| (i64.add |
| (i64.extend_i32_u |
| (local.get $x) |
| ) |
| (local.tee $y |
| (i64.const 42) |
| ) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $wrap-i64-to-i32-local-no (param $x i64) (result i32) |
| ;; CHECK-NEXT: (i32.wrap_i64 |
| ;; CHECK-NEXT: (i64.div_s |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 42) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $wrap-i64-to-i32-local-no (param $x i64) (result i32) |
| ;; We do not optimize here for now as an input ($x) is an i64. TODO |
| (i32.wrap_i64 |
| (i64.div_s |
| (local.get $x) |
| (i64.const 42) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $gt_u-added-constant (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.gt_u |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $gt_u-added-constant (param $x i32) |
| ;; x + C1 > C2 => x > (C2-C1), iff x+C1 and C2-C1 don't over/underflow |
| (drop |
| (i32.gt_u |
| (i32.add |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 5) |
| ) |
| (i32.const 11) |
| ) |
| ) |
| ;; We can optimize even if the constants are equal. |
| (drop |
| (i32.gt_u |
| (i32.add |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 5) |
| ) |
| (i32.const 5) |
| ) |
| ) |
| ;; x + C1 > C2 => x + (C1-C2) > 0, iff x+C1 and C1-C2 don't over/underflow |
| ;; After doing that, further optimizations are possible here. |
| (drop |
| (i32.gt_u |
| (i32.add |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 6) |
| ) |
| (i32.const 5) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $gt_u-added-constant-no (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.gt_u |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.gt_u |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.gt_u |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $gt_u-added-constant-no (param $x i32) |
| ;; As above, but without the shr_u, A is big enough for a possible overflow, |
| ;; and we cannot optimize. |
| (drop |
| (i32.gt_u |
| (i32.add |
| (local.get $x) |
| (i32.const 5) |
| ) |
| (i32.const 11) |
| ) |
| ) |
| ;; With the added constant too big, it might overflow, and we cannot |
| ;; optimize. |
| (drop |
| (i32.gt_u |
| (i32.add |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 0x80000000) |
| ) |
| (i32.const 11) |
| ) |
| ) |
| (drop |
| (i32.gt_u |
| (i32.add |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 0xffffffff) |
| ) |
| (i32.const 11) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $ge_u-added-constant (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_u |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; 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: ) |
| (func $ge_u-added-constant (param $x i32) |
| ;; As above, but with ge rather than gt. We can optimize here. |
| (drop |
| (i32.ge_u |
| (i32.add |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 5) |
| ) |
| (i32.const 11) |
| ) |
| ) |
| (drop |
| (i32.ge_u |
| (i32.add |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 5) |
| ) |
| (i32.const 5) |
| ) |
| ) |
| (drop |
| (i32.ge_u |
| (i32.add |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 6) |
| ) |
| (i32.const 5) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $ge_u-added-constant-no (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_u |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_u |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ge_u |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ge_u-added-constant-no (param $x i32) |
| ;; As above, but with ge rather than gt. We cannot optimize here. |
| (drop |
| (i32.ge_u |
| (i32.add |
| (local.get $x) |
| (i32.const 5) |
| ) |
| (i32.const 11) |
| ) |
| ) |
| (drop |
| (i32.ge_u |
| (i32.add |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 0x80000000) |
| ) |
| (i32.const 11) |
| ) |
| ) |
| (drop |
| (i32.ge_u |
| (i32.add |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 0xffffffff) |
| ) |
| (i32.const 11) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $eq-added-constant (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.eq |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $eq-added-constant (param $x i32) |
| ;; As above, but with eq rather than gt. We can optimize here. |
| (drop |
| (i32.eq |
| (i32.add |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 5) |
| ) |
| (i32.const 11) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $ne-added-constant (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 6) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $ne-added-constant (param $x i32) |
| ;; As above, but with ne rather than gt. We can optimize here. |
| (drop |
| (i32.ne |
| (i32.add |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 5) |
| ) |
| (i32.const 11) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $lt-added-constant (param $x i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.lt_s |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 5) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 11) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $lt-added-constant (param $x i32) |
| ;; As above, but with lt_s rather than gt_u. We can optimize here. |
| (drop |
| (i32.lt_s |
| (i32.add |
| (i32.shr_u |
| (local.get $x) |
| (i32.const 1) |
| ) |
| (i32.const 5) |
| ) |
| (i32.const 11) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $too-few-bits (param $x i32) |
| ;; 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 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 $too-few-bits (param $x i32) |
| ;; Comparison of something with at most 8 bits to something with more than |
| ;; 8. These must all be false. |
| (drop |
| (i32.eq |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 256) |
| ) |
| ) |
| (drop |
| (i32.gt_s |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 256) |
| ) |
| ) |
| (drop |
| (i32.gt_u |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 256) |
| ) |
| ) |
| (drop |
| (i32.ge_s |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 256) |
| ) |
| ) |
| (drop |
| (i32.ge_u |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 256) |
| ) |
| ) |
| ;; These are all true. |
| (drop |
| (i32.ne |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 256) |
| ) |
| ) |
| (drop |
| (i32.lt_s |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 256) |
| ) |
| ) |
| (drop |
| (i32.lt_u |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 256) |
| ) |
| ) |
| (drop |
| (i32.le_s |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 256) |
| ) |
| ) |
| (drop |
| (i32.le_u |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 256) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $too-few-bits-no (param $x i32) |
| ;; 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 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.ne |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.lt_u |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.lt_u |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.le_u |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.le_u |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.gt_u |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.gt_u |
| ;; CHECK-NEXT: (i32.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; 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 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; 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 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $too-few-bits-no (param $x i32) |
| ;; Identical to the above, but the constant is changed from 256 to 255. We |
| ;; cannot optimize here: the number of bits is the same and we can't infer |
| ;; anything. |
| (drop |
| (i32.eq |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 255) |
| ) |
| ) |
| (drop |
| (i32.ne |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 255) |
| ) |
| ) |
| (drop |
| (i32.lt_s |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 255) |
| ) |
| ) |
| (drop |
| (i32.lt_u |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 255) |
| ) |
| ) |
| (drop |
| (i32.le_s |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 255) |
| ) |
| ) |
| (drop |
| (i32.le_u |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 255) |
| ) |
| ) |
| (drop |
| (i32.gt_s |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 255) |
| ) |
| ) |
| (drop |
| (i32.gt_u |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 255) |
| ) |
| ) |
| (drop |
| (i32.ge_s |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 255) |
| ) |
| ) |
| (drop |
| (i32.ge_u |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 255) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $too-few-bits-signed (param $x i32) |
| ;; 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 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; 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: ) |
| (func $too-few-bits-signed (param $x i32) |
| ;; As above, but now using only signed operations and the constant on the |
| ;; right has the sign bit set. The left side is non-negative, which lets us |
| ;; infer the results here. |
| ;; These are all false: |
| (drop |
| (i32.lt_s |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 0x80000000) ;; -2147483648 |
| ) |
| ) |
| (drop |
| (i32.le_s |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 0x80000000) ;; -2147483648 |
| ) |
| ) |
| ;; These are all true: |
| (drop |
| (i32.gt_s |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 0x80000000) ;; -2147483648 |
| ) |
| ) |
| (drop |
| (i32.ge_s |
| (i32.and |
| (local.get $x) |
| (i32.const 255) |
| ) |
| (i32.const 0x80000000) ;; -2147483648 |
| ) |
| ) |
| ;; This cannot be inferred, as the left has too many possible bits (so it |
| ;; may have the sign bit set). |
| (drop |
| (i32.gt_s |
| (local.get $x) |
| (i32.const 0x80000000) ;; -2147483648 |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $too-few-bits-i64 (param $x i64) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i64.eq |
| ;; CHECK-NEXT: (i64.and |
| ;; CHECK-NEXT: (local.get $x) |
| ;; CHECK-NEXT: (i64.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 255) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $too-few-bits-i64 (param $x i64) |
| ;; As above, but with i64 values. We can infer 0 here. |
| (drop |
| (i64.eq |
| (i64.and |
| (local.get $x) |
| (i64.const 255) |
| ) |
| (i64.const 256) |
| ) |
| ) |
| ;; The constant is now 255 and we cannot optimize here. |
| (drop |
| (i64.eq |
| (i64.and |
| (local.get $x) |
| (i64.const 255) |
| ) |
| (i64.const 255) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $skip-added-constants-overflow (result i32) |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $skip-added-constants-overflow (result i32) |
| ;; If we subtracted 0x80000000 - 1 we'd get something that changes sign if |
| ;; the comparison is signed (as the sign bit is no longer set). To avoid |
| ;; that we skip optimizing cases where subtracting the constants might lead |
| ;; to an overflow. |
| (i32.ge_s |
| (i32.add |
| (i32.shr_u |
| (i32.load |
| (i32.const 0) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const 0x80000000) |
| ) |
| ) |
| |
| ;; CHECK: (func $skip-added-constants-overflow-unsigned (result i32) |
| ;; CHECK-NEXT: (i32.ge_u |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 2147483647) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $skip-added-constants-overflow-unsigned (result i32) |
| ;; As above, but unsigned. This is ok for us to optimize. |
| (i32.ge_u |
| (i32.add |
| (i32.shr_u |
| (i32.load |
| (i32.const 0) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const 0x80000000) |
| ) |
| ) |
| |
| ;; CHECK: (func $skip-added-constants-zero (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| (func $skip-added-constants-zero (result i32) |
| ;; A zero in either constant means we should not optimize using an added |
| ;; constant. However, other optimizations kick in here, as adding zero does |
| ;; nothing, and we end up with [max 31 bits] >=_s MIN_INT which is true. |
| (i32.ge_s |
| (i32.add |
| (i32.shr_u |
| (i32.load |
| (i32.const 0) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const 0) |
| ) |
| (i32.const 0x80000000) |
| ) |
| ) |
| |
| ;; CHECK: (func $skip-added-constants-zero-a (result i32) |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -2147483648) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $skip-added-constants-zero-a (result i32) |
| ;; A zero in the last constant means we should not optimize. |
| (i32.ge_s |
| (i32.add |
| (i32.shr_u |
| (i32.load |
| (i32.const 0) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const 0x80000000) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| |
| ;; CHECK: (func $skip-added-constants-zero-b (result i32) |
| ;; CHECK-NEXT: (i32.ge_u |
| ;; CHECK-NEXT: (i32.add |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $skip-added-constants-zero-b (result i32) |
| ;; Parallel case to the above, with a zero in the added constant. We do not |
| ;; optimize. |
| (i32.ge_u |
| (i32.add |
| (i32.shr_u |
| (i32.load |
| (i32.const 0) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const 0) |
| ) |
| ) |
| |
| ;; CHECK: (func $skip-added-constants-negative (result i32) |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -20) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $skip-added-constants-negative (result i32) |
| ;; Reasonable negative constants can be optimized. But the add is |
| ;; canoncalized into a sub, and atm we do not optimize such added constants. |
| (i32.ge_s |
| (i32.add |
| (i32.shr_u |
| (i32.load |
| (i32.const 0) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const -10) |
| ) |
| (i32.const -20) |
| ) |
| ) |
| |
| ;; CHECK: (func $skip-added-constants-negative-flip (result i32) |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 20) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const -10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $skip-added-constants-negative-flip (result i32) |
| ;; As above, but flipped. The add is canoncalized into a sub, and atm we do |
| ;; not optimize such added constants. |
| (i32.ge_s |
| (i32.add |
| (i32.shr_u |
| (i32.load |
| (i32.const 0) |
| ) |
| (i32.const 1) |
| ) |
| (i32.const -20) |
| ) |
| (i32.const -10) |
| ) |
| ) |
| |
| ;; CHECK: (func $skip-added-constants-mix (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| (func $skip-added-constants-mix (result i32) |
| ;; A case of one negative and one positive constant. Here we have |
| ;; [max 16 bits] + 10 >=_s -20 which is always true. |
| (i32.ge_s |
| (i32.add |
| (i32.shr_u |
| (i32.load |
| (i32.const 0) |
| ) |
| (i32.const 16) |
| ) |
| (i32.const 10) |
| ) |
| (i32.const -20) |
| ) |
| ) |
| |
| ;; CHECK: (func $skip-added-constants-mix-flip (result i32) |
| ;; CHECK-NEXT: (i32.ge_s |
| ;; CHECK-NEXT: (i32.sub |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 20) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 10) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $skip-added-constants-mix-flip (result i32) |
| ;; As above, but with sign flipped. The add is canoncalized into a sub, and |
| ;; atm we do not optimize such added constants. |
| (i32.ge_s |
| (i32.add |
| (i32.shr_u |
| (i32.load |
| (i32.const 0) |
| ) |
| (i32.const 16) |
| ) |
| (i32.const -20) |
| ) |
| (i32.const 10) |
| ) |
| ) |
| |
| ;; CHECK: (func $skip-added-constants-mix-flip-other (result i32) |
| ;; CHECK-NEXT: (drop |
| ;; CHECK-NEXT: (i32.shr_u |
| ;; CHECK-NEXT: (i32.load |
| ;; CHECK-NEXT: (i32.const 0) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 16) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i32.const 1) |
| ;; CHECK-NEXT: ) |
| (func $skip-added-constants-mix-flip-other (result i32) |
| ;; As above, but with the sign the same while the absolute values are |
| ;; flipped. Here we have [max 16 bits] + 20 >=_s -10 which is always true. |
| (i32.ge_s |
| (i32.add |
| (i32.shr_u |
| (i32.load |
| (i32.const 0) |
| ) |
| (i32.const 16) |
| ) |
| (i32.const 20) |
| ) |
| (i32.const -10) |
| ) |
| ) |
| |
| ;; CHECK: (func $skip-added-constants-signed-overflow (result i32) |
| ;; CHECK-NEXT: (i64.lt_s |
| ;; CHECK-NEXT: (i64.add |
| ;; CHECK-NEXT: (i64.or |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: (i64.const 9223372036854775807) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 1) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: (i64.const 2) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $skip-added-constants-signed-overflow (result i32) |
| ;; Adding 1 to 0x7fffffffffffffff turns it into 0x8000000000000000, which |
| ;; when signed is -1, that is, we overflow. So we can't subtract 1 from the |
| ;; gt_s arms. |
| ;; (The i64.or is needed to avoid other opts.) |
| (i64.gt_s |
| (i64.const 2) |
| (i64.add |
| (i64.const 1) |
| (i64.or |
| (i64.const 0) |
| (i64.const 0x7fffffffffffffff) |
| ) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $added-constants-unsigned (result i32) |
| ;; CHECK-NEXT: (i64.eqz |
| ;; CHECK-NEXT: (i64.or |
| ;; CHECK-NEXT: (i64.const 0) |
| ;; CHECK-NEXT: (i64.const 9223372036854775807) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| ;; CHECK-NEXT: ) |
| (func $added-constants-unsigned (result i32) |
| ;; As above, but unsigned. This is ok, as it can't overflow as unsigned. |
| (i64.gt_u |
| (i64.const 2) |
| (i64.add |
| (i64.const 1) |
| (i64.or |
| (i64.const 0) |
| (i64.const 0x7fffffffffffffff) |
| ) |
| ) |
| ) |
| ) |
| |
| ;; CHECK: (func $added-constants-remaining-constant (result i32) |
| ;; CHECK-NEXT: (i32.const 32) |
| ;; CHECK-NEXT: ) |
| (func $added-constants-remaining-constant (result i32) |
| ;; optimizeAddedConstants will simplify this step by step and end up with |
| ;; both an accumulated value and a constant to add it to (the 1 at the |
| ;; bottom). We should not hit an assert here and return the proper value, |
| ;; 32. (This is tricky for optimizeAddedConstants because of the shift that |
| ;; does nothing, which it correctly ignores, but it also leads to having |
| ;; something to add at the very end of the process.) |
| (i32.sub ;; This subtracts 33 by 1 to get 32. |
| (i32.add ;; This adds 1 to 32 to get 33. |
| (i32.shl ;; This shift by 32 does nothing, so it is 1. |
| (i32.const 1) |
| (i32.add ;; This is 32 |
| (i32.const 0) |
| (i32.const 32) |
| ) |
| ) |
| (i32.const 32) |
| ) |
| (i32.const 1) |
| ) |
| ) |
| ) |