| ;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. | |
| ;; Floating-point numbers are not optimized without fast-math, as NaN operations | |
| ;; do not follow the rules of logic and we might misoptimize them. | |
| ;; RUN: wasm-opt %s --constraint-analysis -all -S -o - | filecheck %s | |
| ;; RUN: wasm-opt %s --constraint-analysis --fast-math -all -S -o - | filecheck %s --check-prefix=FASTM | |
| (module | |
| ;; CHECK: (func $float-zero (type $0) | |
| ;; CHECK-NEXT: (local $f f64) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (f64.eq | |
| ;; CHECK-NEXT: (local.get $f) | |
| ;; CHECK-NEXT: (local.get $f) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (nop) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; FASTM: (func $float-zero (type $0) | |
| ;; FASTM-NEXT: (local $f f64) | |
| ;; FASTM-NEXT: (if | |
| ;; FASTM-NEXT: (i32.const 1) | |
| ;; FASTM-NEXT: (then | |
| ;; FASTM-NEXT: (nop) | |
| ;; FASTM-NEXT: ) | |
| ;; FASTM-NEXT: ) | |
| ;; FASTM-NEXT: ) | |
| (func $float-zero | |
| (local $f f64) | |
| ;; When fast-math is enabled, we can optimize f == f to 1, as NaNs are not | |
| ;; important. | |
| (if | |
| (f64.eq | |
| (local.get $f) | |
| (local.get $f) | |
| ) | |
| (then | |
| (nop) | |
| ) | |
| ) | |
| ) | |
| ;; CHECK: (func $float-negative-zero (type $0) | |
| ;; CHECK-NEXT: (local $f f64) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (f64.eq | |
| ;; CHECK-NEXT: (local.get $f) | |
| ;; CHECK-NEXT: (f64.const -0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (nop) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (if | |
| ;; CHECK-NEXT: (f64.eq | |
| ;; CHECK-NEXT: (local.get $f) | |
| ;; CHECK-NEXT: (f64.const 0) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (then | |
| ;; CHECK-NEXT: (nop) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; FASTM: (func $float-negative-zero (type $0) | |
| ;; FASTM-NEXT: (local $f f64) | |
| ;; FASTM-NEXT: (if | |
| ;; FASTM-NEXT: (i32.const 1) | |
| ;; FASTM-NEXT: (then | |
| ;; FASTM-NEXT: (nop) | |
| ;; FASTM-NEXT: ) | |
| ;; FASTM-NEXT: ) | |
| ;; FASTM-NEXT: (if | |
| ;; FASTM-NEXT: (i32.const 1) | |
| ;; FASTM-NEXT: (then | |
| ;; FASTM-NEXT: (nop) | |
| ;; FASTM-NEXT: ) | |
| ;; FASTM-NEXT: ) | |
| ;; FASTM-NEXT: ) | |
| (func $float-negative-zero | |
| (local $f f64) | |
| ;; Negative zero is equal to zero, even though it has a different bit | |
| ;; pattern. Both conditions here should be optimized to 1 in fast-math | |
| ;; mode (but not otherwise). | |
| (if | |
| (f64.eq | |
| (local.get $f) | |
| (f64.const -0) | |
| ) | |
| (then | |
| (nop) | |
| ) | |
| ) | |
| (if | |
| (f64.eq | |
| (local.get $f) | |
| (f64.const 0) | |
| ) | |
| (then | |
| (nop) | |
| ) | |
| ) | |
| ) | |
| ;; CHECK: (func $float-ne-nan (type $1) (result i32) | |
| ;; CHECK-NEXT: (local $nan f64) | |
| ;; CHECK-NEXT: (local.set $nan | |
| ;; CHECK-NEXT: (f64.const nan:0x8000000000000) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: (f64.ne | |
| ;; CHECK-NEXT: (local.get $nan) | |
| ;; CHECK-NEXT: (local.get $nan) | |
| ;; CHECK-NEXT: ) | |
| ;; CHECK-NEXT: ) | |
| ;; FASTM: (func $float-ne-nan (type $1) (result i32) | |
| ;; FASTM-NEXT: (local $nan f64) | |
| ;; FASTM-NEXT: (local.set $nan | |
| ;; FASTM-NEXT: (f64.const nan:0x8000000000000) | |
| ;; FASTM-NEXT: ) | |
| ;; FASTM-NEXT: (i32.const 0) | |
| ;; FASTM-NEXT: ) | |
| (func $float-ne-nan (result i32) | |
| (local $nan f64) | |
| (local.set $nan | |
| (f64.const nan) | |
| ) | |
| ;; This should be 1: the number is a NaN, and NaN != NaN. However, we | |
| ;; misoptimize this to 0 in fast-math mode (which is fine, as that mode | |
| ;; ignores the possibility of NaNs). In normal mode we do not optimize, | |
| ;; avoiding a misoptimization. | |
| (f64.ne | |
| (local.get $nan) | |
| (local.get $nan) | |
| ) | |
| ) | |
| ) |