;; 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 (result i32))) (type $0 (func (param i32 i64))) ;; CHECK: (type $0 (func (param i32 i64))) ;; CHECK: (import "a" "b" (func $get-f64 (result f64))) (import "a" "b" (func $get-f64 (result f64))) (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 $loop-in (result i32) ;; CHECK-NEXT: (i32.const 6) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (block (result i32) ;; CHECK-NEXT: (i32.const 8) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $loop-in1 (result i32) ;; CHECK-NEXT: (i32.const 7) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (block (result i32) ;; CHECK-NEXT: (i32.const 10) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $loop-in3 (result i32) ;; CHECK-NEXT: (call $and-pos1) ;; CHECK-NEXT: (i32.const 9) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (block (result i32) ;; CHECK-NEXT: (call $and-pos1) ;; CHECK-NEXT: (i32.const 12) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $loop-in5 (result i32) ;; CHECK-NEXT: (i32.const 11) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (loop $loop-in7 (result i32) ;; CHECK-NEXT: (call $and-pos1) ;; CHECK-NEXT: (i32.const 13) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (block (result i32) ;; CHECK-NEXT: (call $and-pos1) ;; CHECK-NEXT: (i32.const 14) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (block (result i32) ;; CHECK-NEXT: (call $and-pos1) ;; CHECK-NEXT: (i32.const 14) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (loop $loop-in10 (result i32) ;; CHECK-NEXT: (call $and-pos1) ;; CHECK-NEXT: (i32.const 13) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $canonicalize-block-loop (drop (i32.and (block (result i32) (i32.const 5) ) (loop (result i32) (i32.const 6) ) )) (drop (i32.and (loop (result i32) (i32.const 7) ) (block (result i32) (i32.const 8) ) )) (drop (i32.and (loop (result i32) (call $and-pos1) (i32.const 9) ) (block (result i32) (i32.const 10) ) )) (drop (i32.and (loop (result i32) (i32.const 11) ) (block (result i32) (call $and-pos1) (i32.const 12) ) )) (drop (i32.and (loop (result i32) (call $and-pos1) (i32.const 13) ) (block (result i32) (call $and-pos1) (i32.const 14) ) )) (drop (i32.and (block (result i32) (call $and-pos1) (i32.const 14) ) (loop (result i32) (call $and-pos1) (i32.const 13) ) )) ) ;; CHECK: (func $canonicalize-gt_s-gt-u ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (i32.gt_u ;; CHECK-NEXT: (i32.const 16) ;; CHECK-NEXT: (i32.const 17) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.gt_u ;; CHECK-NEXT: (i32.const 18) ;; CHECK-NEXT: (i32.const 19) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.and ;; CHECK-NEXT: (i32.gt_u ;; CHECK-NEXT: (i32.const 20) ;; CHECK-NEXT: (i32.const 21) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (i32.gt_u ;; CHECK-NEXT: (i32.const 22) ;; CHECK-NEXT: (i32.const 23) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $canonicalize-gt_s-gt-u (drop (i32.and (i32.gt_s (i32.const 16) (i32.const 17) ) (i32.gt_u (i32.const 18) (i32.const 19) ) )) (drop (i32.and (i32.gt_u (i32.const 20) (i32.const 21) ) (i32.gt_s (i32.const 22) (i32.const 23) ) )) ) ;; CHECK: (func $canonicalize-cmp-near-zero (param $x i32) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.ge_s ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.lt_s ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.ge_s ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.lt_s ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.le_s ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.gt_s ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.eqz ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (i32.ne ;; CHECK-NEXT: (local.get $x) ;; CHECK-NEXT: (i32.const 0) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) (func $canonicalize-cmp-near-zero (param $x i32) ;; i32(x) > -1 ==> x >= 0 (drop (i32.gt_s (local.get $x) (i32.const -1) )) ;; i32(x) <= -1 ==> x < 0 (drop (i32.le_s (local.get $x) (i32.const -1) )) ;; -1 < i32(x) ==> x >= 0 (drop (i32.lt_s (i32.const -1) (local.get $x) )) ;; -1 >= i32(x) ==> x < 0 (drop (i32.ge_s (i32.const -1) (local.get $x) )) ;; i32(x) < 1 ==> x <= 0 (drop (i32.lt_s (local.get $x) (i32.const 1) )) ;; (signed)x >= 1 ==> x > 0 (drop (i32.ge_s (local.get $x) (i32.const 1) )) ;; u32(x) < 1 ==> x == 0 (drop (i32.lt_u (local.get $x) (i32.const 1) )) ;; u32(x) >= 1 ==> x != 0 (drop (i32.ge_u (local.get $x) (i32.const 1) )) ) ;; CHECK: (func $canonicalize-cmp-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 $loop-in (result i32) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: ) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (drop ;; CHECK-NEXT: (local.get $x3) ;; CHECK-NEXT: ) ;; CHECK-NEXT: (local.set $x4 ;; CHECK-NEXT: (if (result i32) ;; CHECK-NEXT: (i32.const 1) ;; CHECK-NEXT: (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 (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 $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-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) ) ) )