[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