[llvm] [WebAssembly][GlobalISel] Add legalization & selection of most integer ops (PR #190234)

Demetrius Kanios via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 3 11:22:38 PDT 2026


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

>From 1793931d81517b9274b691ae413700deadd4d77c Mon Sep 17 00:00:00 2001
From: Demetrius Kanios <demetrius at kanios.net>
Date: Thu, 2 Apr 2026 11:54:20 -0700
Subject: [PATCH 1/3] Add legalization, regbank, and isel for most integer ops.

---
 .../GISel/WebAssemblyInstructionSelector.cpp  |  52 +++
 .../GISel/WebAssemblyLegalizerInfo.cpp        |  61 ++-
 .../GISel/WebAssemblyLegalizerInfo.h          |   3 +
 .../GISel/WebAssemblyRegisterBankInfo.cpp     |  41 +-
 .../WebAssembly/WebAssemblyInstrInteger.td    |   8 +
 .../GlobalISel/instruction-select/bitwise.mir | 433 +++++++++++++++++-
 .../GlobalISel/instruction-select/consts.mir  |  76 +++
 .../instruction-select/ext-trunc.mir          | 186 ++++++++
 .../instruction-select/int-arithmetic.mir     | 271 ++++++++++-
 .../WebAssembly/GlobalISel/legalizer/add.mir  |  61 ++-
 .../WebAssembly/GlobalISel/legalizer/and.mir  | 116 +++++
 .../GlobalISel/legalizer/anyext.mir           |  95 ++++
 .../WebAssembly/GlobalISel/legalizer/ashr.mir | 331 +++++++++++++
 .../GlobalISel/legalizer/constant.mir         | 145 ++++++
 .../WebAssembly/GlobalISel/legalizer/ctlz.mir | 152 ++++++
 .../GlobalISel/legalizer/ctlz_zero_undef.mir  | 148 ++++++
 .../GlobalISel/legalizer/ctpop.mir            | 148 ++++++
 .../WebAssembly/GlobalISel/legalizer/cttz.mir | 148 ++++++
 .../GlobalISel/legalizer/cttz_zero_undef.mir  | 144 ++++++
 .../WebAssembly/GlobalISel/legalizer/fshl.mir | 393 ++++++++++++++++
 .../WebAssembly/GlobalISel/legalizer/fshr.mir | 389 ++++++++++++++++
 .../GlobalISel/legalizer/implicit_def.mir     |  72 +++
 .../WebAssembly/GlobalISel/legalizer/lshr.mir | 286 ++++++++++++
 .../WebAssembly/GlobalISel/legalizer/mul.mir  |  91 ++++
 .../WebAssembly/GlobalISel/legalizer/or.mir   | 117 +++++
 .../WebAssembly/GlobalISel/legalizer/rotl.mir | 303 ++++++++++++
 .../WebAssembly/GlobalISel/legalizer/rotr.mir | 303 ++++++++++++
 .../WebAssembly/GlobalISel/legalizer/sdiv.mir | 126 +++++
 .../WebAssembly/GlobalISel/legalizer/sext.mir | 138 ++++++
 .../GlobalISel/legalizer/sext_inreg.mir       | 181 ++++++++
 .../WebAssembly/GlobalISel/legalizer/shl.mir  | 278 +++++++++++
 .../WebAssembly/GlobalISel/legalizer/srem.mir | 126 +++++
 .../WebAssembly/GlobalISel/legalizer/sub.mir  |  91 ++++
 .../GlobalISel/legalizer/trunc.mir            |  95 ++++
 .../WebAssembly/GlobalISel/legalizer/udiv.mir |  99 ++++
 .../WebAssembly/GlobalISel/legalizer/urem.mir |  99 ++++
 .../WebAssembly/GlobalISel/legalizer/xor.mir  | 116 +++++
 .../WebAssembly/GlobalISel/legalizer/zext.mir | 103 +++++
 .../GlobalISel/regbankselect/bitwise.mir      | 414 ++++++++++++++++-
 .../GlobalISel/regbankselect/consts.mir       |  72 +++
 .../GlobalISel/regbankselect/ext-trunc.mir    | 177 +++++++
 .../regbankselect/int-arithmetic.mir          | 259 ++++++++++-
 42 files changed, 6913 insertions(+), 34 deletions(-)
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/consts.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/ext-trunc.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/and.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/anyext.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ashr.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/constant.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctlz.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctlz_zero_undef.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctpop.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz_zero_undef.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/fshl.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/fshr.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/implicit_def.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/lshr.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/mul.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/or.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/rotl.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/rotr.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sdiv.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sext.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sext_inreg.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/shl.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/srem.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sub.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/trunc.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/udiv.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/urem.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/xor.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/zext.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/consts.mir
 create mode 100644 llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/ext-trunc.mir

diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
index 463d3977c329d..7359156ccf60c 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
@@ -23,6 +23,7 @@
 #include "llvm/CodeGen/MachineOperand.h"
 #include "llvm/CodeGen/TargetLowering.h"
 #include "llvm/IR/IntrinsicsWebAssembly.h"
+#include "llvm/Support/ErrorHandling.h"
 
 #define DEBUG_TYPE "wasm-isel"
 
@@ -83,7 +84,35 @@ WebAssemblyInstructionSelector::WebAssemblyInstructionSelector(
 {
 }
 
+static const TargetRegisterClass &getRegClassForBank(const RegisterBank &RB) {
+  switch (RB.getID()) {
+  case WebAssembly::I32RegBankID:
+    return WebAssembly::I32RegClass;
+  case WebAssembly::I64RegBankID:
+    return WebAssembly::I64RegClass;
+  case WebAssembly::F32RegBankID:
+    return WebAssembly::F32RegClass;
+  case WebAssembly::F64RegBankID:
+    return WebAssembly::F64RegClass;
+  case WebAssembly::EXNREFRegBankID:
+    return WebAssembly::EXNREFRegClass;
+  case WebAssembly::EXTERNREFRegBankID:
+    return WebAssembly::EXTERNREFRegClass;
+  case WebAssembly::FUNCREFRegBankID:
+    return WebAssembly::FUNCREFRegClass;
+  case WebAssembly::V128RegBankID:
+    return WebAssembly::V128RegClass;
+  default:
+    reportFatalInternalError(
+        "Found unexpected RegisterBank in `getRegClassForBank`");
+  }
+}
+
 bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
+  MachineBasicBlock &MBB = *I.getParent();
+  MachineFunction &MF = *MBB.getParent();
+  MachineRegisterInfo &MRI = MF.getRegInfo();
+
   if (!I.isPreISelOpcode()) {
     return true;
   }
@@ -91,6 +120,29 @@ bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
   if (selectImpl(I, *CoverageInfo))
     return true;
 
+  using namespace TargetOpcode;
+
+  switch (I.getOpcode()) {
+  case G_IMPLICIT_DEF: {
+    const Register DefReg = I.getOperand(0).getReg();
+    const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(DefReg);
+
+    const TargetRegisterClass *DefRC =
+        dyn_cast<const TargetRegisterClass *>(RegClassOrBank);
+
+    if (!DefRC) {
+      const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
+      DefRC = &getRegClassForBank(RB);
+    }
+
+    I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
+
+    return RBI.constrainGenericRegister(DefReg, *DefRC, MRI) != nullptr;
+  }
+  default:
+    break;
+  }
+
   return false;
 }
 
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
index ecbaf79db751d..0b9bbc1a6853a 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
@@ -12,6 +12,8 @@
 
 #include "WebAssemblyLegalizerInfo.h"
 #include "WebAssemblySubtarget.h"
+#include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
+#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
 
 #define DEBUG_TYPE "wasm-legalinfo"
 
@@ -25,18 +27,71 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
   const LLT s32 = LLT::scalar(32);
   const LLT s64 = LLT::scalar(64);
 
-  getActionDefinitionsBuilder({G_CONSTANT, G_ADD, G_AND})
+  getActionDefinitionsBuilder({G_CONSTANT, G_IMPLICIT_DEF, G_ADD, G_SUB, G_MUL,
+                               G_UDIV, G_SDIV, G_UREM, G_SREM, G_AND, G_OR,
+                               G_XOR})
       .legalFor({s32, s64})
       .widenScalarToNextPow2(0)
       .clampScalar(0, s32, s64);
 
-  getActionDefinitionsBuilder({G_ASHR, G_SHL})
+  getActionDefinitionsBuilder({G_ASHR, G_LSHR, G_SHL})
       .legalFor({{s32, s32}, {s64, s64}})
       .widenScalarToNextPow2(0)
       .clampScalar(0, s32, s64)
       .scalarSameSizeAs(1, 0);
 
-  getActionDefinitionsBuilder(G_SEXT_INREG).lower();
+  getActionDefinitionsBuilder(
+      {G_CTLZ, G_CTLZ_ZERO_UNDEF, G_CTTZ, G_CTTZ_ZERO_UNDEF, G_CTPOP})
+      .legalFor({{s32, s32}, {s64, s64}})
+      .widenScalarToNextPow2(1)
+      .clampScalar(1, s32, s64)
+      .scalarSameSizeAs(0, 1);
+
+  getActionDefinitionsBuilder({G_ROTL, G_ROTR})
+      .legalFor({{s32, s32}, {s64, s64}})
+      .scalarSameSizeAs(1, 0)
+      .lower();
+
+  getActionDefinitionsBuilder({G_FSHL, G_FSHR}).lower();
+
+  getActionDefinitionsBuilder({G_ANYEXT, G_SEXT, G_ZEXT})
+      .legalFor({{s64, s32}})
+      .clampScalar(0, s64, s64)
+      .clampScalar(1, s32, s32);
+
+  getActionDefinitionsBuilder(G_TRUNC)
+      .legalFor({{s32, s64}})
+      .clampScalar(0, s32, s32)
+      .clampScalar(1, s64, s64);
+
+  getActionDefinitionsBuilder(G_SEXT_INREG)
+      .clampScalar(0, s32, s64)
+      .customFor(ST.hasSignExt(), {s32, s64})
+      .lower();
 
   getLegacyLegalizerInfo().computeTables();
 }
+
+bool WebAssemblyLegalizerInfo::legalizeCustom(
+    LegalizerHelper &Helper, MachineInstr &MI,
+    LostDebugLocObserver &LocObserver) const {
+  switch (MI.getOpcode()) {
+  case TargetOpcode::G_SEXT_INREG: {
+    assert(MI.getOperand(2).isImm() && "Expected immediate");
+
+    // Mark only 8/16/32-bit SEXT_INREG as legal
+    auto [DstType, SrcType] = MI.getFirst2LLTs();
+    auto ExtFromWidth = MI.getOperand(2).getImm();
+
+    if (ExtFromWidth == 8 || ExtFromWidth == 16 ||
+        (DstType.getScalarSizeInBits() == 64 && ExtFromWidth == 32)) {
+      return true;
+    }
+
+    return Helper.lower(MI, 0, DstType);
+  }
+  default:
+    break;
+  }
+  return false;
+}
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.h b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.h
index 61f4aa621d44f..45f21d7190abe 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.h
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.h
@@ -24,6 +24,9 @@ class WebAssemblySubtarget;
 class WebAssemblyLegalizerInfo : public LegalizerInfo {
 public:
   WebAssemblyLegalizerInfo(const WebAssemblySubtarget &ST);
+
+  bool legalizeCustom(LegalizerHelper &Helper, MachineInstr &MI,
+                      LostDebugLocObserver &LocObserver) const override;
 };
 } // namespace llvm
 #endif
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp
index 4aaf04eb2496e..f7be420b49d2f 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyRegisterBankInfo.cpp
@@ -88,14 +88,51 @@ WebAssemblyRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
 
   using namespace TargetOpcode;
   switch (Opc) {
+  case G_CONSTANT:
+    OperandsMapping = getOperandsMapping({&Op0IntValueMapping, nullptr});
+    break;
+  case G_IMPLICIT_DEF:
+    OperandsMapping = &Op0IntValueMapping;
+    break;
   case G_ADD:
+  case G_SUB:
+  case G_MUL:
+  case G_UDIV:
+  case G_SDIV:
+  case G_UREM:
+  case G_SREM:
   case G_AND:
+  case G_OR:
+  case G_XOR:
   case G_ASHR:
+  case G_LSHR:
   case G_SHL:
+  case G_CTLZ:
+  case G_CTLZ_ZERO_UNDEF:
+  case G_CTTZ:
+  case G_CTTZ_ZERO_UNDEF:
+  case G_CTPOP:
+  case G_ROTL:
+  case G_ROTR:
     OperandsMapping = &Op0IntValueMapping;
     break;
-  case G_CONSTANT:
-    OperandsMapping = getOperandsMapping({&Op0IntValueMapping, nullptr});
+  case G_ZEXT:
+  case G_ANYEXT:
+  case G_SEXT:
+  case G_TRUNC: {
+    const LLT Op1Ty = MRI.getType(MI.getOperand(1).getReg());
+    unsigned Op1Size = Op1Ty.getSizeInBits();
+
+    auto &Op1IntValueMapping =
+        WebAssembly::ValueMappings[Op1Size == 64 ? WebAssembly::I64Idx
+                                                 : WebAssembly::I32Idx];
+    OperandsMapping =
+        getOperandsMapping({&Op0IntValueMapping, &Op1IntValueMapping});
+    break;
+  }
+  case G_SEXT_INREG:
+    OperandsMapping =
+        getOperandsMapping({&Op0IntValueMapping, &Op0IntValueMapping, nullptr});
     break;
   }
 
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
index 991507e883f28..99ca22e21f70b 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
@@ -82,10 +82,18 @@ defm LE_U : ComparisonInt<SETULE, "le_u", 0x4d, 0x58>;
 defm GE_S : ComparisonInt<SETGE,  "ge_s", 0x4e, 0x59>;
 defm GE_U : ComparisonInt<SETUGE, "ge_u", 0x4f, 0x5a>;
 
+
 defm CLZ : UnaryInt<ctlz, "clz ", 0x67, 0x79>;
+def : Pat<(ctlz_zero_undef I32:$src), (CLZ_I32 I32:$src)>;
+def : Pat<(ctlz_zero_undef I64:$src), (CLZ_I64 I64:$src)>;
+
 defm CTZ : UnaryInt<cttz, "ctz ", 0x68, 0x7a>;
+def : Pat<(cttz_zero_undef I32:$src), (CTZ_I32 I32:$src)>;
+def : Pat<(cttz_zero_undef I64:$src), (CTZ_I64 I64:$src)>;
+
 defm POPCNT : UnaryInt<ctpop, "popcnt", 0x69, 0x7b>;
 
+
 defm EQZ_I32 : I<(outs I32:$dst), (ins I32:$src), (outs), (ins),
                  [(set I32:$dst, (setcc I32:$src, 0, SETEQ))],
                  "i32.eqz \t$dst, $src", "i32.eqz", 0x45>;
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/bitwise.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/bitwise.mir
index c1c111606d15f..1a5943259b521 100644
--- a/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/bitwise.mir
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/bitwise.mir
@@ -23,7 +23,6 @@ body:             |
     %2:i32regbank(s32) = G_AND %0, %1
     RETURN %2(s32), implicit-def $arguments
 ...
-
 ---
 name:            and_i64
 alignment:       1
@@ -47,6 +46,96 @@ body:             |
     RETURN %2(s64), implicit-def $arguments
 ...
 
+---
+name:            or_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: or_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[OR_I32_:%[0-9]+]]:i32 = OR_I32 [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[OR_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:i32regbank(s32) = G_OR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            or_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: or_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[OR_I64_:%[0-9]+]]:i64 = OR_I64 [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[OR_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:i64regbank(s64) = G_OR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            xor_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: xor_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[XOR_I32_:%[0-9]+]]:i32 = XOR_I32 [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[XOR_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:i32regbank(s32) = G_XOR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            xor_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: xor_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[XOR_I64_:%[0-9]+]]:i64 = XOR_I64 [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[XOR_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:i64regbank(s64) = G_XOR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
 ---
 name:            shl_i32
 alignment:       1
@@ -69,7 +158,6 @@ body:             |
     %2:i32regbank(s32) = G_SHL %0, %1
     RETURN %2(s32), implicit-def $arguments
 ...
-
 ---
 name:            shl_i64
 alignment:       1
@@ -115,7 +203,6 @@ body:             |
     %2:i32regbank(s32) = G_ASHR %0, %1
     RETURN %2(s32), implicit-def $arguments
 ...
-
 ---
 name:            ashr_i64
 alignment:       1
@@ -138,3 +225,343 @@ body:             |
     %2:i64regbank(s64) = G_ASHR %0, %1
     RETURN %2(s64), implicit-def $arguments
 ...
+
+---
+name:            lshr_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshr_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CONST_I32_:%[0-9]+]]:i32 = CONST_I32 5, implicit-def dead $arguments
+    ; CHECK-NEXT: [[SHR_U_I32_:%[0-9]+]]:i32 = SHR_U_I32 [[ARGUMENT_i32_]], [[CONST_I32_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[SHR_U_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32regbank(s32) = G_CONSTANT i32 5
+    %2:i32regbank(s32) = G_LSHR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            lshr_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshr_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CONST_I64_:%[0-9]+]]:i64 = CONST_I64 37, implicit-def dead $arguments
+    ; CHECK-NEXT: [[SHR_U_I64_:%[0-9]+]]:i64 = SHR_U_I64 [[ARGUMENT_i64_]], [[CONST_I64_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[SHR_U_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64regbank(s64) = G_CONSTANT i64 37
+    %2:i64regbank(s64) = G_LSHR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            ctlz_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CLZ_I32_:%[0-9]+]]:i32 = CLZ_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[CLZ_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32regbank(s32) = G_CTLZ %0
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            ctlz_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CLZ_I64_:%[0-9]+]]:i64 = CLZ_I64 [[ARGUMENT_i64_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[CLZ_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64regbank(s64) = G_CTLZ %0
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name:            ctlz_zundef_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_zundef_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CLZ_I32_:%[0-9]+]]:i32 = CLZ_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[CLZ_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32regbank(s32) = G_CTLZ_ZERO_UNDEF %0
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            ctlz_zundef_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_zundef_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CLZ_I64_:%[0-9]+]]:i64 = CLZ_I64 [[ARGUMENT_i64_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[CLZ_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64regbank(s64) = G_CTLZ_ZERO_UNDEF %0
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name:            cttz_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTZ_I32_:%[0-9]+]]:i32 = CTZ_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[CTZ_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32regbank(s32) = G_CTTZ %0
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            cttz_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTZ_I64_:%[0-9]+]]:i64 = CTZ_I64 [[ARGUMENT_i64_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[CTZ_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64regbank(s64) = G_CTTZ %0
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name:            cttz_zundef_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_zundef_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTZ_I32_:%[0-9]+]]:i32 = CTZ_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[CTZ_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32regbank(s32) = G_CTTZ_ZERO_UNDEF %0
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            cttz_zundef_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_zundef_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTZ_I64_:%[0-9]+]]:i64 = CTZ_I64 [[ARGUMENT_i64_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[CTZ_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64regbank(s64) = G_CTTZ_ZERO_UNDEF %0
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name:            ctpop_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctpop_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[POPCNT_I32_:%[0-9]+]]:i32 = POPCNT_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[POPCNT_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32regbank(s32) = G_CTPOP %0
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            ctpop_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctpop_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[POPCNT_I64_:%[0-9]+]]:i64 = POPCNT_I64 [[ARGUMENT_i64_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[POPCNT_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64regbank(s64) = G_CTPOP %0
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name:            rotl_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotl_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ROTL_I32_:%[0-9]+]]:i32 = ROTL_I32 [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[ROTL_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:i32regbank(s32) = G_ROTL %0, %1(s32)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            rotl_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotl_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[ROTL_I64_:%[0-9]+]]:i64 = ROTL_I64 [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[ROTL_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:i64regbank(s64) = G_ROTL %0, %1(s64)
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            rotr_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotr_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ROTR_I32_:%[0-9]+]]:i32 = ROTR_I32 [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[ROTR_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:i32regbank(s32) = G_ROTR %0, %1(s32)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            rotr_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotr_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[ROTR_I64_:%[0-9]+]]:i64 = ROTR_I64 [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[ROTR_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:i64regbank(s64) = G_ROTR %0, %1(s64)
+    RETURN %2(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/consts.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/consts.mir
new file mode 100644
index 0000000000000..f3ee685d18a85
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/consts.mir
@@ -0,0 +1,76 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name:            const_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: const_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[CONST_I32_:%[0-9]+]]:i32 = CONST_I32 0, implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[CONST_I32_]], implicit-def $arguments
+    %0:i32regbank(s32) = G_CONSTANT i32 0
+    RETURN %0(s32), implicit-def $arguments
+...
+---
+name:            const_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: const_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[CONST_I64_:%[0-9]+]]:i64 = CONST_I64 0, implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[CONST_I64_]], implicit-def $arguments
+    %0:i64regbank(s64) = G_CONSTANT i64 0
+    RETURN %0(s64), implicit-def $arguments
+...
+
+---
+name:            implicit_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: implicit_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[DEF:%[0-9]+]]:i32 = IMPLICIT_DEF
+    ; CHECK-NEXT: RETURN [[DEF]], implicit-def $arguments
+    %0:i32regbank(s32) = G_IMPLICIT_DEF
+    RETURN %0(s32), implicit-def $arguments
+...
+---
+name:            implicit_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: implicit_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[DEF:%[0-9]+]]:i64 = IMPLICIT_DEF
+    ; CHECK-NEXT: RETURN [[DEF]], implicit-def $arguments
+    %0:i64regbank(s64) = G_IMPLICIT_DEF
+    RETURN %0(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/ext-trunc.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/ext-trunc.mir
new file mode 100644
index 0000000000000..6c150bd2884cf
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/ext-trunc.mir
@@ -0,0 +1,186 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=instruction-select -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name:            anyext
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: anyext
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[I64_EXTEND_U_I32_:%[0-9]+]]:i64 = I64_EXTEND_U_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[I64_EXTEND_U_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i64regbank(s64) = G_ANYEXT %0
+    RETURN %1(s64), implicit-def $arguments
+...
+---
+name:            sext
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[I64_EXTEND_S_I32_:%[0-9]+]]:i64 = I64_EXTEND_S_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[I64_EXTEND_S_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i64regbank(s64) = G_SEXT %0
+    RETURN %1(s64), implicit-def $arguments
+...
+---
+name:            zext
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: zext
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[I64_EXTEND_U_I32_:%[0-9]+]]:i64 = I64_EXTEND_U_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[I64_EXTEND_U_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i64regbank(s64) = G_ZEXT %0
+    RETURN %1(s64), implicit-def $arguments
+...
+---
+name:            trunc
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: trunc
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[I32_WRAP_I64_:%[0-9]+]]:i32 = I32_WRAP_I64 [[ARGUMENT_i64_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[I32_WRAP_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i32regbank(s32) = G_TRUNC %0
+    RETURN %1(s32), implicit-def $arguments
+...
+
+---
+name:            sext_inreg_i32_8
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext_inreg_i32_8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[I32_EXTEND8_S_I32_:%[0-9]+]]:i32 = I32_EXTEND8_S_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[I32_EXTEND8_S_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32regbank(s32) = G_SEXT_INREG %0, 8
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            sext_inreg_i64_8
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext_inreg_i64_8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[I64_EXTEND8_S_I64_:%[0-9]+]]:i64 = I64_EXTEND8_S_I64 [[ARGUMENT_i64_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[I64_EXTEND8_S_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64regbank(s64) = G_SEXT_INREG %0, 8
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name:            sext_inreg_i32_16
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext_inreg_i32_16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[I32_EXTEND16_S_I32_:%[0-9]+]]:i32 = I32_EXTEND16_S_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[I32_EXTEND16_S_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32regbank(s32) = G_SEXT_INREG %0, 16
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            sext_inreg_i64_16
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext_inreg_i64_16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[I64_EXTEND16_S_I64_:%[0-9]+]]:i64 = I64_EXTEND16_S_I64 [[ARGUMENT_i64_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[I64_EXTEND16_S_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64regbank(s64) = G_SEXT_INREG %0, 16
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name:            sext_inreg_i64_32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext_inreg_i64_32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[I64_EXTEND32_S_I64_:%[0-9]+]]:i64 = I64_EXTEND32_S_I64 [[ARGUMENT_i64_]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[I64_EXTEND32_S_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64regbank(s64) = G_SEXT_INREG %0, 32
+    RETURN %1(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/int-arithmetic.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/int-arithmetic.mir
index 60c916c372636..2d13318da5a84 100644
--- a/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/int-arithmetic.mir
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/int-arithmetic.mir
@@ -23,7 +23,6 @@ body:             |
     %2:i32regbank(s32) = G_ADD %0, %1
     RETURN %2(s32), implicit-def $arguments
 ...
-
 ---
 name:            add_i64
 alignment:       1
@@ -46,3 +45,273 @@ body:             |
     %2:i64regbank(s64) = G_ADD %0, %1
     RETURN %2(s64), implicit-def $arguments
 ...
+
+---
+name:            sub_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sub_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[SUB_I32_:%[0-9]+]]:i32 = SUB_I32 [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[SUB_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:i32regbank(s32) = G_SUB %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            sub_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sub_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[SUB_I64_:%[0-9]+]]:i64 = SUB_I64 [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[SUB_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:i64regbank(s64) = G_SUB %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            mul_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: mul_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[MUL_I32_:%[0-9]+]]:i32 = MUL_I32 [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[MUL_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:i32regbank(s32) = G_MUL %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            mul_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: mul_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[MUL_I64_:%[0-9]+]]:i64 = MUL_I64 [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[MUL_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:i64regbank(s64) = G_MUL %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            udiv_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: udiv_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[DIV_U_I32_:%[0-9]+]]:i32 = DIV_U_I32 [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[DIV_U_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:i32regbank(s32) = G_UDIV %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            udiv_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: udiv_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[DIV_U_I64_:%[0-9]+]]:i64 = DIV_U_I64 [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[DIV_U_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:i64regbank(s64) = G_UDIV %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            sdiv_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sdiv_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[DIV_S_I32_:%[0-9]+]]:i32 = DIV_S_I32 [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[DIV_S_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:i32regbank(s32) = G_SDIV %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            sdiv_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sdiv_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[DIV_S_I64_:%[0-9]+]]:i64 = DIV_S_I64 [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[DIV_S_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:i64regbank(s64) = G_SDIV %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            urem_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: urem_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[REM_U_I32_:%[0-9]+]]:i32 = REM_U_I32 [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[REM_U_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:i32regbank(s32) = G_UREM %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            urem_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: urem_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[REM_U_I64_:%[0-9]+]]:i64 = REM_U_I64 [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[REM_U_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:i64regbank(s64) = G_UREM %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            srem_i32
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: srem_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32 = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[REM_S_I32_:%[0-9]+]]:i32 = REM_S_I32 [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[REM_S_I32_]], implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:i32regbank(s32) = G_SREM %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            srem_i64
+alignment:       1
+legalized:       true
+regBankSelected: true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: srem_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64 = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[REM_S_I64_:%[0-9]+]]:i64 = REM_S_I64 [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]], implicit-def dead $arguments
+    ; CHECK-NEXT: RETURN [[REM_S_I64_]], implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:i64regbank(s64) = G_SREM %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/add.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/add.mir
index 0d12b749e461e..8865e0e730f61 100644
--- a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/add.mir
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/add.mir
@@ -1,5 +1,6 @@
 # NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
-# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -mattr=-sign-ext -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,NO-SIGNEXT
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -mattr=+sign-ext -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,SIGNEXT
 
 ---
 name:            add_i8_zext
@@ -35,16 +36,25 @@ body:             |
   bb.1.entry:
     liveins: $arguments
 
-    ; CHECK-LABEL: name: add_i8_sext
-    ; CHECK: liveins: $arguments
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
-    ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
-    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
-    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ADD]], [[C]](s32)
-    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:i32(s32) = G_ASHR [[SHL]], [[C]](s32)
-    ; CHECK-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    ; NO-SIGNEXT-LABEL: name: add_i8_sext
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ADD]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:i32(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: add_i8_sext
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; SIGNEXT-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:i32(s32) = G_SEXT_INREG [[ADD]], 8
+    ; SIGNEXT-NEXT: RETURN [[SEXT_INREG]](s32), implicit-def $arguments
     %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     %0:_(s8) = G_TRUNC %2(s32)
     %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
@@ -113,16 +123,25 @@ body:             |
   bb.1.entry:
     liveins: $arguments
 
-    ; CHECK-LABEL: name: add_i16_sext
-    ; CHECK: liveins: $arguments
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
-    ; CHECK-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
-    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
-    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ADD]], [[C]](s32)
-    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:i32(s32) = G_ASHR [[SHL]], [[C]](s32)
-    ; CHECK-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    ; NO-SIGNEXT-LABEL: name: add_i16_sext
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ADD]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:i32(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: add_i16_sext
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; SIGNEXT-NEXT: [[ADD:%[0-9]+]]:_(s32) = G_ADD [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:i32(s32) = G_SEXT_INREG [[ADD]], 16
+    ; SIGNEXT-NEXT: RETURN [[SEXT_INREG]](s32), implicit-def $arguments
     %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     %0:_(s16) = G_TRUNC %2(s32)
     %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/and.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/and.mir
new file mode 100644
index 0000000000000..52c2de6715dd3
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/and.mir
@@ -0,0 +1,116 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: and_i1
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: and_i1
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[ARGUMENT_i32_]]
+    ; CHECK-NEXT: RETURN [[AND]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s1) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s1) = G_TRUNC %3(s32)
+    %4:_(s1) = G_AND %1, %0
+    %5:_(s32) = G_ANYEXT %4(s1)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: and_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: and_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[ARGUMENT_i32_]]
+    ; CHECK-NEXT: RETURN [[AND]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_AND %1, %0
+    %5:_(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: and_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: and_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[ARGUMENT_i32_]]
+    ; CHECK-NEXT: RETURN [[AND]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_AND %1, %0
+    %5:_(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: and_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: and_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[ARGUMENT_i32_]]
+    ; CHECK-NEXT: RETURN [[AND]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_AND %1, %0
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: and_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: and_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[ARGUMENT_i64_1]], [[ARGUMENT_i64_]]
+    ; CHECK-NEXT: RETURN [[AND]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_AND %1, %0
+    RETURN %2(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/anyext.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/anyext.mir
new file mode 100644
index 0000000000000..7380ad857cd9d
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/anyext.mir
@@ -0,0 +1,95 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: aext_i8_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: aext_i8_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: RETURN [[ARGUMENT_i32_]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:i32(s32) = G_ANYEXT %0(s8)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: aext_i8_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: aext_i8_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:i32(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[ANYEXT]](s64), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:i32(s64) = G_ANYEXT %0(s8)
+    RETURN %2(s64), implicit-def $arguments
+...
+---
+name: aext_i16_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: aext_i16_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: RETURN [[ARGUMENT_i32_]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:i32(s32) = G_ANYEXT %0(s16)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: aext_i16_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: aext_i16_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:i32(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[ANYEXT]](s64), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:i32(s64) = G_ANYEXT %0(s16)
+    RETURN %2(s64), implicit-def $arguments
+...
+---
+name: aext_i32_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: aext_i32_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:i32(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[ANYEXT]](s64), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s64) = G_ANYEXT %0(s32)
+    RETURN %1(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ashr.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ashr.mir
new file mode 100644
index 0000000000000..e38b3b87c9e8d
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ashr.mir
@@ -0,0 +1,331 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -mattr=-sign-ext -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,NO-SIGNEXT
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -mattr=+sign-ext -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,SIGNEXT
+
+---
+name: ashr_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: ashr_i8
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+    ; NO-SIGNEXT-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C1]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C1]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[ASHR]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR1]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: ashr_i8
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[ARGUMENT_i32_]], 8
+    ; SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SEXT_INREG]], [[C]](s32)
+    ; SIGNEXT-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %1:_(s8) = G_CONSTANT i8 5
+    %3:_(s8) = G_ASHR %0, %1
+    %4:_(s32) = G_ANYEXT %3(s8)
+    RETURN %4(s32), implicit-def $arguments
+
+...
+---
+name: ashrv_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: ashrv_i8
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; NO-SIGNEXT-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C1]]
+    ; NO-SIGNEXT-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[ASHR]], [[AND]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR1]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: ashrv_i8
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[ARGUMENT_i32_]], 8
+    ; SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; SIGNEXT-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C]]
+    ; SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SEXT_INREG]], [[AND]](s32)
+    ; SIGNEXT-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_ASHR %0, %1
+    %5:_(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: ashr_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: ashr_i16
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 13
+    ; NO-SIGNEXT-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C1]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C1]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[ASHR]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR1]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: ashr_i16
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 13
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[ARGUMENT_i32_]], 16
+    ; SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SEXT_INREG]], [[C]](s32)
+    ; SIGNEXT-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %1:_(s16) = G_CONSTANT i16 13
+    %3:_(s16) = G_ASHR %0, %1
+    %4:_(s32) = G_ANYEXT %3(s16)
+    RETURN %4(s32), implicit-def $arguments
+
+...
+---
+name: ashrv_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: ashrv_i16
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; NO-SIGNEXT-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C1]]
+    ; NO-SIGNEXT-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[ASHR]], [[AND]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR1]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: ashrv_i16
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[ARGUMENT_i32_]], 16
+    ; SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; SIGNEXT-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C]]
+    ; SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SEXT_INREG]], [[AND]](s32)
+    ; SIGNEXT-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_ASHR %0, %1
+    %5:_(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: ashr_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ashr_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CONSTANT i32 21
+    %2:_(s32) = G_ASHR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: ashrv_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ashrv_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]](s32)
+    ; CHECK-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_ASHR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: ashr_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ashr_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s8) = G_CONSTANT i8 21
+    %2:_(s32) = G_ASHR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: ashrv_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ashrv_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C]]
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[ARGUMENT_i32_]], [[AND]](s32)
+    ; CHECK-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %2:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %2(s32)
+    %3:_(s32) = G_ASHR %0, %1
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: ashr_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ashr_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 37
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[ARGUMENT_i64_]], [[C]](s64)
+    ; CHECK-NEXT: RETURN [[ASHR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CONSTANT i64 37
+    %2:_(s64) = G_ASHR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: ashrv_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ashrv_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]](s64)
+    ; CHECK-NEXT: RETURN [[ASHR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_ASHR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: ashr_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ashr_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 37
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[C]], [[C1]]
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[ARGUMENT_i64_]], [[AND]](s64)
+    ; CHECK-NEXT: RETURN [[ASHR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s8) = G_CONSTANT i8 37
+    %2:_(s64) = G_ASHR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: ashrv_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ashrv_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C]]
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[ARGUMENT_i64_]], [[AND]](s64)
+    ; CHECK-NEXT: RETURN [[ASHR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %2:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %2(s32)
+    %3:_(s64) = G_ASHR %0, %1
+    RETURN %3(s64), implicit-def $arguments
+
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/constant.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/constant.mir
new file mode 100644
index 0000000000000..41b06f5c5c836
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/constant.mir
@@ -0,0 +1,145 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name:            const_i8_zext
+alignment:       1
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: const_i8_zext
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: RETURN [[C]](s32), implicit-def $arguments
+    %0:_(s8) = G_CONSTANT i8 255
+    %1:_(s32) = G_ZEXT %0(s8)
+    RETURN %1(s32), implicit-def $arguments
+...
+
+---
+name:            const_i8_sext
+alignment:       1
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: const_i8_sext
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: RETURN [[C]](s32), implicit-def $arguments
+    %0:_(s8) = G_CONSTANT i8 255
+    %1:_(s32) = G_SEXT %0(s8)
+    RETURN %1(s32), implicit-def $arguments
+...
+
+---
+name:            const_i8_aext
+alignment:       1
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: const_i8_aext
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: RETURN [[C]](s32), implicit-def $arguments
+    %0:_(s8) = G_CONSTANT i8 255
+    %1:_(s32) = G_ANYEXT %0(s8)
+    RETURN %1(s32), implicit-def $arguments
+...
+
+
+---
+name:            const_i16_zext
+alignment:       1
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: const_i16_zext
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: RETURN [[C]](s32), implicit-def $arguments
+    %0:_(s16) = G_CONSTANT i16 65535
+    %1:_(s32) = G_ZEXT %0(s16)
+    RETURN %1(s32), implicit-def $arguments
+...
+
+---
+name:            const_i16_sext
+alignment:       1
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: const_i16_sext
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: RETURN [[C]](s32), implicit-def $arguments
+    %0:_(s16) = G_CONSTANT i16 65535
+    %1:_(s32) = G_SEXT %0(s16)
+    RETURN %1(s32), implicit-def $arguments
+...
+
+---
+name:            const_i16_aext
+alignment:       1
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: const_i16_aext
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: RETURN [[C]](s32), implicit-def $arguments
+    %0:_(s16) = G_CONSTANT i16 65535
+    %1:_(s32) = G_ANYEXT %0(s16)
+    RETURN %1(s32), implicit-def $arguments
+...
+
+---
+name:            const_i32
+alignment:       1
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: const_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: RETURN [[C]](s32), implicit-def $arguments
+    %0:_(s32) = G_CONSTANT i32 4294967295
+    RETURN %0(s32), implicit-def $arguments
+...
+
+---
+name:            const_i64
+alignment:       1
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: const_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
+    ; CHECK-NEXT: RETURN [[C]](s64), implicit-def $arguments
+    %0:_(s64) = G_CONSTANT i64 18446744073709551615
+    RETURN %0(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctlz.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctlz.mir
new file mode 100644
index 0000000000000..39e1531194711
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctlz.mir
@@ -0,0 +1,152 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: ctlz_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s32) = G_CTLZ [[AND]](s32)
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = nuw G_SUB [[CTLZ]], [[C1]]
+    ; CHECK-NEXT: RETURN [[SUB]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:_(s8) = G_CTLZ %0
+    %3:_(s32) = G_ANYEXT %2(s8)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: ctlz_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s32) = G_CTLZ [[AND]](s32)
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = nuw G_SUB [[CTLZ]], [[C1]]
+    ; CHECK-NEXT: RETURN [[SUB]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:_(s16) = G_CTLZ %0
+    %3:_(s32) = G_ANYEXT %2(s16)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: ctlz_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s32) = G_CTLZ [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTLZ]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CTLZ %0
+    RETURN %1(s32), implicit-def $arguments
+
+...
+---
+name: ctlz_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s32) = G_CTLZ [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTLZ]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s8) = G_CTLZ %0
+    %2:_(s32) = G_ANYEXT %1(s8)
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: ctlz_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[CTLZ]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CTLZ %0
+    RETURN %1(s64), implicit-def $arguments
+
+...
+---
+name: ctlz_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTLZ]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s8) = G_CTLZ %0
+    %2:_(s32) = G_ANYEXT %1(s8)
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: ctlz_i64_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_i64_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTLZ]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s32) = G_CTLZ %0
+    RETURN %1(s32), implicit-def $arguments
+
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctlz_zero_undef.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctlz_zero_undef.mir
new file mode 100644
index 0000000000000..045706eb22c14
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctlz_zero_undef.mir
@@ -0,0 +1,148 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: ctlz_zundef_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_zundef_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[SHL]](s32)
+    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:_(s8) = G_CTLZ_ZERO_UNDEF %0
+    %3:_(s32) = G_ANYEXT %2(s8)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: ctlz_zundef_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_zundef_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[SHL]](s32)
+    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:_(s16) = G_CTLZ_ZERO_UNDEF %0
+    %3:_(s32) = G_ANYEXT %2(s16)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: ctlz_zundef_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_zundef_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CTLZ_ZERO_UNDEF %0
+    RETURN %1(s32), implicit-def $arguments
+
+...
+---
+name: ctlz_zundef_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_zundef_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s8) = G_CTLZ_ZERO_UNDEF %0
+    %2:_(s32) = G_ANYEXT %1(s8)
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: ctlz_zundef_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_zundef_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CTLZ_ZERO_UNDEF %0
+    RETURN %1(s64), implicit-def $arguments
+
+...
+---
+name: ctlz_zundef_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_zundef_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTLZ_ZERO_UNDEF]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s8) = G_CTLZ_ZERO_UNDEF %0
+    %2:_(s32) = G_ANYEXT %1(s8)
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: ctlz_zundef_i64_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_zundef_i64_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTLZ_ZERO_UNDEF]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s32) = G_CTLZ_ZERO_UNDEF %0
+    RETURN %1(s32), implicit-def $arguments
+
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctpop.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctpop.mir
new file mode 100644
index 0000000000000..3dcbd10b40447
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctpop.mir
@@ -0,0 +1,148 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: ctpop_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctpop_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[CTPOP:%[0-9]+]]:_(s32) = G_CTPOP [[AND]](s32)
+    ; CHECK-NEXT: RETURN [[CTPOP]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:_(s8) = G_CTPOP %0
+    %3:_(s32) = G_ANYEXT %2(s8)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: ctpop_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctpop_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[CTPOP:%[0-9]+]]:_(s32) = G_CTPOP [[AND]](s32)
+    ; CHECK-NEXT: RETURN [[CTPOP]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:_(s16) = G_CTPOP %0
+    %3:_(s32) = G_ANYEXT %2(s16)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: ctpop_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctpop_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTPOP:%[0-9]+]]:_(s32) = G_CTPOP [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTPOP]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CTPOP %0
+    RETURN %1(s32), implicit-def $arguments
+
+...
+---
+name: ctpop_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctpop_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTPOP:%[0-9]+]]:_(s32) = G_CTPOP [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTPOP]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s8) = G_CTPOP %0
+    %2:_(s32) = G_ANYEXT %1(s8)
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: ctpop_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctpop_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTPOP:%[0-9]+]]:_(s64) = G_CTPOP [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[CTPOP]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CTPOP %0
+    RETURN %1(s64), implicit-def $arguments
+
+...
+---
+name: ctpop_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctpop_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTPOP:%[0-9]+]]:_(s64) = G_CTPOP [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTPOP]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s8) = G_CTPOP %0
+    %2:_(s32) = G_ANYEXT %1(s8)
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: ctpop_i64_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctpop_i64_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTPOP:%[0-9]+]]:_(s64) = G_CTPOP [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTPOP]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s32) = G_CTPOP %0
+    RETURN %1(s32), implicit-def $arguments
+
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz.mir
new file mode 100644
index 0000000000000..1d1d90b8420d6
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz.mir
@@ -0,0 +1,148 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: cttz_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 256
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[OR]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:_(s8) = G_CTTZ %0
+    %3:_(s32) = G_ANYEXT %2(s8)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: cttz_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65536
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[OR]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:_(s16) = G_CTTZ %0
+    %3:_(s32) = G_ANYEXT %2(s16)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: cttz_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s32) = G_CTTZ [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CTTZ %0
+    RETURN %1(s32), implicit-def $arguments
+
+...
+---
+name: cttz_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s32) = G_CTTZ [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s8) = G_CTTZ %0
+    %2:_(s32) = G_ANYEXT %1(s8)
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: cttz_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s64) = G_CTTZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[CTTZ]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CTTZ %0
+    RETURN %1(s64), implicit-def $arguments
+
+...
+---
+name: cttz_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s64) = G_CTTZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTTZ]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s8) = G_CTTZ %0
+    %2:_(s32) = G_ANYEXT %1(s8)
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: cttz_i64_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_i64_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s64) = G_CTTZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTTZ]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s32) = G_CTTZ %0
+    RETURN %1(s32), implicit-def $arguments
+
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz_zero_undef.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz_zero_undef.mir
new file mode 100644
index 0000000000000..adb0cab5879d0
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz_zero_undef.mir
@@ -0,0 +1,144 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: cttz_zundef_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_zundef_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:_(s8) = G_CTTZ_ZERO_UNDEF %0
+    %3:_(s32) = G_ANYEXT %2(s8)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: cttz_zundef_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_zundef_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:_(s16) = G_CTTZ_ZERO_UNDEF %0
+    %3:_(s32) = G_ANYEXT %2(s16)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: cttz_zundef_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_zundef_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CTTZ_ZERO_UNDEF %0
+    RETURN %1(s32), implicit-def $arguments
+
+...
+---
+name: cttz_zundef_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_zundef_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s8) = G_CTTZ_ZERO_UNDEF %0
+    %2:_(s32) = G_ANYEXT %1(s8)
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: cttz_zundef_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_zundef_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CTTZ_ZERO_UNDEF %0
+    RETURN %1(s64), implicit-def $arguments
+
+...
+---
+name: cttz_zundef_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_zundef_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTTZ_ZERO_UNDEF]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s8) = G_CTTZ_ZERO_UNDEF %0
+    %2:_(s32) = G_ANYEXT %1(s8)
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: cttz_zundef_i64_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_zundef_i64_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTTZ_ZERO_UNDEF]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s32) = G_CTTZ_ZERO_UNDEF %0
+    RETURN %1(s32), implicit-def $arguments
+
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/fshl.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/fshl.mir
new file mode 100644
index 0000000000000..3aa32c39ee15f
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/fshl.mir
@@ -0,0 +1,393 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: fshl_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshl_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C2]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[C1]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_CONSTANT i8 5
+    %5:_(s8) = G_FSHL %0, %1, %4(s8)
+    %6:_(s32) = G_ANYEXT %5(s8)
+    RETURN %6(s32), implicit-def $arguments
+
+...
+---
+name: fshlv_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshlv_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_2:%[0-9]+]]:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 7
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_2]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_2]], [[C1]]
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[XOR]], [[C]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[AND]](s32)
+    ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C3]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND2]], [[C2]](s32)
+    ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[LSHR]], [[C4]]
+    ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(s32) = G_LSHR [[AND3]], [[AND1]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR1]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %3:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %3(s32)
+    %4:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %4(s32)
+    %5:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    %2:_(s8) = G_TRUNC %5(s32)
+    %6:_(s8) = G_FSHL %0, %1, %2(s8)
+    %7:_(s32) = G_ANYEXT %6(s8)
+    RETURN %7(s32), implicit-def $arguments
+
+...
+---
+name: fshl_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshl_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 13
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C2]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[C1]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_CONSTANT i16 13
+    %5:_(s16) = G_FSHL %0, %1, %4(s16)
+    %6:_(s32) = G_ANYEXT %5(s16)
+    RETURN %6(s32), implicit-def $arguments
+
+...
+---
+name: fshlv_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshlv_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_2:%[0-9]+]]:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 15
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_2]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_2]], [[C1]]
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[XOR]], [[C]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[AND]](s32)
+    ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C3]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND2]], [[C2]](s32)
+    ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND3:%[0-9]+]]:_(s32) = G_AND [[LSHR]], [[C4]]
+    ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(s32) = G_LSHR [[AND3]], [[AND1]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR1]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %3:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %3(s32)
+    %4:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %4(s32)
+    %5:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    %2:_(s16) = G_TRUNC %5(s32)
+    %6:_(s16) = G_FSHL %0, %1, %2(s16)
+    %7:_(s32) = G_ANYEXT %6(s16)
+    RETURN %7(s32), implicit-def $arguments
+
+...
+---
+name: fshl_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshl_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 11
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ARGUMENT_i32_1]], [[C1]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_CONSTANT i32 21
+    %3:_(s32) = G_FSHL %0, %1, %2(s32)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: fshlv_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshlv_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_2:%[0-9]+]]:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_2]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_2]], [[C1]]
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[XOR]], [[C]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[AND]](s32)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ARGUMENT_i32_1]], [[C2]](s32)
+    ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(s32) = G_LSHR [[LSHR]], [[AND1]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR1]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    %3:_(s32) = G_FSHL %0, %1, %2(s32)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: fshl_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshl_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 11
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ARGUMENT_i32_1]], [[C1]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s8) = G_CONSTANT i8 21
+    %3:_(s32) = G_FSHL %0, %1, %2(s8)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: fshlv_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshlv_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_2:%[0-9]+]]:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_2]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_2]], [[C1]]
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[XOR]], [[C]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[AND]](s32)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ARGUMENT_i32_1]], [[C2]](s32)
+    ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(s32) = G_LSHR [[LSHR]], [[AND1]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR1]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %3:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    %2:_(s8) = G_TRUNC %3(s32)
+    %4:_(s32) = G_FSHL %0, %1, %2(s8)
+    RETURN %4(s32), implicit-def $arguments
+
+...
+---
+name: fshl_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshl_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 37
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 27
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ARGUMENT_i64_]], [[C]](s64)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ARGUMENT_i64_1]], [[C1]](s64)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_CONSTANT i64 37
+    %3:_(s64) = G_FSHL %0, %1, %2(s64)
+    RETURN %3(s64), implicit-def $arguments
+
+...
+---
+name: fshlv_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshlv_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_2:%[0-9]+]]:i64(s64) = ARGUMENT_i64 2, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 63
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[ARGUMENT_i64_2]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s64) = G_XOR [[ARGUMENT_i64_2]], [[C1]]
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s64) = G_AND [[XOR]], [[C]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ARGUMENT_i64_]], [[AND]](s64)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ARGUMENT_i64_1]], [[C2]](s64)
+    ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(s64) = G_LSHR [[LSHR]], [[AND1]](s64)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = disjoint G_OR [[SHL]], [[LSHR1]]
+    ; CHECK-NEXT: RETURN [[OR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:i64(s64) = ARGUMENT_i64 2, implicit $arguments
+    %3:_(s64) = G_FSHL %0, %1, %2(s64)
+    RETURN %3(s64), implicit-def $arguments
+
+...
+---
+name: fshl_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshl_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 21
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[C]], [[C1]]
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ARGUMENT_i64_]], [[AND]](s64)
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 43
+    ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s64) = G_AND [[C2]], [[C3]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ARGUMENT_i64_1]], [[AND1]](s64)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s8) = G_CONSTANT i8 21
+    %3:_(s64) = G_FSHL %0, %1, %2(s8)
+    RETURN %3(s64), implicit-def $arguments
+
+...
+---
+name: fshlv_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshlv_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 63
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_]], [[C1]]
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[XOR]], [[C]]
+    ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[AND]](s32)
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C2]]
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ARGUMENT_i64_]], [[AND2]](s64)
+    ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+    ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND3:%[0-9]+]]:_(s64) = G_AND [[C3]], [[C4]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ARGUMENT_i64_1]], [[AND3]](s64)
+    ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s64) = G_ANYEXT [[AND1]](s32)
+    ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND4:%[0-9]+]]:_(s64) = G_AND [[ANYEXT1]], [[C5]]
+    ; CHECK-NEXT: [[LSHR1:%[0-9]+]]:_(s64) = G_LSHR [[LSHR]], [[AND4]](s64)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = disjoint G_OR [[SHL]], [[LSHR1]]
+    ; CHECK-NEXT: RETURN [[OR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %3:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    %2:_(s8) = G_TRUNC %3(s32)
+    %4:_(s64) = G_FSHL %0, %1, %2(s8)
+    RETURN %4(s64), implicit-def $arguments
+
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/fshr.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/fshr.mir
new file mode 100644
index 0000000000000..0437c51d310c9
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/fshr.mir
@@ -0,0 +1,389 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: fshr_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshr_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C1]](s32)
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C2]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[C]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_CONSTANT i8 5
+    %5:_(s8) = G_FSHR %0, %1, %4(s8)
+    %6:_(s32) = G_ANYEXT %5(s8)
+    RETURN %6(s32), implicit-def $arguments
+
+...
+---
+name: fshrv_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshrv_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_2:%[0-9]+]]:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 7
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_2]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_2]], [[C1]]
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[XOR]], [[C]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C2]](s32)
+    ; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[SHL]], [[AND1]](s32)
+    ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C3]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND2]], [[AND]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL1]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %3:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %3(s32)
+    %4:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %4(s32)
+    %5:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    %2:_(s8) = G_TRUNC %5(s32)
+    %6:_(s8) = G_FSHR %0, %1, %2(s8)
+    %7:_(s32) = G_ANYEXT %6(s8)
+    RETURN %7(s32), implicit-def $arguments
+
+...
+---
+name: fshr_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshr_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 13
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C1]](s32)
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C2]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[C]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_CONSTANT i16 13
+    %5:_(s16) = G_FSHR %0, %1, %4(s16)
+    %6:_(s32) = G_ANYEXT %5(s16)
+    RETURN %6(s32), implicit-def $arguments
+
+...
+---
+name: fshrv_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshrv_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_2:%[0-9]+]]:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 15
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_2]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_2]], [[C1]]
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[XOR]], [[C]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C2]](s32)
+    ; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[SHL]], [[AND1]](s32)
+    ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C3]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND2]], [[AND]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL1]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %3:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %3(s32)
+    %4:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %4(s32)
+    %5:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    %2:_(s16) = G_TRUNC %5(s32)
+    %6:_(s16) = G_FSHR %0, %1, %2(s16)
+    %7:_(s32) = G_ANYEXT %6(s16)
+    RETURN %7(s32), implicit-def $arguments
+
+...
+---
+name: fshr_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshr_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 11
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C1]](s32)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ARGUMENT_i32_1]], [[C]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_CONSTANT i32 21
+    %3:_(s32) = G_FSHR %0, %1, %2(s32)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: fshrv_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshrv_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_2:%[0-9]+]]:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_2]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_2]], [[C1]]
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[XOR]], [[C]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C2]](s32)
+    ; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[SHL]], [[AND1]](s32)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ARGUMENT_i32_1]], [[AND]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL1]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    %3:_(s32) = G_FSHR %0, %1, %2(s32)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: fshr_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshr_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 11
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C1]](s32)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ARGUMENT_i32_1]], [[C]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s8) = G_CONSTANT i8 21
+    %3:_(s32) = G_FSHR %0, %1, %2(s8)
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: fshrv_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshrv_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_2:%[0-9]+]]:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_2]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_2]], [[C1]]
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[XOR]], [[C]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 1
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C2]](s32)
+    ; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[SHL]], [[AND1]](s32)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ARGUMENT_i32_1]], [[AND]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL1]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %3:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    %2:_(s8) = G_TRUNC %3(s32)
+    %4:_(s32) = G_FSHR %0, %1, %2(s8)
+    RETURN %4(s32), implicit-def $arguments
+
+...
+---
+name: fshr_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshr_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 37
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 27
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ARGUMENT_i64_]], [[C1]](s64)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ARGUMENT_i64_1]], [[C]](s64)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_CONSTANT i64 37
+    %3:_(s64) = G_FSHR %0, %1, %2(s64)
+    RETURN %3(s64), implicit-def $arguments
+
+...
+---
+name: fshrv_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshrv_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_2:%[0-9]+]]:i64(s64) = ARGUMENT_i64 2, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 63
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[ARGUMENT_i64_2]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 -1
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s64) = G_XOR [[ARGUMENT_i64_2]], [[C1]]
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s64) = G_AND [[XOR]], [[C]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ARGUMENT_i64_]], [[C2]](s64)
+    ; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s64) = G_SHL [[SHL]], [[AND1]](s64)
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ARGUMENT_i64_1]], [[AND]](s64)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = disjoint G_OR [[SHL1]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:i64(s64) = ARGUMENT_i64 2, implicit $arguments
+    %3:_(s64) = G_FSHR %0, %1, %2(s64)
+    RETURN %3(s64), implicit-def $arguments
+
+...
+---
+name: fshr_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshr_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 43
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[C]], [[C1]]
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ARGUMENT_i64_]], [[AND]](s64)
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 21
+    ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s64) = G_AND [[C2]], [[C3]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ARGUMENT_i64_1]], [[AND1]](s64)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s8) = G_CONSTANT i8 21
+    %3:_(s64) = G_FSHR %0, %1, %2(s8)
+    RETURN %3(s64), implicit-def $arguments
+
+...
+---
+name: fshrv_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: fshrv_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 63
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 -1
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_]], [[C1]]
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[XOR]], [[C]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s64) = G_CONSTANT i64 1
+    ; CHECK-NEXT: [[C3:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s64) = G_AND [[C2]], [[C3]]
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ARGUMENT_i64_]], [[AND2]](s64)
+    ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[AND1]](s32)
+    ; CHECK-NEXT: [[C4:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND3:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C4]]
+    ; CHECK-NEXT: [[SHL1:%[0-9]+]]:_(s64) = G_SHL [[SHL]], [[AND3]](s64)
+    ; CHECK-NEXT: [[ANYEXT1:%[0-9]+]]:_(s64) = G_ANYEXT [[AND]](s32)
+    ; CHECK-NEXT: [[C5:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND4:%[0-9]+]]:_(s64) = G_AND [[ANYEXT1]], [[C5]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ARGUMENT_i64_1]], [[AND4]](s64)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = disjoint G_OR [[SHL1]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %3:i32(s32) = ARGUMENT_i32 2, implicit $arguments
+    %2:_(s8) = G_TRUNC %3(s32)
+    %4:_(s64) = G_FSHR %0, %1, %2(s8)
+    RETURN %4(s64), implicit-def $arguments
+
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/implicit_def.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/implicit_def.mir
new file mode 100644
index 0000000000000..4b6685214a963
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/implicit_def.mir
@@ -0,0 +1,72 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name:            implicit_def_i8
+alignment:       1
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: implicit_def_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
+    ; CHECK-NEXT: RETURN [[DEF]](s32), implicit-def $arguments
+    %0:_(s8) = G_IMPLICIT_DEF
+    %1:_(s32) = G_ANYEXT %0(s8)
+    RETURN %1(s32), implicit-def $arguments
+...
+
+---
+name:            implicit_def_i16
+alignment:       1
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: implicit_def_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
+    ; CHECK-NEXT: RETURN [[DEF]](s32), implicit-def $arguments
+    %0:_(s16) = G_IMPLICIT_DEF
+    %1:_(s32) = G_ANYEXT %0(s16)
+    RETURN %1(s32), implicit-def $arguments
+...
+
+---
+name:            implicit_def_i32
+alignment:       1
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: implicit_def_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s32) = G_IMPLICIT_DEF
+    ; CHECK-NEXT: RETURN [[DEF]](s32), implicit-def $arguments
+    %0:_(s32) = G_IMPLICIT_DEF
+    RETURN %0(s32), implicit-def $arguments
+...
+
+---
+name:            implicit_def_i64
+alignment:       1
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: implicit_def_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[DEF:%[0-9]+]]:_(s64) = G_IMPLICIT_DEF
+    ; CHECK-NEXT: RETURN [[DEF]](s64), implicit-def $arguments
+    %0:_(s64) = G_IMPLICIT_DEF
+    RETURN %0(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/lshr.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/lshr.mir
new file mode 100644
index 0000000000000..f8150c9cfd7a4
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/lshr.mir
@@ -0,0 +1,286 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: lshr_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshr_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C1]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[LSHR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %1:_(s8) = G_CONSTANT i8 5
+    %3:_(s8) = G_LSHR %0, %1
+    %4:_(s32) = G_ANYEXT %3(s8)
+    RETURN %4(s32), implicit-def $arguments
+
+...
+---
+name: lshrv_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshrv_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C1]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[AND1]](s32)
+    ; CHECK-NEXT: RETURN [[LSHR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_LSHR %0, %1
+    %5:_(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: lshr_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshr_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 13
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C1]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[LSHR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %1:_(s16) = G_CONSTANT i16 13
+    %3:_(s16) = G_LSHR %0, %1
+    %4:_(s32) = G_ANYEXT %3(s16)
+    RETURN %4(s32), implicit-def $arguments
+
+...
+---
+name: lshrv_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshrv_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C1]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[AND1]](s32)
+    ; CHECK-NEXT: RETURN [[LSHR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_LSHR %0, %1
+    %5:_(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: lshr_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshr_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[LSHR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CONSTANT i32 21
+    %2:_(s32) = G_LSHR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: lshrv_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshrv_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]](s32)
+    ; CHECK-NEXT: RETURN [[LSHR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_LSHR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: lshr_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshr_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[LSHR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s8) = G_CONSTANT i8 21
+    %2:_(s32) = G_LSHR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: lshrv_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshrv_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[ARGUMENT_i32_]], [[AND]](s32)
+    ; CHECK-NEXT: RETURN [[LSHR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %2:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %2(s32)
+    %3:_(s32) = G_LSHR %0, %1
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: lshr_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshr_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 37
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ARGUMENT_i64_]], [[C]](s64)
+    ; CHECK-NEXT: RETURN [[LSHR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CONSTANT i64 37
+    %2:_(s64) = G_LSHR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: lshrv_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshrv_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]](s64)
+    ; CHECK-NEXT: RETURN [[LSHR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_LSHR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: lshr_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshr_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 37
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[C]], [[C1]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ARGUMENT_i64_]], [[AND]](s64)
+    ; CHECK-NEXT: RETURN [[LSHR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s8) = G_CONSTANT i8 37
+    %2:_(s64) = G_LSHR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: lshrv_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshrv_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s64) = G_LSHR [[ARGUMENT_i64_]], [[AND]](s64)
+    ; CHECK-NEXT: RETURN [[LSHR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %2:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %2(s32)
+    %3:_(s64) = G_LSHR %0, %1
+    RETURN %3(s64), implicit-def $arguments
+
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/mul.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/mul.mir
new file mode 100644
index 0000000000000..537d8f9fcf52d
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/mul.mir
@@ -0,0 +1,91 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: mul_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: mul_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[MUL]](s32)
+    ; CHECK-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_MUL %0, %1
+    %5:i32(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+...
+---
+name: mul_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: mul_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[MUL]](s32)
+    ; CHECK-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_MUL %0, %1
+    %5:i32(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+...
+---
+name: mul_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: mul_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s32) = G_MUL [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[MUL]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_MUL %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: mul_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: mul_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:_(s64) = G_MUL [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[MUL]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_MUL %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/or.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/or.mir
new file mode 100644
index 0000000000000..d86bd04d2e455
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/or.mir
@@ -0,0 +1,117 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: or_i1
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: or_i1
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[ARGUMENT_i32_1]], [[ARGUMENT_i32_]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s1) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s1) = G_TRUNC %3(s32)
+    %4:_(s1) = G_OR %1, %0
+    %5:_(s32) = G_ANYEXT %4(s1)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: or_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: or_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[ARGUMENT_i32_1]], [[ARGUMENT_i32_]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_OR %1, %0
+    %5:_(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: or_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: or_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[ARGUMENT_i32_1]], [[ARGUMENT_i32_]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_OR %1, %0
+    %5:_(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: or_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: or_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[ARGUMENT_i32_1]], [[ARGUMENT_i32_]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_OR %1, %0
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: or_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: or_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s64) = G_OR [[ARGUMENT_i64_1]], [[ARGUMENT_i64_]]
+    ; CHECK-NEXT: RETURN [[OR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_OR %1, %0
+    RETURN %2(s64), implicit-def $arguments
+
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/rotl.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/rotl.mir
new file mode 100644
index 0000000000000..82c1bcf76ae5b
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/rotl.mir
@@ -0,0 +1,303 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+
+---
+name: rotl_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotl_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C2]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[C1]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %1:_(s8) = G_CONSTANT i8 5
+    %3:_(s8) = G_ROTL %0, %1
+    %4:_(s32) = G_ANYEXT %3(s8)
+    RETURN %4(s32), implicit-def $arguments
+
+...
+---
+name: rotlv_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotlv_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 7
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C1]]
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[AND]](s32)
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[SUB]], [[C1]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C2]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND2]], [[AND1]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_ROTL %0, %1
+    %5:_(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: rotl_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotl_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 13
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C2]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[C1]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %1:_(s16) = G_CONSTANT i16 13
+    %3:_(s16) = G_ROTL %0, %1
+    %4:_(s32) = G_ANYEXT %3(s16)
+    RETURN %4(s32), implicit-def $arguments
+
+...
+---
+name: rotlv_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotlv_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 15
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C1]]
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[AND]](s32)
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[SUB]], [[C1]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C2]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND2]], [[AND1]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[SHL]], [[LSHR]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_ROTL %0, %1
+    %5:_(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: rotl_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotl_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[ROTL:%[0-9]+]]:_(s32) = G_ROTL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[ROTL]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CONSTANT i32 21
+    %2:_(s32) = G_ROTL %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: rotlv_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotlv_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ROTL:%[0-9]+]]:_(s32) = G_ROTL [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]](s32)
+    ; CHECK-NEXT: RETURN [[ROTL]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_ROTL %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: rotl_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotl_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[ROTL:%[0-9]+]]:_(s32) = G_ROTL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[ROTL]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s8) = G_CONSTANT i8 21
+    %2:_(s32) = G_ROTL %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: rotlv_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotlv_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C]]
+    ; CHECK-NEXT: [[ROTL:%[0-9]+]]:_(s32) = G_ROTL [[ARGUMENT_i32_]], [[AND]](s32)
+    ; CHECK-NEXT: RETURN [[ROTL]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %2:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %2(s32)
+    %3:_(s32) = G_ROTL %0, %1
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: rotl_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotl_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 37
+    ; CHECK-NEXT: [[ROTL:%[0-9]+]]:_(s64) = G_ROTL [[ARGUMENT_i64_]], [[C]](s64)
+    ; CHECK-NEXT: RETURN [[ROTL]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CONSTANT i64 37
+    %2:_(s64) = G_ROTL %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: rotlv_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotlv_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[ROTL:%[0-9]+]]:_(s64) = G_ROTL [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]](s64)
+    ; CHECK-NEXT: RETURN [[ROTL]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_ROTL %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: rotl_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotl_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 37
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[C]], [[C1]]
+    ; CHECK-NEXT: [[ROTL:%[0-9]+]]:_(s64) = G_ROTL [[ARGUMENT_i64_]], [[AND]](s64)
+    ; CHECK-NEXT: RETURN [[ROTL]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s8) = G_CONSTANT i8 37
+    %2:_(s64) = G_ROTL %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: rotlv_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotlv_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C]]
+    ; CHECK-NEXT: [[ROTL:%[0-9]+]]:_(s64) = G_ROTL [[ARGUMENT_i64_]], [[AND]](s64)
+    ; CHECK-NEXT: RETURN [[ROTL]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %2:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %2(s32)
+    %3:_(s64) = G_ROTL %0, %1
+    RETURN %3(s64), implicit-def $arguments
+
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/rotr.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/rotr.mir
new file mode 100644
index 0000000000000..e8fc7e5db324e
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/rotr.mir
@@ -0,0 +1,303 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+
+---
+name: rotr_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotr_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C1]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[C]](s32)
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C2]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[LSHR]], [[SHL]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %1:_(s8) = G_CONSTANT i8 5
+    %3:_(s8) = G_ROTR %0, %1
+    %4:_(s32) = G_ANYEXT %3(s8)
+    RETURN %4(s32), implicit-def $arguments
+
+...
+---
+name: rotrv_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotrv_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 7
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C1]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C2]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND1]], [[AND]](s32)
+    ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[SUB]], [[C1]]
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[AND2]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[LSHR]], [[SHL]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_ROTR %0, %1
+    %5:_(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: rotr_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotr_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 13
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C1]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND]], [[C]](s32)
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 3
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C2]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[LSHR]], [[SHL]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %1:_(s16) = G_CONSTANT i16 13
+    %3:_(s16) = G_ROTR %0, %1
+    %4:_(s32) = G_ANYEXT %3(s16)
+    RETURN %4(s32), implicit-def $arguments
+
+...
+---
+name: rotrv_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotrv_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 0
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 15
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[C]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C1]]
+    ; CHECK-NEXT: [[C2:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C2]]
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:_(s32) = G_LSHR [[AND1]], [[AND]](s32)
+    ; CHECK-NEXT: [[AND2:%[0-9]+]]:_(s32) = G_AND [[SUB]], [[C1]]
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[AND2]](s32)
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = disjoint G_OR [[LSHR]], [[SHL]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_ROTR %0, %1
+    %5:_(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: rotr_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotr_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[ROTR:%[0-9]+]]:_(s32) = G_ROTR [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[ROTR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CONSTANT i32 21
+    %2:_(s32) = G_ROTR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: rotrv_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotrv_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ROTR:%[0-9]+]]:_(s32) = G_ROTR [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]](s32)
+    ; CHECK-NEXT: RETURN [[ROTR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_ROTR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: rotr_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotr_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[ROTR:%[0-9]+]]:_(s32) = G_ROTR [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[ROTR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s8) = G_CONSTANT i8 21
+    %2:_(s32) = G_ROTR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: rotrv_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotrv_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C]]
+    ; CHECK-NEXT: [[ROTR:%[0-9]+]]:_(s32) = G_ROTR [[ARGUMENT_i32_]], [[AND]](s32)
+    ; CHECK-NEXT: RETURN [[ROTR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %2:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %2(s32)
+    %3:_(s32) = G_ROTR %0, %1
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: rotr_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotr_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 37
+    ; CHECK-NEXT: [[ROTR:%[0-9]+]]:_(s64) = G_ROTR [[ARGUMENT_i64_]], [[C]](s64)
+    ; CHECK-NEXT: RETURN [[ROTR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CONSTANT i64 37
+    %2:_(s64) = G_ROTR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: rotrv_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotrv_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[ROTR:%[0-9]+]]:_(s64) = G_ROTR [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]](s64)
+    ; CHECK-NEXT: RETURN [[ROTR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_ROTR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: rotr_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotr_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 37
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[C]], [[C1]]
+    ; CHECK-NEXT: [[ROTR:%[0-9]+]]:_(s64) = G_ROTR [[ARGUMENT_i64_]], [[AND]](s64)
+    ; CHECK-NEXT: RETURN [[ROTR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s8) = G_CONSTANT i8 37
+    %2:_(s64) = G_ROTR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: rotrv_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotrv_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C]]
+    ; CHECK-NEXT: [[ROTR:%[0-9]+]]:_(s64) = G_ROTR [[ARGUMENT_i64_]], [[AND]](s64)
+    ; CHECK-NEXT: RETURN [[ROTR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %2:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %2(s32)
+    %3:_(s64) = G_ROTR %0, %1
+    RETURN %3(s64), implicit-def $arguments
+
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sdiv.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sdiv.mir
new file mode 100644
index 0000000000000..e7d3581e1c1b7
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sdiv.mir
@@ -0,0 +1,126 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -mattr=-sign-ext -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,NO-SIGNEXT
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -mattr=+sign-ext -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,SIGNEXT
+
+---
+name: sdiv_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: sdiv_i8
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; NO-SIGNEXT-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_1]], [[C1]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]](s32)
+    ; NO-SIGNEXT-NEXT: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[ASHR]], [[ASHR1]]
+    ; NO-SIGNEXT-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[SDIV]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: sdiv_i8
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[ARGUMENT_i32_]], 8
+    ; SIGNEXT-NEXT: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[ARGUMENT_i32_1]], 8
+    ; SIGNEXT-NEXT: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[SEXT_INREG]], [[SEXT_INREG1]]
+    ; SIGNEXT-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[SDIV]](s32)
+    ; SIGNEXT-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_SDIV %0, %1
+    %5:i32(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+...
+---
+name: sdiv_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: sdiv_i16
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; NO-SIGNEXT-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_1]], [[C1]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]](s32)
+    ; NO-SIGNEXT-NEXT: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[ASHR]], [[ASHR1]]
+    ; NO-SIGNEXT-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[SDIV]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: sdiv_i16
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[ARGUMENT_i32_]], 16
+    ; SIGNEXT-NEXT: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[ARGUMENT_i32_1]], 16
+    ; SIGNEXT-NEXT: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[SEXT_INREG]], [[SEXT_INREG1]]
+    ; SIGNEXT-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[SDIV]](s32)
+    ; SIGNEXT-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_SDIV %0, %1
+    %5:i32(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+...
+---
+name: sdiv_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sdiv_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[SDIV:%[0-9]+]]:_(s32) = G_SDIV [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[SDIV]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_SDIV %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: sdiv_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sdiv_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[SDIV:%[0-9]+]]:_(s64) = G_SDIV [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[SDIV]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_SDIV %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sext.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sext.mir
new file mode 100644
index 0000000000000..6b443b1f91e82
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sext.mir
@@ -0,0 +1,138 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -mattr=-sign-ext -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,NO-SIGNEXT
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -mattr=+sign-ext -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,SIGNEXT
+
+---
+name: sext_i8_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: sext_i8_i32
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:i32(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: sext_i8_i32
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:i32(s32) = G_SEXT_INREG [[ARGUMENT_i32_]], 8
+    ; SIGNEXT-NEXT: RETURN [[SEXT_INREG]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:i32(s32) = G_SEXT %0(s8)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: sext_i8_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: sext_i8_i64
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 56
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ANYEXT]], [[C]](s64)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:i32(s64) = G_ASHR [[SHL]], [[C]](s64)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR]](s64), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: sext_i8_i64
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:i32(s64) = G_SEXT_INREG [[ANYEXT]], 8
+    ; SIGNEXT-NEXT: RETURN [[SEXT_INREG]](s64), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:i32(s64) = G_SEXT %0(s8)
+    RETURN %2(s64), implicit-def $arguments
+...
+---
+name: sext_i16_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: sext_i16_i32
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:i32(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: sext_i16_i32
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:i32(s32) = G_SEXT_INREG [[ARGUMENT_i32_]], 16
+    ; SIGNEXT-NEXT: RETURN [[SEXT_INREG]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:i32(s32) = G_SEXT %0(s16)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: sext_i16_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: sext_i16_i64
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 48
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ANYEXT]], [[C]](s64)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:i32(s64) = G_ASHR [[SHL]], [[C]](s64)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR]](s64), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: sext_i16_i64
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:i32(s64) = G_SEXT_INREG [[ANYEXT]], 16
+    ; SIGNEXT-NEXT: RETURN [[SEXT_INREG]](s64), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:i32(s64) = G_SEXT %0(s16)
+    RETURN %2(s64), implicit-def $arguments
+...
+---
+name: sext_i32_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext_i32_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[SEXT:%[0-9]+]]:i32(s64) = G_SEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[SEXT]](s64), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s64) = G_SEXT %0(s32)
+    RETURN %1(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sext_inreg.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sext_inreg.mir
new file mode 100644
index 0000000000000..2d5daf7b906f3
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sext_inreg.mir
@@ -0,0 +1,181 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -mattr=-sign-ext -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,NO-SIGNEXT
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -mattr=+sign-ext -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,SIGNEXT
+
+---
+name: sext_inreg_i1_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext_inreg_i1_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 31
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL %1, [[C]](s32)
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_SEXT_INREG %1(s32), 1
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name: sext_inreg_i8_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: sext_inreg_i8_i32
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL %1, [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: sext_inreg_i8_i32
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[SEXT_INREG]], 8
+    ; SIGNEXT-NEXT: RETURN [[SEXT_INREG]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_SEXT_INREG %1(s32), 8
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name: sext_inreg_i16_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: sext_inreg_i16_i32
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL %1, [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: sext_inreg_i16_i32
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[SEXT_INREG]], 16
+    ; SIGNEXT-NEXT: RETURN [[SEXT_INREG]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_SEXT_INREG %1(s32), 16
+    RETURN %1(s32), implicit-def $arguments
+...
+
+---
+name: sext_inreg_i1_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext_inreg_i1_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 63
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL %1, [[C]](s64)
+    ; CHECK-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[SHL]], [[C]](s64)
+    ; CHECK-NEXT: RETURN [[ASHR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_SEXT_INREG %1(s64), 1
+    RETURN %1(s64), implicit-def $arguments
+...
+---
+name: sext_inreg_i8_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: sext_inreg_i8_i64
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 56
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL %1, [[C]](s64)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[SHL]], [[C]](s64)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR]](s64), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: sext_inreg_i8_i64
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[SEXT_INREG]], 8
+    ; SIGNEXT-NEXT: RETURN [[SEXT_INREG]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_SEXT_INREG %1(s64), 8
+    RETURN %1(s64), implicit-def $arguments
+...
+---
+name: sext_inreg_i16_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: sext_inreg_i16_i64
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 48
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL %1, [[C]](s64)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[SHL]], [[C]](s64)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR]](s64), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: sext_inreg_i16_i64
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[SEXT_INREG]], 16
+    ; SIGNEXT-NEXT: RETURN [[SEXT_INREG]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_SEXT_INREG %1(s64), 16
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name: sext_inreg_i32_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: sext_inreg_i32_i64
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 32
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL %1, [[C]](s64)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s64) = G_ASHR [[SHL]], [[C]](s64)
+    ; NO-SIGNEXT-NEXT: RETURN [[ASHR]](s64), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: sext_inreg_i32_i64
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s64) = G_SEXT_INREG [[SEXT_INREG]], 32
+    ; SIGNEXT-NEXT: RETURN [[SEXT_INREG]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_SEXT_INREG %1(s64), 32
+    RETURN %1(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/shl.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/shl.mir
new file mode 100644
index 0000000000000..25c75c551a1e7
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/shl.mir
@@ -0,0 +1,278 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: shl_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: shl_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 5
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[SHL]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %1:_(s8) = G_CONSTANT i8 5
+    %3:_(s8) = G_SHL %0, %1
+    %4:_(s32) = G_ANYEXT %3(s8)
+    RETURN %4(s32), implicit-def $arguments
+
+...
+---
+name: shlv_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: shlv_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C]]
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[AND]](s32)
+    ; CHECK-NEXT: RETURN [[SHL]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_SHL %0, %1
+    %5:_(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: shl_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: shl_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 13
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[SHL]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %1:_(s16) = G_CONSTANT i16 13
+    %3:_(s16) = G_SHL %0, %1
+    %4:_(s32) = G_ANYEXT %3(s16)
+    RETURN %4(s32), implicit-def $arguments
+
+...
+---
+name: shlv_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: shlv_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C]]
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[AND]](s32)
+    ; CHECK-NEXT: RETURN [[SHL]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_SHL %0, %1
+    %5:_(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: shl_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: shl_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[SHL]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CONSTANT i32 21
+    %2:_(s32) = G_SHL %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: shlv_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: shlv_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]](s32)
+    ; CHECK-NEXT: RETURN [[SHL]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_SHL %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: shl_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: shl_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 21
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[SHL]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s8) = G_CONSTANT i8 21
+    %2:_(s32) = G_SHL %0, %1
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: shlv_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: shlv_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C]]
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[AND]](s32)
+    ; CHECK-NEXT: RETURN [[SHL]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %2:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %2(s32)
+    %3:_(s32) = G_SHL %0, %1
+    RETURN %3(s32), implicit-def $arguments
+
+...
+---
+name: shl_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: shl_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 37
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ARGUMENT_i64_]], [[C]](s64)
+    ; CHECK-NEXT: RETURN [[SHL]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CONSTANT i64 37
+    %2:_(s64) = G_SHL %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: shlv_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: shlv_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]](s64)
+    ; CHECK-NEXT: RETURN [[SHL]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_SHL %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: shl_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: shl_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 37
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[C]], [[C1]]
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ARGUMENT_i64_]], [[AND]](s64)
+    ; CHECK-NEXT: RETURN [[SHL]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s8) = G_CONSTANT i8 37
+    %2:_(s64) = G_SHL %0, %1
+    RETURN %2(s64), implicit-def $arguments
+
+...
+---
+name: shlv_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: shlv_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s64) = G_AND [[ANYEXT]], [[C]]
+    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s64) = G_SHL [[ARGUMENT_i64_]], [[AND]](s64)
+    ; CHECK-NEXT: RETURN [[SHL]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %2:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %2(s32)
+    %3:_(s64) = G_SHL %0, %1
+    RETURN %3(s64), implicit-def $arguments
+
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/srem.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/srem.mir
new file mode 100644
index 0000000000000..e6d9d2c5bad2d
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/srem.mir
@@ -0,0 +1,126 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -mattr=-sign-ext -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,NO-SIGNEXT
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -mattr=+sign-ext -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s -check-prefixes=CHECK,SIGNEXT
+
+---
+name: srem_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: srem_i8
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; NO-SIGNEXT-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_1]], [[C1]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]](s32)
+    ; NO-SIGNEXT-NEXT: [[SREM:%[0-9]+]]:_(s32) = G_SREM [[ASHR]], [[ASHR1]]
+    ; NO-SIGNEXT-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[SREM]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: srem_i8
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[ARGUMENT_i32_]], 8
+    ; SIGNEXT-NEXT: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[ARGUMENT_i32_1]], 8
+    ; SIGNEXT-NEXT: [[SREM:%[0-9]+]]:_(s32) = G_SREM [[SEXT_INREG]], [[SEXT_INREG1]]
+    ; SIGNEXT-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[SREM]](s32)
+    ; SIGNEXT-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_SREM %0, %1
+    %5:i32(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+...
+---
+name: srem_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; NO-SIGNEXT-LABEL: name: srem_i16
+    ; NO-SIGNEXT: liveins: $arguments
+    ; NO-SIGNEXT-NEXT: {{  $}}
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; NO-SIGNEXT-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; NO-SIGNEXT-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR:%[0-9]+]]:_(s32) = G_ASHR [[SHL]], [[C]](s32)
+    ; NO-SIGNEXT-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; NO-SIGNEXT-NEXT: [[SHL1:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_1]], [[C1]](s32)
+    ; NO-SIGNEXT-NEXT: [[ASHR1:%[0-9]+]]:_(s32) = G_ASHR [[SHL1]], [[C1]](s32)
+    ; NO-SIGNEXT-NEXT: [[SREM:%[0-9]+]]:_(s32) = G_SREM [[ASHR]], [[ASHR1]]
+    ; NO-SIGNEXT-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[SREM]](s32)
+    ; NO-SIGNEXT-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    ;
+    ; SIGNEXT-LABEL: name: srem_i16
+    ; SIGNEXT: liveins: $arguments
+    ; SIGNEXT-NEXT: {{  $}}
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; SIGNEXT-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; SIGNEXT-NEXT: [[SEXT_INREG:%[0-9]+]]:_(s32) = G_SEXT_INREG [[ARGUMENT_i32_]], 16
+    ; SIGNEXT-NEXT: [[SEXT_INREG1:%[0-9]+]]:_(s32) = G_SEXT_INREG [[ARGUMENT_i32_1]], 16
+    ; SIGNEXT-NEXT: [[SREM:%[0-9]+]]:_(s32) = G_SREM [[SEXT_INREG]], [[SEXT_INREG1]]
+    ; SIGNEXT-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[SREM]](s32)
+    ; SIGNEXT-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_SREM %0, %1
+    %5:i32(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+...
+---
+name: srem_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: srem_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[SREM:%[0-9]+]]:_(s32) = G_SREM [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[SREM]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_SREM %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: srem_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: srem_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[SREM:%[0-9]+]]:_(s64) = G_SREM [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[SREM]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_SREM %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sub.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sub.mir
new file mode 100644
index 0000000000000..97770cb6280cb
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/sub.mir
@@ -0,0 +1,91 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: sub_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sub_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[SUB]](s32)
+    ; CHECK-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_SUB %0, %1
+    %5:i32(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+...
+---
+name: sub_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sub_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[SUB]](s32)
+    ; CHECK-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_SUB %0, %1
+    %5:i32(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+...
+---
+name: sub_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sub_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = G_SUB [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[SUB]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_SUB %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: sub_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sub_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s64) = G_SUB [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[SUB]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_SUB %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/trunc.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/trunc.mir
new file mode 100644
index 0000000000000..c9dfd3175e6d6
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/trunc.mir
@@ -0,0 +1,95 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: trunc_i32_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: trunc_i32_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: RETURN [[ARGUMENT_i32_]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:i32(s32) = G_ANYEXT %0(s8)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: trunc_i32_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: trunc_i32_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: RETURN [[ARGUMENT_i32_]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:i32(s32) = G_ANYEXT %0(s16)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: trunc_i64_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: trunc_i64_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:i32(s32) = G_TRUNC [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %1:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %1(s64)
+    %2:i32(s32) = G_ANYEXT %0(s8)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: trunc_i64_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: trunc_i64_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:i32(s32) = G_TRUNC [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %1:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %1(s64)
+    %2:i32(s32) = G_ANYEXT %0(s16)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: trunc_i64_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: trunc_i64_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %1:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %0:_(s32) = G_TRUNC %1(s64)
+    RETURN %0(s32), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/udiv.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/udiv.mir
new file mode 100644
index 0000000000000..9d547bf0a110a
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/udiv.mir
@@ -0,0 +1,99 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: udiv_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: udiv_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C1]]
+    ; CHECK-NEXT: [[UDIV:%[0-9]+]]:_(s32) = G_UDIV [[AND]], [[AND1]]
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[UDIV]](s32)
+    ; CHECK-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_UDIV %0, %1
+    %5:i32(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+...
+---
+name: udiv_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: udiv_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C1]]
+    ; CHECK-NEXT: [[UDIV:%[0-9]+]]:_(s32) = G_UDIV [[AND]], [[AND1]]
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[UDIV]](s32)
+    ; CHECK-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_UDIV %0, %1
+    %5:i32(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+...
+---
+name: udiv_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: udiv_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[UDIV:%[0-9]+]]:_(s32) = G_UDIV [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[UDIV]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_UDIV %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: udiv_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: udiv_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[UDIV:%[0-9]+]]:_(s64) = G_UDIV [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[UDIV]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_UDIV %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/urem.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/urem.mir
new file mode 100644
index 0000000000000..068023509eb07
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/urem.mir
@@ -0,0 +1,99 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: urem_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: urem_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C1]]
+    ; CHECK-NEXT: [[UREM:%[0-9]+]]:_(s32) = G_UREM [[AND]], [[AND1]]
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[UREM]](s32)
+    ; CHECK-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_UREM %0, %1
+    %5:i32(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+...
+---
+name: urem_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: urem_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND1:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_1]], [[C1]]
+    ; CHECK-NEXT: [[UREM:%[0-9]+]]:_(s32) = G_UREM [[AND]], [[AND1]]
+    ; CHECK-NEXT: [[COPY:%[0-9]+]]:i32(s32) = COPY [[UREM]](s32)
+    ; CHECK-NEXT: RETURN [[COPY]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_UREM %0, %1
+    %5:i32(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+...
+---
+name: urem_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: urem_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[UREM:%[0-9]+]]:_(s32) = G_UREM [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[UREM]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_UREM %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: urem_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: urem_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[UREM:%[0-9]+]]:_(s64) = G_UREM [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[UREM]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_UREM %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/xor.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/xor.mir
new file mode 100644
index 0000000000000..1bc7ace2b3e7f
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/xor.mir
@@ -0,0 +1,116 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: xor_i1
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: xor_i1
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_1]], [[ARGUMENT_i32_]]
+    ; CHECK-NEXT: RETURN [[XOR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s1) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s1) = G_TRUNC %3(s32)
+    %4:_(s1) = G_XOR %1, %0
+    %5:_(s32) = G_ANYEXT %4(s1)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: xor_i8
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: xor_i8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_1]], [[ARGUMENT_i32_]]
+    ; CHECK-NEXT: RETURN [[XOR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s8) = G_TRUNC %3(s32)
+    %4:_(s8) = G_XOR %1, %0
+    %5:_(s32) = G_ANYEXT %4(s8)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: xor_i16
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: xor_i16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_1]], [[ARGUMENT_i32_]]
+    ; CHECK-NEXT: RETURN [[XOR]](s32), implicit-def $arguments
+    %2:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %2(s32)
+    %3:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %1:_(s16) = G_TRUNC %3(s32)
+    %4:_(s16) = G_XOR %1, %0
+    %5:_(s32) = G_ANYEXT %4(s16)
+    RETURN %5(s32), implicit-def $arguments
+
+...
+---
+name: xor_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: xor_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s32) = G_XOR [[ARGUMENT_i32_1]], [[ARGUMENT_i32_]]
+    ; CHECK-NEXT: RETURN [[XOR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_XOR %1, %0
+    RETURN %2(s32), implicit-def $arguments
+
+...
+---
+name: xor_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: xor_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:_(s64) = G_XOR [[ARGUMENT_i64_1]], [[ARGUMENT_i64_]]
+    ; CHECK-NEXT: RETURN [[XOR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_XOR %1, %0
+    RETURN %2(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/zext.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/zext.mir
new file mode 100644
index 0000000000000..84ee4cc9ac3e1
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/zext.mir
@@ -0,0 +1,103 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=legalizer -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name: zext_i8_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: zext_i8_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:i32(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: RETURN [[AND]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:i32(s32) = G_ZEXT %0(s8)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: zext_i8_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: zext_i8_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:i32(s64) = G_AND [[ANYEXT]], [[C]]
+    ; CHECK-NEXT: RETURN [[AND]](s64), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s8) = G_TRUNC %1(s32)
+    %2:i32(s64) = G_ZEXT %0(s8)
+    RETURN %2(s64), implicit-def $arguments
+...
+---
+name: zext_i16_i32
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: zext_i16_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:i32(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: RETURN [[AND]](s32), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:i32(s32) = G_ZEXT %0(s16)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name: zext_i16_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: zext_i16_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:_(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s64) = G_CONSTANT i64 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:i32(s64) = G_AND [[ANYEXT]], [[C]]
+    ; CHECK-NEXT: RETURN [[AND]](s64), implicit-def $arguments
+    %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %0:_(s16) = G_TRUNC %1(s32)
+    %2:i32(s64) = G_ZEXT %0(s16)
+    RETURN %2(s64), implicit-def $arguments
+...
+---
+name: zext_i32_i64
+alignment: 1
+tracksRegLiveness: true
+body: |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: zext_i32_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:i32(s64) = G_ZEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[ZEXT]](s64), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s64) = G_ZEXT %0(s32)
+    RETURN %1(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/bitwise.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/bitwise.mir
index 157ef5b9034c2..185ab2d550084 100644
--- a/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/bitwise.mir
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/bitwise.mir
@@ -22,7 +22,6 @@ body:             |
     %2:_(s32) = G_AND %0, %1
     RETURN %2(s32), implicit-def $arguments
 ...
-
 ---
 name:            and_i64
 alignment:       1
@@ -45,6 +44,92 @@ body:             |
     RETURN %2(s64), implicit-def $arguments
 ...
 
+---
+name:            or_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: or_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:i32regbank(s32) = G_OR [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[OR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_OR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            or_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: or_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:i64regbank(s64) = G_OR [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[OR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_OR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            xor_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: xor_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:i32regbank(s32) = G_XOR [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[XOR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_XOR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            xor_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: xor_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[XOR:%[0-9]+]]:i64regbank(s64) = G_XOR [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[XOR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_XOR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
 ---
 name:            shl_i32
 alignment:       1
@@ -66,7 +151,6 @@ body:             |
     %2:_(s32) = G_SHL %0, %1
     RETURN %2(s32), implicit-def $arguments
 ...
-
 ---
 name:            shl_i64
 alignment:       1
@@ -110,7 +194,6 @@ body:             |
     %2:_(s32) = G_ASHR %0, %1
     RETURN %2(s32), implicit-def $arguments
 ...
-
 ---
 name:            ashr_i64
 alignment:       1
@@ -132,3 +215,328 @@ body:             |
     %2:_(s64) = G_ASHR %0, %1
     RETURN %2(s64), implicit-def $arguments
 ...
+
+---
+name:            lshr_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshr_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:i32regbank(s32) = G_CONSTANT i32 5
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:i32regbank(s32) = G_LSHR [[ARGUMENT_i32_]], [[C]](s32)
+    ; CHECK-NEXT: RETURN [[LSHR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CONSTANT i32 5
+    %2:_(s32) = G_LSHR %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            lshr_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: lshr_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:i64regbank(s64) = G_CONSTANT i64 37
+    ; CHECK-NEXT: [[LSHR:%[0-9]+]]:i64regbank(s64) = G_LSHR [[ARGUMENT_i64_]], [[C]](s64)
+    ; CHECK-NEXT: RETURN [[LSHR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CONSTANT i64 37
+    %2:_(s64) = G_LSHR %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            ctlz_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:i32regbank(s32) = G_CTLZ [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTLZ]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CTLZ %0
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            ctlz_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:i64regbank(s64) = G_CTLZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[CTLZ]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CTLZ %0
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name:            ctlz_zundef_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_zundef_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:i32regbank(s32) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CTLZ_ZERO_UNDEF %0
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            ctlz_zundef_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctlz_zundef_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:i64regbank(s64) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CTLZ_ZERO_UNDEF %0
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name:            cttz_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:i32regbank(s32) = G_CTTZ [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CTTZ %0
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            cttz_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:i64regbank(s64) = G_CTTZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[CTTZ]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CTTZ %0
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name:            cttz_zundef_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_zundef_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:i32regbank(s32) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CTTZ_ZERO_UNDEF %0
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            cttz_zundef_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: cttz_zundef_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:i64regbank(s64) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CTTZ_ZERO_UNDEF %0
+    RETURN %1(s64), implicit-def $arguments
+...
+
+
+---
+name:            ctpop_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctpop_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[CTPOP:%[0-9]+]]:i32regbank(s32) = G_CTPOP [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTPOP]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_CTPOP %0
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            ctpop_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: ctpop_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[CTPOP:%[0-9]+]]:i64regbank(s64) = G_CTPOP [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[CTPOP]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_CTPOP %0
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name:            rotl_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotl_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ROTL:%[0-9]+]]:i32regbank(s32) = G_ROTL [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]](s32)
+    ; CHECK-NEXT: RETURN [[ROTL]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_ROTL %0, %1(s32)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            rotl_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotl_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[ROTL:%[0-9]+]]:i64regbank(s64) = G_ROTL [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]](s64)
+    ; CHECK-NEXT: RETURN [[ROTL]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_ROTL %0, %1(s64)
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            rotr_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotr_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[ROTR:%[0-9]+]]:i32regbank(s32) = G_ROTR [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]](s32)
+    ; CHECK-NEXT: RETURN [[ROTR]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_ROTR %0, %1(s32)
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            rotr_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: rotr_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[ROTR:%[0-9]+]]:i64regbank(s64) = G_ROTR [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]](s64)
+    ; CHECK-NEXT: RETURN [[ROTR]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_ROTR %0, %1(s64)
+    RETURN %2(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/consts.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/consts.mir
new file mode 100644
index 0000000000000..3cf45bbcf3702
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/consts.mir
@@ -0,0 +1,72 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name:            const_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: const_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[C:%[0-9]+]]:i32regbank(s32) = G_CONSTANT i32 0
+    ; CHECK-NEXT: RETURN [[C]](s32), implicit-def $arguments
+    %0:_(s32) = G_CONSTANT i32 0
+    RETURN %0(s32), implicit-def $arguments
+...
+---
+name:            const_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: const_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[C:%[0-9]+]]:i64regbank(s64) = G_CONSTANT i64 0
+    ; CHECK-NEXT: RETURN [[C]](s64), implicit-def $arguments
+    %0:_(s64) = G_CONSTANT i64 0
+    RETURN %0(s64), implicit-def $arguments
+...
+
+---
+name:            implicit_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: implicit_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[DEF:%[0-9]+]]:i32regbank(s32) = G_IMPLICIT_DEF
+    ; CHECK-NEXT: RETURN [[DEF]](s32), implicit-def $arguments
+    %0:_(s32) = G_IMPLICIT_DEF
+    RETURN %0(s32), implicit-def $arguments
+...
+---
+name:            implicit_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: implicit_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[DEF:%[0-9]+]]:i64regbank(s64) = G_IMPLICIT_DEF
+    ; CHECK-NEXT: RETURN [[DEF]](s64), implicit-def $arguments
+    %0:_(s64) = G_IMPLICIT_DEF
+    RETURN %0(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/ext-trunc.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/ext-trunc.mir
new file mode 100644
index 0000000000000..a95bb61143547
--- /dev/null
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/ext-trunc.mir
@@ -0,0 +1,177 @@
+# NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 6
+# RUN: llc -O0 -mtriple=wasm32-unknown-unknown -run-pass=regbankselect -verify-machineinstrs %s -o - | FileCheck %s
+
+---
+name:            anyext
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: anyext
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ANYEXT:%[0-9]+]]:i64regbank(s64) = G_ANYEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[ANYEXT]](s64), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s64) = G_ANYEXT %0
+    RETURN %1(s64), implicit-def $arguments
+...
+---
+name:            sext
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[SEXT:%[0-9]+]]:i64regbank(s64) = G_SEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[SEXT]](s64), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s64) = G_SEXT %0
+    RETURN %1(s64), implicit-def $arguments
+...
+---
+name:            zext
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: zext
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ZEXT:%[0-9]+]]:i64regbank(s64) = G_ZEXT [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[ZEXT]](s64), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s64) = G_ZEXT %0
+    RETURN %1(s64), implicit-def $arguments
+...
+---
+name:            trunc
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: trunc
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:i32regbank(s32) = G_TRUNC [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s32) = G_TRUNC %0
+    RETURN %1(s32), implicit-def $arguments
+...
+
+---
+name:            sext_inreg_i32_8
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext_inreg_i32_8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:i32regbank(s32) = G_SEXT_INREG [[ARGUMENT_i32_]], 8
+    ; CHECK-NEXT: RETURN [[SEXT_INREG]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_SEXT_INREG %0, 8
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            sext_inreg_i64_8
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext_inreg_i64_8
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:i64regbank(s64) = G_SEXT_INREG [[ARGUMENT_i64_]], 8
+    ; CHECK-NEXT: RETURN [[SEXT_INREG]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_SEXT_INREG %0, 8
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name:            sext_inreg_i32_16
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext_inreg_i32_16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:i32regbank(s32) = G_SEXT_INREG [[ARGUMENT_i32_]], 16
+    ; CHECK-NEXT: RETURN [[SEXT_INREG]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:_(s32) = G_SEXT_INREG %0, 16
+    RETURN %1(s32), implicit-def $arguments
+...
+---
+name:            sext_inreg_i64_16
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext_inreg_i64_16
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:i64regbank(s64) = G_SEXT_INREG [[ARGUMENT_i64_]], 16
+    ; CHECK-NEXT: RETURN [[SEXT_INREG]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_SEXT_INREG %0, 16
+    RETURN %1(s64), implicit-def $arguments
+...
+
+---
+name:            sext_inreg_i64_32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sext_inreg_i64_32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[SEXT_INREG:%[0-9]+]]:i64regbank(s64) = G_SEXT_INREG [[ARGUMENT_i64_]], 32
+    ; CHECK-NEXT: RETURN [[SEXT_INREG]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:_(s64) = G_SEXT_INREG %0, 32
+    RETURN %1(s64), implicit-def $arguments
+...
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/int-arithmetic.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/int-arithmetic.mir
index 1a2515d4b9abe..a2118b9744051 100644
--- a/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/int-arithmetic.mir
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/int-arithmetic.mir
@@ -22,7 +22,6 @@ body:             |
     %2:_(s32) = G_ADD %0, %1
     RETURN %2(s32), implicit-def $arguments
 ...
-
 ---
 name:            add_i64
 alignment:       1
@@ -44,3 +43,261 @@ body:             |
     %2:_(s64) = G_ADD %0, %1
     RETURN %2(s64), implicit-def $arguments
 ...
+
+---
+name:            sub_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sub_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:i32regbank(s32) = G_SUB [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[SUB]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_SUB %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            sub_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sub_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:i64regbank(s64) = G_SUB [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[SUB]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_SUB %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            mul_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: mul_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:i32regbank(s32) = G_MUL [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[MUL]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_MUL %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            mul_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: mul_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[MUL:%[0-9]+]]:i64regbank(s64) = G_MUL [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[MUL]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_MUL %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            udiv_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: udiv_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[UDIV:%[0-9]+]]:i32regbank(s32) = G_UDIV [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[UDIV]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_UDIV %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            udiv_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: udiv_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[UDIV:%[0-9]+]]:i64regbank(s64) = G_UDIV [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[UDIV]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_UDIV %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            sdiv_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sdiv_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[SDIV:%[0-9]+]]:i32regbank(s32) = G_SDIV [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[SDIV]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_SDIV %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            sdiv_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: sdiv_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[SDIV:%[0-9]+]]:i64regbank(s64) = G_SDIV [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[SDIV]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_SDIV %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            urem_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: urem_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[UREM:%[0-9]+]]:i32regbank(s32) = G_UREM [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[UREM]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_UREM %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            urem_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: urem_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[UREM:%[0-9]+]]:i64regbank(s64) = G_UREM [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[UREM]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_UREM %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...
+
+---
+name:            srem_i32
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: srem_i32
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i32_1:%[0-9]+]]:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    ; CHECK-NEXT: [[SREM:%[0-9]+]]:i32regbank(s32) = G_SREM [[ARGUMENT_i32_]], [[ARGUMENT_i32_1]]
+    ; CHECK-NEXT: RETURN [[SREM]](s32), implicit-def $arguments
+    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
+    %1:i32(s32) = ARGUMENT_i32 1, implicit $arguments
+    %2:_(s32) = G_SREM %0, %1
+    RETURN %2(s32), implicit-def $arguments
+...
+---
+name:            srem_i64
+alignment:       1
+legalized:       true
+tracksRegLiveness: true
+body:             |
+  bb.1.entry:
+    liveins: $arguments
+
+    ; CHECK-LABEL: name: srem_i64
+    ; CHECK: liveins: $arguments
+    ; CHECK-NEXT: {{  $}}
+    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    ; CHECK-NEXT: [[ARGUMENT_i64_1:%[0-9]+]]:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    ; CHECK-NEXT: [[SREM:%[0-9]+]]:i64regbank(s64) = G_SREM [[ARGUMENT_i64_]], [[ARGUMENT_i64_1]]
+    ; CHECK-NEXT: RETURN [[SREM]](s64), implicit-def $arguments
+    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
+    %1:i64(s64) = ARGUMENT_i64 1, implicit $arguments
+    %2:_(s64) = G_SREM %0, %1
+    RETURN %2(s64), implicit-def $arguments
+...

>From 579a3c5a1127c26774ac84dfdfd30164de7e4c7a Mon Sep 17 00:00:00 2001
From: Demetrius Kanios <demetrius at kanios.net>
Date: Fri, 3 Apr 2026 10:33:55 -0700
Subject: [PATCH 2/3] Address review comments

---
 .../GISel/WebAssemblyInstructionSelector.cpp  | 31 +------------
 .../GISel/WebAssemblyLegalizerInfo.cpp        |  2 +-
 .../WebAssembly/WebAssemblyRegisterInfo.cpp   | 46 +++++++++++++++++++
 .../WebAssembly/WebAssemblyRegisterInfo.h     |  3 ++
 4 files changed, 52 insertions(+), 30 deletions(-)

diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
index 7359156ccf60c..19b4cffa334bc 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyInstructionSelector.cpp
@@ -84,30 +84,6 @@ WebAssemblyInstructionSelector::WebAssemblyInstructionSelector(
 {
 }
 
-static const TargetRegisterClass &getRegClassForBank(const RegisterBank &RB) {
-  switch (RB.getID()) {
-  case WebAssembly::I32RegBankID:
-    return WebAssembly::I32RegClass;
-  case WebAssembly::I64RegBankID:
-    return WebAssembly::I64RegClass;
-  case WebAssembly::F32RegBankID:
-    return WebAssembly::F32RegClass;
-  case WebAssembly::F64RegBankID:
-    return WebAssembly::F64RegClass;
-  case WebAssembly::EXNREFRegBankID:
-    return WebAssembly::EXNREFRegClass;
-  case WebAssembly::EXTERNREFRegBankID:
-    return WebAssembly::EXTERNREFRegClass;
-  case WebAssembly::FUNCREFRegBankID:
-    return WebAssembly::FUNCREFRegClass;
-  case WebAssembly::V128RegBankID:
-    return WebAssembly::V128RegClass;
-  default:
-    reportFatalInternalError(
-        "Found unexpected RegisterBank in `getRegClassForBank`");
-  }
-}
-
 bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
   MachineBasicBlock &MBB = *I.getParent();
   MachineFunction &MF = *MBB.getParent();
@@ -125,18 +101,15 @@ bool WebAssemblyInstructionSelector::select(MachineInstr &I) {
   switch (I.getOpcode()) {
   case G_IMPLICIT_DEF: {
     const Register DefReg = I.getOperand(0).getReg();
-    const RegClassOrRegBank &RegClassOrBank = MRI.getRegClassOrRegBank(DefReg);
 
     const TargetRegisterClass *DefRC =
-        dyn_cast<const TargetRegisterClass *>(RegClassOrBank);
+        TRI.getConstrainedRegClassForOperand(I.getOperand(0), MRI);
 
     if (!DefRC) {
-      const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
-      DefRC = &getRegClassForBank(RB);
+      return false;
     }
 
     I.setDesc(TII.get(TargetOpcode::IMPLICIT_DEF));
-
     return RBI.constrainGenericRegister(DefReg, *DefRC, MRI) != nullptr;
   }
   default:
diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
index 0b9bbc1a6853a..ab19ad9499048 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
@@ -65,8 +65,8 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
       .clampScalar(1, s64, s64);
 
   getActionDefinitionsBuilder(G_SEXT_INREG)
-      .clampScalar(0, s32, s64)
       .customFor(ST.hasSignExt(), {s32, s64})
+      .clampScalar(0, s32, s64)
       .lower();
 
   getLegacyLegalizerInfo().computeTables();
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
index ebb5f555df67a..4b4f07bd782ad 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.cpp
@@ -13,6 +13,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "WebAssemblyRegisterInfo.h"
+#include "GISel/WebAssemblyRegisterBankInfo.h"
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
 #include "WebAssemblyFrameLowering.h"
 #include "WebAssemblyInstrInfo.h"
@@ -154,3 +155,48 @@ WebAssemblyRegisterInfo::getPointerRegClass(unsigned Kind) const {
   return TT.getArch() == Triple::wasm64 ? &WebAssembly::I64RegClass
                                         : &WebAssembly::I32RegClass;
 }
+
+static const TargetRegisterClass &getRegClassForBank(const RegisterBank &RB) {
+  switch (RB.getID()) {
+  case WebAssembly::I32RegBankID:
+    return WebAssembly::I32RegClass;
+  case WebAssembly::I64RegBankID:
+    return WebAssembly::I64RegClass;
+  case WebAssembly::F32RegBankID:
+    return WebAssembly::F32RegClass;
+  case WebAssembly::F64RegBankID:
+    return WebAssembly::F64RegClass;
+  case WebAssembly::EXNREFRegBankID:
+    return WebAssembly::EXNREFRegClass;
+  case WebAssembly::EXTERNREFRegBankID:
+    return WebAssembly::EXTERNREFRegClass;
+  case WebAssembly::FUNCREFRegBankID:
+    return WebAssembly::FUNCREFRegClass;
+  case WebAssembly::V128RegBankID:
+    return WebAssembly::V128RegClass;
+  default:
+    llvm_unreachable("Found unexpected RegisterBank in `getRegClassForBank`");
+  }
+}
+
+const TargetRegisterClass *
+WebAssemblyRegisterInfo::getConstrainedRegClassForOperand(
+    const MachineOperand &MO, const MachineRegisterInfo &MRI) const {
+  assert(MO.isReg());
+
+  const RegClassOrRegBank &RegClassOrBank =
+      MRI.getRegClassOrRegBank(MO.getReg());
+
+  if (RegClassOrBank.isNull())
+    return nullptr;
+
+  const TargetRegisterClass *DefRC =
+      dyn_cast<const TargetRegisterClass *>(RegClassOrBank);
+
+  if (!DefRC) {
+    const RegisterBank &RB = *cast<const RegisterBank *>(RegClassOrBank);
+    DefRC = &getRegClassForBank(RB);
+  }
+
+  return DefRC;
+}
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h
index 3a73ff6b1b3b0..5b4293b9ec590 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRegisterInfo.h
@@ -45,6 +45,9 @@ class WebAssemblyRegisterInfo final : public WebAssemblyGenRegisterInfo {
   getPointerRegClass(unsigned Kind = 0) const override;
   // This does not apply to wasm.
   const uint32_t *getNoPreservedMask() const override { return nullptr; }
+
+  const TargetRegisterClass *getConstrainedRegClassForOperand(
+      const MachineOperand &MO, const MachineRegisterInfo &MRI) const override;
 };
 
 } // end namespace llvm

>From c49ab5144c596e445a162ba5794a6302b973b290 Mon Sep 17 00:00:00 2001
From: Demetrius Kanios <demetrius at kanios.net>
Date: Fri, 3 Apr 2026 11:21:42 -0700
Subject: [PATCH 3/3] Lower `G_[CTLZ|CTTZ]_ZERO_UNDEF` instead of legal

---
 .../GISel/WebAssemblyLegalizerInfo.cpp        |  6 +-
 .../WebAssembly/WebAssemblyInstrInteger.td    |  8 --
 .../GlobalISel/instruction-select/bitwise.mir | 82 -------------------
 .../GlobalISel/legalizer/ctlz_zero_undef.mir  | 40 +++++----
 .../WebAssembly/GlobalISel/legalizer/cttz.mir |  8 +-
 .../GlobalISel/legalizer/cttz_zero_undef.mir  | 32 ++++----
 .../GlobalISel/regbankselect/bitwise.mir      | 79 ------------------
 7 files changed, 48 insertions(+), 207 deletions(-)

diff --git a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
index ab19ad9499048..293ba88605354 100644
--- a/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
+++ b/llvm/lib/Target/WebAssembly/GISel/WebAssemblyLegalizerInfo.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "WebAssemblyLegalizerInfo.h"
+#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
 #include "WebAssemblySubtarget.h"
 #include "llvm/CodeGen/GlobalISel/LegalizerHelper.h"
 #include "llvm/CodeGen/GlobalISel/LegalizerInfo.h"
@@ -40,13 +41,14 @@ WebAssemblyLegalizerInfo::WebAssemblyLegalizerInfo(
       .clampScalar(0, s32, s64)
       .scalarSameSizeAs(1, 0);
 
-  getActionDefinitionsBuilder(
-      {G_CTLZ, G_CTLZ_ZERO_UNDEF, G_CTTZ, G_CTTZ_ZERO_UNDEF, G_CTPOP})
+  getActionDefinitionsBuilder({G_CTLZ, G_CTTZ, G_CTPOP})
       .legalFor({{s32, s32}, {s64, s64}})
       .widenScalarToNextPow2(1)
       .clampScalar(1, s32, s64)
       .scalarSameSizeAs(0, 1);
 
+  getActionDefinitionsBuilder({G_CTLZ_ZERO_UNDEF, G_CTTZ_ZERO_UNDEF}).lower();
+
   getActionDefinitionsBuilder({G_ROTL, G_ROTR})
       .legalFor({{s32, s32}, {s64, s64}})
       .scalarSameSizeAs(1, 0)
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
index 99ca22e21f70b..991507e883f28 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInteger.td
@@ -82,18 +82,10 @@ defm LE_U : ComparisonInt<SETULE, "le_u", 0x4d, 0x58>;
 defm GE_S : ComparisonInt<SETGE,  "ge_s", 0x4e, 0x59>;
 defm GE_U : ComparisonInt<SETUGE, "ge_u", 0x4f, 0x5a>;
 
-
 defm CLZ : UnaryInt<ctlz, "clz ", 0x67, 0x79>;
-def : Pat<(ctlz_zero_undef I32:$src), (CLZ_I32 I32:$src)>;
-def : Pat<(ctlz_zero_undef I64:$src), (CLZ_I64 I64:$src)>;
-
 defm CTZ : UnaryInt<cttz, "ctz ", 0x68, 0x7a>;
-def : Pat<(cttz_zero_undef I32:$src), (CTZ_I32 I32:$src)>;
-def : Pat<(cttz_zero_undef I64:$src), (CTZ_I64 I64:$src)>;
-
 defm POPCNT : UnaryInt<ctpop, "popcnt", 0x69, 0x7b>;
 
-
 defm EQZ_I32 : I<(outs I32:$dst), (ins I32:$src), (outs), (ins),
                  [(set I32:$dst, (setcc I32:$src, 0, SETEQ))],
                  "i32.eqz \t$dst, $src", "i32.eqz", 0x45>;
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/bitwise.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/bitwise.mir
index 1a5943259b521..2af53ff71ce2d 100644
--- a/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/bitwise.mir
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/instruction-select/bitwise.mir
@@ -312,47 +312,6 @@ body:             |
     RETURN %1(s64), implicit-def $arguments
 ...
 
----
-name:            ctlz_zundef_i32
-alignment:       1
-legalized:       true
-regBankSelected: true
-tracksRegLiveness: true
-body:             |
-  bb.1.entry:
-    liveins: $arguments
-
-    ; CHECK-LABEL: name: ctlz_zundef_i32
-    ; CHECK: liveins: $arguments
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[CLZ_I32_:%[0-9]+]]:i32 = CLZ_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
-    ; CHECK-NEXT: RETURN [[CLZ_I32_]], implicit-def $arguments
-    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    %1:i32regbank(s32) = G_CTLZ_ZERO_UNDEF %0
-    RETURN %1(s32), implicit-def $arguments
-...
----
-name:            ctlz_zundef_i64
-alignment:       1
-legalized:       true
-regBankSelected: true
-tracksRegLiveness: true
-body:             |
-  bb.1.entry:
-    liveins: $arguments
-
-    ; CHECK-LABEL: name: ctlz_zundef_i64
-    ; CHECK: liveins: $arguments
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
-    ; CHECK-NEXT: [[CLZ_I64_:%[0-9]+]]:i64 = CLZ_I64 [[ARGUMENT_i64_]], implicit-def dead $arguments
-    ; CHECK-NEXT: RETURN [[CLZ_I64_]], implicit-def $arguments
-    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
-    %1:i64regbank(s64) = G_CTLZ_ZERO_UNDEF %0
-    RETURN %1(s64), implicit-def $arguments
-...
-
 ---
 name:            cttz_i32
 alignment:       1
@@ -394,47 +353,6 @@ body:             |
     RETURN %1(s64), implicit-def $arguments
 ...
 
----
-name:            cttz_zundef_i32
-alignment:       1
-legalized:       true
-regBankSelected: true
-tracksRegLiveness: true
-body:             |
-  bb.1.entry:
-    liveins: $arguments
-
-    ; CHECK-LABEL: name: cttz_zundef_i32
-    ; CHECK: liveins: $arguments
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32 = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[CTZ_I32_:%[0-9]+]]:i32 = CTZ_I32 [[ARGUMENT_i32_]], implicit-def dead $arguments
-    ; CHECK-NEXT: RETURN [[CTZ_I32_]], implicit-def $arguments
-    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    %1:i32regbank(s32) = G_CTTZ_ZERO_UNDEF %0
-    RETURN %1(s32), implicit-def $arguments
-...
----
-name:            cttz_zundef_i64
-alignment:       1
-legalized:       true
-regBankSelected: true
-tracksRegLiveness: true
-body:             |
-  bb.1.entry:
-    liveins: $arguments
-
-    ; CHECK-LABEL: name: cttz_zundef_i64
-    ; CHECK: liveins: $arguments
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64 = ARGUMENT_i64 0, implicit $arguments
-    ; CHECK-NEXT: [[CTZ_I64_:%[0-9]+]]:i64 = CTZ_I64 [[ARGUMENT_i64_]], implicit-def dead $arguments
-    ; CHECK-NEXT: RETURN [[CTZ_I64_]], implicit-def $arguments
-    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
-    %1:i64regbank(s64) = G_CTTZ_ZERO_UNDEF %0
-    RETURN %1(s64), implicit-def $arguments
-...
-
 ---
 name:            ctpop_i32
 alignment:       1
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctlz_zero_undef.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctlz_zero_undef.mir
index 045706eb22c14..e00396d20b7e3 100644
--- a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctlz_zero_undef.mir
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/ctlz_zero_undef.mir
@@ -13,10 +13,12 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
-    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
-    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[SHL]](s32)
-    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 255
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s32) = G_CTLZ [[AND]](s32)
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 24
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = nuw G_SUB [[CTLZ]], [[C1]]
+    ; CHECK-NEXT: RETURN [[SUB]](s32), implicit-def $arguments
     %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     %0:_(s8) = G_TRUNC %1(s32)
     %2:_(s8) = G_CTLZ_ZERO_UNDEF %0
@@ -36,10 +38,12 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
-    ; CHECK-NEXT: [[SHL:%[0-9]+]]:_(s32) = G_SHL [[ARGUMENT_i32_]], [[C]](s32)
-    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[SHL]](s32)
-    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65535
+    ; CHECK-NEXT: [[AND:%[0-9]+]]:_(s32) = G_AND [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s32) = G_CTLZ [[AND]](s32)
+    ; CHECK-NEXT: [[C1:%[0-9]+]]:_(s32) = G_CONSTANT i32 16
+    ; CHECK-NEXT: [[SUB:%[0-9]+]]:_(s32) = nuw G_SUB [[CTLZ]], [[C1]]
+    ; CHECK-NEXT: RETURN [[SUB]](s32), implicit-def $arguments
     %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     %0:_(s16) = G_TRUNC %1(s32)
     %2:_(s16) = G_CTLZ_ZERO_UNDEF %0
@@ -59,8 +63,8 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
-    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s32) = G_CTLZ [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTLZ]](s32), implicit-def $arguments
     %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     %1:_(s32) = G_CTLZ_ZERO_UNDEF %0
     RETURN %1(s32), implicit-def $arguments
@@ -78,8 +82,8 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
-    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s32) = G_CTLZ [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTLZ]](s32), implicit-def $arguments
     %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     %1:_(s8) = G_CTLZ_ZERO_UNDEF %0
     %2:_(s32) = G_ANYEXT %1(s8)
@@ -98,8 +102,8 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
-    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
-    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s64), implicit-def $arguments
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[CTLZ]](s64), implicit-def $arguments
     %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
     %1:_(s64) = G_CTLZ_ZERO_UNDEF %0
     RETURN %1(s64), implicit-def $arguments
@@ -117,8 +121,8 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
-    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
-    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTLZ_ZERO_UNDEF]](s64)
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTLZ]](s64)
     ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
     %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
     %1:_(s8) = G_CTLZ_ZERO_UNDEF %0
@@ -138,8 +142,8 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
-    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:_(s64) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
-    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTLZ_ZERO_UNDEF]](s64)
+    ; CHECK-NEXT: [[CTLZ:%[0-9]+]]:_(s64) = G_CTLZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTLZ]](s64)
     ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
     %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
     %1:_(s32) = G_CTLZ_ZERO_UNDEF %0
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz.mir
index 1d1d90b8420d6..2feeb10b39c38 100644
--- a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz.mir
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz.mir
@@ -15,8 +15,8 @@ body: |
     ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 256
     ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[ARGUMENT_i32_]], [[C]]
-    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[OR]](s32)
-    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s32) = G_CTTZ [[OR]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ]](s32), implicit-def $arguments
     %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     %0:_(s8) = G_TRUNC %1(s32)
     %2:_(s8) = G_CTTZ %0
@@ -38,8 +38,8 @@ body: |
     ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65536
     ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[ARGUMENT_i32_]], [[C]]
-    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[OR]](s32)
-    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s32) = G_CTTZ [[OR]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ]](s32), implicit-def $arguments
     %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     %0:_(s16) = G_TRUNC %1(s32)
     %2:_(s16) = G_CTTZ %0
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz_zero_undef.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz_zero_undef.mir
index adb0cab5879d0..b76234b48fe10 100644
--- a/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz_zero_undef.mir
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/legalizer/cttz_zero_undef.mir
@@ -13,8 +13,10 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
-    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 256
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s32) = G_CTTZ [[OR]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ]](s32), implicit-def $arguments
     %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     %0:_(s8) = G_TRUNC %1(s32)
     %2:_(s8) = G_CTTZ_ZERO_UNDEF %0
@@ -34,8 +36,10 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
-    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    ; CHECK-NEXT: [[C:%[0-9]+]]:_(s32) = G_CONSTANT i32 65536
+    ; CHECK-NEXT: [[OR:%[0-9]+]]:_(s32) = G_OR [[ARGUMENT_i32_]], [[C]]
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s32) = G_CTTZ [[OR]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ]](s32), implicit-def $arguments
     %1:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     %0:_(s16) = G_TRUNC %1(s32)
     %2:_(s16) = G_CTTZ_ZERO_UNDEF %0
@@ -55,8 +59,8 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
-    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s32) = G_CTTZ [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ]](s32), implicit-def $arguments
     %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     %1:_(s32) = G_CTTZ_ZERO_UNDEF %0
     RETURN %1(s32), implicit-def $arguments
@@ -74,8 +78,8 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s32) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
-    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s32) = G_CTTZ [[ARGUMENT_i32_]](s32)
+    ; CHECK-NEXT: RETURN [[CTTZ]](s32), implicit-def $arguments
     %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
     %1:_(s8) = G_CTTZ_ZERO_UNDEF %0
     %2:_(s32) = G_ANYEXT %1(s8)
@@ -94,8 +98,8 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
-    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
-    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s64), implicit-def $arguments
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s64) = G_CTTZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: RETURN [[CTTZ]](s64), implicit-def $arguments
     %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
     %1:_(s64) = G_CTTZ_ZERO_UNDEF %0
     RETURN %1(s64), implicit-def $arguments
@@ -113,8 +117,8 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
-    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
-    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTTZ_ZERO_UNDEF]](s64)
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s64) = G_CTTZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTTZ]](s64)
     ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
     %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
     %1:_(s8) = G_CTTZ_ZERO_UNDEF %0
@@ -134,8 +138,8 @@ body: |
     ; CHECK: liveins: $arguments
     ; CHECK-NEXT: {{  $}}
     ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
-    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:_(s64) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
-    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTTZ_ZERO_UNDEF]](s64)
+    ; CHECK-NEXT: [[CTTZ:%[0-9]+]]:_(s64) = G_CTTZ [[ARGUMENT_i64_]](s64)
+    ; CHECK-NEXT: [[TRUNC:%[0-9]+]]:_(s32) = G_TRUNC [[CTTZ]](s64)
     ; CHECK-NEXT: RETURN [[TRUNC]](s32), implicit-def $arguments
     %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
     %1:_(s32) = G_CTTZ_ZERO_UNDEF %0
diff --git a/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/bitwise.mir b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/bitwise.mir
index 185ab2d550084..9657732d43aaf 100644
--- a/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/bitwise.mir
+++ b/llvm/test/CodeGen/WebAssembly/GlobalISel/regbankselect/bitwise.mir
@@ -298,45 +298,6 @@ body:             |
     RETURN %1(s64), implicit-def $arguments
 ...
 
----
-name:            ctlz_zundef_i32
-alignment:       1
-legalized:       true
-tracksRegLiveness: true
-body:             |
-  bb.1.entry:
-    liveins: $arguments
-
-    ; CHECK-LABEL: name: ctlz_zundef_i32
-    ; CHECK: liveins: $arguments
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:i32regbank(s32) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
-    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s32), implicit-def $arguments
-    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    %1:_(s32) = G_CTLZ_ZERO_UNDEF %0
-    RETURN %1(s32), implicit-def $arguments
-...
----
-name:            ctlz_zundef_i64
-alignment:       1
-legalized:       true
-tracksRegLiveness: true
-body:             |
-  bb.1.entry:
-    liveins: $arguments
-
-    ; CHECK-LABEL: name: ctlz_zundef_i64
-    ; CHECK: liveins: $arguments
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
-    ; CHECK-NEXT: [[CTLZ_ZERO_UNDEF:%[0-9]+]]:i64regbank(s64) = G_CTLZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
-    ; CHECK-NEXT: RETURN [[CTLZ_ZERO_UNDEF]](s64), implicit-def $arguments
-    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
-    %1:_(s64) = G_CTLZ_ZERO_UNDEF %0
-    RETURN %1(s64), implicit-def $arguments
-...
-
 ---
 name:            cttz_i32
 alignment:       1
@@ -376,46 +337,6 @@ body:             |
     RETURN %1(s64), implicit-def $arguments
 ...
 
----
-name:            cttz_zundef_i32
-alignment:       1
-legalized:       true
-tracksRegLiveness: true
-body:             |
-  bb.1.entry:
-    liveins: $arguments
-
-    ; CHECK-LABEL: name: cttz_zundef_i32
-    ; CHECK: liveins: $arguments
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: [[ARGUMENT_i32_:%[0-9]+]]:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:i32regbank(s32) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i32_]](s32)
-    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s32), implicit-def $arguments
-    %0:i32(s32) = ARGUMENT_i32 0, implicit $arguments
-    %1:_(s32) = G_CTTZ_ZERO_UNDEF %0
-    RETURN %1(s32), implicit-def $arguments
-...
----
-name:            cttz_zundef_i64
-alignment:       1
-legalized:       true
-tracksRegLiveness: true
-body:             |
-  bb.1.entry:
-    liveins: $arguments
-
-    ; CHECK-LABEL: name: cttz_zundef_i64
-    ; CHECK: liveins: $arguments
-    ; CHECK-NEXT: {{  $}}
-    ; CHECK-NEXT: [[ARGUMENT_i64_:%[0-9]+]]:i64(s64) = ARGUMENT_i64 0, implicit $arguments
-    ; CHECK-NEXT: [[CTTZ_ZERO_UNDEF:%[0-9]+]]:i64regbank(s64) = G_CTTZ_ZERO_UNDEF [[ARGUMENT_i64_]](s64)
-    ; CHECK-NEXT: RETURN [[CTTZ_ZERO_UNDEF]](s64), implicit-def $arguments
-    %0:i64(s64) = ARGUMENT_i64 0, implicit $arguments
-    %1:_(s64) = G_CTTZ_ZERO_UNDEF %0
-    RETURN %1(s64), implicit-def $arguments
-...
-
-
 ---
 name:            ctpop_i32
 alignment:       1



More information about the llvm-commits mailing list