[llvm] [WebAssembly][GlobalISel] Implement integer comparisons and `G_SELECT` (PR #197257)
Demetrius Kanios via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 30 00:35:59 PDT 2026
https://github.com/QuantumSegfault updated https://github.com/llvm/llvm-project/pull/197257
>From 3cbe21e7de737af9fc1382660a437ab197a5f286 Mon Sep 17 00:00:00 2001
From: Demetrius Kanios <demetrius at kanios.net>
Date: Mon, 11 May 2026 22:34:37 -0700
Subject: [PATCH 1/3] Implement int <=> fp ops
---
.../GISel/WebAssemblyLegalizerInfo.cpp | 28 ++
.../GlobalISel/instructions/bitcast.ll | 48 +++
.../GlobalISel/instructions/fptosi.ll | 301 ++++++++++++++++
.../GlobalISel/instructions/fptoui.ll | 325 ++++++++++++++++++
.../GlobalISel/instructions/sitofp.ll | 96 ++++++
.../GlobalISel/instructions/uitofp.ll | 100 ++++++
6 files changed, 898 insertions(+)
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/bitcast.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptosi.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptoui.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/sitofp.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/uitofp.ll
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
index fb499d0db1733..3b78e542cabfb 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
@@ -103,6 +103,34 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
.clampScalar(0, s32, s32)
.clampScalar(1, s64, s64);
+ getActionDefinitionsBuilder(G_BITCAST)
+ .legalFor({{i32, f32}, {f32, i32}, {i64, f64}, {f64, i64}})
+ .clampScalar(0, s32, s64)
+ .clampScalar(1, s32, s64);
+
+ getActionDefinitionsBuilder({G_FPTOSI, G_FPTOUI})
+ .legalForCartesianProduct({i32, i64}, {f32, f64})
+ .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_SITOFP, G_UITOFP})
+ .legalForCartesianProduct({f32, f64}, {i32, i64})
+ .minScalar(0, s32)
+ .clampScalar(1, s32, s64);
+
getLegacyLegalizerInfo().computeTables();
}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/bitcast.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/bitcast.ll
new file mode 100644
index 0000000000000..6c210e6a4e58f
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/bitcast.ll
@@ -0,0 +1,48 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+define float @bitcast_i32_to_f32(i32 %x) {
+; CHECK-LABEL: bitcast_i32_to_f32:
+; CHECK: .functype bitcast_i32_to_f32 (i32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push1=, 0
+; CHECK-NEXT: f32.reinterpret_i32 $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = bitcast i32 %x to float
+ ret float %a
+}
+
+define i32 @bitcast_f32_to_i32(float %x) {
+; CHECK-LABEL: bitcast_f32_to_i32:
+; CHECK: .functype bitcast_f32_to_i32 (f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push1=, 0
+; CHECK-NEXT: i32.reinterpret_f32 $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = bitcast float %x to i32
+ ret i32 %a
+}
+
+define double @bitcast_i64_to_f64(i64 %x) {
+; CHECK-LABEL: bitcast_i64_to_f64:
+; CHECK: .functype bitcast_i64_to_f64 (i64) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push1=, 0
+; CHECK-NEXT: f64.reinterpret_i64 $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = bitcast i64 %x to double
+ ret double %a
+}
+
+define i64 @bitcast_f64_to_i64(double %x) {
+; CHECK-LABEL: bitcast_f64_to_i64:
+; CHECK: .functype bitcast_f64_to_i64 (f64) -> (i64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push1=, 0
+; CHECK-NEXT: i64.reinterpret_f64 $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = bitcast double %x to i64
+ ret i64 %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptosi.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptosi.ll
new file mode 100644
index 0000000000000..04a714e0ead76
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptosi.ll
@@ -0,0 +1,301 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=-nontrapping-fptoint | FileCheck %s -check-prefix=TRAPPING
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=+nontrapping-fptoint | FileCheck %s -check-prefix=NONTRAPPING
+
+target triple = "wasm32-unknown-unknown"
+
+define i8 @fptosi_f32_to_i8(float %x) {
+; TRAPPING-LABEL: fptosi_f32_to_i8:
+; TRAPPING: .functype fptosi_f32_to_i8 (f32) -> (i32)
+; TRAPPING-NEXT: .local i32
+; TRAPPING-NEXT: # %bb.0:
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: local.get $push5=, 0
+; TRAPPING-NEXT: f32.abs $push1=, $pop5
+; TRAPPING-NEXT: f32.const $push2=, 0x1p31
+; TRAPPING-NEXT: f32.lt $push3=, $pop1, $pop2
+; TRAPPING-NEXT: i32.eqz $push4=, $pop3
+; TRAPPING-NEXT: br_if 0, $pop4 # 0: down to label1
+; TRAPPING-NEXT: # %bb.1:
+; TRAPPING-NEXT: local.get $push6=, 0
+; TRAPPING-NEXT: i32.trunc_f32_s $push7=, $pop6
+; TRAPPING-NEXT: local.set 1, $pop7
+; TRAPPING-NEXT: br 1 # 1: down to label0
+; TRAPPING-NEXT: .LBB0_2:
+; TRAPPING-NEXT: end_block # label1:
+; TRAPPING-NEXT: i32.const $push8=, -2147483648
+; TRAPPING-NEXT: local.set 1, $pop8
+; TRAPPING-NEXT: .LBB0_3:
+; TRAPPING-NEXT: end_block # label0:
+; TRAPPING-NEXT: local.get $push0=, 1
+; TRAPPING-NEXT: return $pop0
+;
+; NONTRAPPING-LABEL: fptosi_f32_to_i8:
+; NONTRAPPING: .functype fptosi_f32_to_i8 (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 = fptosi float %x to i8
+ ret i8 %a
+}
+
+define i16 @fptosi_f32_to_i16(float %x) {
+; TRAPPING-LABEL: fptosi_f32_to_i16:
+; TRAPPING: .functype fptosi_f32_to_i16 (f32) -> (i32)
+; TRAPPING-NEXT: .local i32
+; TRAPPING-NEXT: # %bb.0:
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: local.get $push5=, 0
+; TRAPPING-NEXT: f32.abs $push1=, $pop5
+; TRAPPING-NEXT: f32.const $push2=, 0x1p31
+; TRAPPING-NEXT: f32.lt $push3=, $pop1, $pop2
+; TRAPPING-NEXT: i32.eqz $push4=, $pop3
+; TRAPPING-NEXT: br_if 0, $pop4 # 0: down to label3
+; TRAPPING-NEXT: # %bb.1:
+; TRAPPING-NEXT: local.get $push6=, 0
+; TRAPPING-NEXT: i32.trunc_f32_s $push7=, $pop6
+; TRAPPING-NEXT: local.set 1, $pop7
+; TRAPPING-NEXT: br 1 # 1: down to label2
+; TRAPPING-NEXT: .LBB1_2:
+; TRAPPING-NEXT: end_block # label3:
+; TRAPPING-NEXT: i32.const $push8=, -2147483648
+; TRAPPING-NEXT: local.set 1, $pop8
+; TRAPPING-NEXT: .LBB1_3:
+; TRAPPING-NEXT: end_block # label2:
+; TRAPPING-NEXT: local.get $push0=, 1
+; TRAPPING-NEXT: return $pop0
+;
+; NONTRAPPING-LABEL: fptosi_f32_to_i16:
+; NONTRAPPING: .functype fptosi_f32_to_i16 (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 = fptosi float %x to i16
+ ret i16 %a
+}
+
+define i32 @fptosi_f32_to_i32(float %x) {
+; TRAPPING-LABEL: fptosi_f32_to_i32:
+; TRAPPING: .functype fptosi_f32_to_i32 (f32) -> (i32)
+; TRAPPING-NEXT: .local i32
+; TRAPPING-NEXT: # %bb.0:
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: local.get $push5=, 0
+; TRAPPING-NEXT: f32.abs $push1=, $pop5
+; TRAPPING-NEXT: f32.const $push2=, 0x1p31
+; TRAPPING-NEXT: f32.lt $push3=, $pop1, $pop2
+; TRAPPING-NEXT: i32.eqz $push4=, $pop3
+; TRAPPING-NEXT: br_if 0, $pop4 # 0: down to label5
+; TRAPPING-NEXT: # %bb.1:
+; TRAPPING-NEXT: local.get $push6=, 0
+; TRAPPING-NEXT: i32.trunc_f32_s $push7=, $pop6
+; TRAPPING-NEXT: local.set 1, $pop7
+; TRAPPING-NEXT: br 1 # 1: down to label4
+; TRAPPING-NEXT: .LBB2_2:
+; TRAPPING-NEXT: end_block # label5:
+; TRAPPING-NEXT: i32.const $push8=, -2147483648
+; TRAPPING-NEXT: local.set 1, $pop8
+; TRAPPING-NEXT: .LBB2_3:
+; TRAPPING-NEXT: end_block # label4:
+; TRAPPING-NEXT: local.get $push0=, 1
+; TRAPPING-NEXT: return $pop0
+;
+; NONTRAPPING-LABEL: fptosi_f32_to_i32:
+; NONTRAPPING: .functype fptosi_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 = fptosi float %x to i32
+ ret i32 %a
+}
+
+define i64 @fptosi_f32_to_i64(float %x) {
+; TRAPPING-LABEL: fptosi_f32_to_i64:
+; TRAPPING: .functype fptosi_f32_to_i64 (f32) -> (i64)
+; TRAPPING-NEXT: .local i64
+; TRAPPING-NEXT: # %bb.0:
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: local.get $push5=, 0
+; TRAPPING-NEXT: f32.abs $push1=, $pop5
+; TRAPPING-NEXT: f32.const $push2=, 0x1p63
+; TRAPPING-NEXT: f32.lt $push3=, $pop1, $pop2
+; TRAPPING-NEXT: i32.eqz $push4=, $pop3
+; TRAPPING-NEXT: br_if 0, $pop4 # 0: down to label7
+; TRAPPING-NEXT: # %bb.1:
+; TRAPPING-NEXT: local.get $push6=, 0
+; TRAPPING-NEXT: i64.trunc_f32_s $push7=, $pop6
+; TRAPPING-NEXT: local.set 1, $pop7
+; TRAPPING-NEXT: br 1 # 1: down to label6
+; TRAPPING-NEXT: .LBB3_2:
+; TRAPPING-NEXT: end_block # label7:
+; TRAPPING-NEXT: i64.const $push8=, -9223372036854775808
+; TRAPPING-NEXT: local.set 1, $pop8
+; TRAPPING-NEXT: .LBB3_3:
+; TRAPPING-NEXT: end_block # label6:
+; TRAPPING-NEXT: local.get $push0=, 1
+; TRAPPING-NEXT: return $pop0
+;
+; NONTRAPPING-LABEL: fptosi_f32_to_i64:
+; NONTRAPPING: .functype fptosi_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 = fptosi float %x to i64
+ ret i64 %a
+}
+
+define i8 @fptosi_f64_to_i8(double %x) {
+; TRAPPING-LABEL: fptosi_f64_to_i8:
+; TRAPPING: .functype fptosi_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_f64_to_i8:
+; NONTRAPPING: .functype fptosi_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_f64_to_i16(double %x) {
+; TRAPPING-LABEL: fptosi_f64_to_i16:
+; TRAPPING: .functype fptosi_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_f64_to_i16:
+; NONTRAPPING: .functype fptosi_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_f64_to_i32(double %x) {
+; TRAPPING-LABEL: fptosi_f64_to_i32:
+; TRAPPING: .functype fptosi_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_f64_to_i32:
+; NONTRAPPING: .functype fptosi_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_f64_to_i64(double %x) {
+; TRAPPING-LABEL: fptosi_f64_to_i64:
+; TRAPPING: .functype fptosi_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_f64_to_i64:
+; NONTRAPPING: .functype fptosi_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.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptoui.ll
new file mode 100644
index 0000000000000..2ac18875763ee
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fptoui.ll
@@ -0,0 +1,325 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=-nontrapping-fptoint | FileCheck %s -check-prefix=TRAPPING
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers -mattr=+nontrapping-fptoint | FileCheck %s -check-prefix=NONTRAPPING
+
+target triple = "wasm32-unknown-unknown"
+
+define i8 @fptoui_f32_to_i8(float %x) {
+; TRAPPING-LABEL: fptoui_f32_to_i8:
+; TRAPPING: .functype fptoui_f32_to_i8 (f32) -> (i32)
+; TRAPPING-NEXT: .local i32
+; TRAPPING-NEXT: # %bb.0:
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: local.get $push7=, 0
+; TRAPPING-NEXT: f32.const $push1=, 0x1p32
+; TRAPPING-NEXT: f32.lt $push2=, $pop7, $pop1
+; TRAPPING-NEXT: local.get $push8=, 0
+; TRAPPING-NEXT: f32.const $push4=, 0x0p0
+; TRAPPING-NEXT: f32.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 label1
+; TRAPPING-NEXT: # %bb.1:
+; TRAPPING-NEXT: local.get $push9=, 0
+; TRAPPING-NEXT: i32.trunc_f32_u $push10=, $pop9
+; TRAPPING-NEXT: local.set 1, $pop10
+; TRAPPING-NEXT: br 1 # 1: down to label0
+; TRAPPING-NEXT: .LBB0_2:
+; TRAPPING-NEXT: end_block # label1:
+; TRAPPING-NEXT: i32.const $push11=, 0
+; TRAPPING-NEXT: local.set 1, $pop11
+; TRAPPING-NEXT: .LBB0_3:
+; TRAPPING-NEXT: end_block # label0:
+; TRAPPING-NEXT: local.get $push0=, 1
+; TRAPPING-NEXT: return $pop0
+;
+; NONTRAPPING-LABEL: fptoui_f32_to_i8:
+; NONTRAPPING: .functype fptoui_f32_to_i8 (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 = fptoui float %x to i8
+ ret i8 %a
+}
+
+define i16 @fptoui_f32_to_i16(float %x) {
+; TRAPPING-LABEL: fptoui_f32_to_i16:
+; TRAPPING: .functype fptoui_f32_to_i16 (f32) -> (i32)
+; TRAPPING-NEXT: .local i32
+; TRAPPING-NEXT: # %bb.0:
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: local.get $push7=, 0
+; TRAPPING-NEXT: f32.const $push1=, 0x1p32
+; TRAPPING-NEXT: f32.lt $push2=, $pop7, $pop1
+; TRAPPING-NEXT: local.get $push8=, 0
+; TRAPPING-NEXT: f32.const $push4=, 0x0p0
+; TRAPPING-NEXT: f32.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 label3
+; TRAPPING-NEXT: # %bb.1:
+; TRAPPING-NEXT: local.get $push9=, 0
+; TRAPPING-NEXT: i32.trunc_f32_u $push10=, $pop9
+; TRAPPING-NEXT: local.set 1, $pop10
+; TRAPPING-NEXT: br 1 # 1: down to label2
+; TRAPPING-NEXT: .LBB1_2:
+; TRAPPING-NEXT: end_block # label3:
+; TRAPPING-NEXT: i32.const $push11=, 0
+; TRAPPING-NEXT: local.set 1, $pop11
+; TRAPPING-NEXT: .LBB1_3:
+; TRAPPING-NEXT: end_block # label2:
+; TRAPPING-NEXT: local.get $push0=, 1
+; TRAPPING-NEXT: return $pop0
+;
+; NONTRAPPING-LABEL: fptoui_f32_to_i16:
+; NONTRAPPING: .functype fptoui_f32_to_i16 (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 = fptoui float %x to i16
+ ret i16 %a
+}
+
+define i32 @fptoui_f32_to_i32(float %x) {
+; TRAPPING-LABEL: fptoui_f32_to_i32:
+; TRAPPING: .functype fptoui_f32_to_i32 (f32) -> (i32)
+; TRAPPING-NEXT: .local i32
+; TRAPPING-NEXT: # %bb.0:
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: local.get $push7=, 0
+; TRAPPING-NEXT: f32.const $push1=, 0x1p32
+; TRAPPING-NEXT: f32.lt $push2=, $pop7, $pop1
+; TRAPPING-NEXT: local.get $push8=, 0
+; TRAPPING-NEXT: f32.const $push4=, 0x0p0
+; TRAPPING-NEXT: f32.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 label5
+; TRAPPING-NEXT: # %bb.1:
+; TRAPPING-NEXT: local.get $push9=, 0
+; TRAPPING-NEXT: i32.trunc_f32_u $push10=, $pop9
+; TRAPPING-NEXT: local.set 1, $pop10
+; TRAPPING-NEXT: br 1 # 1: down to label4
+; TRAPPING-NEXT: .LBB2_2:
+; TRAPPING-NEXT: end_block # label5:
+; TRAPPING-NEXT: i32.const $push11=, 0
+; TRAPPING-NEXT: local.set 1, $pop11
+; TRAPPING-NEXT: .LBB2_3:
+; TRAPPING-NEXT: end_block # label4:
+; TRAPPING-NEXT: local.get $push0=, 1
+; TRAPPING-NEXT: return $pop0
+;
+; NONTRAPPING-LABEL: fptoui_f32_to_i32:
+; NONTRAPPING: .functype fptoui_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 = fptoui float %x to i32
+ ret i32 %a
+}
+
+define i64 @fptoui_f32_to_i64(float %x) {
+; TRAPPING-LABEL: fptoui_f32_to_i64:
+; TRAPPING: .functype fptoui_f32_to_i64 (f32) -> (i64)
+; TRAPPING-NEXT: .local i64
+; TRAPPING-NEXT: # %bb.0:
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: block
+; TRAPPING-NEXT: local.get $push7=, 0
+; TRAPPING-NEXT: f32.const $push1=, 0x1p64
+; TRAPPING-NEXT: f32.lt $push2=, $pop7, $pop1
+; TRAPPING-NEXT: local.get $push8=, 0
+; TRAPPING-NEXT: f32.const $push4=, 0x0p0
+; TRAPPING-NEXT: f32.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 label7
+; TRAPPING-NEXT: # %bb.1:
+; TRAPPING-NEXT: local.get $push9=, 0
+; TRAPPING-NEXT: i64.trunc_f32_u $push10=, $pop9
+; TRAPPING-NEXT: local.set 1, $pop10
+; TRAPPING-NEXT: br 1 # 1: down to label6
+; TRAPPING-NEXT: .LBB3_2:
+; TRAPPING-NEXT: end_block # label7:
+; TRAPPING-NEXT: i64.const $push11=, 0
+; TRAPPING-NEXT: local.set 1, $pop11
+; TRAPPING-NEXT: .LBB3_3:
+; TRAPPING-NEXT: end_block # label6:
+; TRAPPING-NEXT: local.get $push0=, 1
+; TRAPPING-NEXT: return $pop0
+;
+; NONTRAPPING-LABEL: fptoui_f32_to_i64:
+; NONTRAPPING: .functype fptoui_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 = fptoui float %x to i64
+ ret i64 %a
+}
+
+define i8 @fptoui_f64_to_i8(double %x) {
+; TRAPPING-LABEL: fptoui_f64_to_i8:
+; TRAPPING: .functype fptoui_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_f64_to_i8:
+; NONTRAPPING: .functype fptoui_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_f64_to_i16(double %x) {
+; TRAPPING-LABEL: fptoui_f64_to_i16:
+; TRAPPING: .functype fptoui_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_f64_to_i16:
+; NONTRAPPING: .functype fptoui_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_f64_to_i32(double %x) {
+; TRAPPING-LABEL: fptoui_f64_to_i32:
+; TRAPPING: .functype fptoui_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_f64_to_i32:
+; NONTRAPPING: .functype fptoui_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_f64_to_i64(double %x) {
+; TRAPPING-LABEL: fptoui_f64_to_i64:
+; TRAPPING: .functype fptoui_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_f64_to_i64:
+; NONTRAPPING: .functype fptoui_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
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/sitofp.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/sitofp.ll
new file mode 100644
index 0000000000000..44aa82934831a
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/sitofp.ll
@@ -0,0 +1,96 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+define float @sitofp_i8_to_f32(i8 %x) {
+; CHECK-LABEL: sitofp_i8_to_f32:
+; CHECK: .functype sitofp_i8_to_f32 (i32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: i32.extend8_s $push1=, $pop2
+; CHECK-NEXT: f32.convert_i32_s $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = sitofp i8 %x to float
+ ret float %a
+}
+
+define float @sitofp_i16_to_f32(i16 %x) {
+; CHECK-LABEL: sitofp_i16_to_f32:
+; CHECK: .functype sitofp_i16_to_f32 (i32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: i32.extend16_s $push1=, $pop2
+; CHECK-NEXT: f32.convert_i32_s $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = sitofp i16 %x to float
+ ret float %a
+}
+
+define float @sitofp_i32_to_f32(i32 %x) {
+; CHECK-LABEL: sitofp_i32_to_f32:
+; CHECK: .functype sitofp_i32_to_f32 (i32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push1=, 0
+; CHECK-NEXT: f32.convert_i32_s $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = sitofp i32 %x to float
+ ret float %a
+}
+
+define float @sitofp_i64_to_f32(i64 %x) {
+; CHECK-LABEL: sitofp_i64_to_f32:
+; CHECK: .functype sitofp_i64_to_f32 (i64) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push1=, 0
+; CHECK-NEXT: f32.convert_i64_s $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = sitofp i64 %x to float
+ ret float %a
+}
+
+define double @sitofp_i8_to_f64(i8 %x) {
+; CHECK-LABEL: sitofp_i8_to_f64:
+; CHECK: .functype sitofp_i8_to_f64 (i32) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: i32.extend8_s $push1=, $pop2
+; CHECK-NEXT: f64.convert_i32_s $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = sitofp i8 %x to double
+ ret double %a
+}
+
+define double @sitofp_i16_to_f64(i16 %x) {
+; CHECK-LABEL: sitofp_i16_to_f64:
+; CHECK: .functype sitofp_i16_to_f64 (i32) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: i32.extend16_s $push1=, $pop2
+; CHECK-NEXT: f64.convert_i32_s $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = sitofp i16 %x to double
+ ret double %a
+}
+
+define double @sitofp_i32_to_f64(i32 %x) {
+; CHECK-LABEL: sitofp_i32_to_f64:
+; CHECK: .functype sitofp_i32_to_f64 (i32) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push1=, 0
+; CHECK-NEXT: f64.convert_i32_s $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = sitofp i32 %x to double
+ ret double %a
+}
+
+define double @sitofp_i64_to_f64(i64 %x) {
+; CHECK-LABEL: sitofp_i64_to_f64:
+; CHECK: .functype sitofp_i64_to_f64 (i64) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push1=, 0
+; CHECK-NEXT: f64.convert_i64_s $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = sitofp i64 %x to double
+ ret double %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/uitofp.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/uitofp.ll
new file mode 100644
index 0000000000000..2348135ef2a4e
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/uitofp.ll
@@ -0,0 +1,100 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+define float @uitofp_i8_to_f32(i8 %x) {
+; CHECK-LABEL: uitofp_i8_to_f32:
+; CHECK: .functype uitofp_i8_to_f32 (i32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: i32.const $push2=, 255
+; CHECK-NEXT: i32.and $push1=, $pop3, $pop2
+; CHECK-NEXT: f32.convert_i32_u $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = uitofp i8 %x to float
+ ret float %a
+}
+
+define float @uitofp_i16_to_f32(i16 %x) {
+; CHECK-LABEL: uitofp_i16_to_f32:
+; CHECK: .functype uitofp_i16_to_f32 (i32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: i32.const $push2=, 65535
+; CHECK-NEXT: i32.and $push1=, $pop3, $pop2
+; CHECK-NEXT: f32.convert_i32_u $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = uitofp i16 %x to float
+ ret float %a
+}
+
+define float @uitofp_i32_to_f32(i32 %x) {
+; CHECK-LABEL: uitofp_i32_to_f32:
+; CHECK: .functype uitofp_i32_to_f32 (i32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push1=, 0
+; CHECK-NEXT: f32.convert_i32_u $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = uitofp i32 %x to float
+ ret float %a
+}
+
+define float @uitofp_i64_to_f32(i64 %x) {
+; CHECK-LABEL: uitofp_i64_to_f32:
+; CHECK: .functype uitofp_i64_to_f32 (i64) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push1=, 0
+; CHECK-NEXT: f32.convert_i64_u $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = uitofp i64 %x to float
+ ret float %a
+}
+
+define double @uitofp_i8_to_f64(i8 %x) {
+; CHECK-LABEL: uitofp_i8_to_f64:
+; CHECK: .functype uitofp_i8_to_f64 (i32) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: i32.const $push2=, 255
+; CHECK-NEXT: i32.and $push1=, $pop3, $pop2
+; CHECK-NEXT: f64.convert_i32_u $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = uitofp i8 %x to double
+ ret double %a
+}
+
+define double @uitofp_i16_to_f64(i16 %x) {
+; CHECK-LABEL: uitofp_i16_to_f64:
+; CHECK: .functype uitofp_i16_to_f64 (i32) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: i32.const $push2=, 65535
+; CHECK-NEXT: i32.and $push1=, $pop3, $pop2
+; CHECK-NEXT: f64.convert_i32_u $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = uitofp i16 %x to double
+ ret double %a
+}
+
+define double @uitofp_i32_to_f64(i32 %x) {
+; CHECK-LABEL: uitofp_i32_to_f64:
+; CHECK: .functype uitofp_i32_to_f64 (i32) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push1=, 0
+; CHECK-NEXT: f64.convert_i32_u $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = uitofp i32 %x to double
+ ret double %a
+}
+
+define double @uitofp_i64_to_f64(i64 %x) {
+; CHECK-LABEL: uitofp_i64_to_f64:
+; CHECK: .functype uitofp_i64_to_f64 (i64) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push1=, 0
+; CHECK-NEXT: f64.convert_i64_u $push0=, $pop1
+; CHECK-NEXT: return $pop0
+ %a = uitofp i64 %x to double
+ ret double %a
+}
>From bfbb0fd2240d4648deb292dd64cd7b999b940d9b Mon Sep 17 00:00:00 2001
From: Demetrius Kanios <demetrius at kanios.net>
Date: Tue, 12 May 2026 00:37:05 -0700
Subject: [PATCH 2/3] Implement `COPY`
---
.../GISel/WebAssemblyInstructionSelector.cpp | 58 +++-
.../WebAssembly/WebAssemblyRegisterInfo.cpp | 19 +-
.../GlobalISel/instructions/copy.mir | 294 ++++++++++++++++++
3 files changed, 368 insertions(+), 3 deletions(-)
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/copy.mir
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
index 5c27dd9b5b201..2331b8b636603 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
@@ -46,6 +46,7 @@ class WebAssemblyInstructionSelector : public InstructionSelector {
private:
bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const;
+ bool selectCopy(MachineInstr &I, MachineRegisterInfo &MRI) const;
const WebAssemblyTargetMachine &TM;
// const WebAssemblySubtarget &STI;
@@ -83,13 +84,68 @@ WebAssemblyInstructionSelector::WebAssemblyInstructionSelector(
{
}
+bool WebAssemblyInstructionSelector::selectCopy(
+ MachineInstr &I, MachineRegisterInfo &MRI) const {
+ const TargetRegisterClass *DstRC =
+ TRI.getConstrainedRegClassForOperand(I.getOperand(0), MRI);
+ if (!DstRC)
+ return false;
+
+ const TargetRegisterClass *SrcRC =
+ TRI.getConstrainedRegClassForOperand(I.getOperand(1), MRI);
+ if (!SrcRC)
+ return false;
+
+ Register DstReg = I.getOperand(0).getReg();
+ Register SrcReg = I.getOperand(1).getReg();
+
+ if (DstReg.isVirtual())
+ RBI.constrainGenericRegister(DstReg, *DstRC, MRI);
+ if (SrcReg.isVirtual())
+ RBI.constrainGenericRegister(SrcReg, *SrcRC, MRI);
+
+ if (DstRC != SrcRC) {
+ if (DstReg.isPhysical() || SrcReg.isPhysical())
+ llvm_unreachable("COPY to/from SP[32/64] or FP[32/64] with mismatching "
+ "classes not currently supported");
+
+ if (DstRC == &WebAssembly::I32RegClass &&
+ SrcRC == &WebAssembly::F32RegClass) {
+ I.setDesc(TII.get(WebAssembly::I32_REINTERPRET_F32));
+ return true;
+ }
+ if (DstRC == &WebAssembly::F32RegClass &&
+ SrcRC == &WebAssembly::I32RegClass) {
+ I.setDesc(TII.get(WebAssembly::F32_REINTERPRET_I32));
+ return true;
+ }
+ if (DstRC == &WebAssembly::I64RegClass &&
+ SrcRC == &WebAssembly::F64RegClass) {
+ I.setDesc(TII.get(WebAssembly::I64_REINTERPRET_F64));
+ return true;
+ }
+ if (DstRC == &WebAssembly::F64RegClass &&
+ SrcRC == &WebAssembly::I64RegClass) {
+ I.setDesc(TII.get(WebAssembly::F64_REINTERPRET_I64));
+ return true;
+ }
+
+ llvm_unreachable("COPY between unsupported reg classes.");
+ }
+
+ return true;
+}
+
bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
MachineBasicBlock &MBB = *I.getParent();
MachineFunction &MF = *MBB.getParent();
MachineRegisterInfo &MRI = MF.getRegInfo();
- if (!I.isPreISelOpcode())
+ if (!I.isPreISelOpcode()) {
+ if (I.isCopy())
+ return selectCopy(I, MRI);
return true;
+ }
if (selectImpl(I, *CoverageInfo))
return true;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
index 4b4f07bd782ad..0c8241461f805 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
@@ -184,8 +184,23 @@ WebAssemblyRegisterInfo::getConstrainedRegClassForOperand(
const MachineOperand &MO, const MachineRegisterInfo &MRI) const {
assert(MO.isReg());
- const RegClassOrRegBank &RegClassOrBank =
- MRI.getRegClassOrRegBank(MO.getReg());
+ Register Reg = MO.getReg();
+
+ if (Reg.isPhysical()) {
+ switch (Reg.id()) {
+ case WebAssembly::SP32:
+ case WebAssembly::FP32:
+ return &WebAssembly::I32RegClass;
+ case WebAssembly::SP64:
+ case WebAssembly::FP64:
+ return &WebAssembly::I64RegClass;
+ break;
+ default:
+ return nullptr;
+ }
+ }
+
+ const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(Reg);
if (RegClassOrBank.isNull())
return nullptr;
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/copy.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/copy.mir
new file mode 100644
index 0000000000000..a692af7437071
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/copy.mir
@@ -0,0 +1,294 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -mtriple=wasm32-unknown-unknown -run-pass=regbankselect,instruction-select %s -o - | FileCheck %s
+
+---
+name: copy_i32
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_i32
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+ ; CHECK-NEXT: RETURN [[ARGUMENT_i32_]], implicit-def $arguments
+ %0:i32(i32) = ARGUMENT_i32 0, implicit $arguments
+ %1:_(i32) = COPY %0(i32)
+ RETURN %1(i32), implicit-def $arguments
+...
+
+---
+name: copy_i64
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_i64
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+ ; CHECK-NEXT: RETURN [[ARGUMENT_i64_]], implicit-def $arguments
+ %0:i64(i64) = ARGUMENT_i64 0, implicit $arguments
+ %1:_(i64) = COPY %0(i64)
+ RETURN %1(i64), implicit-def $arguments
+...
+
+---
+name: copy_f32
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_f32
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_f32_:%[0-9]+]]:f32 = ARGUMENT_f32 0, implicit $arguments
+ ; CHECK-NEXT: RETURN [[ARGUMENT_f32_]], implicit-def $arguments
+ %0:f32(f32) = ARGUMENT_f32 0, implicit $arguments
+ %1:_(f32) = COPY %0(f32)
+ RETURN %1(f32), implicit-def $arguments
+...
+
+---
+name: copy_f64
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_f64
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_f64_:%[0-9]+]]:f64 = ARGUMENT_f64 0, implicit $arguments
+ ; CHECK-NEXT: RETURN [[ARGUMENT_f64_]], implicit-def $arguments
+ %0:f64(f64) = ARGUMENT_f64 0, implicit $arguments
+ %1:_(f64) = COPY %0(f64)
+ RETURN %1(f64), implicit-def $arguments
+...
+
+---
+name: copy_to_sp32
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_to_sp32
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+ ; CHECK-NEXT: $sp32 = COPY [[ARGUMENT_i32_]]
+ ; CHECK-NEXT: RETURN implicit-def $arguments
+ %0:i32(i32) = ARGUMENT_i32 0, implicit $arguments
+ $sp32 = COPY %0(i32)
+ RETURN implicit-def $arguments
+...
+
+---
+name: copy_to_sp64
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_to_sp64
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+ ; CHECK-NEXT: $sp64 = COPY [[ARGUMENT_i64_]]
+ ; CHECK-NEXT: RETURN implicit-def $arguments
+ %0:i64(i64) = ARGUMENT_i64 0, implicit $arguments
+ $sp64 = COPY %0(i64)
+ RETURN implicit-def $arguments
+...
+
+---
+name: copy_from_sp32
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_from_sp32
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:i32 = COPY $sp32
+ ; CHECK-NEXT: RETURN [[COPY]], implicit-def $arguments
+ %0:_(i32) = COPY $sp32
+ RETURN %0(i32), implicit-def $arguments
+...
+
+---
+name: copy_from_sp64
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_from_sp64
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:i64 = COPY $sp64
+ ; CHECK-NEXT: RETURN [[COPY]], implicit-def $arguments
+ %0:_(i64) = COPY $sp64
+ RETURN %0(i64), implicit-def $arguments
+...
+
+---
+name: copy_to_fp32
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_to_fp32
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+ ; CHECK-NEXT: $fp32 = COPY [[ARGUMENT_i32_]]
+ ; CHECK-NEXT: RETURN implicit-def $arguments
+ %0:i32(i32) = ARGUMENT_i32 0, implicit $arguments
+ $fp32 = COPY %0(i32)
+ RETURN implicit-def $arguments
+...
+
+---
+name: copy_to_fp64
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_to_fp64
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+ ; CHECK-NEXT: $fp64 = COPY [[ARGUMENT_i64_]]
+ ; CHECK-NEXT: RETURN implicit-def $arguments
+ %0:i64(i64) = ARGUMENT_i64 0, implicit $arguments
+ $fp64 = COPY %0(i64)
+ RETURN implicit-def $arguments
+...
+
+---
+name: copy_from_fp32
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_from_fp32
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:i32 = COPY $fp32
+ ; CHECK-NEXT: RETURN [[COPY]], implicit-def $arguments
+ %0:_(i32) = COPY $fp32
+ RETURN %0(i32), implicit-def $arguments
+...
+
+---
+name: copy_from_fp64
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_from_fp64
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[COPY:%[0-9]+]]:i64 = COPY $fp64
+ ; CHECK-NEXT: RETURN [[COPY]], implicit-def $arguments
+ %0:_(i64) = COPY $fp64
+ RETURN %0(i64), implicit-def $arguments
+...
+
+---
+name: copy_i32_to_f32
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_i32_to_f32
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+ ; CHECK-NEXT: [[F32_REINTERPRET_I32_:%[0-9]+]]:f32 = F32_REINTERPRET_I32 [[ARGUMENT_i32_]]
+ ; CHECK-NEXT: RETURN [[F32_REINTERPRET_I32_]], implicit-def $arguments
+ %0:i32 = ARGUMENT_i32 0, implicit $arguments
+ %1:f32 = COPY %0
+ RETURN %1, implicit-def $arguments
+...
+
+---
+name: copy_f32_to_i32
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_f32_to_i32
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_f32_:%[0-9]+]]:f32 = ARGUMENT_f32 0, implicit $arguments
+ ; CHECK-NEXT: [[I32_REINTERPRET_F32_:%[0-9]+]]:i32 = I32_REINTERPRET_F32 [[ARGUMENT_f32_]]
+ ; CHECK-NEXT: RETURN [[I32_REINTERPRET_F32_]], implicit-def $arguments
+ %0:f32 = ARGUMENT_f32 0, implicit $arguments
+ %1:i32 = COPY %0
+ RETURN %1, implicit-def $arguments
+...
+
+---
+name: copy_i64_to_f64
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_i64_to_f64
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+ ; CHECK-NEXT: [[F64_REINTERPRET_I64_:%[0-9]+]]:f64 = F64_REINTERPRET_I64 [[ARGUMENT_i64_]]
+ ; CHECK-NEXT: RETURN [[F64_REINTERPRET_I64_]], implicit-def $arguments
+ %0:i64 = ARGUMENT_i64 0, implicit $arguments
+ %1:f64 = COPY %0
+ RETURN %1, implicit-def $arguments
+...
+
+---
+name: copy_f64_to_f64
+legalized: true
+tracksRegLiveness: true
+body: |
+ bb.1.entry:
+ liveins: $arguments
+
+ ; CHECK-LABEL: name: copy_f64_to_f64
+ ; CHECK: liveins: $arguments
+ ; CHECK-NEXT: {{ $}}
+ ; CHECK-NEXT: [[ARGUMENT_f64_:%[0-9]+]]:f64 = ARGUMENT_f64 0, implicit $arguments
+ ; CHECK-NEXT: [[I64_REINTERPRET_F64_:%[0-9]+]]:i64 = I64_REINTERPRET_F64 [[ARGUMENT_f64_]]
+ ; CHECK-NEXT: RETURN [[I64_REINTERPRET_F64_]], implicit-def $arguments
+ %0:f64 = ARGUMENT_f64 0, implicit $arguments
+ %1:i64 = COPY %0
+ RETURN %1, implicit-def $arguments
+...
>From ca66a0a26f6978e27ba0eb4d6f064998884c153b Mon Sep 17 00:00:00 2001
From: Demetrius Kanios <demetrius at kanios.net>
Date: Tue, 12 May 2026 00:41:27 -0700
Subject: [PATCH 3/3] Implement integer comparisons and `G_SELECT`
---
.../GISel/WebAssemblyLegalizerInfo.cpp | 16 +
.../GlobalISel/instructions/icmp.ll | 277 ++++++++++++++++++
.../GlobalISel/instructions/scmp.ll | 81 +++++
.../GlobalISel/instructions/select.ll | 94 ++++++
.../GlobalISel/instructions/smax.ll | 73 +++++
.../GlobalISel/instructions/smin.ll | 73 +++++
.../GlobalISel/instructions/ucmp.ll | 89 ++++++
.../GlobalISel/instructions/umax.ll | 77 +++++
.../GlobalISel/instructions/umin.ll | 77 +++++
9 files changed, 857 insertions(+)
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/icmp.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/scmp.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/select.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/smax.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/smin.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ucmp.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/umax.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/umin.ll
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
index 3b78e542cabfb..d91ec459397ba 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
@@ -66,6 +66,16 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
getActionDefinitionsBuilder({G_FSHL, G_FSHR}).lower();
+ getActionDefinitionsBuilder(G_ICMP)
+ .legalForCartesianProduct({i32}, {i32, i64})
+ .widenScalarToNextPow2(1)
+ .clampScalar(0, s32, s32)
+ .clampScalar(1, s32, s64);
+
+ getActionDefinitionsBuilder({G_UMIN, G_UMAX, G_SMIN, G_SMAX}).lower();
+
+ getActionDefinitionsBuilder({G_SCMP, G_UCMP}).lower();
+
getActionDefinitionsBuilder({G_ANYEXT, G_SEXT, G_ZEXT})
.legalFor({{i64, i32}})
.clampScalar(0, s64, s64)
@@ -131,6 +141,12 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
.minScalar(0, s32)
.clampScalar(1, s32, s64);
+ getActionDefinitionsBuilder(G_SELECT)
+ .legalForCartesianProduct({i32, i64, f32, f64}, {i32})
+ .widenScalarToNextPow2(0)
+ .clampScalar(0, s32, s64)
+ .clampScalar(1, s32, s32);
+
getLegacyLegalizerInfo().computeTables();
}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/icmp.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/icmp.ll
new file mode 100644
index 0000000000000..7747643efc857
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/icmp.ll
@@ -0,0 +1,277 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+define i1 @icmp_i8(i8 %x, i8 %y) {
+; CHECK-LABEL: icmp_i8:
+; CHECK: .functype icmp_i8 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: i32.const $push4=, 255
+; CHECK-NEXT: i32.and $push1=, $pop5, $pop4
+; CHECK-NEXT: local.get $push6=, 1
+; CHECK-NEXT: i32.const $push3=, 255
+; CHECK-NEXT: i32.and $push2=, $pop6, $pop3
+; CHECK-NEXT: i32.eq $push0=, $pop1, $pop2
+; CHECK-NEXT: return $pop0
+ %a = icmp eq i8 %x, %y
+ ret i1 %a
+}
+
+
+define i1 @icmp_i16(i16 %x, i16 %y) {
+; CHECK-LABEL: icmp_i16:
+; CHECK: .functype icmp_i16 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: i32.const $push4=, 65535
+; CHECK-NEXT: i32.and $push1=, $pop5, $pop4
+; CHECK-NEXT: local.get $push6=, 1
+; CHECK-NEXT: i32.const $push3=, 65535
+; CHECK-NEXT: i32.and $push2=, $pop6, $pop3
+; CHECK-NEXT: i32.eq $push0=, $pop1, $pop2
+; CHECK-NEXT: return $pop0
+ %a = icmp eq i16 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_eq_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: icmp_eq_i32:
+; CHECK: .functype icmp_eq_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i32.eq $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp eq i32 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_ne_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: icmp_ne_i32:
+; CHECK: .functype icmp_ne_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i32.ne $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp ne i32 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_ugt_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: icmp_ugt_i32:
+; CHECK: .functype icmp_ugt_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i32.gt_u $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp ugt i32 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_uge_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: icmp_uge_i32:
+; CHECK: .functype icmp_uge_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i32.ge_u $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp uge i32 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_ult_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: icmp_ult_i32:
+; CHECK: .functype icmp_ult_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i32.lt_u $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp ult i32 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_ule_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: icmp_ule_i32:
+; CHECK: .functype icmp_ule_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i32.le_u $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp ule i32 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_sgt_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: icmp_sgt_i32:
+; CHECK: .functype icmp_sgt_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i32.gt_s $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp sgt i32 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_sge_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: icmp_sge_i32:
+; CHECK: .functype icmp_sge_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i32.ge_s $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp sge i32 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_slt_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: icmp_slt_i32:
+; CHECK: .functype icmp_slt_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i32.lt_s $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp slt i32 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_sle_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: icmp_sle_i32:
+; CHECK: .functype icmp_sle_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i32.le_s $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp sle i32 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_eq_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: icmp_eq_i64:
+; CHECK: .functype icmp_eq_i64 (i64, i64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i64.eq $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp eq i64 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_ne_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: icmp_ne_i64:
+; CHECK: .functype icmp_ne_i64 (i64, i64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i64.ne $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp ne i64 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_ugt_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: icmp_ugt_i64:
+; CHECK: .functype icmp_ugt_i64 (i64, i64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i64.gt_u $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp ugt i64 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_uge_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: icmp_uge_i64:
+; CHECK: .functype icmp_uge_i64 (i64, i64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i64.ge_u $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp uge i64 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_ult_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: icmp_ult_i64:
+; CHECK: .functype icmp_ult_i64 (i64, i64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i64.lt_u $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp ult i64 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_ule_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: icmp_ule_i64:
+; CHECK: .functype icmp_ule_i64 (i64, i64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i64.le_u $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp ule i64 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_sgt_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: icmp_sgt_i64:
+; CHECK: .functype icmp_sgt_i64 (i64, i64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i64.gt_s $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp sgt i64 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_sge_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: icmp_sge_i64:
+; CHECK: .functype icmp_sge_i64 (i64, i64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i64.ge_s $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp sge i64 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_slt_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: icmp_slt_i64:
+; CHECK: .functype icmp_slt_i64 (i64, i64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i64.lt_s $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp slt i64 %x, %y
+ ret i1 %a
+}
+
+define i1 @icmp_sle_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: icmp_sle_i64:
+; CHECK: .functype icmp_sle_i64 (i64, i64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: i64.le_s $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = icmp sle i64 %x, %y
+ ret i1 %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/scmp.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/scmp.ll
new file mode 100644
index 0000000000000..4231d732ccdfd
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/scmp.ll
@@ -0,0 +1,81 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+declare i2 @llvm.scmp.i2.i8(i8, i8)
+declare i2 @llvm.scmp.i2.i16(i16, i16)
+declare i2 @llvm.scmp.i2.i32(i32, i32)
+declare i2 @llvm.scmp.i2.i64(i64, i64)
+
+define i2 @scmp_i8(i8 %x, i8 %y) {
+; CHECK-LABEL: scmp_i8:
+; CHECK: .functype scmp_i8 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push7=, 0
+; CHECK-NEXT: i32.extend8_s $push5=, $pop7
+; CHECK-NEXT: local.get $push8=, 1
+; CHECK-NEXT: i32.extend8_s $push6=, $pop8
+; CHECK-NEXT: i32.gt_s $push4=, $pop5, $pop6
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: i32.extend8_s $push2=, $pop9
+; CHECK-NEXT: local.get $push10=, 1
+; CHECK-NEXT: i32.extend8_s $push3=, $pop10
+; CHECK-NEXT: i32.lt_s $push1=, $pop2, $pop3
+; CHECK-NEXT: i32.sub $push0=, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i2 @llvm.scmp.i2.i8(i8 %x, i8 %y)
+ ret i2 %a
+}
+
+define i2 @scmp_i16(i16 %x, i16 %y) {
+; CHECK-LABEL: scmp_i16:
+; CHECK: .functype scmp_i16 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push7=, 0
+; CHECK-NEXT: i32.extend16_s $push5=, $pop7
+; CHECK-NEXT: local.get $push8=, 1
+; CHECK-NEXT: i32.extend16_s $push6=, $pop8
+; CHECK-NEXT: i32.gt_s $push4=, $pop5, $pop6
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: i32.extend16_s $push2=, $pop9
+; CHECK-NEXT: local.get $push10=, 1
+; CHECK-NEXT: i32.extend16_s $push3=, $pop10
+; CHECK-NEXT: i32.lt_s $push1=, $pop2, $pop3
+; CHECK-NEXT: i32.sub $push0=, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i2 @llvm.scmp.i2.i16(i16 %x, i16 %y)
+ ret i2 %a
+}
+
+define i2 @scmp_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: scmp_i32:
+; CHECK: .functype scmp_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: i32.gt_s $push2=, $pop4, $pop3
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: i32.lt_s $push1=, $pop6, $pop5
+; CHECK-NEXT: i32.sub $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i2 @llvm.scmp.i2.i32(i32 %x, i32 %y)
+ ret i2 %a
+}
+
+define i2 @scmp_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: scmp_i64:
+; CHECK: .functype scmp_i64 (i64, i64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: i64.gt_s $push2=, $pop4, $pop3
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: i64.lt_s $push1=, $pop6, $pop5
+; CHECK-NEXT: i32.sub $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i2 @llvm.scmp.i2.i64(i64 %x, i64 %y)
+ ret i2 %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/select.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/select.ll
new file mode 100644
index 0000000000000..7f5e8fe80c191
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/select.ll
@@ -0,0 +1,94 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+define i8 @select_i8(i1 %cond, i8 %x, i8 %y) {
+; CHECK-LABEL: select_i8:
+; CHECK: .functype select_i8 (i32, i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: local.get $push4=, 2
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: i32.const $push2=, 1
+; CHECK-NEXT: i32.and $push1=, $pop3, $pop2
+; CHECK-NEXT: i32.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = select i1 %cond, i8 %x, i8 %y
+ ret i8 %a
+}
+
+define i16 @select_i16(i1 %cond, i16 %x, i16 %y) {
+; CHECK-LABEL: select_i16:
+; CHECK: .functype select_i16 (i32, i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: local.get $push4=, 2
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: i32.const $push2=, 1
+; CHECK-NEXT: i32.and $push1=, $pop3, $pop2
+; CHECK-NEXT: i32.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = select i1 %cond, i16 %x, i16 %y
+ ret i16 %a
+}
+
+define i32 @select_i32(i1 %cond, i32 %x, i32 %y) {
+; CHECK-LABEL: select_i32:
+; CHECK: .functype select_i32 (i32, i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: local.get $push4=, 2
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: i32.const $push2=, 1
+; CHECK-NEXT: i32.and $push1=, $pop3, $pop2
+; CHECK-NEXT: i32.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = select i1 %cond, i32 %x, i32 %y
+ ret i32 %a
+}
+
+define i64 @select_i64(i1 %cond, i64 %x, i64 %y) {
+; CHECK-LABEL: select_i64:
+; CHECK: .functype select_i64 (i32, i64, i64) -> (i64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: local.get $push4=, 2
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: i32.const $push2=, 1
+; CHECK-NEXT: i32.and $push1=, $pop3, $pop2
+; CHECK-NEXT: i64.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = select i1 %cond, i64 %x, i64 %y
+ ret i64 %a
+}
+
+define float @select_f32(i1 %cond, float %x, float %y) {
+; CHECK-LABEL: select_f32:
+; CHECK: .functype select_f32 (i32, f32, f32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: local.get $push4=, 2
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: i32.const $push2=, 1
+; CHECK-NEXT: i32.and $push1=, $pop3, $pop2
+; CHECK-NEXT: f32.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = select i1 %cond, float %x, float %y
+ ret float %a
+}
+
+define double @select_f64(i1 %cond, double %x, double %y) {
+; CHECK-LABEL: select_f64:
+; CHECK: .functype select_f64 (i32, f64, f64) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: local.get $push4=, 2
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: i32.const $push2=, 1
+; CHECK-NEXT: i32.and $push1=, $pop3, $pop2
+; CHECK-NEXT: f64.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = select i1 %cond, double %x, double %y
+ ret double %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/smax.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/smax.ll
new file mode 100644
index 0000000000000..1cc43886d2701
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/smax.ll
@@ -0,0 +1,73 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+declare i8 @llvm.smax.i8(i8, i8)
+declare i16 @llvm.smax.i16(i16, i16)
+declare i32 @llvm.smax.i32(i32, i32)
+declare i64 @llvm.smax.i64(i64, i64)
+
+define i8 @smax_i8(i8 %x, i8 %y) {
+; CHECK-LABEL: smax_i8:
+; CHECK: .functype smax_i8 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push7=, 0
+; CHECK-NEXT: local.get $push6=, 1
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: i32.extend8_s $push2=, $pop4
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: i32.extend8_s $push3=, $pop5
+; CHECK-NEXT: i32.gt_s $push1=, $pop2, $pop3
+; CHECK-NEXT: i32.select $push0=, $pop7, $pop6, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i8 @llvm.smax.i8(i8 %x, i8 %y)
+ ret i8 %a
+}
+
+define i16 @smax_i16(i16 %x, i16 %y) {
+; CHECK-LABEL: smax_i16:
+; CHECK: .functype smax_i16 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push7=, 0
+; CHECK-NEXT: local.get $push6=, 1
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: i32.extend16_s $push2=, $pop4
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: i32.extend16_s $push3=, $pop5
+; CHECK-NEXT: i32.gt_s $push1=, $pop2, $pop3
+; CHECK-NEXT: i32.select $push0=, $pop7, $pop6, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i16 @llvm.smax.i16(i16 %x, i16 %y)
+ ret i16 %a
+}
+
+define i32 @smax_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: smax_i32:
+; CHECK: .functype smax_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: local.get $push4=, 1
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: local.get $push2=, 1
+; CHECK-NEXT: i32.gt_s $push1=, $pop3, $pop2
+; CHECK-NEXT: i32.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i32 @llvm.smax.i32(i32 %x, i32 %y)
+ ret i32 %a
+}
+
+define i64 @smax_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: smax_i64:
+; CHECK: .functype smax_i64 (i64, i64) -> (i64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: local.get $push4=, 1
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: local.get $push2=, 1
+; CHECK-NEXT: i64.gt_s $push1=, $pop3, $pop2
+; CHECK-NEXT: i64.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i64 @llvm.smax.i64(i64 %x, i64 %y)
+ ret i64 %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/smin.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/smin.ll
new file mode 100644
index 0000000000000..e6f9e09a0b40e
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/smin.ll
@@ -0,0 +1,73 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+declare i8 @llvm.smin.i8(i8, i8)
+declare i16 @llvm.smin.i16(i16, i16)
+declare i32 @llvm.smin.i32(i32, i32)
+declare i64 @llvm.smin.i64(i64, i64)
+
+define i8 @smin_i8(i8 %x, i8 %y) {
+; CHECK-LABEL: smin_i8:
+; CHECK: .functype smin_i8 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push7=, 0
+; CHECK-NEXT: local.get $push6=, 1
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: i32.extend8_s $push2=, $pop4
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: i32.extend8_s $push3=, $pop5
+; CHECK-NEXT: i32.lt_s $push1=, $pop2, $pop3
+; CHECK-NEXT: i32.select $push0=, $pop7, $pop6, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i8 @llvm.smin.i8(i8 %x, i8 %y)
+ ret i8 %a
+}
+
+define i16 @smin_i16(i16 %x, i16 %y) {
+; CHECK-LABEL: smin_i16:
+; CHECK: .functype smin_i16 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push7=, 0
+; CHECK-NEXT: local.get $push6=, 1
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: i32.extend16_s $push2=, $pop4
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: i32.extend16_s $push3=, $pop5
+; CHECK-NEXT: i32.lt_s $push1=, $pop2, $pop3
+; CHECK-NEXT: i32.select $push0=, $pop7, $pop6, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i16 @llvm.smin.i16(i16 %x, i16 %y)
+ ret i16 %a
+}
+
+define i32 @smin_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: smin_i32:
+; CHECK: .functype smin_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: local.get $push4=, 1
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: local.get $push2=, 1
+; CHECK-NEXT: i32.lt_s $push1=, $pop3, $pop2
+; CHECK-NEXT: i32.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i32 @llvm.smin.i32(i32 %x, i32 %y)
+ ret i32 %a
+}
+
+define i64 @smin_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: smin_i64:
+; CHECK: .functype smin_i64 (i64, i64) -> (i64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: local.get $push4=, 1
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: local.get $push2=, 1
+; CHECK-NEXT: i64.lt_s $push1=, $pop3, $pop2
+; CHECK-NEXT: i64.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i64 @llvm.smin.i64(i64 %x, i64 %y)
+ ret i64 %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ucmp.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ucmp.ll
new file mode 100644
index 0000000000000..e16e5f0b67dd6
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/ucmp.ll
@@ -0,0 +1,89 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+declare i2 @llvm.ucmp.i2.i8(i8, i8)
+declare i2 @llvm.ucmp.i2.i16(i16, i16)
+declare i2 @llvm.ucmp.i2.i32(i32, i32)
+declare i2 @llvm.ucmp.i2.i64(i64, i64)
+
+define i2 @ucmp_i8(i8 %x, i8 %y) {
+; CHECK-LABEL: ucmp_i8:
+; CHECK: .functype ucmp_i8 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push11=, 0
+; CHECK-NEXT: i32.const $push8=, 255
+; CHECK-NEXT: i32.and $push5=, $pop11, $pop8
+; CHECK-NEXT: local.get $push12=, 1
+; CHECK-NEXT: i32.const $push7=, 255
+; CHECK-NEXT: i32.and $push6=, $pop12, $pop7
+; CHECK-NEXT: i32.gt_u $push4=, $pop5, $pop6
+; CHECK-NEXT: local.get $push13=, 0
+; CHECK-NEXT: i32.const $push10=, 255
+; CHECK-NEXT: i32.and $push2=, $pop13, $pop10
+; CHECK-NEXT: local.get $push14=, 1
+; CHECK-NEXT: i32.const $push9=, 255
+; CHECK-NEXT: i32.and $push3=, $pop14, $pop9
+; CHECK-NEXT: i32.lt_u $push1=, $pop2, $pop3
+; CHECK-NEXT: i32.sub $push0=, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i2 @llvm.ucmp.i2.i8(i8 %x, i8 %y)
+ ret i2 %a
+}
+
+define i2 @ucmp_i16(i16 %x, i16 %y) {
+; CHECK-LABEL: ucmp_i16:
+; CHECK: .functype ucmp_i16 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push11=, 0
+; CHECK-NEXT: i32.const $push8=, 65535
+; CHECK-NEXT: i32.and $push5=, $pop11, $pop8
+; CHECK-NEXT: local.get $push12=, 1
+; CHECK-NEXT: i32.const $push7=, 65535
+; CHECK-NEXT: i32.and $push6=, $pop12, $pop7
+; CHECK-NEXT: i32.gt_u $push4=, $pop5, $pop6
+; CHECK-NEXT: local.get $push13=, 0
+; CHECK-NEXT: i32.const $push10=, 65535
+; CHECK-NEXT: i32.and $push2=, $pop13, $pop10
+; CHECK-NEXT: local.get $push14=, 1
+; CHECK-NEXT: i32.const $push9=, 65535
+; CHECK-NEXT: i32.and $push3=, $pop14, $pop9
+; CHECK-NEXT: i32.lt_u $push1=, $pop2, $pop3
+; CHECK-NEXT: i32.sub $push0=, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i2 @llvm.ucmp.i2.i16(i16 %x, i16 %y)
+ ret i2 %a
+}
+
+define i2 @ucmp_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: ucmp_i32:
+; CHECK: .functype ucmp_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: i32.gt_u $push2=, $pop4, $pop3
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: i32.lt_u $push1=, $pop6, $pop5
+; CHECK-NEXT: i32.sub $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i2 @llvm.ucmp.i2.i32(i32 %x, i32 %y)
+ ret i2 %a
+}
+
+define i2 @ucmp_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: ucmp_i64:
+; CHECK: .functype ucmp_i64 (i64, i64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: i64.gt_u $push2=, $pop4, $pop3
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: i64.lt_u $push1=, $pop6, $pop5
+; CHECK-NEXT: i32.sub $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i2 @llvm.ucmp.i2.i64(i64 %x, i64 %y)
+ ret i2 %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/umax.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/umax.ll
new file mode 100644
index 0000000000000..b4b8d05185247
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/umax.ll
@@ -0,0 +1,77 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+declare i8 @llvm.umax.i8(i8, i8)
+declare i16 @llvm.umax.i16(i16, i16)
+declare i32 @llvm.umax.i32(i32, i32)
+declare i64 @llvm.umax.i64(i64, i64)
+
+define i8 @umax_i8(i8 %x, i8 %y) {
+; CHECK-LABEL: umax_i8:
+; CHECK: .functype umax_i8 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: local.get $push8=, 1
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: i32.const $push5=, 255
+; CHECK-NEXT: i32.and $push2=, $pop6, $pop5
+; CHECK-NEXT: local.get $push7=, 1
+; CHECK-NEXT: i32.const $push4=, 255
+; CHECK-NEXT: i32.and $push3=, $pop7, $pop4
+; CHECK-NEXT: i32.gt_u $push1=, $pop2, $pop3
+; CHECK-NEXT: i32.select $push0=, $pop9, $pop8, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i8 @llvm.umax.i8(i8 %x, i8 %y)
+ ret i8 %a
+}
+
+define i16 @umax_i16(i16 %x, i16 %y) {
+; CHECK-LABEL: umax_i16:
+; CHECK: .functype umax_i16 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: local.get $push8=, 1
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: i32.const $push5=, 65535
+; CHECK-NEXT: i32.and $push2=, $pop6, $pop5
+; CHECK-NEXT: local.get $push7=, 1
+; CHECK-NEXT: i32.const $push4=, 65535
+; CHECK-NEXT: i32.and $push3=, $pop7, $pop4
+; CHECK-NEXT: i32.gt_u $push1=, $pop2, $pop3
+; CHECK-NEXT: i32.select $push0=, $pop9, $pop8, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i16 @llvm.umax.i16(i16 %x, i16 %y)
+ ret i16 %a
+}
+
+define i32 @umax_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: umax_i32:
+; CHECK: .functype umax_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: local.get $push4=, 1
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: local.get $push2=, 1
+; CHECK-NEXT: i32.gt_u $push1=, $pop3, $pop2
+; CHECK-NEXT: i32.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i32 @llvm.umax.i32(i32 %x, i32 %y)
+ ret i32 %a
+}
+
+define i64 @umax_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: umax_i64:
+; CHECK: .functype umax_i64 (i64, i64) -> (i64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: local.get $push4=, 1
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: local.get $push2=, 1
+; CHECK-NEXT: i64.gt_u $push1=, $pop3, $pop2
+; CHECK-NEXT: i64.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i64 @llvm.umax.i64(i64 %x, i64 %y)
+ ret i64 %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/umin.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/umin.ll
new file mode 100644
index 0000000000000..235944da59f97
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/umin.ll
@@ -0,0 +1,77 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc < %s -O0 --global-isel -disable-wasm-fallthrough-return-opt -wasm-keep-registers | FileCheck %s
+
+target triple = "wasm32-unknown-unknown"
+
+declare i8 @llvm.umin.i8(i8, i8)
+declare i16 @llvm.umin.i16(i16, i16)
+declare i32 @llvm.umin.i32(i32, i32)
+declare i64 @llvm.umin.i64(i64, i64)
+
+define i8 @umin_i8(i8 %x, i8 %y) {
+; CHECK-LABEL: umin_i8:
+; CHECK: .functype umin_i8 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: local.get $push8=, 1
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: i32.const $push5=, 255
+; CHECK-NEXT: i32.and $push2=, $pop6, $pop5
+; CHECK-NEXT: local.get $push7=, 1
+; CHECK-NEXT: i32.const $push4=, 255
+; CHECK-NEXT: i32.and $push3=, $pop7, $pop4
+; CHECK-NEXT: i32.lt_u $push1=, $pop2, $pop3
+; CHECK-NEXT: i32.select $push0=, $pop9, $pop8, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i8 @llvm.umin.i8(i8 %x, i8 %y)
+ ret i8 %a
+}
+
+define i16 @umin_i16(i16 %x, i16 %y) {
+; CHECK-LABEL: umin_i16:
+; CHECK: .functype umin_i16 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: local.get $push8=, 1
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: i32.const $push5=, 65535
+; CHECK-NEXT: i32.and $push2=, $pop6, $pop5
+; CHECK-NEXT: local.get $push7=, 1
+; CHECK-NEXT: i32.const $push4=, 65535
+; CHECK-NEXT: i32.and $push3=, $pop7, $pop4
+; CHECK-NEXT: i32.lt_u $push1=, $pop2, $pop3
+; CHECK-NEXT: i32.select $push0=, $pop9, $pop8, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i16 @llvm.umin.i16(i16 %x, i16 %y)
+ ret i16 %a
+}
+
+define i32 @umin_i32(i32 %x, i32 %y) {
+; CHECK-LABEL: umin_i32:
+; CHECK: .functype umin_i32 (i32, i32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: local.get $push4=, 1
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: local.get $push2=, 1
+; CHECK-NEXT: i32.lt_u $push1=, $pop3, $pop2
+; CHECK-NEXT: i32.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i32 @llvm.umin.i32(i32 %x, i32 %y)
+ ret i32 %a
+}
+
+define i64 @umin_i64(i64 %x, i64 %y) {
+; CHECK-LABEL: umin_i64:
+; CHECK: .functype umin_i64 (i64, i64) -> (i64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: local.get $push4=, 1
+; CHECK-NEXT: local.get $push3=, 0
+; CHECK-NEXT: local.get $push2=, 1
+; CHECK-NEXT: i64.lt_u $push1=, $pop3, $pop2
+; CHECK-NEXT: i64.select $push0=, $pop5, $pop4, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call i64 @llvm.umin.i64(i64 %x, i64 %y)
+ ret i64 %a
+}
More information about the llvm-commits
mailing list