[llvm-branch-commits] [llvm] Implement floating-point comparisons (PR #197258)
Demetrius Kanios via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Tue May 12 10:50:04 PDT 2026
https://github.com/QuantumSegfault created https://github.com/llvm/llvm-project/pull/197258
None
>From 6ce35c950533ef41c08de8e7c7998a390e4f0668 Mon Sep 17 00:00:00 2001
From: Demetrius Kanios <demetrius at kanios.net>
Date: Tue, 12 May 2026 00:42:59 -0700
Subject: [PATCH] Implement floating-point comparisons
---
.../GISel/WebAssemblyLegalizerInfo.cpp | 312 +++++++++++
.../GlobalISel/instructions/fcmp.ll | 436 ++++++++++++++++
.../GlobalISel/instructions/fmaximum.ll | 32 ++
.../GlobalISel/instructions/fmaximumnum.ll | 219 ++++++++
.../GlobalISel/instructions/fmaxnum.ll | 55 ++
.../GlobalISel/instructions/fminimum.ll | 32 ++
.../GlobalISel/instructions/fminimumnum.ll | 225 ++++++++
.../GlobalISel/instructions/fminnum.ll | 55 ++
.../GlobalISel/instructions/is_fpclass.ll | 490 ++++++++++++++++++
9 files changed, 1856 insertions(+)
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fcmp.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmaximum.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmaximumnum.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmaxnum.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fminimum.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fminimumnum.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fminnum.ll
create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/is_fpclass.ll
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
index d91ec459397ba..0c8f17c04f2d8 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
@@ -103,6 +103,23 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
.minScalar(0, s32)
.scalarSameSizeAs(1, 0);
+ getActionDefinitionsBuilder(G_FCMP)
+ .customForCartesianProduct({i32}, {f32, f64})
+ .clampScalar(0, s32, s32);
+
+ getActionDefinitionsBuilder({G_FMINIMUM, G_FMAXIMUM})
+ .legalFor({f32, f64})
+ .minScalar(0, s32);
+
+ getActionDefinitionsBuilder(
+ {G_FMINNUM, G_FMAXNUM, G_FMINIMUMNUM, G_FMAXIMUMNUM})
+ .customFor({f32, f64})
+ .minScalar(0, s32);
+
+ getActionDefinitionsBuilder(G_IS_FPCLASS)
+ .lowerForCartesianProduct({i32}, {f32, f64})
+ .clampScalar(0, s32, s32);
+
getActionDefinitionsBuilder(G_FPEXT)
.legalFor({{f64, f32}})
.clampScalar(0, s64, s64)
@@ -153,6 +170,11 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
bool WebAssemblyLegalizerInfo::legalizeCustom(
LegalizerHelper &Helper, MachineInstr &MI,
LostDebugLocObserver &LocObserver) const {
+ MachineRegisterInfo &MRI = *Helper.MIRBuilder.getMRI();
+ auto &MIRBuilder = Helper.MIRBuilder;
+
+ const LLT i1 = LLT::integer(1);
+
switch (MI.getOpcode()) {
case TargetOpcode::G_SEXT_INREG: {
assert(MI.getOperand(2).isImm() && "Expected immediate");
@@ -168,6 +190,296 @@ bool WebAssemblyLegalizerInfo::legalizeCustom(
return Helper.lower(MI, 0, DstType) != LegalizerHelper::UnableToLegalize;
}
+ case TargetOpcode::G_FCMP: {
+ Register LHS = MI.getOperand(2).getReg();
+ Register RHS = MI.getOperand(3).getReg();
+ CmpInst::Predicate Pred =
+ static_cast<CmpInst::Predicate>(MI.getOperand(1).getPredicate());
+
+ Register Result = MI.getOperand(0).getReg();
+
+ switch (Pred) {
+ case CmpInst::FCMP_FALSE:
+ MIRBuilder.buildBoolExt(Result, MIRBuilder.buildConstant(i1, 0), false);
+ break;
+ case CmpInst::FCMP_OEQ:
+ return true;
+ case CmpInst::FCMP_OGT:
+ return true;
+ case CmpInst::FCMP_OGE:
+ return true;
+ case CmpInst::FCMP_OLT:
+ return true;
+ case CmpInst::FCMP_OLE:
+ return true;
+ case CmpInst::FCMP_ONE: {
+ MIRBuilder.buildBoolExt(
+ Result,
+ MIRBuilder.buildOr(
+ i1,
+ MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, i1, LHS, RHS).getReg(0),
+ MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, i1, LHS, RHS).getReg(0)),
+ false);
+ break;
+ }
+ case CmpInst::FCMP_ORD: {
+ MIRBuilder.buildBoolExt(
+ Result,
+ MIRBuilder.buildAnd(
+ i1,
+ MIRBuilder.buildFCmp(CmpInst::FCMP_OEQ, i1, RHS, RHS).getReg(0),
+ MIRBuilder.buildFCmp(CmpInst::FCMP_OEQ, i1, LHS, LHS).getReg(0)),
+ false);
+ break;
+ }
+ case CmpInst::FCMP_UNO: {
+ MIRBuilder.buildBoolExt(
+ Result,
+ MIRBuilder.buildOr(
+ i1,
+ MIRBuilder.buildFCmp(CmpInst::FCMP_UNE, i1, RHS, RHS).getReg(0),
+ MIRBuilder.buildFCmp(CmpInst::FCMP_UNE, i1, LHS, LHS).getReg(0)),
+ false);
+ break;
+ }
+ case CmpInst::FCMP_UEQ: {
+ MIRBuilder.buildBoolExt(
+ Result,
+ MIRBuilder.buildNot(
+ i1,
+ MIRBuilder.buildFCmp(CmpInst::FCMP_ONE, i1, LHS, RHS).getReg(0)),
+ false);
+ break;
+ }
+ case CmpInst::FCMP_UGT: {
+ MIRBuilder.buildBoolExt(
+ Result,
+ MIRBuilder.buildNot(
+ i1,
+ MIRBuilder.buildFCmp(CmpInst::FCMP_OLE, i1, LHS, RHS).getReg(0)),
+ false);
+ break;
+ }
+ case CmpInst::FCMP_UGE: {
+ MIRBuilder.buildBoolExt(
+ Result,
+ MIRBuilder.buildNot(
+ i1,
+ MIRBuilder.buildFCmp(CmpInst::FCMP_OLT, i1, LHS, RHS).getReg(0)),
+ false);
+ break;
+ }
+ case CmpInst::FCMP_ULT: {
+ MIRBuilder.buildBoolExt(
+ Result,
+ MIRBuilder.buildNot(
+ i1,
+ MIRBuilder.buildFCmp(CmpInst::FCMP_OGE, i1, LHS, RHS).getReg(0)),
+ false);
+ break;
+ }
+ case CmpInst::FCMP_ULE: {
+ MIRBuilder.buildBoolExt(
+ Result,
+ MIRBuilder.buildNot(
+ i1,
+ MIRBuilder.buildFCmp(CmpInst::FCMP_OGT, i1, LHS, RHS).getReg(0)),
+ false);
+ break;
+ }
+ case CmpInst::FCMP_UNE:
+ return true;
+ case CmpInst::FCMP_TRUE:
+ MIRBuilder.buildBoolExt(Result, MIRBuilder.buildConstant(i1, 1), false);
+ break;
+ default:
+ llvm_unreachable("Unknown FCMP predicate");
+ }
+
+ MI.eraseFromParent();
+
+ return true;
+ }
+ case TargetOpcode::G_FMINNUM: {
+ // We can only use G_FMINIMUM if we can be sure no NaN is present.
+ // This is because G_FMINIMUM propogates NaN, while G_FMINNUM says that
+ // the non-NaN operand must result.
+ if (!MI.getFlag(MachineInstr::MIFlag::FmNoNans))
+ return Helper.libcall(MI, LocObserver) !=
+ LegalizerHelper::UnableToLegalize;
+
+ // this respects maxnum signed zero handling. G_FMINNUM has undefined zeros
+ // handling, so G_FMINIMUM's specific choice of zero is irrelavent.
+ MIRBuilder.buildInstr(TargetOpcode::G_FMINIMUM)
+ .addDef(MI.getOperand(0).getReg())
+ .addUse(MI.getOperand(1).getReg())
+ .addUse(MI.getOperand(2).getReg())
+ .setMIFlags(MI.getFlags());
+
+ MI.eraseFromParent();
+ return true;
+ }
+ case TargetOpcode::G_FMAXNUM: {
+ // We can only use G_FMAXIMUM if we can be sure no NaN is present.
+ // This is because G_FMAXIMUM propogates NaN, while G_MAXNUM says that
+ // the non-NaN operand must result.
+ if (!MI.getFlag(MachineInstr::MIFlag::FmNoNans))
+ return Helper.libcall(MI, LocObserver) !=
+ LegalizerHelper::UnableToLegalize;
+
+ // this respects maxnum signed zero handling. G_FMAXNUM has undefined zeros
+ // handling, so G_FMAXIMUM's specific choice of zero is irrelavent.
+ MIRBuilder.buildInstr(TargetOpcode::G_FMAXIMUM)
+ .addDef(MI.getOperand(0).getReg())
+ .addUse(MI.getOperand(1).getReg())
+ .addUse(MI.getOperand(2).getReg())
+ .setMIFlags(MI.getFlags());
+
+ MI.eraseFromParent();
+ return true;
+ }
+ case WebAssembly::G_FMINIMUMNUM: {
+ // This is a stripped down version of fminimumnum handling for SelectionDAG
+ // TargetLowering
+ Register Result = MI.getOperand(0).getReg();
+ LLT ResultTy = MRI.getType(Result);
+
+ if (MI.getFlag(MachineInstr::MIFlag::FmNoNans)) {
+ MIRBuilder.buildInstr(TargetOpcode::G_FMINIMUM)
+ .addDef(MI.getOperand(0).getReg())
+ .addUse(MI.getOperand(1).getReg())
+ .addUse(MI.getOperand(2).getReg())
+ .setMIFlags(MI.getFlags());
+ } else {
+ Register LHS = MI.getOperand(1).getReg();
+ Register RHS = MI.getOperand(2).getReg();
+
+ LHS = MIRBuilder
+ .buildSelect(ResultTy,
+ MIRBuilder.buildFCmp(CmpInst::Predicate::FCMP_UNO,
+ i1, LHS, LHS),
+ RHS, LHS)
+ ->getOperand(0)
+ .getReg();
+ RHS = MIRBuilder
+ .buildSelect(ResultTy,
+ MIRBuilder.buildFCmp(CmpInst::Predicate::FCMP_UNO,
+ i1, RHS, RHS),
+ LHS, RHS)
+ ->getOperand(0)
+ .getReg();
+
+ if (MI.getFlag(MachineInstr::MIFlag::FmNsz)) {
+ MIRBuilder.buildSelect(
+ Result,
+ MIRBuilder.buildFCmp(CmpInst::Predicate::FCMP_OLT, i1, LHS, RHS),
+ LHS, RHS);
+ } else {
+ Register MinMax =
+ MIRBuilder
+ .buildSelect(ResultTy,
+ MIRBuilder.buildFCmp(CmpInst::Predicate::FCMP_OLT,
+ i1, LHS, RHS),
+ LHS, RHS)
+ ->getOperand(0)
+ .getReg();
+
+ Register IsZero =
+ MIRBuilder
+ .buildFCmp(CmpInst::Predicate::FCMP_OEQ, i1, MinMax,
+ MIRBuilder.buildFConstant(ResultTy, 0.0))
+ ->getOperand(0)
+ .getReg();
+
+ // It's OK to select from LHS and MinMax, with only one ISD::IS_FPCLASS,
+ // as we preferred RHS when generate MinMax, if the operands are equal.
+ Register RetZero =
+ MIRBuilder
+ .buildSelect(ResultTy,
+ MIRBuilder.buildIsFPClass(i1, LHS, fcNegZero), LHS,
+ MinMax)
+ .setMIFlags(MI.getFlags())
+ ->getOperand(0)
+ .getReg();
+ MIRBuilder.buildSelect(Result, IsZero, RetZero, MinMax)
+ .setMIFlags(MI.getFlags());
+ }
+ }
+
+ MI.eraseFromParent();
+ return true;
+ }
+ case WebAssembly::G_FMAXIMUMNUM: {
+ // This is a stripped down version of fmaximumnum handling for SelectionDAG
+ // TargetLowering
+ Register Result = MI.getOperand(0).getReg();
+ LLT ResultTy = MRI.getType(Result);
+
+ if (MI.getFlag(MachineInstr::MIFlag::FmNoNans)) {
+ MIRBuilder.buildInstr(TargetOpcode::G_FMINIMUM)
+ .addDef(MI.getOperand(0).getReg())
+ .addUse(MI.getOperand(1).getReg())
+ .addUse(MI.getOperand(2).getReg())
+ .setMIFlags(MI.getFlags());
+ } else {
+ Register LHS = MI.getOperand(1).getReg();
+ Register RHS = MI.getOperand(2).getReg();
+
+ LHS = MIRBuilder
+ .buildSelect(ResultTy,
+ MIRBuilder.buildFCmp(CmpInst::Predicate::FCMP_UNO,
+ i1, LHS, LHS),
+ RHS, LHS)
+ ->getOperand(0)
+ .getReg();
+ RHS = MIRBuilder
+ .buildSelect(ResultTy,
+ MIRBuilder.buildFCmp(CmpInst::Predicate::FCMP_UNO,
+ i1, RHS, RHS),
+ LHS, RHS)
+ ->getOperand(0)
+ .getReg();
+
+ if (MI.getFlag(MachineInstr::MIFlag::FmNsz)) {
+ MIRBuilder.buildSelect(
+ Result,
+ MIRBuilder.buildFCmp(CmpInst::Predicate::FCMP_OGT, i1, LHS, RHS),
+ LHS, RHS);
+ } else {
+ Register MinMax =
+ MIRBuilder
+ .buildSelect(ResultTy,
+ MIRBuilder.buildFCmp(CmpInst::Predicate::FCMP_OGT,
+ i1, LHS, RHS),
+ LHS, RHS)
+ ->getOperand(0)
+ .getReg();
+
+ Register IsZero =
+ MIRBuilder
+ .buildFCmp(CmpInst::Predicate::FCMP_OEQ, i1, MinMax,
+ MIRBuilder.buildFConstant(ResultTy, 0.0))
+ ->getOperand(0)
+ .getReg();
+
+ // It's OK to select from LHS and MinMax, with only one ISD::IS_FPCLASS,
+ // as we preferred RHS when generate MinMax, if the operands are equal.
+ Register RetZero =
+ MIRBuilder
+ .buildSelect(ResultTy,
+ MIRBuilder.buildIsFPClass(i1, LHS, fcPosZero), LHS,
+ MinMax)
+ .setMIFlags(MI.getFlags())
+ ->getOperand(0)
+ .getReg();
+ MIRBuilder.buildSelect(Result, IsZero, RetZero, MinMax)
+ .setMIFlags(MI.getFlags());
+ }
+ }
+
+ MI.eraseFromParent();
+ return true;
+ }
default:
break;
}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fcmp.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fcmp.ll
new file mode 100644
index 0000000000000..e92e523e44cd3
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fcmp.ll
@@ -0,0 +1,436 @@
+; 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 @fcmp_false_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_false_f32:
+; CHECK: .functype fcmp_false_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: i32.const $push0=, 0
+; CHECK-NEXT: return $pop0
+ %a = fcmp false float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_oeq_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_oeq_f32:
+; CHECK: .functype fcmp_oeq_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f32.eq $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp oeq float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ogt_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_ogt_f32:
+; CHECK: .functype fcmp_ogt_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f32.gt $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp ogt float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_oge_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_oge_f32:
+; CHECK: .functype fcmp_oge_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f32.ge $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp oge float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_olt_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_olt_f32:
+; CHECK: .functype fcmp_olt_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f32.lt $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp olt float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ole_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_ole_f32:
+; CHECK: .functype fcmp_ole_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f32.le $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp ole float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_one_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_one_f32:
+; CHECK: .functype fcmp_one_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f32.lt $push2=, $pop4, $pop3
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: f32.gt $push1=, $pop6, $pop5
+; CHECK-NEXT: i32.or $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp one float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ord_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_ord_f32:
+; CHECK: .functype fcmp_ord_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 1
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f32.eq $push2=, $pop4, $pop3
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: f32.eq $push1=, $pop6, $pop5
+; CHECK-NEXT: i32.and $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp ord float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ueq_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_ueq_f32:
+; CHECK: .functype fcmp_ueq_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push8=, 0
+; CHECK-NEXT: local.get $push7=, 1
+; CHECK-NEXT: f32.lt $push5=, $pop8, $pop7
+; CHECK-NEXT: local.get $push10=, 0
+; CHECK-NEXT: local.get $push9=, 1
+; CHECK-NEXT: f32.gt $push4=, $pop10, $pop9
+; CHECK-NEXT: i32.or $push3=, $pop5, $pop4
+; CHECK-NEXT: i32.const $push2=, 1
+; CHECK-NEXT: i32.xor $push1=, $pop3, $pop2
+; CHECK-NEXT: i32.const $push6=, 1
+; CHECK-NEXT: i32.and $push0=, $pop1, $pop6
+; CHECK-NEXT: return $pop0
+ %a = fcmp ueq float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ugt_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_ugt_f32:
+; CHECK: .functype fcmp_ugt_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f32.le $push2=, $pop4, $pop3
+; CHECK-NEXT: i32.const $push1=, 1
+; CHECK-NEXT: i32.xor $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp ugt float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_uge_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_uge_f32:
+; CHECK: .functype fcmp_uge_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f32.lt $push2=, $pop4, $pop3
+; CHECK-NEXT: i32.const $push1=, 1
+; CHECK-NEXT: i32.xor $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp uge float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ult_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_ult_f32:
+; CHECK: .functype fcmp_ult_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f32.ge $push2=, $pop4, $pop3
+; CHECK-NEXT: i32.const $push1=, 1
+; CHECK-NEXT: i32.xor $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp ult float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ule_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_ule_f32:
+; CHECK: .functype fcmp_ule_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f32.gt $push2=, $pop4, $pop3
+; CHECK-NEXT: i32.const $push1=, 1
+; CHECK-NEXT: i32.xor $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp ule float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_une_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_une_f32:
+; CHECK: .functype fcmp_une_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f32.ne $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp une float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_uno_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_uno_f32:
+; CHECK: .functype fcmp_uno_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 1
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f32.ne $push2=, $pop4, $pop3
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: f32.ne $push1=, $pop6, $pop5
+; CHECK-NEXT: i32.or $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp uno float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_true_f32(float %x, float %y) {
+; CHECK-LABEL: fcmp_true_f32:
+; CHECK: .functype fcmp_true_f32 (f32, f32) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: i32.const $push0=, 1
+; CHECK-NEXT: return $pop0
+ %a = fcmp true float %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_false_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_false_f64:
+; CHECK: .functype fcmp_false_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: i32.const $push0=, 0
+; CHECK-NEXT: return $pop0
+ %a = fcmp false double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_oeq_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_oeq_f64:
+; CHECK: .functype fcmp_oeq_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f64.eq $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp oeq double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ogt_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_ogt_f64:
+; CHECK: .functype fcmp_ogt_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f64.gt $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp ogt double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_oge_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_oge_f64:
+; CHECK: .functype fcmp_oge_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f64.ge $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp oge double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_olt_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_olt_f64:
+; CHECK: .functype fcmp_olt_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f64.lt $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp olt double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ole_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_ole_f64:
+; CHECK: .functype fcmp_ole_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f64.le $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp ole double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_one_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_one_f64:
+; CHECK: .functype fcmp_one_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f64.lt $push2=, $pop4, $pop3
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: f64.gt $push1=, $pop6, $pop5
+; CHECK-NEXT: i32.or $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp one double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ord_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_ord_f64:
+; CHECK: .functype fcmp_ord_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 1
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f64.eq $push2=, $pop4, $pop3
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: f64.eq $push1=, $pop6, $pop5
+; CHECK-NEXT: i32.and $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp ord double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ueq_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_ueq_f64:
+; CHECK: .functype fcmp_ueq_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push8=, 0
+; CHECK-NEXT: local.get $push7=, 1
+; CHECK-NEXT: f64.lt $push5=, $pop8, $pop7
+; CHECK-NEXT: local.get $push10=, 0
+; CHECK-NEXT: local.get $push9=, 1
+; CHECK-NEXT: f64.gt $push4=, $pop10, $pop9
+; CHECK-NEXT: i32.or $push3=, $pop5, $pop4
+; CHECK-NEXT: i32.const $push2=, 1
+; CHECK-NEXT: i32.xor $push1=, $pop3, $pop2
+; CHECK-NEXT: i32.const $push6=, 1
+; CHECK-NEXT: i32.and $push0=, $pop1, $pop6
+; CHECK-NEXT: return $pop0
+ %a = fcmp ueq double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ugt_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_ugt_f64:
+; CHECK: .functype fcmp_ugt_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f64.le $push2=, $pop4, $pop3
+; CHECK-NEXT: i32.const $push1=, 1
+; CHECK-NEXT: i32.xor $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp ugt double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_uge_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_uge_f64:
+; CHECK: .functype fcmp_uge_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f64.lt $push2=, $pop4, $pop3
+; CHECK-NEXT: i32.const $push1=, 1
+; CHECK-NEXT: i32.xor $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp uge double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ult_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_ult_f64:
+; CHECK: .functype fcmp_ult_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f64.ge $push2=, $pop4, $pop3
+; CHECK-NEXT: i32.const $push1=, 1
+; CHECK-NEXT: i32.xor $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp ult double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_ule_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_ule_f64:
+; CHECK: .functype fcmp_ule_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f64.gt $push2=, $pop4, $pop3
+; CHECK-NEXT: i32.const $push1=, 1
+; CHECK-NEXT: i32.xor $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp ule double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_une_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_une_f64:
+; CHECK: .functype fcmp_une_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f64.ne $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp une double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_uno_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_uno_f64:
+; CHECK: .functype fcmp_uno_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 1
+; CHECK-NEXT: local.get $push3=, 1
+; CHECK-NEXT: f64.ne $push2=, $pop4, $pop3
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: f64.ne $push1=, $pop6, $pop5
+; CHECK-NEXT: i32.or $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = fcmp uno double %x, %y
+ ret i1 %a
+}
+
+define i1 @fcmp_true_f64(double %x, double %y) {
+; CHECK-LABEL: fcmp_true_f64:
+; CHECK: .functype fcmp_true_f64 (f64, f64) -> (i32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: i32.const $push0=, 1
+; CHECK-NEXT: return $pop0
+ %a = fcmp true double %x, %y
+ ret i1 %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmaximum.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmaximum.ll
new file mode 100644
index 0000000000000..117ea3ecc8d0f
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmaximum.ll
@@ -0,0 +1,32 @@
+; 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 float @llvm.maximum.f32(float, float)
+declare double @llvm.maximum.f64(double, double)
+
+
+define float @fmaximum_f32(float %x, float %y) {
+; CHECK-LABEL: fmaximum_f32:
+; CHECK: .functype fmaximum_f32 (f32, f32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f32.max $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call float @llvm.maximum.f32(float %x, float %y)
+ ret float %a
+}
+
+define double @fmaximum_f64(double %x, double %y) {
+; CHECK-LABEL: fmaximum_f64:
+; CHECK: .functype fmaximum_f64 (f64, f64) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f64.max $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call double @llvm.maximum.f64(double %x, double %y)
+ ret double %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmaximumnum.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmaximumnum.ll
new file mode 100644
index 0000000000000..45d822f952f8f
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmaximumnum.ll
@@ -0,0 +1,219 @@
+; 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 float @llvm.maximumnum.f32(float, float)
+declare double @llvm.maximumnum.f64(double, double)
+
+define float @fmaximumnum_f32(float %x, float %y) {
+; CHECK-LABEL: fmaximumnum_f32:
+; CHECK: .functype fmaximumnum_f32 (f32, f32) -> (f32)
+; CHECK-NEXT: .local f32, f32, f32, i32, i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push19=, 1
+; CHECK-NEXT: local.get $push18=, 0
+; CHECK-NEXT: local.get $push14=, 0
+; CHECK-NEXT: local.get $push13=, 0
+; CHECK-NEXT: f32.ne $push12=, $pop14, $pop13
+; CHECK-NEXT: local.get $push16=, 0
+; CHECK-NEXT: local.get $push15=, 0
+; CHECK-NEXT: f32.ne $push11=, $pop16, $pop15
+; CHECK-NEXT: i32.or $push10=, $pop12, $pop11
+; CHECK-NEXT: f32.select $push17=, $pop19, $pop18, $pop10
+; CHECK-NEXT: local.set 2, $pop17
+; CHECK-NEXT: local.get $push26=, 2
+; CHECK-NEXT: local.get $push25=, 1
+; CHECK-NEXT: local.get $push21=, 1
+; CHECK-NEXT: local.get $push20=, 1
+; CHECK-NEXT: f32.ne $push9=, $pop21, $pop20
+; CHECK-NEXT: local.get $push23=, 1
+; CHECK-NEXT: local.get $push22=, 1
+; CHECK-NEXT: f32.ne $push8=, $pop23, $pop22
+; CHECK-NEXT: i32.or $push7=, $pop9, $pop8
+; CHECK-NEXT: f32.select $push24=, $pop26, $pop25, $pop7
+; CHECK-NEXT: local.set 3, $pop24
+; CHECK-NEXT: local.get $push31=, 2
+; CHECK-NEXT: local.get $push30=, 3
+; CHECK-NEXT: local.get $push28=, 2
+; CHECK-NEXT: local.get $push27=, 3
+; CHECK-NEXT: f32.gt $push6=, $pop28, $pop27
+; CHECK-NEXT: f32.select $push29=, $pop31, $pop30, $pop6
+; CHECK-NEXT: local.set 4, $pop29
+; CHECK-NEXT: local.get $push33=, 4
+; CHECK-NEXT: f32.const $push1=, 0x0p0
+; CHECK-NEXT: f32.eq $push32=, $pop33, $pop1
+; CHECK-NEXT: local.set 5, $pop32
+; CHECK-NEXT: local.get $push35=, 2
+; CHECK-NEXT: i32.reinterpret_f32 $push34=, $pop35
+; CHECK-NEXT: local.set 6, $pop34
+; CHECK-NEXT: local.get $push38=, 2
+; CHECK-NEXT: local.get $push37=, 4
+; CHECK-NEXT: i32.const $push3=, 0
+; CHECK-NEXT: local.get $push36=, 6
+; CHECK-NEXT: i32.eqz $push4=, $pop36
+; CHECK-NEXT: i32.or $push5=, $pop3, $pop4
+; CHECK-NEXT: f32.select $push2=, $pop38, $pop37, $pop5
+; CHECK-NEXT: local.get $push40=, 4
+; CHECK-NEXT: local.get $push39=, 5
+; CHECK-NEXT: f32.select $push0=, $pop2, $pop40, $pop39
+; CHECK-NEXT: return $pop0
+ %a = call float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %a
+}
+
+define double @fmaximumnum_f64(double %x, double %y) {
+; CHECK-LABEL: fmaximumnum_f64:
+; CHECK: .functype fmaximumnum_f64 (f64, f64) -> (f64)
+; CHECK-NEXT: .local f64, f64, f64, i32, i64
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push19=, 1
+; CHECK-NEXT: local.get $push18=, 0
+; CHECK-NEXT: local.get $push14=, 0
+; CHECK-NEXT: local.get $push13=, 0
+; CHECK-NEXT: f64.ne $push12=, $pop14, $pop13
+; CHECK-NEXT: local.get $push16=, 0
+; CHECK-NEXT: local.get $push15=, 0
+; CHECK-NEXT: f64.ne $push11=, $pop16, $pop15
+; CHECK-NEXT: i32.or $push10=, $pop12, $pop11
+; CHECK-NEXT: f64.select $push17=, $pop19, $pop18, $pop10
+; CHECK-NEXT: local.set 2, $pop17
+; CHECK-NEXT: local.get $push26=, 2
+; CHECK-NEXT: local.get $push25=, 1
+; CHECK-NEXT: local.get $push21=, 1
+; CHECK-NEXT: local.get $push20=, 1
+; CHECK-NEXT: f64.ne $push9=, $pop21, $pop20
+; CHECK-NEXT: local.get $push23=, 1
+; CHECK-NEXT: local.get $push22=, 1
+; CHECK-NEXT: f64.ne $push8=, $pop23, $pop22
+; CHECK-NEXT: i32.or $push7=, $pop9, $pop8
+; CHECK-NEXT: f64.select $push24=, $pop26, $pop25, $pop7
+; CHECK-NEXT: local.set 3, $pop24
+; CHECK-NEXT: local.get $push31=, 2
+; CHECK-NEXT: local.get $push30=, 3
+; CHECK-NEXT: local.get $push28=, 2
+; CHECK-NEXT: local.get $push27=, 3
+; CHECK-NEXT: f64.gt $push6=, $pop28, $pop27
+; CHECK-NEXT: f64.select $push29=, $pop31, $pop30, $pop6
+; CHECK-NEXT: local.set 4, $pop29
+; CHECK-NEXT: local.get $push33=, 4
+; CHECK-NEXT: f64.const $push1=, 0x0p0
+; CHECK-NEXT: f64.eq $push32=, $pop33, $pop1
+; CHECK-NEXT: local.set 5, $pop32
+; CHECK-NEXT: local.get $push35=, 2
+; CHECK-NEXT: i64.reinterpret_f64 $push34=, $pop35
+; CHECK-NEXT: local.set 6, $pop34
+; CHECK-NEXT: local.get $push38=, 2
+; CHECK-NEXT: local.get $push37=, 4
+; CHECK-NEXT: i32.const $push3=, 0
+; CHECK-NEXT: local.get $push36=, 6
+; CHECK-NEXT: i64.eqz $push4=, $pop36
+; CHECK-NEXT: i32.or $push5=, $pop3, $pop4
+; CHECK-NEXT: f64.select $push2=, $pop38, $pop37, $pop5
+; CHECK-NEXT: local.get $push40=, 4
+; CHECK-NEXT: local.get $push39=, 5
+; CHECK-NEXT: f64.select $push0=, $pop2, $pop40, $pop39
+; CHECK-NEXT: return $pop0
+ %a = call double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %a
+}
+
+define float @fmaximumnum_f32_nsz(float %x, float %y) {
+; CHECK-LABEL: fmaximumnum_f32_nsz:
+; CHECK: .functype fmaximumnum_f32_nsz (f32, f32) -> (f32)
+; CHECK-NEXT: .local f32, f32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push14=, 1
+; CHECK-NEXT: local.get $push13=, 0
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: local.get $push8=, 0
+; CHECK-NEXT: f32.ne $push7=, $pop9, $pop8
+; CHECK-NEXT: local.get $push11=, 0
+; CHECK-NEXT: local.get $push10=, 0
+; CHECK-NEXT: f32.ne $push6=, $pop11, $pop10
+; CHECK-NEXT: i32.or $push5=, $pop7, $pop6
+; CHECK-NEXT: f32.select $push12=, $pop14, $pop13, $pop5
+; CHECK-NEXT: local.set 2, $pop12
+; CHECK-NEXT: local.get $push21=, 2
+; CHECK-NEXT: local.get $push20=, 1
+; CHECK-NEXT: local.get $push16=, 1
+; CHECK-NEXT: local.get $push15=, 1
+; CHECK-NEXT: f32.ne $push4=, $pop16, $pop15
+; CHECK-NEXT: local.get $push18=, 1
+; CHECK-NEXT: local.get $push17=, 1
+; CHECK-NEXT: f32.ne $push3=, $pop18, $pop17
+; CHECK-NEXT: i32.or $push2=, $pop4, $pop3
+; CHECK-NEXT: f32.select $push19=, $pop21, $pop20, $pop2
+; CHECK-NEXT: local.set 3, $pop19
+; CHECK-NEXT: local.get $push25=, 2
+; CHECK-NEXT: local.get $push24=, 3
+; CHECK-NEXT: local.get $push23=, 2
+; CHECK-NEXT: local.get $push22=, 3
+; CHECK-NEXT: f32.gt $push1=, $pop23, $pop22
+; CHECK-NEXT: f32.select $push0=, $pop25, $pop24, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call nsz float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %a
+}
+
+define double @fmaximumnum_f64_nsz(double %x, double %y) {
+; CHECK-LABEL: fmaximumnum_f64_nsz:
+; CHECK: .functype fmaximumnum_f64_nsz (f64, f64) -> (f64)
+; CHECK-NEXT: .local f64, f64
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push14=, 1
+; CHECK-NEXT: local.get $push13=, 0
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: local.get $push8=, 0
+; CHECK-NEXT: f64.ne $push7=, $pop9, $pop8
+; CHECK-NEXT: local.get $push11=, 0
+; CHECK-NEXT: local.get $push10=, 0
+; CHECK-NEXT: f64.ne $push6=, $pop11, $pop10
+; CHECK-NEXT: i32.or $push5=, $pop7, $pop6
+; CHECK-NEXT: f64.select $push12=, $pop14, $pop13, $pop5
+; CHECK-NEXT: local.set 2, $pop12
+; CHECK-NEXT: local.get $push21=, 2
+; CHECK-NEXT: local.get $push20=, 1
+; CHECK-NEXT: local.get $push16=, 1
+; CHECK-NEXT: local.get $push15=, 1
+; CHECK-NEXT: f64.ne $push4=, $pop16, $pop15
+; CHECK-NEXT: local.get $push18=, 1
+; CHECK-NEXT: local.get $push17=, 1
+; CHECK-NEXT: f64.ne $push3=, $pop18, $pop17
+; CHECK-NEXT: i32.or $push2=, $pop4, $pop3
+; CHECK-NEXT: f64.select $push19=, $pop21, $pop20, $pop2
+; CHECK-NEXT: local.set 3, $pop19
+; CHECK-NEXT: local.get $push25=, 2
+; CHECK-NEXT: local.get $push24=, 3
+; CHECK-NEXT: local.get $push23=, 2
+; CHECK-NEXT: local.get $push22=, 3
+; CHECK-NEXT: f64.gt $push1=, $pop23, $pop22
+; CHECK-NEXT: f64.select $push0=, $pop25, $pop24, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call nsz double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %a
+}
+
+define float @fmaximumnum_f32_nnan(float %x, float %y) {
+; CHECK-LABEL: fmaximumnum_f32_nnan:
+; CHECK: .functype fmaximumnum_f32_nnan (f32, f32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f32.min $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call nnan float @llvm.maximumnum.f32(float %x, float %y)
+ ret float %a
+}
+
+define double @fmaximumnum_f64_nnan(double %x, double %y) {
+; CHECK-LABEL: fmaximumnum_f64_nnan:
+; CHECK: .functype fmaximumnum_f64_nnan (f64, f64) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f64.min $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call nnan double @llvm.maximumnum.f64(double %x, double %y)
+ ret double %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmaxnum.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmaxnum.ll
new file mode 100644
index 0000000000000..4fb5119c171f4
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fmaxnum.ll
@@ -0,0 +1,55 @@
+; 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 float @llvm.maxnum.f32(float, float)
+declare double @llvm.maxnum.f64(double, double)
+
+define float @fmaxnum_f32(float %x, float %y) {
+; CHECK-LABEL: fmaxnum_f32:
+; CHECK: .functype fmaxnum_f32 (f32, f32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: call $push0=, fmaxf, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call float @llvm.maxnum.f32(float %x, float %y)
+ ret float %a
+}
+
+define double @fmaxnum_f64(double %x, double %y) {
+; CHECK-LABEL: fmaxnum_f64:
+; CHECK: .functype fmaxnum_f64 (f64, f64) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: call $push0=, fmax, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call double @llvm.maxnum.f64(double %x, double %y)
+ ret double %a
+}
+
+define float @fmaxnum_f32_nnan(float %x, float %y) {
+; CHECK-LABEL: fmaxnum_f32_nnan:
+; CHECK: .functype fmaxnum_f32_nnan (f32, f32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f32.max $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call nnan float @llvm.maxnum.f32(float %x, float %y)
+ ret float %a
+}
+
+define double @fmaxnum_f64_nnan(double %x, double %y) {
+; CHECK-LABEL: fmaxnum_f64_nnan:
+; CHECK: .functype fmaxnum_f64_nnan (f64, f64) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f64.max $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call nnan double @llvm.maxnum.f64(double %x, double %y)
+ ret double %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fminimum.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fminimum.ll
new file mode 100644
index 0000000000000..cab1ae23c0e4c
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fminimum.ll
@@ -0,0 +1,32 @@
+; 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 float @llvm.minimum.f32(float, float)
+declare double @llvm.minimum.f64(double, double)
+
+
+define float @fminimum_f32(float %x, float %y) {
+; CHECK-LABEL: fminimum_f32:
+; CHECK: .functype fminimum_f32 (f32, f32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f32.min $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call float @llvm.minimum.f32(float %x, float %y)
+ ret float %a
+}
+
+define double @fminimum_f64(double %x, double %y) {
+; CHECK-LABEL: fminimum_f64:
+; CHECK: .functype fminimum_f64 (f64, f64) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f64.min $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call double @llvm.minimum.f64(double %x, double %y)
+ ret double %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fminimumnum.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fminimumnum.ll
new file mode 100644
index 0000000000000..d7530a5a4a0df
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fminimumnum.ll
@@ -0,0 +1,225 @@
+; 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 float @llvm.minimumnum.f32(float, float)
+declare double @llvm.minimumnum.f64(double, double)
+
+define float @fminimumnum_f32(float %x, float %y) {
+; CHECK-LABEL: fminimumnum_f32:
+; CHECK: .functype fminimumnum_f32 (f32, f32) -> (f32)
+; CHECK-NEXT: .local f32, f32, f32, i32, i32, i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push19=, 1
+; CHECK-NEXT: local.get $push18=, 0
+; CHECK-NEXT: local.get $push14=, 0
+; CHECK-NEXT: local.get $push13=, 0
+; CHECK-NEXT: f32.ne $push12=, $pop14, $pop13
+; CHECK-NEXT: local.get $push16=, 0
+; CHECK-NEXT: local.get $push15=, 0
+; CHECK-NEXT: f32.ne $push11=, $pop16, $pop15
+; CHECK-NEXT: i32.or $push10=, $pop12, $pop11
+; CHECK-NEXT: f32.select $push17=, $pop19, $pop18, $pop10
+; CHECK-NEXT: local.set 2, $pop17
+; CHECK-NEXT: local.get $push26=, 2
+; CHECK-NEXT: local.get $push25=, 1
+; CHECK-NEXT: local.get $push21=, 1
+; CHECK-NEXT: local.get $push20=, 1
+; CHECK-NEXT: f32.ne $push9=, $pop21, $pop20
+; CHECK-NEXT: local.get $push23=, 1
+; CHECK-NEXT: local.get $push22=, 1
+; CHECK-NEXT: f32.ne $push8=, $pop23, $pop22
+; CHECK-NEXT: i32.or $push7=, $pop9, $pop8
+; CHECK-NEXT: f32.select $push24=, $pop26, $pop25, $pop7
+; CHECK-NEXT: local.set 3, $pop24
+; CHECK-NEXT: local.get $push31=, 2
+; CHECK-NEXT: local.get $push30=, 3
+; CHECK-NEXT: local.get $push28=, 2
+; CHECK-NEXT: local.get $push27=, 3
+; CHECK-NEXT: f32.lt $push6=, $pop28, $pop27
+; CHECK-NEXT: f32.select $push29=, $pop31, $pop30, $pop6
+; CHECK-NEXT: local.set 4, $pop29
+; CHECK-NEXT: local.get $push33=, 4
+; CHECK-NEXT: f32.const $push1=, 0x0p0
+; CHECK-NEXT: f32.eq $push32=, $pop33, $pop1
+; CHECK-NEXT: local.set 5, $pop32
+; CHECK-NEXT: local.get $push35=, 2
+; CHECK-NEXT: i32.reinterpret_f32 $push34=, $pop35
+; CHECK-NEXT: local.set 6, $pop34
+; CHECK-NEXT: i32.const $push36=, -2147483648
+; CHECK-NEXT: local.set 7, $pop36
+; CHECK-NEXT: local.get $push40=, 2
+; CHECK-NEXT: local.get $push39=, 4
+; CHECK-NEXT: i32.const $push3=, 0
+; CHECK-NEXT: local.get $push38=, 6
+; CHECK-NEXT: local.get $push37=, 7
+; CHECK-NEXT: i32.eq $push4=, $pop38, $pop37
+; CHECK-NEXT: i32.or $push5=, $pop3, $pop4
+; CHECK-NEXT: f32.select $push2=, $pop40, $pop39, $pop5
+; CHECK-NEXT: local.get $push42=, 4
+; CHECK-NEXT: local.get $push41=, 5
+; CHECK-NEXT: f32.select $push0=, $pop2, $pop42, $pop41
+; CHECK-NEXT: return $pop0
+ %a = call float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %a
+}
+
+define double @fminimumnum_f64(double %x, double %y) {
+; CHECK-LABEL: fminimumnum_f64:
+; CHECK: .functype fminimumnum_f64 (f64, f64) -> (f64)
+; CHECK-NEXT: .local f64, f64, f64, i32, i64, i64
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push19=, 1
+; CHECK-NEXT: local.get $push18=, 0
+; CHECK-NEXT: local.get $push14=, 0
+; CHECK-NEXT: local.get $push13=, 0
+; CHECK-NEXT: f64.ne $push12=, $pop14, $pop13
+; CHECK-NEXT: local.get $push16=, 0
+; CHECK-NEXT: local.get $push15=, 0
+; CHECK-NEXT: f64.ne $push11=, $pop16, $pop15
+; CHECK-NEXT: i32.or $push10=, $pop12, $pop11
+; CHECK-NEXT: f64.select $push17=, $pop19, $pop18, $pop10
+; CHECK-NEXT: local.set 2, $pop17
+; CHECK-NEXT: local.get $push26=, 2
+; CHECK-NEXT: local.get $push25=, 1
+; CHECK-NEXT: local.get $push21=, 1
+; CHECK-NEXT: local.get $push20=, 1
+; CHECK-NEXT: f64.ne $push9=, $pop21, $pop20
+; CHECK-NEXT: local.get $push23=, 1
+; CHECK-NEXT: local.get $push22=, 1
+; CHECK-NEXT: f64.ne $push8=, $pop23, $pop22
+; CHECK-NEXT: i32.or $push7=, $pop9, $pop8
+; CHECK-NEXT: f64.select $push24=, $pop26, $pop25, $pop7
+; CHECK-NEXT: local.set 3, $pop24
+; CHECK-NEXT: local.get $push31=, 2
+; CHECK-NEXT: local.get $push30=, 3
+; CHECK-NEXT: local.get $push28=, 2
+; CHECK-NEXT: local.get $push27=, 3
+; CHECK-NEXT: f64.lt $push6=, $pop28, $pop27
+; CHECK-NEXT: f64.select $push29=, $pop31, $pop30, $pop6
+; CHECK-NEXT: local.set 4, $pop29
+; CHECK-NEXT: local.get $push33=, 4
+; CHECK-NEXT: f64.const $push1=, 0x0p0
+; CHECK-NEXT: f64.eq $push32=, $pop33, $pop1
+; CHECK-NEXT: local.set 5, $pop32
+; CHECK-NEXT: local.get $push35=, 2
+; CHECK-NEXT: i64.reinterpret_f64 $push34=, $pop35
+; CHECK-NEXT: local.set 6, $pop34
+; CHECK-NEXT: i64.const $push36=, -9223372036854775808
+; CHECK-NEXT: local.set 7, $pop36
+; CHECK-NEXT: local.get $push40=, 2
+; CHECK-NEXT: local.get $push39=, 4
+; CHECK-NEXT: i32.const $push3=, 0
+; CHECK-NEXT: local.get $push38=, 6
+; CHECK-NEXT: local.get $push37=, 7
+; CHECK-NEXT: i64.eq $push4=, $pop38, $pop37
+; CHECK-NEXT: i32.or $push5=, $pop3, $pop4
+; CHECK-NEXT: f64.select $push2=, $pop40, $pop39, $pop5
+; CHECK-NEXT: local.get $push42=, 4
+; CHECK-NEXT: local.get $push41=, 5
+; CHECK-NEXT: f64.select $push0=, $pop2, $pop42, $pop41
+; CHECK-NEXT: return $pop0
+ %a = call double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %a
+}
+
+define float @fminimumnum_f32_nsz(float %x, float %y) {
+; CHECK-LABEL: fminimumnum_f32_nsz:
+; CHECK: .functype fminimumnum_f32_nsz (f32, f32) -> (f32)
+; CHECK-NEXT: .local f32, f32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push14=, 1
+; CHECK-NEXT: local.get $push13=, 0
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: local.get $push8=, 0
+; CHECK-NEXT: f32.ne $push7=, $pop9, $pop8
+; CHECK-NEXT: local.get $push11=, 0
+; CHECK-NEXT: local.get $push10=, 0
+; CHECK-NEXT: f32.ne $push6=, $pop11, $pop10
+; CHECK-NEXT: i32.or $push5=, $pop7, $pop6
+; CHECK-NEXT: f32.select $push12=, $pop14, $pop13, $pop5
+; CHECK-NEXT: local.set 2, $pop12
+; CHECK-NEXT: local.get $push21=, 2
+; CHECK-NEXT: local.get $push20=, 1
+; CHECK-NEXT: local.get $push16=, 1
+; CHECK-NEXT: local.get $push15=, 1
+; CHECK-NEXT: f32.ne $push4=, $pop16, $pop15
+; CHECK-NEXT: local.get $push18=, 1
+; CHECK-NEXT: local.get $push17=, 1
+; CHECK-NEXT: f32.ne $push3=, $pop18, $pop17
+; CHECK-NEXT: i32.or $push2=, $pop4, $pop3
+; CHECK-NEXT: f32.select $push19=, $pop21, $pop20, $pop2
+; CHECK-NEXT: local.set 3, $pop19
+; CHECK-NEXT: local.get $push25=, 2
+; CHECK-NEXT: local.get $push24=, 3
+; CHECK-NEXT: local.get $push23=, 2
+; CHECK-NEXT: local.get $push22=, 3
+; CHECK-NEXT: f32.lt $push1=, $pop23, $pop22
+; CHECK-NEXT: f32.select $push0=, $pop25, $pop24, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call nsz float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %a
+}
+
+define double @fminimumnum_f64_nsz(double %x, double %y) {
+; CHECK-LABEL: fminimumnum_f64_nsz:
+; CHECK: .functype fminimumnum_f64_nsz (f64, f64) -> (f64)
+; CHECK-NEXT: .local f64, f64
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push14=, 1
+; CHECK-NEXT: local.get $push13=, 0
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: local.get $push8=, 0
+; CHECK-NEXT: f64.ne $push7=, $pop9, $pop8
+; CHECK-NEXT: local.get $push11=, 0
+; CHECK-NEXT: local.get $push10=, 0
+; CHECK-NEXT: f64.ne $push6=, $pop11, $pop10
+; CHECK-NEXT: i32.or $push5=, $pop7, $pop6
+; CHECK-NEXT: f64.select $push12=, $pop14, $pop13, $pop5
+; CHECK-NEXT: local.set 2, $pop12
+; CHECK-NEXT: local.get $push21=, 2
+; CHECK-NEXT: local.get $push20=, 1
+; CHECK-NEXT: local.get $push16=, 1
+; CHECK-NEXT: local.get $push15=, 1
+; CHECK-NEXT: f64.ne $push4=, $pop16, $pop15
+; CHECK-NEXT: local.get $push18=, 1
+; CHECK-NEXT: local.get $push17=, 1
+; CHECK-NEXT: f64.ne $push3=, $pop18, $pop17
+; CHECK-NEXT: i32.or $push2=, $pop4, $pop3
+; CHECK-NEXT: f64.select $push19=, $pop21, $pop20, $pop2
+; CHECK-NEXT: local.set 3, $pop19
+; CHECK-NEXT: local.get $push25=, 2
+; CHECK-NEXT: local.get $push24=, 3
+; CHECK-NEXT: local.get $push23=, 2
+; CHECK-NEXT: local.get $push22=, 3
+; CHECK-NEXT: f64.lt $push1=, $pop23, $pop22
+; CHECK-NEXT: f64.select $push0=, $pop25, $pop24, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call nsz double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %a
+}
+
+define float @fminimumnum_f32_nnan(float %x, float %y) {
+; CHECK-LABEL: fminimumnum_f32_nnan:
+; CHECK: .functype fminimumnum_f32_nnan (f32, f32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f32.min $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call nnan float @llvm.minimumnum.f32(float %x, float %y)
+ ret float %a
+}
+
+define double @fminimumnum_f64_nnan(double %x, double %y) {
+; CHECK-LABEL: fminimumnum_f64_nnan:
+; CHECK: .functype fminimumnum_f64_nnan (f64, f64) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f64.min $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call nnan double @llvm.minimumnum.f64(double %x, double %y)
+ ret double %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fminnum.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fminnum.ll
new file mode 100644
index 0000000000000..026df12684264
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/fminnum.ll
@@ -0,0 +1,55 @@
+; 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 float @llvm.minnum.f32(float, float)
+declare double @llvm.minnum.f64(double, double)
+
+define float @fminnum_f32(float %x, float %y) {
+; CHECK-LABEL: fminnum_f32:
+; CHECK: .functype fminnum_f32 (f32, f32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: call $push0=, fminf, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call float @llvm.minnum.f32(float %x, float %y)
+ ret float %a
+}
+
+define double @fminnum_f64(double %x, double %y) {
+; CHECK-LABEL: fminnum_f64:
+; CHECK: .functype fminnum_f64 (f64, f64) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: call $push0=, fmin, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call double @llvm.minnum.f64(double %x, double %y)
+ ret double %a
+}
+
+define float @fminnum_f32_nnan(float %x, float %y) {
+; CHECK-LABEL: fminnum_f32_nnan:
+; CHECK: .functype fminnum_f32_nnan (f32, f32) -> (f32)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f32.min $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call nnan float @llvm.minnum.f32(float %x, float %y)
+ ret float %a
+}
+
+define double @fminnum_f64_nnan(double %x, double %y) {
+; CHECK-LABEL: fminnum_f64_nnan:
+; CHECK: .functype fminnum_f64_nnan (f64, f64) -> (f64)
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push2=, 0
+; CHECK-NEXT: local.get $push1=, 1
+; CHECK-NEXT: f64.min $push0=, $pop2, $pop1
+; CHECK-NEXT: return $pop0
+ %a = call nnan double @llvm.minnum.f64(double %x, double %y)
+ ret double %a
+}
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/is_fpclass.ll b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/is_fpclass.ll
new file mode 100644
index 0000000000000..03d9ad65ec887
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instructions/is_fpclass.ll
@@ -0,0 +1,490 @@
+; 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 i1 @llvm.is.fpclass.f32(float, i32)
+declare i1 @llvm.is.fpclass.f64(double, i32)
+
+define i1 @is_fpclass_f32_snan(float %x) {
+; CHECK-LABEL: is_fpclass_f32_snan:
+; CHECK: .functype is_fpclass_f32_snan (f32) -> (i32)
+; CHECK-NEXT: .local i32, i32, i32, i32, i32, i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: i32.reinterpret_f32 $push4=, $pop5
+; CHECK-NEXT: local.set 1, $pop4
+; CHECK-NEXT: i32.const $push6=, 2147483647
+; CHECK-NEXT: local.set 2, $pop6
+; CHECK-NEXT: i32.const $push7=, 2139095040
+; CHECK-NEXT: local.set 3, $pop7
+; CHECK-NEXT: local.get $push10=, 1
+; CHECK-NEXT: local.get $push9=, 2
+; CHECK-NEXT: i32.and $push8=, $pop10, $pop9
+; CHECK-NEXT: local.set 4, $pop8
+; CHECK-NEXT: i32.const $push11=, 0
+; CHECK-NEXT: local.set 5, $pop11
+; CHECK-NEXT: i32.const $push12=, 2143289344
+; CHECK-NEXT: local.set 6, $pop12
+; CHECK-NEXT: local.get $push17=, 5
+; CHECK-NEXT: local.get $push14=, 4
+; CHECK-NEXT: local.get $push13=, 3
+; CHECK-NEXT: i32.gt_u $push0=, $pop14, $pop13
+; CHECK-NEXT: local.get $push16=, 4
+; CHECK-NEXT: local.get $push15=, 6
+; CHECK-NEXT: i32.lt_u $push1=, $pop16, $pop15
+; CHECK-NEXT: i32.and $push2=, $pop0, $pop1
+; CHECK-NEXT: i32.or $push3=, $pop17, $pop2
+; CHECK-NEXT: return $pop3
+ %a = call i1 @llvm.is.fpclass.f32(float %x, i32 1)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f32_qnan(float %x) {
+; CHECK-LABEL: is_fpclass_f32_qnan:
+; CHECK: .functype is_fpclass_f32_qnan (f32) -> (i32)
+; CHECK-NEXT: .local i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: i32.reinterpret_f32 $push0=, $pop6
+; CHECK-NEXT: i32.const $push1=, 2147483647
+; CHECK-NEXT: i32.and $push7=, $pop0, $pop1
+; CHECK-NEXT: local.set 1, $pop7
+; CHECK-NEXT: i32.const $push2=, 0
+; CHECK-NEXT: local.get $push8=, 1
+; CHECK-NEXT: i32.const $push3=, 2143289344
+; CHECK-NEXT: i32.ge_u $push4=, $pop8, $pop3
+; CHECK-NEXT: i32.or $push5=, $pop2, $pop4
+; CHECK-NEXT: return $pop5
+ %a = call i1 @llvm.is.fpclass.f32(float %x, i32 2)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f32_neginf(float %x) {
+; CHECK-LABEL: is_fpclass_f32_neginf:
+; CHECK: .functype is_fpclass_f32_neginf (f32) -> (i32)
+; CHECK-NEXT: .local i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: i32.reinterpret_f32 $push4=, $pop5
+; CHECK-NEXT: local.set 1, $pop4
+; CHECK-NEXT: i32.const $push0=, 0
+; CHECK-NEXT: local.get $push6=, 1
+; CHECK-NEXT: i32.const $push1=, -8388608
+; CHECK-NEXT: i32.eq $push2=, $pop6, $pop1
+; CHECK-NEXT: i32.or $push3=, $pop0, $pop2
+; CHECK-NEXT: return $pop3
+ %a = call i1 @llvm.is.fpclass.f32(float %x, i32 4)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f32_negnormal(float %x) {
+; CHECK-LABEL: is_fpclass_f32_negnormal:
+; CHECK: .functype is_fpclass_f32_negnormal (f32) -> (i32)
+; CHECK-NEXT: .local i32, i32, i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: i32.reinterpret_f32 $push8=, $pop9
+; CHECK-NEXT: local.set 1, $pop8
+; CHECK-NEXT: local.get $push11=, 1
+; CHECK-NEXT: i32.const $push0=, 2147483647
+; CHECK-NEXT: i32.and $push10=, $pop11, $pop0
+; CHECK-NEXT: local.set 2, $pop10
+; CHECK-NEXT: local.get $push14=, 1
+; CHECK-NEXT: local.get $push13=, 2
+; CHECK-NEXT: i32.ne $push12=, $pop14, $pop13
+; CHECK-NEXT: local.set 3, $pop12
+; CHECK-NEXT: i32.const $push1=, 0
+; CHECK-NEXT: local.get $push16=, 3
+; CHECK-NEXT: local.get $push15=, 2
+; CHECK-NEXT: i32.const $push2=, 8388608
+; CHECK-NEXT: i32.sub $push3=, $pop15, $pop2
+; CHECK-NEXT: i32.const $push4=, 2130706432
+; CHECK-NEXT: i32.lt_u $push5=, $pop3, $pop4
+; CHECK-NEXT: i32.and $push6=, $pop16, $pop5
+; CHECK-NEXT: i32.or $push7=, $pop1, $pop6
+; CHECK-NEXT: return $pop7
+ %a = call i1 @llvm.is.fpclass.f32(float %x, i32 8)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f32_negsubnorm(float %x) {
+; CHECK-LABEL: is_fpclass_f32_negsubnorm:
+; CHECK: .functype is_fpclass_f32_negsubnorm (f32) -> (i32)
+; CHECK-NEXT: .local i32, i32, i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: i32.reinterpret_f32 $push8=, $pop9
+; CHECK-NEXT: local.set 1, $pop8
+; CHECK-NEXT: local.get $push11=, 1
+; CHECK-NEXT: i32.const $push0=, 2147483647
+; CHECK-NEXT: i32.and $push10=, $pop11, $pop0
+; CHECK-NEXT: local.set 2, $pop10
+; CHECK-NEXT: local.get $push14=, 1
+; CHECK-NEXT: local.get $push13=, 2
+; CHECK-NEXT: i32.ne $push12=, $pop14, $pop13
+; CHECK-NEXT: local.set 3, $pop12
+; CHECK-NEXT: i32.const $push1=, 0
+; CHECK-NEXT: local.get $push16=, 3
+; CHECK-NEXT: local.get $push15=, 2
+; CHECK-NEXT: i32.const $push2=, 1
+; CHECK-NEXT: i32.sub $push3=, $pop15, $pop2
+; CHECK-NEXT: i32.const $push4=, 8388607
+; CHECK-NEXT: i32.lt_u $push5=, $pop3, $pop4
+; CHECK-NEXT: i32.and $push6=, $pop16, $pop5
+; CHECK-NEXT: i32.or $push7=, $pop1, $pop6
+; CHECK-NEXT: return $pop7
+ %a = call i1 @llvm.is.fpclass.f32(float %x, i32 16)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f32_negzero(float %x) {
+; CHECK-LABEL: is_fpclass_f32_negzero:
+; CHECK: .functype is_fpclass_f32_negzero (f32) -> (i32)
+; CHECK-NEXT: .local i32, i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: i32.reinterpret_f32 $push3=, $pop4
+; CHECK-NEXT: local.set 1, $pop3
+; CHECK-NEXT: i32.const $push5=, -2147483648
+; CHECK-NEXT: local.set 2, $pop5
+; CHECK-NEXT: i32.const $push0=, 0
+; CHECK-NEXT: local.get $push7=, 1
+; CHECK-NEXT: local.get $push6=, 2
+; CHECK-NEXT: i32.eq $push1=, $pop7, $pop6
+; CHECK-NEXT: i32.or $push2=, $pop0, $pop1
+; CHECK-NEXT: return $pop2
+ %a = call i1 @llvm.is.fpclass.f32(float %x, i32 32)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f32_poszero(float %x) {
+; CHECK-LABEL: is_fpclass_f32_poszero:
+; CHECK: .functype is_fpclass_f32_poszero (f32) -> (i32)
+; CHECK-NEXT: .local i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: i32.reinterpret_f32 $push3=, $pop4
+; CHECK-NEXT: local.set 1, $pop3
+; CHECK-NEXT: i32.const $push0=, 0
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: i32.eqz $push1=, $pop5
+; CHECK-NEXT: i32.or $push2=, $pop0, $pop1
+; CHECK-NEXT: return $pop2
+ %a = call i1 @llvm.is.fpclass.f32(float %x, i32 64)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f32_possubnorm(float %x) {
+; CHECK-LABEL: is_fpclass_f32_possubnorm:
+; CHECK: .functype is_fpclass_f32_possubnorm (f32) -> (i32)
+; CHECK-NEXT: .local i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push7=, 0
+; CHECK-NEXT: i32.reinterpret_f32 $push6=, $pop7
+; CHECK-NEXT: local.set 1, $pop6
+; CHECK-NEXT: i32.const $push0=, 0
+; CHECK-NEXT: local.get $push8=, 1
+; CHECK-NEXT: i32.const $push1=, 1
+; CHECK-NEXT: i32.sub $push2=, $pop8, $pop1
+; CHECK-NEXT: i32.const $push3=, 8388607
+; CHECK-NEXT: i32.lt_u $push4=, $pop2, $pop3
+; CHECK-NEXT: i32.or $push5=, $pop0, $pop4
+; CHECK-NEXT: return $pop5
+ %a = call i1 @llvm.is.fpclass.f32(float %x, i32 128)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f32_posnormal(float %x) {
+; CHECK-LABEL: is_fpclass_f32_posnormal:
+; CHECK: .functype is_fpclass_f32_posnormal (f32) -> (i32)
+; CHECK-NEXT: .local i32, i32, i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push11=, 0
+; CHECK-NEXT: i32.reinterpret_f32 $push10=, $pop11
+; CHECK-NEXT: local.set 1, $pop10
+; CHECK-NEXT: local.get $push13=, 1
+; CHECK-NEXT: i32.const $push0=, 2147483647
+; CHECK-NEXT: i32.and $push12=, $pop13, $pop0
+; CHECK-NEXT: local.set 2, $pop12
+; CHECK-NEXT: local.get $push16=, 1
+; CHECK-NEXT: local.get $push15=, 2
+; CHECK-NEXT: i32.ne $push14=, $pop16, $pop15
+; CHECK-NEXT: local.set 3, $pop14
+; CHECK-NEXT: i32.const $push1=, 0
+; CHECK-NEXT: local.get $push17=, 2
+; CHECK-NEXT: i32.const $push2=, 8388608
+; CHECK-NEXT: i32.sub $push3=, $pop17, $pop2
+; CHECK-NEXT: i32.const $push4=, 2130706432
+; CHECK-NEXT: i32.lt_u $push5=, $pop3, $pop4
+; CHECK-NEXT: local.get $push18=, 3
+; CHECK-NEXT: i32.const $push6=, -1
+; CHECK-NEXT: i32.xor $push7=, $pop18, $pop6
+; CHECK-NEXT: i32.and $push8=, $pop5, $pop7
+; CHECK-NEXT: i32.or $push9=, $pop1, $pop8
+; CHECK-NEXT: return $pop9
+ %a = call i1 @llvm.is.fpclass.f32(float %x, i32 256)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f32_posinf(float %x) {
+; CHECK-LABEL: is_fpclass_f32_posinf:
+; CHECK: .functype is_fpclass_f32_posinf (f32) -> (i32)
+; CHECK-NEXT: .local i32, i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: i32.reinterpret_f32 $push3=, $pop4
+; CHECK-NEXT: local.set 1, $pop3
+; CHECK-NEXT: i32.const $push5=, 2139095040
+; CHECK-NEXT: local.set 2, $pop5
+; CHECK-NEXT: i32.const $push0=, 0
+; CHECK-NEXT: local.get $push7=, 1
+; CHECK-NEXT: local.get $push6=, 2
+; CHECK-NEXT: i32.eq $push1=, $pop7, $pop6
+; CHECK-NEXT: i32.or $push2=, $pop0, $pop1
+; CHECK-NEXT: return $pop2
+ %a = call i1 @llvm.is.fpclass.f32(float %x, i32 512)
+ ret i1 %a
+}
+
+
+define i1 @is_fpclass_f64_snan(double %x) {
+; CHECK-LABEL: is_fpclass_f64_snan:
+; CHECK: .functype is_fpclass_f64_snan (f64) -> (i32)
+; CHECK-NEXT: .local i64, i64, i64, i64, i32, i64
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: i64.reinterpret_f64 $push4=, $pop5
+; CHECK-NEXT: local.set 1, $pop4
+; CHECK-NEXT: i64.const $push6=, 9223372036854775807
+; CHECK-NEXT: local.set 2, $pop6
+; CHECK-NEXT: i64.const $push7=, 9218868437227405312
+; CHECK-NEXT: local.set 3, $pop7
+; CHECK-NEXT: local.get $push10=, 1
+; CHECK-NEXT: local.get $push9=, 2
+; CHECK-NEXT: i64.and $push8=, $pop10, $pop9
+; CHECK-NEXT: local.set 4, $pop8
+; CHECK-NEXT: i32.const $push11=, 0
+; CHECK-NEXT: local.set 5, $pop11
+; CHECK-NEXT: i64.const $push12=, 9221120237041090560
+; CHECK-NEXT: local.set 6, $pop12
+; CHECK-NEXT: local.get $push17=, 5
+; CHECK-NEXT: local.get $push14=, 4
+; CHECK-NEXT: local.get $push13=, 3
+; CHECK-NEXT: i64.gt_u $push0=, $pop14, $pop13
+; CHECK-NEXT: local.get $push16=, 4
+; CHECK-NEXT: local.get $push15=, 6
+; CHECK-NEXT: i64.lt_u $push1=, $pop16, $pop15
+; CHECK-NEXT: i32.and $push2=, $pop0, $pop1
+; CHECK-NEXT: i32.or $push3=, $pop17, $pop2
+; CHECK-NEXT: return $pop3
+ %a = call i1 @llvm.is.fpclass.f64(double %x, i32 1)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f64_qnan(double %x) {
+; CHECK-LABEL: is_fpclass_f64_qnan:
+; CHECK: .functype is_fpclass_f64_qnan (f64) -> (i32)
+; CHECK-NEXT: .local i64
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push6=, 0
+; CHECK-NEXT: i64.reinterpret_f64 $push0=, $pop6
+; CHECK-NEXT: i64.const $push1=, 9223372036854775807
+; CHECK-NEXT: i64.and $push7=, $pop0, $pop1
+; CHECK-NEXT: local.set 1, $pop7
+; CHECK-NEXT: i32.const $push2=, 0
+; CHECK-NEXT: local.get $push8=, 1
+; CHECK-NEXT: i64.const $push3=, 9221120237041090560
+; CHECK-NEXT: i64.ge_u $push4=, $pop8, $pop3
+; CHECK-NEXT: i32.or $push5=, $pop2, $pop4
+; CHECK-NEXT: return $pop5
+ %a = call i1 @llvm.is.fpclass.f64(double %x, i32 2)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f64_neginf(double %x) {
+; CHECK-LABEL: is_fpclass_f64_neginf:
+; CHECK: .functype is_fpclass_f64_neginf (f64) -> (i32)
+; CHECK-NEXT: .local i64
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push5=, 0
+; CHECK-NEXT: i64.reinterpret_f64 $push4=, $pop5
+; CHECK-NEXT: local.set 1, $pop4
+; CHECK-NEXT: i32.const $push0=, 0
+; CHECK-NEXT: local.get $push6=, 1
+; CHECK-NEXT: i64.const $push1=, -4503599627370496
+; CHECK-NEXT: i64.eq $push2=, $pop6, $pop1
+; CHECK-NEXT: i32.or $push3=, $pop0, $pop2
+; CHECK-NEXT: return $pop3
+ %a = call i1 @llvm.is.fpclass.f64(double %x, i32 4)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f64_negnormal(double %x) {
+; CHECK-LABEL: is_fpclass_f64_negnormal:
+; CHECK: .functype is_fpclass_f64_negnormal (f64) -> (i32)
+; CHECK-NEXT: .local i64, i64, i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: i64.reinterpret_f64 $push8=, $pop9
+; CHECK-NEXT: local.set 1, $pop8
+; CHECK-NEXT: local.get $push11=, 1
+; CHECK-NEXT: i64.const $push0=, 9223372036854775807
+; CHECK-NEXT: i64.and $push10=, $pop11, $pop0
+; CHECK-NEXT: local.set 2, $pop10
+; CHECK-NEXT: local.get $push14=, 1
+; CHECK-NEXT: local.get $push13=, 2
+; CHECK-NEXT: i64.ne $push12=, $pop14, $pop13
+; CHECK-NEXT: local.set 3, $pop12
+; CHECK-NEXT: i32.const $push1=, 0
+; CHECK-NEXT: local.get $push16=, 3
+; CHECK-NEXT: local.get $push15=, 2
+; CHECK-NEXT: i64.const $push2=, 4503599627370496
+; CHECK-NEXT: i64.sub $push3=, $pop15, $pop2
+; CHECK-NEXT: i64.const $push4=, 9214364837600034816
+; CHECK-NEXT: i64.lt_u $push5=, $pop3, $pop4
+; CHECK-NEXT: i32.and $push6=, $pop16, $pop5
+; CHECK-NEXT: i32.or $push7=, $pop1, $pop6
+; CHECK-NEXT: return $pop7
+ %a = call i1 @llvm.is.fpclass.f64(double %x, i32 8)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f64_negsubnorm(double %x) {
+; CHECK-LABEL: is_fpclass_f64_negsubnorm:
+; CHECK: .functype is_fpclass_f64_negsubnorm (f64) -> (i32)
+; CHECK-NEXT: .local i64, i64, i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push9=, 0
+; CHECK-NEXT: i64.reinterpret_f64 $push8=, $pop9
+; CHECK-NEXT: local.set 1, $pop8
+; CHECK-NEXT: local.get $push11=, 1
+; CHECK-NEXT: i64.const $push0=, 9223372036854775807
+; CHECK-NEXT: i64.and $push10=, $pop11, $pop0
+; CHECK-NEXT: local.set 2, $pop10
+; CHECK-NEXT: local.get $push14=, 1
+; CHECK-NEXT: local.get $push13=, 2
+; CHECK-NEXT: i64.ne $push12=, $pop14, $pop13
+; CHECK-NEXT: local.set 3, $pop12
+; CHECK-NEXT: i32.const $push1=, 0
+; CHECK-NEXT: local.get $push16=, 3
+; CHECK-NEXT: local.get $push15=, 2
+; CHECK-NEXT: i64.const $push2=, 1
+; CHECK-NEXT: i64.sub $push3=, $pop15, $pop2
+; CHECK-NEXT: i64.const $push4=, 4503599627370495
+; CHECK-NEXT: i64.lt_u $push5=, $pop3, $pop4
+; CHECK-NEXT: i32.and $push6=, $pop16, $pop5
+; CHECK-NEXT: i32.or $push7=, $pop1, $pop6
+; CHECK-NEXT: return $pop7
+ %a = call i1 @llvm.is.fpclass.f64(double %x, i32 16)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f64_negzero(double %x) {
+; CHECK-LABEL: is_fpclass_f64_negzero:
+; CHECK: .functype is_fpclass_f64_negzero (f64) -> (i32)
+; CHECK-NEXT: .local i64, i64
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: i64.reinterpret_f64 $push3=, $pop4
+; CHECK-NEXT: local.set 1, $pop3
+; CHECK-NEXT: i64.const $push5=, -9223372036854775808
+; CHECK-NEXT: local.set 2, $pop5
+; CHECK-NEXT: i32.const $push0=, 0
+; CHECK-NEXT: local.get $push7=, 1
+; CHECK-NEXT: local.get $push6=, 2
+; CHECK-NEXT: i64.eq $push1=, $pop7, $pop6
+; CHECK-NEXT: i32.or $push2=, $pop0, $pop1
+; CHECK-NEXT: return $pop2
+ %a = call i1 @llvm.is.fpclass.f64(double %x, i32 32)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f64_poszero(double %x) {
+; CHECK-LABEL: is_fpclass_f64_poszero:
+; CHECK: .functype is_fpclass_f64_poszero (f64) -> (i32)
+; CHECK-NEXT: .local i64
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: i64.reinterpret_f64 $push3=, $pop4
+; CHECK-NEXT: local.set 1, $pop3
+; CHECK-NEXT: i32.const $push0=, 0
+; CHECK-NEXT: local.get $push5=, 1
+; CHECK-NEXT: i64.eqz $push1=, $pop5
+; CHECK-NEXT: i32.or $push2=, $pop0, $pop1
+; CHECK-NEXT: return $pop2
+ %a = call i1 @llvm.is.fpclass.f64(double %x, i32 64)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f64_possubnorm(double %x) {
+; CHECK-LABEL: is_fpclass_f64_possubnorm:
+; CHECK: .functype is_fpclass_f64_possubnorm (f64) -> (i32)
+; CHECK-NEXT: .local i64
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push7=, 0
+; CHECK-NEXT: i64.reinterpret_f64 $push6=, $pop7
+; CHECK-NEXT: local.set 1, $pop6
+; CHECK-NEXT: i32.const $push0=, 0
+; CHECK-NEXT: local.get $push8=, 1
+; CHECK-NEXT: i64.const $push1=, 1
+; CHECK-NEXT: i64.sub $push2=, $pop8, $pop1
+; CHECK-NEXT: i64.const $push3=, 4503599627370495
+; CHECK-NEXT: i64.lt_u $push4=, $pop2, $pop3
+; CHECK-NEXT: i32.or $push5=, $pop0, $pop4
+; CHECK-NEXT: return $pop5
+ %a = call i1 @llvm.is.fpclass.f64(double %x, i32 128)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f64_posnormal(double %x) {
+; CHECK-LABEL: is_fpclass_f64_posnormal:
+; CHECK: .functype is_fpclass_f64_posnormal (f64) -> (i32)
+; CHECK-NEXT: .local i64, i64, i32
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push11=, 0
+; CHECK-NEXT: i64.reinterpret_f64 $push10=, $pop11
+; CHECK-NEXT: local.set 1, $pop10
+; CHECK-NEXT: local.get $push13=, 1
+; CHECK-NEXT: i64.const $push0=, 9223372036854775807
+; CHECK-NEXT: i64.and $push12=, $pop13, $pop0
+; CHECK-NEXT: local.set 2, $pop12
+; CHECK-NEXT: local.get $push16=, 1
+; CHECK-NEXT: local.get $push15=, 2
+; CHECK-NEXT: i64.ne $push14=, $pop16, $pop15
+; CHECK-NEXT: local.set 3, $pop14
+; CHECK-NEXT: i32.const $push1=, 0
+; CHECK-NEXT: local.get $push17=, 2
+; CHECK-NEXT: i64.const $push2=, 4503599627370496
+; CHECK-NEXT: i64.sub $push3=, $pop17, $pop2
+; CHECK-NEXT: i64.const $push4=, 9214364837600034816
+; CHECK-NEXT: i64.lt_u $push5=, $pop3, $pop4
+; CHECK-NEXT: local.get $push18=, 3
+; CHECK-NEXT: i32.const $push6=, -1
+; CHECK-NEXT: i32.xor $push7=, $pop18, $pop6
+; CHECK-NEXT: i32.and $push8=, $pop5, $pop7
+; CHECK-NEXT: i32.or $push9=, $pop1, $pop8
+; CHECK-NEXT: return $pop9
+ %a = call i1 @llvm.is.fpclass.f64(double %x, i32 256)
+ ret i1 %a
+}
+
+define i1 @is_fpclass_f64_posinf(double %x) {
+; CHECK-LABEL: is_fpclass_f64_posinf:
+; CHECK: .functype is_fpclass_f64_posinf (f64) -> (i32)
+; CHECK-NEXT: .local i64, i64
+; CHECK-NEXT: # %bb.0:
+; CHECK-NEXT: local.get $push4=, 0
+; CHECK-NEXT: i64.reinterpret_f64 $push3=, $pop4
+; CHECK-NEXT: local.set 1, $pop3
+; CHECK-NEXT: i64.const $push5=, 9218868437227405312
+; CHECK-NEXT: local.set 2, $pop5
+; CHECK-NEXT: i32.const $push0=, 0
+; CHECK-NEXT: local.get $push7=, 1
+; CHECK-NEXT: local.get $push6=, 2
+; CHECK-NEXT: i64.eq $push1=, $pop7, $pop6
+; CHECK-NEXT: i32.or $push2=, $pop0, $pop1
+; CHECK-NEXT: return $pop2
+ %a = call i1 @llvm.is.fpclass.f64(double %x, i32 512)
+ ret i1 %a
+}
More information about the llvm-branch-commits
mailing list