[llvm-branch-commits] [llvm] [WebAssembly][GlobalISel] Implement saturating floating-point to int (PR #197259)

Demetrius Kanios via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed May 20 00:39:14 PDT 2026


https://github.com/QuantumSegfault updated https://github.com/llvm/llvm-project/pull/197259

>From b1c21d11fbb6273a8037d302650799c299b3df2a Mon Sep 17 00:00:00 2001
From: Demetrius Kanios <demetrius at kanios.net>
Date: Tue, 12 May 2026 00:49:31 -0700
Subject: [PATCH] Implement saturating fp to int

---
 .../GISel/WebAssemblyLegalizerInfo.cpp        |  18 +-
 .../Target/WebAssembly/WebAssemblyGISel.td    |  13 +
 .../GlobalISel/instructions/fptosi_sat.ll     | 418 +++++++++++++++++
 .../GlobalISel/instructions/fptoui_sat.ll     | 424 ++++++++++++++++++
 4 files changed, 861 insertions(+), 12 deletions(-)
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptosi_sat.ll
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptoui_sat.ll

diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
index 045c939383cf4..86bc68b236ef0 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
@@ -140,18 +140,12 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
       .clampScalar(0, s32, s64)
       .minScalar(1, s32);
 
-  // TODO: once comparison ops are in place
-  /*if (ST.hasNontrappingFPToInt()) {
-    getActionDefinitionsBuilder({G_FPTOSI_SAT, G_FPTOUI_SAT})
-        .legalForCartesianProduct({i32, i64}, {f32, f64})
-        .clampScalar(0, s32, s64)
-        .minScalar(1, s32);
-  } else {
-    getActionDefinitionsBuilder({G_FPTOSI_SAT, G_FPTOUI_SAT})
-        .lowerForCartesianProduct({i32, i64}, {f32, f64})
-        .clampScalar(0, s32, s64)
-        .minScalar(1, s32);
-  }*/
+  getActionDefinitionsBuilder({G_FPTOSI_SAT, G_FPTOUI_SAT})
+      .legalFor(ST.hasNontrappingFPToInt(),
+                {{i32, f32}, {i32, f64}, {i64, f32}, {i64, f64}})
+      .clampScalar(0, s32, s64)
+      .minScalar(1, s32)
+      .lower();
 
   getActionDefinitionsBuilder({G_SITOFP, G_UITOFP})
       .legalForCartesianProduct({f32, f64}, {i32, i64})
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyGISel.td b/llvm/lib/Target/WebAssembly/WebAssemblyGISel.td
index 0e49d61deca67..d7f9b47cdabb5 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyGISel.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyGISel.td
@@ -15,3 +15,16 @@
 
 include "WebAssembly.td"
 include "WebAssemblyCombine.td"
+
+//===----------------------------------------------------------------------===//
+// Miscellaneous patterns
+//===----------------------------------------------------------------------===//
+
+def : Pat<(i32 (fp_to_sint_sat_gi F32:$src)), (I32_TRUNC_S_SAT_F32 F32:$src)>;
+def : Pat<(i32 (fp_to_uint_sat_gi F32:$src)), (I32_TRUNC_U_SAT_F32 F32:$src)>;
+def : Pat<(i32 (fp_to_sint_sat_gi F64:$src)), (I32_TRUNC_S_SAT_F64 F64:$src)>;
+def : Pat<(i32 (fp_to_uint_sat_gi F64:$src)), (I32_TRUNC_U_SAT_F64 F64:$src)>;
+def : Pat<(i64 (fp_to_sint_sat_gi F32:$src)), (I64_TRUNC_S_SAT_F32 F32:$src)>;
+def : Pat<(i64 (fp_to_uint_sat_gi F32:$src)), (I64_TRUNC_U_SAT_F32 F32:$src)>;
+def : Pat<(i64 (fp_to_sint_sat_gi F64:$src)), (I64_TRUNC_S_SAT_F64 F64:$src)>;
+def : Pat<(i64 (fp_to_uint_sat_gi F64:$src)), (I64_TRUNC_U_SAT_F64 F64:$src)>;
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptosi_sat.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptosi_sat.ll
new file mode 100644
index 0000000000000..1168fc9600738
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptosi_sat.ll
@@ -0,0 +1,418 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=-nontrapping-fptoint | FileCheck %s -check-prefix=TRAPPING
+; RUN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=+nontrapping-fptoint | FileCheck %s -check-prefix=NONTRAPPING
+
+target triple = "wasm32-unknown-unknown"
+
+declare i8 @llvm.fptosi.sat.i8.f32(float %f)
+declare i16 @llvm.fptosi.sat.i16.f32(float %f)
+declare i32 @llvm.fptosi.sat.i32.f32(float %f)
+declare i64 @llvm.fptosi.sat.i64.f32(float %f)
+declare i8 @llvm.fptosi.sat.i8.f64(double %f)
+declare i16 @llvm.fptosi.sat.i16.f64(double %f)
+declare i32 @llvm.fptosi.sat.i32.f64(double %f)
+declare i64 @llvm.fptosi.sat.i64.f64(double %f)
+
+define i8 @fptosi_sat_f32_to_i8(float %x) {
+; TRAPPING-LABEL: fptosi_sat_f32_to_i8:
+; TRAPPING:         .functype fptosi_sat_f32_to_i8 (f32) -> (i32)
+; TRAPPING-NEXT:    .local f32, i32, i32, i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    local.get $push9=, 0
+; TRAPPING-NEXT:    f32.const $push1=, -0x1p7
+; TRAPPING-NEXT:    f32.max $push2=, $pop9, $pop1
+; TRAPPING-NEXT:    f32.const $push3=, 0x1.fcp6
+; TRAPPING-NEXT:    f32.min $push10=, $pop2, $pop3
+; TRAPPING-NEXT:    local.set 1, $pop10
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push11=, 1
+; TRAPPING-NEXT:    f32.abs $push5=, $pop11
+; TRAPPING-NEXT:    f32.const $push6=, 0x1p31
+; TRAPPING-NEXT:    f32.lt $push7=, $pop5, $pop6
+; TRAPPING-NEXT:    i32.eqz $push8=, $pop7
+; TRAPPING-NEXT:    br_if 0, $pop8 # 0: down to label1
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push12=, 1
+; TRAPPING-NEXT:    i32.trunc_f32_s $push13=, $pop12
+; TRAPPING-NEXT:    local.set 2, $pop13
+; TRAPPING-NEXT:    br 1 # 1: down to label0
+; TRAPPING-NEXT:  .LBB0_2:
+; TRAPPING-NEXT:    end_block # label1:
+; TRAPPING-NEXT:    i32.const $push14=, -2147483648
+; TRAPPING-NEXT:    local.set 2, $pop14
+; TRAPPING-NEXT:  .LBB0_3:
+; TRAPPING-NEXT:    end_block # label0:
+; TRAPPING-NEXT:    local.get $push15=, 2
+; TRAPPING-NEXT:    local.set 3, $pop15
+; TRAPPING-NEXT:    local.get $push18=, 0
+; TRAPPING-NEXT:    local.get $push17=, 0
+; TRAPPING-NEXT:    f32.ne $push16=, $pop18, $pop17
+; TRAPPING-NEXT:    local.set 4, $pop16
+; TRAPPING-NEXT:    i32.const $push4=, 0
+; TRAPPING-NEXT:    local.get $push20=, 3
+; TRAPPING-NEXT:    local.get $push19=, 4
+; TRAPPING-NEXT:    i32.select $push0=, $pop4, $pop20, $pop19
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptosi_sat_f32_to_i8:
+; NONTRAPPING:         .functype fptosi_sat_f32_to_i8 (f32) -> (i32)
+; NONTRAPPING-NEXT:    .local i32, i32
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push6=, 0
+; NONTRAPPING-NEXT:    f32.const $push1=, -0x1p7
+; NONTRAPPING-NEXT:    f32.max $push2=, $pop6, $pop1
+; NONTRAPPING-NEXT:    f32.const $push3=, 0x1.fcp6
+; NONTRAPPING-NEXT:    f32.min $push4=, $pop2, $pop3
+; NONTRAPPING-NEXT:    i32.trunc_sat_f32_s $push7=, $pop4
+; NONTRAPPING-NEXT:    local.set 1, $pop7
+; NONTRAPPING-NEXT:    local.get $push10=, 0
+; NONTRAPPING-NEXT:    local.get $push9=, 0
+; NONTRAPPING-NEXT:    f32.ne $push8=, $pop10, $pop9
+; NONTRAPPING-NEXT:    local.set 2, $pop8
+; NONTRAPPING-NEXT:    i32.const $push5=, 0
+; NONTRAPPING-NEXT:    local.get $push12=, 1
+; NONTRAPPING-NEXT:    local.get $push11=, 2
+; NONTRAPPING-NEXT:    i32.select $push0=, $pop5, $pop12, $pop11
+; NONTRAPPING-NEXT:    return $pop0
+  %a = call i8 @llvm.fptosi.sat.i8.f32(float %x)
+  ret i8 %a
+}
+
+define i16 @fptosi_sat_f32_to_i16(float %x) {
+; TRAPPING-LABEL: fptosi_sat_f32_to_i16:
+; TRAPPING:         .functype fptosi_sat_f32_to_i16 (f32) -> (i32)
+; TRAPPING-NEXT:    .local f32, i32, i32, i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    local.get $push9=, 0
+; TRAPPING-NEXT:    f32.const $push1=, -0x1p15
+; TRAPPING-NEXT:    f32.max $push2=, $pop9, $pop1
+; TRAPPING-NEXT:    f32.const $push3=, 0x1.fffcp14
+; TRAPPING-NEXT:    f32.min $push10=, $pop2, $pop3
+; TRAPPING-NEXT:    local.set 1, $pop10
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push11=, 1
+; TRAPPING-NEXT:    f32.abs $push5=, $pop11
+; TRAPPING-NEXT:    f32.const $push6=, 0x1p31
+; TRAPPING-NEXT:    f32.lt $push7=, $pop5, $pop6
+; TRAPPING-NEXT:    i32.eqz $push8=, $pop7
+; TRAPPING-NEXT:    br_if 0, $pop8 # 0: down to label3
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push12=, 1
+; TRAPPING-NEXT:    i32.trunc_f32_s $push13=, $pop12
+; TRAPPING-NEXT:    local.set 2, $pop13
+; TRAPPING-NEXT:    br 1 # 1: down to label2
+; TRAPPING-NEXT:  .LBB1_2:
+; TRAPPING-NEXT:    end_block # label3:
+; TRAPPING-NEXT:    i32.const $push14=, -2147483648
+; TRAPPING-NEXT:    local.set 2, $pop14
+; TRAPPING-NEXT:  .LBB1_3:
+; TRAPPING-NEXT:    end_block # label2:
+; TRAPPING-NEXT:    local.get $push15=, 2
+; TRAPPING-NEXT:    local.set 3, $pop15
+; TRAPPING-NEXT:    local.get $push18=, 0
+; TRAPPING-NEXT:    local.get $push17=, 0
+; TRAPPING-NEXT:    f32.ne $push16=, $pop18, $pop17
+; TRAPPING-NEXT:    local.set 4, $pop16
+; TRAPPING-NEXT:    i32.const $push4=, 0
+; TRAPPING-NEXT:    local.get $push20=, 3
+; TRAPPING-NEXT:    local.get $push19=, 4
+; TRAPPING-NEXT:    i32.select $push0=, $pop4, $pop20, $pop19
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptosi_sat_f32_to_i16:
+; NONTRAPPING:         .functype fptosi_sat_f32_to_i16 (f32) -> (i32)
+; NONTRAPPING-NEXT:    .local i32, i32
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push6=, 0
+; NONTRAPPING-NEXT:    f32.const $push1=, -0x1p15
+; NONTRAPPING-NEXT:    f32.max $push2=, $pop6, $pop1
+; NONTRAPPING-NEXT:    f32.const $push3=, 0x1.fffcp14
+; NONTRAPPING-NEXT:    f32.min $push4=, $pop2, $pop3
+; NONTRAPPING-NEXT:    i32.trunc_sat_f32_s $push7=, $pop4
+; NONTRAPPING-NEXT:    local.set 1, $pop7
+; NONTRAPPING-NEXT:    local.get $push10=, 0
+; NONTRAPPING-NEXT:    local.get $push9=, 0
+; NONTRAPPING-NEXT:    f32.ne $push8=, $pop10, $pop9
+; NONTRAPPING-NEXT:    local.set 2, $pop8
+; NONTRAPPING-NEXT:    i32.const $push5=, 0
+; NONTRAPPING-NEXT:    local.get $push12=, 1
+; NONTRAPPING-NEXT:    local.get $push11=, 2
+; NONTRAPPING-NEXT:    i32.select $push0=, $pop5, $pop12, $pop11
+; NONTRAPPING-NEXT:    return $pop0
+  %a = call i16 @llvm.fptosi.sat.i16.f32(float %x)
+  ret i16 %a
+}
+
+define i32 @fptosi_sat_f32_to_i32(float %x) {
+; TRAPPING-LABEL: fptosi_sat_f32_to_i32:
+; TRAPPING:         .functype fptosi_sat_f32_to_i32 (f32) -> (i32)
+; TRAPPING-NEXT:    .local i32, i32, i32, i32, i32, i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    local.get $push12=, 0
+; TRAPPING-NEXT:    f32.const $push1=, -0x1p31
+; TRAPPING-NEXT:    f32.ge $push11=, $pop12, $pop1
+; TRAPPING-NEXT:    local.set 1, $pop11
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push13=, 0
+; TRAPPING-NEXT:    f32.abs $push7=, $pop13
+; TRAPPING-NEXT:    f32.const $push8=, 0x1p31
+; TRAPPING-NEXT:    f32.lt $push9=, $pop7, $pop8
+; TRAPPING-NEXT:    i32.eqz $push10=, $pop9
+; TRAPPING-NEXT:    br_if 0, $pop10 # 0: down to label5
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push14=, 0
+; TRAPPING-NEXT:    i32.trunc_f32_s $push15=, $pop14
+; TRAPPING-NEXT:    local.set 2, $pop15
+; TRAPPING-NEXT:    br 1 # 1: down to label4
+; TRAPPING-NEXT:  .LBB2_2:
+; TRAPPING-NEXT:    end_block # label5:
+; TRAPPING-NEXT:    i32.const $push16=, -2147483648
+; TRAPPING-NEXT:    local.set 2, $pop16
+; TRAPPING-NEXT:  .LBB2_3:
+; TRAPPING-NEXT:    end_block # label4:
+; TRAPPING-NEXT:    local.get $push2=, 2
+; TRAPPING-NEXT:    i32.const $push3=, -2147483648
+; TRAPPING-NEXT:    local.get $push18=, 1
+; TRAPPING-NEXT:    i32.select $push17=, $pop2, $pop3, $pop18
+; TRAPPING-NEXT:    local.set 3, $pop17
+; TRAPPING-NEXT:    local.get $push20=, 0
+; TRAPPING-NEXT:    f32.const $push4=, 0x1.fffffep30
+; TRAPPING-NEXT:    f32.gt $push19=, $pop20, $pop4
+; TRAPPING-NEXT:    local.set 4, $pop19
+; TRAPPING-NEXT:    i32.const $push5=, 2147483647
+; TRAPPING-NEXT:    local.get $push23=, 3
+; TRAPPING-NEXT:    local.get $push22=, 4
+; TRAPPING-NEXT:    i32.select $push21=, $pop5, $pop23, $pop22
+; TRAPPING-NEXT:    local.set 5, $pop21
+; TRAPPING-NEXT:    local.get $push26=, 0
+; TRAPPING-NEXT:    local.get $push25=, 0
+; TRAPPING-NEXT:    f32.ne $push24=, $pop26, $pop25
+; TRAPPING-NEXT:    local.set 6, $pop24
+; TRAPPING-NEXT:    i32.const $push6=, 0
+; TRAPPING-NEXT:    local.get $push28=, 5
+; TRAPPING-NEXT:    local.get $push27=, 6
+; TRAPPING-NEXT:    i32.select $push0=, $pop6, $pop28, $pop27
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptosi_sat_f32_to_i32:
+; NONTRAPPING:         .functype fptosi_sat_f32_to_i32 (f32) -> (i32)
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push1=, 0
+; NONTRAPPING-NEXT:    i32.trunc_sat_f32_s $push0=, $pop1
+; NONTRAPPING-NEXT:    return $pop0
+  %a = call i32 @llvm.fptosi.sat.i32.f32(float %x)
+  ret i32 %a
+}
+
+define i64 @fptosi_sat_f32_to_i64(float %x) {
+; TRAPPING-LABEL: fptosi_sat_f32_to_i64:
+; TRAPPING:         .functype fptosi_sat_f32_to_i64 (f32) -> (i64)
+; TRAPPING-NEXT:    .local i32, i64, i64, i32, i64, i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    local.get $push12=, 0
+; TRAPPING-NEXT:    f32.const $push1=, -0x1p63
+; TRAPPING-NEXT:    f32.ge $push11=, $pop12, $pop1
+; TRAPPING-NEXT:    local.set 1, $pop11
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push13=, 0
+; TRAPPING-NEXT:    f32.abs $push7=, $pop13
+; TRAPPING-NEXT:    f32.const $push8=, 0x1p63
+; TRAPPING-NEXT:    f32.lt $push9=, $pop7, $pop8
+; TRAPPING-NEXT:    i32.eqz $push10=, $pop9
+; TRAPPING-NEXT:    br_if 0, $pop10 # 0: down to label7
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push14=, 0
+; TRAPPING-NEXT:    i64.trunc_f32_s $push15=, $pop14
+; TRAPPING-NEXT:    local.set 2, $pop15
+; TRAPPING-NEXT:    br 1 # 1: down to label6
+; TRAPPING-NEXT:  .LBB3_2:
+; TRAPPING-NEXT:    end_block # label7:
+; TRAPPING-NEXT:    i64.const $push16=, -9223372036854775808
+; TRAPPING-NEXT:    local.set 2, $pop16
+; TRAPPING-NEXT:  .LBB3_3:
+; TRAPPING-NEXT:    end_block # label6:
+; TRAPPING-NEXT:    local.get $push2=, 2
+; TRAPPING-NEXT:    i64.const $push3=, -9223372036854775808
+; TRAPPING-NEXT:    local.get $push18=, 1
+; TRAPPING-NEXT:    i64.select $push17=, $pop2, $pop3, $pop18
+; TRAPPING-NEXT:    local.set 3, $pop17
+; TRAPPING-NEXT:    local.get $push20=, 0
+; TRAPPING-NEXT:    f32.const $push4=, 0x1.fffffep62
+; TRAPPING-NEXT:    f32.gt $push19=, $pop20, $pop4
+; TRAPPING-NEXT:    local.set 4, $pop19
+; TRAPPING-NEXT:    i64.const $push5=, 9223372036854775807
+; TRAPPING-NEXT:    local.get $push23=, 3
+; TRAPPING-NEXT:    local.get $push22=, 4
+; TRAPPING-NEXT:    i64.select $push21=, $pop5, $pop23, $pop22
+; TRAPPING-NEXT:    local.set 5, $pop21
+; TRAPPING-NEXT:    local.get $push26=, 0
+; TRAPPING-NEXT:    local.get $push25=, 0
+; TRAPPING-NEXT:    f32.ne $push24=, $pop26, $pop25
+; TRAPPING-NEXT:    local.set 6, $pop24
+; TRAPPING-NEXT:    i64.const $push6=, 0
+; TRAPPING-NEXT:    local.get $push28=, 5
+; TRAPPING-NEXT:    local.get $push27=, 6
+; TRAPPING-NEXT:    i64.select $push0=, $pop6, $pop28, $pop27
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptosi_sat_f32_to_i64:
+; NONTRAPPING:         .functype fptosi_sat_f32_to_i64 (f32) -> (i64)
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push1=, 0
+; NONTRAPPING-NEXT:    i64.trunc_sat_f32_s $push0=, $pop1
+; NONTRAPPING-NEXT:    return $pop0
+  %a = call i64 @llvm.fptosi.sat.i64.f32(float %x)
+  ret i64 %a
+}
+
+define i8 @fptosi_sat_f64_to_i8(double %x) {
+; TRAPPING-LABEL: fptosi_sat_f64_to_i8:
+; TRAPPING:         .functype fptosi_sat_f64_to_i8 (f64) -> (i32)
+; TRAPPING-NEXT:    .local i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push5=, 0
+; TRAPPING-NEXT:    f64.abs $push1=, $pop5
+; TRAPPING-NEXT:    f64.const $push2=, 0x1p31
+; TRAPPING-NEXT:    f64.lt $push3=, $pop1, $pop2
+; TRAPPING-NEXT:    i32.eqz $push4=, $pop3
+; TRAPPING-NEXT:    br_if 0, $pop4 # 0: down to label9
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push6=, 0
+; TRAPPING-NEXT:    i32.trunc_f64_s $push7=, $pop6
+; TRAPPING-NEXT:    local.set 1, $pop7
+; TRAPPING-NEXT:    br 1 # 1: down to label8
+; TRAPPING-NEXT:  .LBB4_2:
+; TRAPPING-NEXT:    end_block # label9:
+; TRAPPING-NEXT:    i32.const $push8=, -2147483648
+; TRAPPING-NEXT:    local.set 1, $pop8
+; TRAPPING-NEXT:  .LBB4_3:
+; TRAPPING-NEXT:    end_block # label8:
+; TRAPPING-NEXT:    local.get $push0=, 1
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptosi_sat_f64_to_i8:
+; NONTRAPPING:         .functype fptosi_sat_f64_to_i8 (f64) -> (i32)
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push1=, 0
+; NONTRAPPING-NEXT:    i32.trunc_sat_f64_s $push0=, $pop1
+; NONTRAPPING-NEXT:    return $pop0
+  %a = fptosi double %x to i8
+  ret i8 %a
+}
+
+define i16 @fptosi_sat_f64_to_i16(double %x) {
+; TRAPPING-LABEL: fptosi_sat_f64_to_i16:
+; TRAPPING:         .functype fptosi_sat_f64_to_i16 (f64) -> (i32)
+; TRAPPING-NEXT:    .local i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push5=, 0
+; TRAPPING-NEXT:    f64.abs $push1=, $pop5
+; TRAPPING-NEXT:    f64.const $push2=, 0x1p31
+; TRAPPING-NEXT:    f64.lt $push3=, $pop1, $pop2
+; TRAPPING-NEXT:    i32.eqz $push4=, $pop3
+; TRAPPING-NEXT:    br_if 0, $pop4 # 0: down to label11
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push6=, 0
+; TRAPPING-NEXT:    i32.trunc_f64_s $push7=, $pop6
+; TRAPPING-NEXT:    local.set 1, $pop7
+; TRAPPING-NEXT:    br 1 # 1: down to label10
+; TRAPPING-NEXT:  .LBB5_2:
+; TRAPPING-NEXT:    end_block # label11:
+; TRAPPING-NEXT:    i32.const $push8=, -2147483648
+; TRAPPING-NEXT:    local.set 1, $pop8
+; TRAPPING-NEXT:  .LBB5_3:
+; TRAPPING-NEXT:    end_block # label10:
+; TRAPPING-NEXT:    local.get $push0=, 1
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptosi_sat_f64_to_i16:
+; NONTRAPPING:         .functype fptosi_sat_f64_to_i16 (f64) -> (i32)
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push1=, 0
+; NONTRAPPING-NEXT:    i32.trunc_sat_f64_s $push0=, $pop1
+; NONTRAPPING-NEXT:    return $pop0
+  %a = fptosi double %x to i16
+  ret i16 %a
+}
+
+define i32 @fptosi_sat_f64_to_i32(double %x) {
+; TRAPPING-LABEL: fptosi_sat_f64_to_i32:
+; TRAPPING:         .functype fptosi_sat_f64_to_i32 (f64) -> (i32)
+; TRAPPING-NEXT:    .local i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push5=, 0
+; TRAPPING-NEXT:    f64.abs $push1=, $pop5
+; TRAPPING-NEXT:    f64.const $push2=, 0x1p31
+; TRAPPING-NEXT:    f64.lt $push3=, $pop1, $pop2
+; TRAPPING-NEXT:    i32.eqz $push4=, $pop3
+; TRAPPING-NEXT:    br_if 0, $pop4 # 0: down to label13
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push6=, 0
+; TRAPPING-NEXT:    i32.trunc_f64_s $push7=, $pop6
+; TRAPPING-NEXT:    local.set 1, $pop7
+; TRAPPING-NEXT:    br 1 # 1: down to label12
+; TRAPPING-NEXT:  .LBB6_2:
+; TRAPPING-NEXT:    end_block # label13:
+; TRAPPING-NEXT:    i32.const $push8=, -2147483648
+; TRAPPING-NEXT:    local.set 1, $pop8
+; TRAPPING-NEXT:  .LBB6_3:
+; TRAPPING-NEXT:    end_block # label12:
+; TRAPPING-NEXT:    local.get $push0=, 1
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptosi_sat_f64_to_i32:
+; NONTRAPPING:         .functype fptosi_sat_f64_to_i32 (f64) -> (i32)
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push1=, 0
+; NONTRAPPING-NEXT:    i32.trunc_sat_f64_s $push0=, $pop1
+; NONTRAPPING-NEXT:    return $pop0
+  %a = fptosi double %x to i32
+  ret i32 %a
+}
+
+define i64 @fptosi_sat_f64_to_i64(double %x) {
+; TRAPPING-LABEL: fptosi_sat_f64_to_i64:
+; TRAPPING:         .functype fptosi_sat_f64_to_i64 (f64) -> (i64)
+; TRAPPING-NEXT:    .local i64
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push5=, 0
+; TRAPPING-NEXT:    f64.abs $push1=, $pop5
+; TRAPPING-NEXT:    f64.const $push2=, 0x1p63
+; TRAPPING-NEXT:    f64.lt $push3=, $pop1, $pop2
+; TRAPPING-NEXT:    i32.eqz $push4=, $pop3
+; TRAPPING-NEXT:    br_if 0, $pop4 # 0: down to label15
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push6=, 0
+; TRAPPING-NEXT:    i64.trunc_f64_s $push7=, $pop6
+; TRAPPING-NEXT:    local.set 1, $pop7
+; TRAPPING-NEXT:    br 1 # 1: down to label14
+; TRAPPING-NEXT:  .LBB7_2:
+; TRAPPING-NEXT:    end_block # label15:
+; TRAPPING-NEXT:    i64.const $push8=, -9223372036854775808
+; TRAPPING-NEXT:    local.set 1, $pop8
+; TRAPPING-NEXT:  .LBB7_3:
+; TRAPPING-NEXT:    end_block # label14:
+; TRAPPING-NEXT:    local.get $push0=, 1
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptosi_sat_f64_to_i64:
+; NONTRAPPING:         .functype fptosi_sat_f64_to_i64 (f64) -> (i64)
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push1=, 0
+; NONTRAPPING-NEXT:    i64.trunc_sat_f64_s $push0=, $pop1
+; NONTRAPPING-NEXT:    return $pop0
+  %a = fptosi double %x to i64
+  ret i64 %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptoui_sat.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptoui_sat.ll
new file mode 100644
index 0000000000000..4987344344d48
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptoui_sat.ll
@@ -0,0 +1,424 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=-nontrapping-fptoint | FileCheck %s -check-prefix=TRAPPING
+; RUN: llc < %s -O0 -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=+nontrapping-fptoint | FileCheck %s -check-prefix=NONTRAPPING
+
+target triple = "wasm32-unknown-unknown"
+
+declare i8 @llvm.fptoui.sat.i8.f32(float %f)
+declare i16 @llvm.fptoui.sat.i16.f32(float %f)
+declare i32 @llvm.fptoui.sat.i32.f32(float %f)
+declare i64 @llvm.fptoui.sat.i64.f32(float %f)
+declare i8 @llvm.fptoui.sat.i8.f64(double %f)
+declare i16 @llvm.fptoui.sat.i16.f64(double %f)
+declare i32 @llvm.fptoui.sat.i32.f64(double %f)
+declare i64 @llvm.fptoui.sat.i64.f64(double %f)
+
+define i8 @fptoui_sat_f32_to_i8(float %x) {
+; TRAPPING-LABEL: fptoui_sat_f32_to_i8:
+; TRAPPING:         .functype fptoui_sat_f32_to_i8 (f32) -> (i32)
+; TRAPPING-NEXT:    .local f32, i32, i32, i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    local.get $push11=, 0
+; TRAPPING-NEXT:    f32.const $push1=, 0x0p0
+; TRAPPING-NEXT:    f32.max $push2=, $pop11, $pop1
+; TRAPPING-NEXT:    f32.const $push3=, 0x1.fep7
+; TRAPPING-NEXT:    f32.min $push12=, $pop2, $pop3
+; TRAPPING-NEXT:    local.set 1, $pop12
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push13=, 1
+; TRAPPING-NEXT:    f32.const $push5=, 0x1p32
+; TRAPPING-NEXT:    f32.lt $push6=, $pop13, $pop5
+; TRAPPING-NEXT:    local.get $push14=, 1
+; TRAPPING-NEXT:    f32.const $push8=, 0x0p0
+; TRAPPING-NEXT:    f32.ge $push9=, $pop14, $pop8
+; TRAPPING-NEXT:    i32.and $push10=, $pop6, $pop9
+; TRAPPING-NEXT:    i32.eqz $push7=, $pop10
+; TRAPPING-NEXT:    br_if 0, $pop7 # 0: down to label1
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push15=, 1
+; TRAPPING-NEXT:    i32.trunc_f32_u $push16=, $pop15
+; TRAPPING-NEXT:    local.set 2, $pop16
+; TRAPPING-NEXT:    br 1 # 1: down to label0
+; TRAPPING-NEXT:  .LBB0_2:
+; TRAPPING-NEXT:    end_block # label1:
+; TRAPPING-NEXT:    i32.const $push17=, 0
+; TRAPPING-NEXT:    local.set 2, $pop17
+; TRAPPING-NEXT:  .LBB0_3:
+; TRAPPING-NEXT:    end_block # label0:
+; TRAPPING-NEXT:    local.get $push18=, 2
+; TRAPPING-NEXT:    local.set 3, $pop18
+; TRAPPING-NEXT:    local.get $push21=, 0
+; TRAPPING-NEXT:    local.get $push20=, 0
+; TRAPPING-NEXT:    f32.ne $push19=, $pop21, $pop20
+; TRAPPING-NEXT:    local.set 4, $pop19
+; TRAPPING-NEXT:    i32.const $push4=, 0
+; TRAPPING-NEXT:    local.get $push23=, 3
+; TRAPPING-NEXT:    local.get $push22=, 4
+; TRAPPING-NEXT:    i32.select $push0=, $pop4, $pop23, $pop22
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptoui_sat_f32_to_i8:
+; NONTRAPPING:         .functype fptoui_sat_f32_to_i8 (f32) -> (i32)
+; NONTRAPPING-NEXT:    .local i32, i32
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push6=, 0
+; NONTRAPPING-NEXT:    f32.const $push1=, 0x0p0
+; NONTRAPPING-NEXT:    f32.max $push2=, $pop6, $pop1
+; NONTRAPPING-NEXT:    f32.const $push3=, 0x1.fep7
+; NONTRAPPING-NEXT:    f32.min $push4=, $pop2, $pop3
+; NONTRAPPING-NEXT:    i32.trunc_sat_f32_u $push7=, $pop4
+; NONTRAPPING-NEXT:    local.set 1, $pop7
+; NONTRAPPING-NEXT:    local.get $push10=, 0
+; NONTRAPPING-NEXT:    local.get $push9=, 0
+; NONTRAPPING-NEXT:    f32.ne $push8=, $pop10, $pop9
+; NONTRAPPING-NEXT:    local.set 2, $pop8
+; NONTRAPPING-NEXT:    i32.const $push5=, 0
+; NONTRAPPING-NEXT:    local.get $push12=, 1
+; NONTRAPPING-NEXT:    local.get $push11=, 2
+; NONTRAPPING-NEXT:    i32.select $push0=, $pop5, $pop12, $pop11
+; NONTRAPPING-NEXT:    return $pop0
+  %a = call i8 @llvm.fptoui.sat.i8.f32(float %x)
+  ret i8 %a
+}
+
+define i16 @fptoui_sat_f32_to_i16(float %x) {
+; TRAPPING-LABEL: fptoui_sat_f32_to_i16:
+; TRAPPING:         .functype fptoui_sat_f32_to_i16 (f32) -> (i32)
+; TRAPPING-NEXT:    .local f32, i32, i32, i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    local.get $push11=, 0
+; TRAPPING-NEXT:    f32.const $push1=, 0x0p0
+; TRAPPING-NEXT:    f32.max $push2=, $pop11, $pop1
+; TRAPPING-NEXT:    f32.const $push3=, 0x1.fffep15
+; TRAPPING-NEXT:    f32.min $push12=, $pop2, $pop3
+; TRAPPING-NEXT:    local.set 1, $pop12
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push13=, 1
+; TRAPPING-NEXT:    f32.const $push5=, 0x1p32
+; TRAPPING-NEXT:    f32.lt $push6=, $pop13, $pop5
+; TRAPPING-NEXT:    local.get $push14=, 1
+; TRAPPING-NEXT:    f32.const $push8=, 0x0p0
+; TRAPPING-NEXT:    f32.ge $push9=, $pop14, $pop8
+; TRAPPING-NEXT:    i32.and $push10=, $pop6, $pop9
+; TRAPPING-NEXT:    i32.eqz $push7=, $pop10
+; TRAPPING-NEXT:    br_if 0, $pop7 # 0: down to label3
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push15=, 1
+; TRAPPING-NEXT:    i32.trunc_f32_u $push16=, $pop15
+; TRAPPING-NEXT:    local.set 2, $pop16
+; TRAPPING-NEXT:    br 1 # 1: down to label2
+; TRAPPING-NEXT:  .LBB1_2:
+; TRAPPING-NEXT:    end_block # label3:
+; TRAPPING-NEXT:    i32.const $push17=, 0
+; TRAPPING-NEXT:    local.set 2, $pop17
+; TRAPPING-NEXT:  .LBB1_3:
+; TRAPPING-NEXT:    end_block # label2:
+; TRAPPING-NEXT:    local.get $push18=, 2
+; TRAPPING-NEXT:    local.set 3, $pop18
+; TRAPPING-NEXT:    local.get $push21=, 0
+; TRAPPING-NEXT:    local.get $push20=, 0
+; TRAPPING-NEXT:    f32.ne $push19=, $pop21, $pop20
+; TRAPPING-NEXT:    local.set 4, $pop19
+; TRAPPING-NEXT:    i32.const $push4=, 0
+; TRAPPING-NEXT:    local.get $push23=, 3
+; TRAPPING-NEXT:    local.get $push22=, 4
+; TRAPPING-NEXT:    i32.select $push0=, $pop4, $pop23, $pop22
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptoui_sat_f32_to_i16:
+; NONTRAPPING:         .functype fptoui_sat_f32_to_i16 (f32) -> (i32)
+; NONTRAPPING-NEXT:    .local i32, i32
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push6=, 0
+; NONTRAPPING-NEXT:    f32.const $push1=, 0x0p0
+; NONTRAPPING-NEXT:    f32.max $push2=, $pop6, $pop1
+; NONTRAPPING-NEXT:    f32.const $push3=, 0x1.fffep15
+; NONTRAPPING-NEXT:    f32.min $push4=, $pop2, $pop3
+; NONTRAPPING-NEXT:    i32.trunc_sat_f32_u $push7=, $pop4
+; NONTRAPPING-NEXT:    local.set 1, $pop7
+; NONTRAPPING-NEXT:    local.get $push10=, 0
+; NONTRAPPING-NEXT:    local.get $push9=, 0
+; NONTRAPPING-NEXT:    f32.ne $push8=, $pop10, $pop9
+; NONTRAPPING-NEXT:    local.set 2, $pop8
+; NONTRAPPING-NEXT:    i32.const $push5=, 0
+; NONTRAPPING-NEXT:    local.get $push12=, 1
+; NONTRAPPING-NEXT:    local.get $push11=, 2
+; NONTRAPPING-NEXT:    i32.select $push0=, $pop5, $pop12, $pop11
+; NONTRAPPING-NEXT:    return $pop0
+  %a = call i16 @llvm.fptoui.sat.i16.f32(float %x)
+  ret i16 %a
+}
+
+define i32 @fptoui_sat_f32_to_i32(float %x) {
+; TRAPPING-LABEL: fptoui_sat_f32_to_i32:
+; TRAPPING:         .functype fptoui_sat_f32_to_i32 (f32) -> (i32)
+; TRAPPING-NEXT:    .local i32, i32, i32, i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    local.get $push13=, 0
+; TRAPPING-NEXT:    f32.const $push1=, 0x0p0
+; TRAPPING-NEXT:    f32.ge $push12=, $pop13, $pop1
+; TRAPPING-NEXT:    local.set 1, $pop12
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push14=, 0
+; TRAPPING-NEXT:    f32.const $push6=, 0x1p32
+; TRAPPING-NEXT:    f32.lt $push7=, $pop14, $pop6
+; TRAPPING-NEXT:    local.get $push15=, 0
+; TRAPPING-NEXT:    f32.const $push9=, 0x0p0
+; TRAPPING-NEXT:    f32.ge $push10=, $pop15, $pop9
+; TRAPPING-NEXT:    i32.and $push11=, $pop7, $pop10
+; TRAPPING-NEXT:    i32.eqz $push8=, $pop11
+; TRAPPING-NEXT:    br_if 0, $pop8 # 0: down to label5
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push16=, 0
+; TRAPPING-NEXT:    i32.trunc_f32_u $push17=, $pop16
+; TRAPPING-NEXT:    local.set 2, $pop17
+; TRAPPING-NEXT:    br 1 # 1: down to label4
+; TRAPPING-NEXT:  .LBB2_2:
+; TRAPPING-NEXT:    end_block # label5:
+; TRAPPING-NEXT:    i32.const $push18=, 0
+; TRAPPING-NEXT:    local.set 2, $pop18
+; TRAPPING-NEXT:  .LBB2_3:
+; TRAPPING-NEXT:    end_block # label4:
+; TRAPPING-NEXT:    local.get $push2=, 2
+; TRAPPING-NEXT:    i32.const $push3=, 0
+; TRAPPING-NEXT:    local.get $push20=, 1
+; TRAPPING-NEXT:    i32.select $push19=, $pop2, $pop3, $pop20
+; TRAPPING-NEXT:    local.set 3, $pop19
+; TRAPPING-NEXT:    local.get $push22=, 0
+; TRAPPING-NEXT:    f32.const $push4=, 0x1.fffffep31
+; TRAPPING-NEXT:    f32.gt $push21=, $pop22, $pop4
+; TRAPPING-NEXT:    local.set 4, $pop21
+; TRAPPING-NEXT:    i32.const $push5=, -1
+; TRAPPING-NEXT:    local.get $push24=, 3
+; TRAPPING-NEXT:    local.get $push23=, 4
+; TRAPPING-NEXT:    i32.select $push0=, $pop5, $pop24, $pop23
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptoui_sat_f32_to_i32:
+; NONTRAPPING:         .functype fptoui_sat_f32_to_i32 (f32) -> (i32)
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push1=, 0
+; NONTRAPPING-NEXT:    i32.trunc_sat_f32_u $push0=, $pop1
+; NONTRAPPING-NEXT:    return $pop0
+  %a = call i32 @llvm.fptoui.sat.i32.f32(float %x)
+  ret i32 %a
+}
+
+define i64 @fptoui_sat_f32_to_i64(float %x) {
+; TRAPPING-LABEL: fptoui_sat_f32_to_i64:
+; TRAPPING:         .functype fptoui_sat_f32_to_i64 (f32) -> (i64)
+; TRAPPING-NEXT:    .local i32, i64, i64, i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    local.get $push13=, 0
+; TRAPPING-NEXT:    f32.const $push1=, 0x0p0
+; TRAPPING-NEXT:    f32.ge $push12=, $pop13, $pop1
+; TRAPPING-NEXT:    local.set 1, $pop12
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push14=, 0
+; TRAPPING-NEXT:    f32.const $push6=, 0x1p64
+; TRAPPING-NEXT:    f32.lt $push7=, $pop14, $pop6
+; TRAPPING-NEXT:    local.get $push15=, 0
+; TRAPPING-NEXT:    f32.const $push9=, 0x0p0
+; TRAPPING-NEXT:    f32.ge $push10=, $pop15, $pop9
+; TRAPPING-NEXT:    i32.and $push11=, $pop7, $pop10
+; TRAPPING-NEXT:    i32.eqz $push8=, $pop11
+; TRAPPING-NEXT:    br_if 0, $pop8 # 0: down to label7
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push16=, 0
+; TRAPPING-NEXT:    i64.trunc_f32_u $push17=, $pop16
+; TRAPPING-NEXT:    local.set 2, $pop17
+; TRAPPING-NEXT:    br 1 # 1: down to label6
+; TRAPPING-NEXT:  .LBB3_2:
+; TRAPPING-NEXT:    end_block # label7:
+; TRAPPING-NEXT:    i64.const $push18=, 0
+; TRAPPING-NEXT:    local.set 2, $pop18
+; TRAPPING-NEXT:  .LBB3_3:
+; TRAPPING-NEXT:    end_block # label6:
+; TRAPPING-NEXT:    local.get $push2=, 2
+; TRAPPING-NEXT:    i64.const $push3=, 0
+; TRAPPING-NEXT:    local.get $push20=, 1
+; TRAPPING-NEXT:    i64.select $push19=, $pop2, $pop3, $pop20
+; TRAPPING-NEXT:    local.set 3, $pop19
+; TRAPPING-NEXT:    local.get $push22=, 0
+; TRAPPING-NEXT:    f32.const $push4=, 0x1.fffffep63
+; TRAPPING-NEXT:    f32.gt $push21=, $pop22, $pop4
+; TRAPPING-NEXT:    local.set 4, $pop21
+; TRAPPING-NEXT:    i64.const $push5=, -1
+; TRAPPING-NEXT:    local.get $push24=, 3
+; TRAPPING-NEXT:    local.get $push23=, 4
+; TRAPPING-NEXT:    i64.select $push0=, $pop5, $pop24, $pop23
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptoui_sat_f32_to_i64:
+; NONTRAPPING:         .functype fptoui_sat_f32_to_i64 (f32) -> (i64)
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push1=, 0
+; NONTRAPPING-NEXT:    i64.trunc_sat_f32_u $push0=, $pop1
+; NONTRAPPING-NEXT:    return $pop0
+  %a = call i64 @llvm.fptoui.sat.i64.f32(float %x)
+  ret i64 %a
+}
+
+define i8 @fptoui_sat_f64_to_i8(double %x) {
+; TRAPPING-LABEL: fptoui_sat_f64_to_i8:
+; TRAPPING:         .functype fptoui_sat_f64_to_i8 (f64) -> (i32)
+; TRAPPING-NEXT:    .local i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push7=, 0
+; TRAPPING-NEXT:    f64.const $push1=, 0x1p32
+; TRAPPING-NEXT:    f64.lt $push2=, $pop7, $pop1
+; TRAPPING-NEXT:    local.get $push8=, 0
+; TRAPPING-NEXT:    f64.const $push4=, 0x0p0
+; TRAPPING-NEXT:    f64.ge $push5=, $pop8, $pop4
+; TRAPPING-NEXT:    i32.and $push6=, $pop2, $pop5
+; TRAPPING-NEXT:    i32.eqz $push3=, $pop6
+; TRAPPING-NEXT:    br_if 0, $pop3 # 0: down to label9
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push9=, 0
+; TRAPPING-NEXT:    i32.trunc_f64_u $push10=, $pop9
+; TRAPPING-NEXT:    local.set 1, $pop10
+; TRAPPING-NEXT:    br 1 # 1: down to label8
+; TRAPPING-NEXT:  .LBB4_2:
+; TRAPPING-NEXT:    end_block # label9:
+; TRAPPING-NEXT:    i32.const $push11=, 0
+; TRAPPING-NEXT:    local.set 1, $pop11
+; TRAPPING-NEXT:  .LBB4_3:
+; TRAPPING-NEXT:    end_block # label8:
+; TRAPPING-NEXT:    local.get $push0=, 1
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptoui_sat_f64_to_i8:
+; NONTRAPPING:         .functype fptoui_sat_f64_to_i8 (f64) -> (i32)
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push1=, 0
+; NONTRAPPING-NEXT:    i32.trunc_sat_f64_u $push0=, $pop1
+; NONTRAPPING-NEXT:    return $pop0
+  %a = fptoui double %x to i8
+  ret i8 %a
+}
+
+define i16 @fptoui_sat_f64_to_i16(double %x) {
+; TRAPPING-LABEL: fptoui_sat_f64_to_i16:
+; TRAPPING:         .functype fptoui_sat_f64_to_i16 (f64) -> (i32)
+; TRAPPING-NEXT:    .local i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push7=, 0
+; TRAPPING-NEXT:    f64.const $push1=, 0x1p32
+; TRAPPING-NEXT:    f64.lt $push2=, $pop7, $pop1
+; TRAPPING-NEXT:    local.get $push8=, 0
+; TRAPPING-NEXT:    f64.const $push4=, 0x0p0
+; TRAPPING-NEXT:    f64.ge $push5=, $pop8, $pop4
+; TRAPPING-NEXT:    i32.and $push6=, $pop2, $pop5
+; TRAPPING-NEXT:    i32.eqz $push3=, $pop6
+; TRAPPING-NEXT:    br_if 0, $pop3 # 0: down to label11
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push9=, 0
+; TRAPPING-NEXT:    i32.trunc_f64_u $push10=, $pop9
+; TRAPPING-NEXT:    local.set 1, $pop10
+; TRAPPING-NEXT:    br 1 # 1: down to label10
+; TRAPPING-NEXT:  .LBB5_2:
+; TRAPPING-NEXT:    end_block # label11:
+; TRAPPING-NEXT:    i32.const $push11=, 0
+; TRAPPING-NEXT:    local.set 1, $pop11
+; TRAPPING-NEXT:  .LBB5_3:
+; TRAPPING-NEXT:    end_block # label10:
+; TRAPPING-NEXT:    local.get $push0=, 1
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptoui_sat_f64_to_i16:
+; NONTRAPPING:         .functype fptoui_sat_f64_to_i16 (f64) -> (i32)
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push1=, 0
+; NONTRAPPING-NEXT:    i32.trunc_sat_f64_u $push0=, $pop1
+; NONTRAPPING-NEXT:    return $pop0
+  %a = fptoui double %x to i16
+  ret i16 %a
+}
+
+define i32 @fptoui_sat_f64_to_i32(double %x) {
+; TRAPPING-LABEL: fptoui_sat_f64_to_i32:
+; TRAPPING:         .functype fptoui_sat_f64_to_i32 (f64) -> (i32)
+; TRAPPING-NEXT:    .local i32
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push7=, 0
+; TRAPPING-NEXT:    f64.const $push1=, 0x1p32
+; TRAPPING-NEXT:    f64.lt $push2=, $pop7, $pop1
+; TRAPPING-NEXT:    local.get $push8=, 0
+; TRAPPING-NEXT:    f64.const $push4=, 0x0p0
+; TRAPPING-NEXT:    f64.ge $push5=, $pop8, $pop4
+; TRAPPING-NEXT:    i32.and $push6=, $pop2, $pop5
+; TRAPPING-NEXT:    i32.eqz $push3=, $pop6
+; TRAPPING-NEXT:    br_if 0, $pop3 # 0: down to label13
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push9=, 0
+; TRAPPING-NEXT:    i32.trunc_f64_u $push10=, $pop9
+; TRAPPING-NEXT:    local.set 1, $pop10
+; TRAPPING-NEXT:    br 1 # 1: down to label12
+; TRAPPING-NEXT:  .LBB6_2:
+; TRAPPING-NEXT:    end_block # label13:
+; TRAPPING-NEXT:    i32.const $push11=, 0
+; TRAPPING-NEXT:    local.set 1, $pop11
+; TRAPPING-NEXT:  .LBB6_3:
+; TRAPPING-NEXT:    end_block # label12:
+; TRAPPING-NEXT:    local.get $push0=, 1
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptoui_sat_f64_to_i32:
+; NONTRAPPING:         .functype fptoui_sat_f64_to_i32 (f64) -> (i32)
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push1=, 0
+; NONTRAPPING-NEXT:    i32.trunc_sat_f64_u $push0=, $pop1
+; NONTRAPPING-NEXT:    return $pop0
+  %a = fptoui double %x to i32
+  ret i32 %a
+}
+
+define i64 @fptoui_sat_f64_to_i64(double %x) {
+; TRAPPING-LABEL: fptoui_sat_f64_to_i64:
+; TRAPPING:         .functype fptoui_sat_f64_to_i64 (f64) -> (i64)
+; TRAPPING-NEXT:    .local i64
+; TRAPPING-NEXT:  # %bb.0:
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    block
+; TRAPPING-NEXT:    local.get $push7=, 0
+; TRAPPING-NEXT:    f64.const $push1=, 0x1p64
+; TRAPPING-NEXT:    f64.lt $push2=, $pop7, $pop1
+; TRAPPING-NEXT:    local.get $push8=, 0
+; TRAPPING-NEXT:    f64.const $push4=, 0x0p0
+; TRAPPING-NEXT:    f64.ge $push5=, $pop8, $pop4
+; TRAPPING-NEXT:    i32.and $push6=, $pop2, $pop5
+; TRAPPING-NEXT:    i32.eqz $push3=, $pop6
+; TRAPPING-NEXT:    br_if 0, $pop3 # 0: down to label15
+; TRAPPING-NEXT:  # %bb.1:
+; TRAPPING-NEXT:    local.get $push9=, 0
+; TRAPPING-NEXT:    i64.trunc_f64_u $push10=, $pop9
+; TRAPPING-NEXT:    local.set 1, $pop10
+; TRAPPING-NEXT:    br 1 # 1: down to label14
+; TRAPPING-NEXT:  .LBB7_2:
+; TRAPPING-NEXT:    end_block # label15:
+; TRAPPING-NEXT:    i64.const $push11=, 0
+; TRAPPING-NEXT:    local.set 1, $pop11
+; TRAPPING-NEXT:  .LBB7_3:
+; TRAPPING-NEXT:    end_block # label14:
+; TRAPPING-NEXT:    local.get $push0=, 1
+; TRAPPING-NEXT:    return $pop0
+;
+; NONTRAPPING-LABEL: fptoui_sat_f64_to_i64:
+; NONTRAPPING:         .functype fptoui_sat_f64_to_i64 (f64) -> (i64)
+; NONTRAPPING-NEXT:  # %bb.0:
+; NONTRAPPING-NEXT:    local.get $push1=, 0
+; NONTRAPPING-NEXT:    i64.trunc_sat_f64_u $push0=, $pop1
+; NONTRAPPING-NEXT:    return $pop0
+  %a = fptoui double %x to i64
+  ret i64 %a
+}



More information about the llvm-branch-commits mailing list