diff --git a/src/passes/RemoveNonJSOps.cpp b/src/passes/RemoveNonJSOps.cpp index 290eec7c8e5..7c7d9d41982 100644 --- a/src/passes/RemoveNonJSOps.cpp +++ b/src/passes/RemoveNonJSOps.cpp @@ -356,9 +356,20 @@ struct StubUnsupportedJSOpsPass void visitUnary(Unary* curr) { switch (curr->op) { + case ConvertSInt64ToFloat32: case ConvertUInt64ToFloat32: - // See detailed comment in lowerConvertIntToFloat in - // I64ToI32Lowering.cpp. + case TruncSatSFloat32ToInt32: + case TruncSatUFloat32ToInt32: + case TruncSatSFloat64ToInt32: + case TruncSatUFloat64ToInt32: + case TruncSatSFloat32ToInt64: + case TruncSatUFloat32ToInt64: + case TruncSatSFloat64ToInt64: + case TruncSatUFloat64ToInt64: + // f32.convert_i64_s and f32.convert_i64_u do not have perfect rounding + // in all cases (see lowerConvertIntToFloat in I64ToI32Lowering.cpp), + // and trunc_sat operations are lowered using non-saturating conversions + // in wasm2js and I64ToI32Lowering. stubOut(curr->value, curr->type); break; default: { diff --git a/test/lit/passes/stub-unsupported-js.wast b/test/lit/passes/stub-unsupported-js.wast new file mode 100644 index 00000000000..71376900bfe --- /dev/null +++ b/test/lit/passes/stub-unsupported-js.wast @@ -0,0 +1,139 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py and should not be edited. + +;; RUN: wasm-opt %s -all --stub-unsupported-js -S -o - | filecheck %s + +(module + ;; CHECK: (func $convert_s_i64_f32 (type $1) (param $x i64) (result f32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (f32.const 0) + ;; CHECK-NEXT: ) + (func $convert_s_i64_f32 (param $x i64) (result f32) + ;; Signed and unsigned i64 to f32 conversions are stubbed out. + (f32.convert_i64_s + (local.get $x) + ) + ) + + ;; CHECK: (func $convert_u_i64_f32 (type $1) (param $x i64) (result f32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (f32.const 0) + ;; CHECK-NEXT: ) + (func $convert_u_i64_f32 (param $x i64) (result f32) + (f32.convert_i64_u + (local.get $x) + ) + ) + + ;; CHECK: (func $trunc_sat_s_f32_i32 (type $0) (param $x f32) (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + (func $trunc_sat_s_f32_i32 (param $x f32) (result i32) + ;; Nontrapping float-to-int conversions are stubbed out. + (i32.trunc_sat_f32_s + (local.get $x) + ) + ) + + ;; CHECK: (func $trunc_sat_u_f32_i32 (type $0) (param $x f32) (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + (func $trunc_sat_u_f32_i32 (param $x f32) (result i32) + (i32.trunc_sat_f32_u + (local.get $x) + ) + ) + + ;; CHECK: (func $trunc_sat_s_f64_i32 (type $2) (param $x f64) (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + (func $trunc_sat_s_f64_i32 (param $x f64) (result i32) + (i32.trunc_sat_f64_s + (local.get $x) + ) + ) + + ;; CHECK: (func $trunc_sat_u_f64_i32 (type $2) (param $x f64) (result i32) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i32.const 0) + ;; CHECK-NEXT: ) + (func $trunc_sat_u_f64_i32 (param $x f64) (result i32) + (i32.trunc_sat_f64_u + (local.get $x) + ) + ) + + ;; CHECK: (func $trunc_sat_s_f32_i64 (type $3) (param $x f32) (result i64) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i64.const 0) + ;; CHECK-NEXT: ) + (func $trunc_sat_s_f32_i64 (param $x f32) (result i64) + (i64.trunc_sat_f32_s + (local.get $x) + ) + ) + + ;; CHECK: (func $trunc_sat_u_f32_i64 (type $3) (param $x f32) (result i64) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i64.const 0) + ;; CHECK-NEXT: ) + (func $trunc_sat_u_f32_i64 (param $x f32) (result i64) + (i64.trunc_sat_f32_u + (local.get $x) + ) + ) + + ;; CHECK: (func $trunc_sat_s_f64_i64 (type $4) (param $x f64) (result i64) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i64.const 0) + ;; CHECK-NEXT: ) + (func $trunc_sat_s_f64_i64 (param $x f64) (result i64) + (i64.trunc_sat_f64_s + (local.get $x) + ) + ) + + ;; CHECK: (func $trunc_sat_u_f64_i64 (type $4) (param $x f64) (result i64) + ;; CHECK-NEXT: (drop + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: (i64.const 0) + ;; CHECK-NEXT: ) + (func $trunc_sat_u_f64_i64 (param $x f64) (result i64) + (i64.trunc_sat_f64_u + (local.get $x) + ) + ) + + ;; CHECK: (func $supported_trunc (type $0) (param $x f32) (result i32) + ;; CHECK-NEXT: (i32.trunc_f32_s + ;; CHECK-NEXT: (local.get $x) + ;; CHECK-NEXT: ) + ;; CHECK-NEXT: ) + (func $supported_trunc (param $x f32) (result i32) + ;; Trapping float-to-int conversions are not stubbed out. + (i32.trunc_f32_s + (local.get $x) + ) + ) +)