//=- WebAssemblyISelLowering.cpp - WebAssembly DAG Lowering Implementation -==//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements the WebAssemblyTargetLowering class.
///
//===----------------------------------------------------------------------===//

#include "WebAssemblyISelLowering.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "Utils/WebAssemblyTypeUtilities.h"
#include "WebAssemblyMachineFunctionInfo.h"
#include "WebAssemblySubtarget.h"
#include "WebAssemblyTargetMachine.h"
#include "WebAssemblyUtilities.h"
#include "llvm/CodeGen/CallingConvLower.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/SDPatternMatch.h"
#include "llvm/CodeGen/SelectionDAG.h"
#include "llvm/CodeGen/SelectionDAGNodes.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsWebAssembly.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/KnownBits.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;

#define DEBUG_TYPE "wasm-lower"

WebAssemblyTargetLowering::WebAssemblyTargetLowering(
    const TargetMachine &TM, const WebAssemblySubtarget &STI)
    : TargetLowering(TM, STI), Subtarget(&STI) {
  auto MVTPtr = Subtarget->hasAddr64() ? MVT::i64 : MVT::i32;

  // Set the load count for memcmp expand optimization
  MaxLoadsPerMemcmp = 8;
  MaxLoadsPerMemcmpOptSize = 4;

  // Booleans always contain 0 or 1.
  setBooleanContents(ZeroOrOneBooleanContent);
  // Except in SIMD vectors
  setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);
  // We don't know the microarchitecture here, so just reduce register pressure.
  setSchedulingPreference(Sched::RegPressure);
  // Tell ISel that we have a stack pointer.
  setStackPointerRegisterToSaveRestore(
      Subtarget->hasAddr64() ? WebAssembly::SP64 : WebAssembly::SP32);
  // Set up the register classes.
  addRegisterClass(MVT::i32, &WebAssembly::I32RegClass);
  addRegisterClass(MVT::i64, &WebAssembly::I64RegClass);
  addRegisterClass(MVT::f32, &WebAssembly::F32RegClass);
  addRegisterClass(MVT::f64, &WebAssembly::F64RegClass);
  if (Subtarget->hasSIMD128()) {
    addRegisterClass(MVT::v16i8, &WebAssembly::V128RegClass);
    addRegisterClass(MVT::v8i16, &WebAssembly::V128RegClass);
    addRegisterClass(MVT::v4i32, &WebAssembly::V128RegClass);
    addRegisterClass(MVT::v4f32, &WebAssembly::V128RegClass);
    addRegisterClass(MVT::v2i64, &WebAssembly::V128RegClass);
    addRegisterClass(MVT::v2f64, &WebAssembly::V128RegClass);
  }
  if (Subtarget->hasFP16()) {
    addRegisterClass(MVT::v8f16, &WebAssembly::V128RegClass);
  }
  if (Subtarget->hasReferenceTypes()) {
    addRegisterClass(MVT::externref, &WebAssembly::EXTERNREFRegClass);
    addRegisterClass(MVT::funcref, &WebAssembly::FUNCREFRegClass);
    if (Subtarget->hasExceptionHandling()) {
      addRegisterClass(MVT::exnref, &WebAssembly::EXNREFRegClass);
    }
  }
  // Compute derived properties from the register classes.
  computeRegisterProperties(Subtarget->getRegisterInfo());

  // Transform loads and stores to pointers in address space 1 to loads and
  // stores to WebAssembly global variables, outside linear memory.
  for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64}) {
    setOperationAction(ISD::LOAD, T, Custom);
    setOperationAction(ISD::STORE, T, Custom);
  }
  if (Subtarget->hasSIMD128()) {
    for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32, MVT::v2i64,
                   MVT::v2f64}) {
      setOperationAction(ISD::LOAD, T, Custom);
      setOperationAction(ISD::STORE, T, Custom);
    }
  }
  if (Subtarget->hasFP16()) {
    setOperationAction(ISD::LOAD, MVT::v8f16, Custom);
    setOperationAction(ISD::STORE, MVT::v8f16, Custom);
  }
  if (Subtarget->hasReferenceTypes()) {
    // We need custom load and store lowering for both externref, funcref and
    // Other. The MVT::Other here represents tables of reference types.
    for (auto T : {MVT::externref, MVT::funcref, MVT::Other}) {
      setOperationAction(ISD::LOAD, T, Custom);
      setOperationAction(ISD::STORE, T, Custom);
    }
  }

  setOperationAction(ISD::GlobalAddress, MVTPtr, Custom);
  setOperationAction(ISD::GlobalTLSAddress, MVTPtr, Custom);
  setOperationAction(ISD::ExternalSymbol, MVTPtr, Custom);
  setOperationAction(ISD::JumpTable, MVTPtr, Custom);
  setOperationAction(ISD::BlockAddress, MVTPtr, Custom);
  setOperationAction(ISD::BRIND, MVT::Other, Custom);
  setOperationAction(ISD::CLEAR_CACHE, MVT::Other, Custom);

  // Take the default expansion for va_arg, va_copy, and va_end. There is no
  // default action for va_start, so we do that custom.
  setOperationAction(ISD::VASTART, MVT::Other, Custom);
  setOperationAction(ISD::VAARG, MVT::Other, Expand);
  setOperationAction(ISD::VACOPY, MVT::Other, Expand);
  setOperationAction(ISD::VAEND, MVT::Other, Expand);

  for (auto T : {MVT::f32, MVT::f64, MVT::v4f32, MVT::v2f64, MVT::v8f16}) {
    if (!Subtarget->hasFP16() && T == MVT::v8f16) {
      continue;
    }
    // Don't expand the floating-point types to constant pools.
    setOperationAction(ISD::ConstantFP, T, Legal);
    // Expand floating-point comparisons.
    for (auto CC : {ISD::SETO, ISD::SETUO, ISD::SETUEQ, ISD::SETONE,
                    ISD::SETULT, ISD::SETULE, ISD::SETUGT, ISD::SETUGE})
      setCondCodeAction(CC, T, Expand);
    // Expand floating-point library function operators.
    for (auto Op : {ISD::FSIN, ISD::FCOS, ISD::FSINCOS, ISD::FPOW, ISD::FMA})
      setOperationAction(Op, T, Expand);
    // Expand vector FREM, but use a libcall rather than an expansion for scalar
    if (MVT(T).isVector())
      setOperationAction(ISD::FREM, T, Expand);
    else
      setOperationAction(ISD::FREM, T, LibCall);
    // Note supported floating-point library function operators that otherwise
    // default to expand.
    for (auto Op : {ISD::FCEIL, ISD::FFLOOR, ISD::FTRUNC, ISD::FNEARBYINT,
                    ISD::FRINT, ISD::FROUNDEVEN})
      setOperationAction(Op, T, Legal);
    // Support minimum and maximum, which otherwise default to expand.
    setOperationAction(ISD::FMINIMUM, T, Legal);
    setOperationAction(ISD::FMAXIMUM, T, Legal);
    if (Subtarget->hasSIMD128() && MVT(T).isVector()) {
      setOperationAction(ISD::PSEUDO_FMIN, T, Legal);
      setOperationAction(ISD::PSEUDO_FMAX, T, Legal);
    }
    // When experimental v8f16 support is enabled these instructions don't need
    // to be expanded.
    if (T != MVT::v8f16) {
      setOperationAction(ISD::FP16_TO_FP, T, Expand);
      setOperationAction(ISD::FP_TO_FP16, T, Expand);
    }
    if (Subtarget->hasFP16() && T == MVT::f32) {
      setLoadExtAction(ISD::EXTLOAD, T, MVT::f16, Legal);
      setTruncStoreAction(T, MVT::f16, Legal);
    } else {
      setLoadExtAction(ISD::EXTLOAD, T, MVT::f16, Expand);
      setTruncStoreAction(T, MVT::f16, Expand);
    }
  }

  // Expand unavailable integer operations.
  for (auto Op :
       {ISD::BSWAP, ISD::SMUL_LOHI, ISD::UMUL_LOHI, ISD::MULHS, ISD::MULHU,
        ISD::SDIVREM, ISD::UDIVREM, ISD::SHL_PARTS, ISD::SRA_PARTS,
        ISD::SRL_PARTS, ISD::ADDC, ISD::ADDE, ISD::SUBC, ISD::SUBE}) {
    for (auto T : {MVT::i32, MVT::i64})
      setOperationAction(Op, T, Expand);
    if (Subtarget->hasSIMD128())
      for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64})
        setOperationAction(Op, T, Expand);
  }

  if (Subtarget->hasWideArithmetic()) {
    setOperationAction(ISD::ADD, MVT::i128, Custom);
    setOperationAction(ISD::SUB, MVT::i128, Custom);
    setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom);
    setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom);
    setOperationAction(ISD::UADDO, MVT::i64, Custom);
  }

  if (Subtarget->hasNontrappingFPToInt())
    for (auto Op : {ISD::FP_TO_SINT_SAT, ISD::FP_TO_UINT_SAT})
      for (auto T : {MVT::i32, MVT::i64})
        setOperationAction(Op, T, Custom);

  if (Subtarget->hasRelaxedSIMD()) {
    setOperationAction(
        {ISD::FMINNUM, ISD::FMINIMUMNUM, ISD::FMAXNUM, ISD::FMAXIMUMNUM},
        {MVT::v4f32, MVT::v2f64}, Custom);
  }

  // Combine expands these operations, because wasi-libc and emscripten do not
  // yet have the dedicated libcalls.
  setTargetDAGCombine(
      {ISD::FMINIMUM, ISD::FMAXIMUM, ISD::FMINIMUMNUM, ISD::FMAXIMUMNUM});

  // SIMD-specific configuration
  if (Subtarget->hasSIMD128()) {

    setTargetDAGCombine(ISD::INTRINSIC_WO_CHAIN);

    // Combine wide-vector muls, with extend inputs, to extmul_half.
    setTargetDAGCombine(ISD::MUL);
    setTargetDAGCombine(ISD::SHL);

    // Combine vector mask reductions into alltrue/anytrue
    setTargetDAGCombine(ISD::SETCC);

    // Convert vector to integer bitcasts to bitmask
    setTargetDAGCombine(ISD::BITCAST);

    // Hoist bitcasts out of shuffles
    setTargetDAGCombine(ISD::VECTOR_SHUFFLE);

    // Combine extends of extract_subvectors into widening ops
    setTargetDAGCombine({ISD::SIGN_EXTEND, ISD::ZERO_EXTEND});

    // Combine int_to_fp or fp_extend of extract_vectors and vice versa into
    // conversions ops
    setTargetDAGCombine({ISD::SINT_TO_FP, ISD::UINT_TO_FP, ISD::FP_EXTEND,
                         ISD::EXTRACT_SUBVECTOR});

    // Combine fp_to_{s,u}int_sat or fp_round of concat_vectors or vice versa
    // into conversion ops
    setTargetDAGCombine({ISD::FP_TO_SINT_SAT, ISD::FP_TO_UINT_SAT,
                         ISD::FP_TO_SINT, ISD::FP_TO_UINT, ISD::FP_ROUND,
                         ISD::CONCAT_VECTORS});

    setTargetDAGCombine(ISD::TRUNCATE);

    // Support saturating add/sub for i8x16 and i16x8
    for (auto Op : {ISD::SADDSAT, ISD::UADDSAT, ISD::SSUBSAT, ISD::USUBSAT})
      for (auto T : {MVT::v16i8, MVT::v8i16})
        setOperationAction(Op, T, Legal);

    // Support integer abs
    for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64})
      setOperationAction(ISD::ABS, T, Legal);

    // Custom lower BUILD_VECTORs to minimize number of replace_lanes
    for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32, MVT::v2i64,
                   MVT::v2f64})
      setOperationAction(ISD::BUILD_VECTOR, T, Custom);

    if (Subtarget->hasFP16()) {
      setOperationAction(ISD::BUILD_VECTOR, MVT::f16, Custom);
      setOperationAction(ISD::FP_ROUND, MVT::v4f16, Custom);
    }

    // We have custom shuffle lowering to expose the shuffle mask
    for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32, MVT::v2i64,
                   MVT::v2f64})
      setOperationAction(ISD::VECTOR_SHUFFLE, T, Custom);

    if (Subtarget->hasFP16())
      setOperationAction(ISD::VECTOR_SHUFFLE, MVT::v8f16, Custom);

    // Support splatting
    for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32, MVT::v2i64,
                   MVT::v2f64})
      setOperationAction(ISD::SPLAT_VECTOR, T, Legal);

    setOperationAction(ISD::AVGCEILU, {MVT::v8i16, MVT::v16i8}, Legal);

    // Custom lowering since wasm shifts must have a scalar shift amount
    for (auto Op : {ISD::SHL, ISD::SRA, ISD::SRL})
      for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64})
        setOperationAction(Op, T, Custom);

    // Custom lower lane accesses to expand out variable indices
    for (auto Op : {ISD::EXTRACT_VECTOR_ELT, ISD::INSERT_VECTOR_ELT})
      for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32, MVT::v2i64,
                     MVT::v2f64})
        setOperationAction(Op, T, Custom);

    // There is no i8x16.mul instruction
    setOperationAction(ISD::MUL, MVT::v16i8, Expand);

    // Expand integer operations supported for scalars but not SIMD
    for (auto Op :
         {ISD::SDIV, ISD::UDIV, ISD::SREM, ISD::UREM, ISD::ROTL, ISD::ROTR})
      for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64})
        setOperationAction(Op, T, Expand);

    // But we do have integer min and max operations
    for (auto Op : {ISD::SMIN, ISD::SMAX, ISD::UMIN, ISD::UMAX})
      for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32})
        setOperationAction(Op, T, Legal);

    // And we have popcnt for i8x16. It can be used to expand ctlz/cttz.
    setOperationAction(ISD::CTPOP, MVT::v16i8, Legal);
    setOperationAction(ISD::CTLZ, MVT::v16i8, Expand);
    setOperationAction(ISD::CTTZ, MVT::v16i8, Expand);

    // Custom lower bit counting operations for other types to scalarize them.
    for (auto Op : {ISD::CTLZ, ISD::CTTZ, ISD::CTPOP})
      for (auto T : {MVT::v8i16, MVT::v4i32, MVT::v2i64})
        setOperationAction(Op, T, Custom);

    // Expand float operations supported for scalars but not SIMD
    for (auto Op : {ISD::FCOPYSIGN, ISD::FLOG, ISD::FLOG2, ISD::FLOG10,
                    ISD::FEXP, ISD::FEXP2, ISD::FEXP10})
      for (auto T : {MVT::v4f32, MVT::v2f64})
        setOperationAction(Op, T, Expand);

    // Unsigned comparison operations are unavailable for i64x2 vectors.
    for (auto CC : {ISD::SETUGT, ISD::SETUGE, ISD::SETULT, ISD::SETULE})
      setCondCodeAction(CC, MVT::v2i64, Custom);

    // 64x2 conversions are not in the spec
    for (auto Op :
         {ISD::SINT_TO_FP, ISD::UINT_TO_FP, ISD::FP_TO_SINT, ISD::FP_TO_UINT})
      for (auto T : {MVT::v2i64, MVT::v2f64})
        setOperationAction(Op, T, Expand);

    // But saturating fp_to_int converstions are
    for (auto Op : {ISD::FP_TO_SINT_SAT, ISD::FP_TO_UINT_SAT}) {
      setOperationAction(Op, MVT::v4i32, Custom);
      if (Subtarget->hasFP16()) {
        setOperationAction(Op, MVT::v8i16, Custom);
      }
    }

    // Support vector extending
    for (auto T : MVT::integer_fixedlen_vector_valuetypes()) {
      setOperationAction(ISD::ANY_EXTEND_VECTOR_INREG, T, Custom);
      setOperationAction(ISD::SIGN_EXTEND_VECTOR_INREG, T, Custom);
      setOperationAction(ISD::ZERO_EXTEND_VECTOR_INREG, T, Custom);
    }

    if (Subtarget->hasFP16()) {
      setOperationAction(ISD::FMA, MVT::v8f16, Legal);
    }

    if (Subtarget->hasRelaxedSIMD()) {
      setOperationAction(ISD::FMULADD, MVT::v4f32, Legal);
      setOperationAction(ISD::FMULADD, MVT::v2f64, Legal);
    }

    // Partial MLA reductions.
    for (auto Op : {ISD::PARTIAL_REDUCE_SMLA, ISD::PARTIAL_REDUCE_UMLA}) {
      setPartialReduceMLAAction(Op, MVT::v4i32, MVT::v16i8, Legal);
      setPartialReduceMLAAction(Op, MVT::v4i32, MVT::v8i16, Legal);
    }
  }

  // As a special case, these operators use the type to mean the type to
  // sign-extend from.
  setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i1, Expand);
  if (!Subtarget->hasSignExt()) {
    // Sign extends are legal only when extending a vector extract
    auto Action = Subtarget->hasSIMD128() ? Custom : Expand;
    for (auto T : {MVT::i8, MVT::i16, MVT::i32})
      setOperationAction(ISD::SIGN_EXTEND_INREG, T, Action);
  }
  for (auto T : MVT::integer_fixedlen_vector_valuetypes())
    setOperationAction(ISD::SIGN_EXTEND_INREG, T, Expand);

  // Dynamic stack allocation: use the default expansion.
  setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
  setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
  setOperationAction(ISD::DYNAMIC_STACKALLOC, MVTPtr, Expand);

  setOperationAction(ISD::FrameIndex, MVT::i32, Custom);
  setOperationAction(ISD::FrameIndex, MVT::i64, Custom);
  setOperationAction(ISD::CopyToReg, MVT::Other, Custom);

  // Expand these forms; we pattern-match the forms that we can handle in isel.
  for (auto T : {MVT::i32, MVT::i64, MVT::f32, MVT::f64})
    for (auto Op : {ISD::BR_CC, ISD::SELECT_CC})
      setOperationAction(Op, T, Expand);

  if (Subtarget->hasReferenceTypes())
    for (auto Op : {ISD::BR_CC, ISD::SELECT_CC})
      for (auto T : {MVT::externref, MVT::funcref})
        setOperationAction(Op, T, Expand);

  // There is no vector conditional select instruction
  for (auto T :
       {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v4f32, MVT::v2i64, MVT::v2f64})
    setOperationAction(ISD::SELECT_CC, T, Expand);

  // We have custom switch handling.
  setOperationAction(ISD::BR_JT, MVT::Other, Custom);

  // WebAssembly doesn't have:
  //  - Floating-point extending loads.
  //  - Floating-point truncating stores.
  //  - i1 extending loads.
  //  - truncating SIMD stores and most extending loads
  setLoadExtAction(ISD::EXTLOAD, MVT::f64, MVT::f32, Expand);
  setTruncStoreAction(MVT::f64, MVT::f32, Expand);
  for (auto T : MVT::integer_valuetypes())
    for (auto Ext : {ISD::EXTLOAD, ISD::ZEXTLOAD, ISD::SEXTLOAD})
      setLoadExtAction(Ext, T, MVT::i1, Promote);
  if (Subtarget->hasSIMD128()) {
    for (auto T : {MVT::v16i8, MVT::v8i16, MVT::v4i32, MVT::v2i64, MVT::v4f32,
                   MVT::v2f64}) {
      for (auto MemT : MVT::fixedlen_vector_valuetypes()) {
        if (MVT(T) != MemT) {
          setTruncStoreAction(T, MemT, Expand);
          for (auto Ext : {ISD::EXTLOAD, ISD::ZEXTLOAD, ISD::SEXTLOAD})
            setLoadExtAction(Ext, T, MemT, Expand);
        }
      }
    }
    // But some vector extending loads are legal
    for (auto Ext : {ISD::EXTLOAD, ISD::SEXTLOAD, ISD::ZEXTLOAD}) {
      setLoadExtAction(Ext, MVT::v8i16, MVT::v8i8, Legal);
      setLoadExtAction(Ext, MVT::v4i32, MVT::v4i16, Legal);
      setLoadExtAction(Ext, MVT::v2i64, MVT::v2i32, Legal);
    }
    setLoadExtAction(ISD::EXTLOAD, MVT::v2f64, MVT::v2f32, Legal);
  }

  // Don't do anything clever with build_pairs
  setOperationAction(ISD::BUILD_PAIR, MVT::i64, Expand);

  // Trap lowers to wasm unreachable
  setOperationAction(ISD::TRAP, MVT::Other, Legal);
  setOperationAction(ISD::DEBUGTRAP, MVT::Other, Legal);

  // Exception handling intrinsics
  setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
  setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::Other, Custom);
  setOperationAction(ISD::INTRINSIC_VOID, MVT::Other, Custom);

  setMaxAtomicSizeInBitsSupported(64);

  // Always convert switches to br_tables unless there is only one case, which
  // is equivalent to a simple branch. This reduces code size for wasm, and we
  // defer possible jump table optimizations to the VM.
  setMinimumJumpTableEntries(2);
}

TargetLowering::AtomicExpansionKind
WebAssemblyTargetLowering::shouldExpandAtomicRMWInIR(
    const AtomicRMWInst *AI) const {
  // We have wasm instructions for these
  switch (AI->getOperation()) {
  case AtomicRMWInst::Add:
  case AtomicRMWInst::Sub:
  case AtomicRMWInst::And:
  case AtomicRMWInst::Or:
  case AtomicRMWInst::Xor:
  case AtomicRMWInst::Xchg:
    return AtomicExpansionKind::None;
  default:
    break;
  }
  return AtomicExpansionKind::CmpXChg;
}

bool WebAssemblyTargetLowering::shouldScalarizeBinop(SDValue VecOp) const {
  // Implementation copied from X86TargetLowering.
  unsigned Opc = VecOp.getOpcode();

  // Assume target opcodes can't be scalarized.
  // TODO - do we have any exceptions?
  if (Opc >= ISD::BUILTIN_OP_END || !isBinOp(Opc))
    return false;

  // If the vector op is not supported, try to convert to scalar.
  EVT VecVT = VecOp.getValueType();
  if (!isOperationLegalOrCustomOrPromote(Opc, VecVT))
    return true;

  // If the vector op is supported, but the scalar op is not, the transform may
  // not be worthwhile.
  EVT ScalarVT = VecVT.getScalarType();
  return isOperationLegalOrCustomOrPromote(Opc, ScalarVT);
}

FastISel *WebAssemblyTargetLowering::createFastISel(
    FunctionLoweringInfo &FuncInfo, const TargetLibraryInfo *LibInfo,
    const LibcallLoweringInfo *LibcallLowering) const {
  return WebAssembly::createFastISel(FuncInfo, LibInfo, LibcallLowering);
}

MVT WebAssemblyTargetLowering::getScalarShiftAmountTy(const DataLayout & /*DL*/,
                                                      EVT VT) const {
  unsigned BitWidth = NextPowerOf2(VT.getSizeInBits() - 1);
  if (BitWidth > 1 && BitWidth < 8)
    BitWidth = 8;

  if (BitWidth > 64) {
    // The shift will be lowered to a libcall, and compiler-rt libcalls expect
    // the count to be an i32.
    BitWidth = 32;
    assert(BitWidth >= Log2_32_Ceil(VT.getSizeInBits()) &&
           "32-bit shift counts ought to be enough for anyone");
  }

  MVT Result = MVT::getIntegerVT(BitWidth);
  assert(Result != MVT::INVALID_SIMPLE_VALUE_TYPE &&
         "Unable to represent scalar shift amount type");
  return Result;
}

// Lower an fp-to-int conversion operator from the LLVM opcode, which has an
// undefined result on invalid/overflow, to the WebAssembly opcode, which
// traps on invalid/overflow.
static MachineBasicBlock *LowerFPToInt(MachineInstr &MI, DebugLoc DL,
                                       MachineBasicBlock *BB,
                                       const TargetInstrInfo &TII,
                                       bool IsUnsigned, bool Int64,
                                       bool Float64, unsigned LoweredOpcode) {
  MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();

  Register OutReg = MI.getOperand(0).getReg();
  Register InReg = MI.getOperand(1).getReg();

  unsigned Abs = Float64 ? WebAssembly::ABS_F64 : WebAssembly::ABS_F32;
  unsigned FConst = Float64 ? WebAssembly::CONST_F64 : WebAssembly::CONST_F32;
  unsigned LT = Float64 ? WebAssembly::LT_F64 : WebAssembly::LT_F32;
  unsigned GE = Float64 ? WebAssembly::GE_F64 : WebAssembly::GE_F32;
  unsigned IConst = Int64 ? WebAssembly::CONST_I64 : WebAssembly::CONST_I32;
  unsigned Eqz = WebAssembly::EQZ_I32;
  unsigned And = WebAssembly::AND_I32;
  int64_t Limit = Int64 ? INT64_MIN : INT32_MIN;
  int64_t Substitute = IsUnsigned ? 0 : Limit;
  double CmpVal = IsUnsigned ? -(double)Limit * 2.0 : -(double)Limit;
  auto &Context = BB->getParent()->getFunction().getContext();
  Type *Ty = Float64 ? Type::getDoubleTy(Context) : Type::getFloatTy(Context);

  const BasicBlock *LLVMBB = BB->getBasicBlock();
  MachineFunction *F = BB->getParent();
  MachineBasicBlock *TrueMBB = F->CreateMachineBasicBlock(LLVMBB);
  MachineBasicBlock *FalseMBB = F->CreateMachineBasicBlock(LLVMBB);
  MachineBasicBlock *DoneMBB = F->CreateMachineBasicBlock(LLVMBB);

  MachineFunction::iterator It = ++BB->getIterator();
  F->insert(It, FalseMBB);
  F->insert(It, TrueMBB);
  F->insert(It, DoneMBB);

  // Transfer the remainder of BB and its successor edges to DoneMBB.
  DoneMBB->splice(DoneMBB->begin(), BB, std::next(MI.getIterator()), BB->end());
  DoneMBB->transferSuccessorsAndUpdatePHIs(BB);

  BB->addSuccessor(TrueMBB);
  BB->addSuccessor(FalseMBB);
  TrueMBB->addSuccessor(DoneMBB);
  FalseMBB->addSuccessor(DoneMBB);

  unsigned Tmp0, Tmp1, CmpReg, EqzReg, FalseReg, TrueReg;
  Tmp0 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
  Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
  CmpReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
  EqzReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
  FalseReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));
  TrueReg = MRI.createVirtualRegister(MRI.getRegClass(OutReg));

  MI.eraseFromParent();
  // For signed numbers, we can do a single comparison to determine whether
  // fabs(x) is within range.
  if (IsUnsigned) {
    Tmp0 = InReg;
  } else {
    BuildMI(BB, DL, TII.get(Abs), Tmp0).addReg(InReg);
  }
  BuildMI(BB, DL, TII.get(FConst), Tmp1)
      .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, CmpVal)));
  BuildMI(BB, DL, TII.get(LT), CmpReg).addReg(Tmp0).addReg(Tmp1);

  // For unsigned numbers, we have to do a separate comparison with zero.
  if (IsUnsigned) {
    Tmp1 = MRI.createVirtualRegister(MRI.getRegClass(InReg));
    Register SecondCmpReg =
        MRI.createVirtualRegister(&WebAssembly::I32RegClass);
    Register AndReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);
    BuildMI(BB, DL, TII.get(FConst), Tmp1)
        .addFPImm(cast<ConstantFP>(ConstantFP::get(Ty, 0.0)));
    BuildMI(BB, DL, TII.get(GE), SecondCmpReg).addReg(Tmp0).addReg(Tmp1);
    BuildMI(BB, DL, TII.get(And), AndReg).addReg(CmpReg).addReg(SecondCmpReg);
    CmpReg = AndReg;
  }

  BuildMI(BB, DL, TII.get(Eqz), EqzReg).addReg(CmpReg);

  // Create the CFG diamond to select between doing the conversion or using
  // the substitute value.
  BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)).addMBB(TrueMBB).addReg(EqzReg);
  BuildMI(FalseMBB, DL, TII.get(LoweredOpcode), FalseReg).addReg(InReg);
  BuildMI(FalseMBB, DL, TII.get(WebAssembly::BR)).addMBB(DoneMBB);
  BuildMI(TrueMBB, DL, TII.get(IConst), TrueReg).addImm(Substitute);
  BuildMI(*DoneMBB, DoneMBB->begin(), DL, TII.get(TargetOpcode::PHI), OutReg)
      .addReg(FalseReg)
      .addMBB(FalseMBB)
      .addReg(TrueReg)
      .addMBB(TrueMBB);

  return DoneMBB;
}

// Lower a `MEMCPY` instruction into a CFG triangle around a `MEMORY_COPY`
// instuction to handle the zero-length case.
static MachineBasicBlock *LowerMemcpy(MachineInstr &MI, DebugLoc DL,
                                      MachineBasicBlock *BB,
                                      const TargetInstrInfo &TII, bool Int64) {
  MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();

  MachineOperand DstMem = MI.getOperand(0);
  MachineOperand SrcMem = MI.getOperand(1);
  MachineOperand Dst = MI.getOperand(2);
  MachineOperand Src = MI.getOperand(3);
  MachineOperand Len = MI.getOperand(4);

  // If the length is a constant, we don't actually need the check.
  if (MachineInstr *Def = MRI.getVRegDef(Len.getReg())) {
    if (Def->getOpcode() == WebAssembly::CONST_I32 ||
        Def->getOpcode() == WebAssembly::CONST_I64) {
      if (Def->getOperand(1).getImm() == 0) {
        // A zero-length memcpy is a no-op.
        MI.eraseFromParent();
        return BB;
      }
      // A non-zero-length memcpy doesn't need a zero check.
      unsigned MemoryCopy =
          Int64 ? WebAssembly::MEMORY_COPY_A64 : WebAssembly::MEMORY_COPY_A32;
      BuildMI(*BB, MI, DL, TII.get(MemoryCopy))
          .add(DstMem)
          .add(SrcMem)
          .add(Dst)
          .add(Src)
          .add(Len);
      MI.eraseFromParent();
      return BB;
    }
  }

  // We're going to add an extra use to `Len` to test if it's zero; that
  // use shouldn't be a kill, even if the original use is.
  MachineOperand NoKillLen = Len;
  NoKillLen.setIsKill(false);

  // Decide on which `MachineInstr` opcode we're going to use.
  unsigned Eqz = Int64 ? WebAssembly::EQZ_I64 : WebAssembly::EQZ_I32;
  unsigned MemoryCopy =
      Int64 ? WebAssembly::MEMORY_COPY_A64 : WebAssembly::MEMORY_COPY_A32;

  // Create two new basic blocks; one for the new `memory.fill` that we can
  // branch over, and one for the rest of the instructions after the original
  // `memory.fill`.
  const BasicBlock *LLVMBB = BB->getBasicBlock();
  MachineFunction *F = BB->getParent();
  MachineBasicBlock *TrueMBB = F->CreateMachineBasicBlock(LLVMBB);
  MachineBasicBlock *DoneMBB = F->CreateMachineBasicBlock(LLVMBB);

  MachineFunction::iterator It = ++BB->getIterator();
  F->insert(It, TrueMBB);
  F->insert(It, DoneMBB);

  // Transfer the remainder of BB and its successor edges to DoneMBB.
  DoneMBB->splice(DoneMBB->begin(), BB, std::next(MI.getIterator()), BB->end());
  DoneMBB->transferSuccessorsAndUpdatePHIs(BB);

  // Connect the CFG edges.
  BB->addSuccessor(TrueMBB);
  BB->addSuccessor(DoneMBB);
  TrueMBB->addSuccessor(DoneMBB);

  // Create a virtual register for the `Eqz` result.
  unsigned EqzReg;
  EqzReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);

  // Erase the original `memory.copy`.
  MI.eraseFromParent();

  // Test if `Len` is zero.
  BuildMI(BB, DL, TII.get(Eqz), EqzReg).add(NoKillLen);

  // Insert a new `memory.copy`.
  BuildMI(TrueMBB, DL, TII.get(MemoryCopy))
      .add(DstMem)
      .add(SrcMem)
      .add(Dst)
      .add(Src)
      .add(Len);

  // Create the CFG triangle.
  BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)).addMBB(DoneMBB).addReg(EqzReg);
  BuildMI(TrueMBB, DL, TII.get(WebAssembly::BR)).addMBB(DoneMBB);

  return DoneMBB;
}

// Lower a `MEMSET` instruction into a CFG triangle around a `MEMORY_FILL`
// instuction to handle the zero-length case.
static MachineBasicBlock *LowerMemset(MachineInstr &MI, DebugLoc DL,
                                      MachineBasicBlock *BB,
                                      const TargetInstrInfo &TII, bool Int64) {
  MachineRegisterInfo &MRI = BB->getParent()->getRegInfo();

  MachineOperand Mem = MI.getOperand(0);
  MachineOperand Dst = MI.getOperand(1);
  MachineOperand Val = MI.getOperand(2);
  MachineOperand Len = MI.getOperand(3);

  // If the length is a constant, we don't actually need the check.
  if (MachineInstr *Def = MRI.getVRegDef(Len.getReg())) {
    if (Def->getOpcode() == WebAssembly::CONST_I32 ||
        Def->getOpcode() == WebAssembly::CONST_I64) {
      if (Def->getOperand(1).getImm() == 0) {
        // A zero-length memset is a no-op.
        MI.eraseFromParent();
        return BB;
      }
      // A non-zero-length memset doesn't need a zero check.
      unsigned MemoryFill =
          Int64 ? WebAssembly::MEMORY_FILL_A64 : WebAssembly::MEMORY_FILL_A32;
      BuildMI(*BB, MI, DL, TII.get(MemoryFill))
          .add(Mem)
          .add(Dst)
          .add(Val)
          .add(Len);
      MI.eraseFromParent();
      return BB;
    }
  }

  // We're going to add an extra use to `Len` to test if it's zero; that
  // use shouldn't be a kill, even if the original use is.
  MachineOperand NoKillLen = Len;
  NoKillLen.setIsKill(false);

  // Decide on which `MachineInstr` opcode we're going to use.
  unsigned Eqz = Int64 ? WebAssembly::EQZ_I64 : WebAssembly::EQZ_I32;
  unsigned MemoryFill =
      Int64 ? WebAssembly::MEMORY_FILL_A64 : WebAssembly::MEMORY_FILL_A32;

  // Create two new basic blocks; one for the new `memory.fill` that we can
  // branch over, and one for the rest of the instructions after the original
  // `memory.fill`.
  const BasicBlock *LLVMBB = BB->getBasicBlock();
  MachineFunction *F = BB->getParent();
  MachineBasicBlock *TrueMBB = F->CreateMachineBasicBlock(LLVMBB);
  MachineBasicBlock *DoneMBB = F->CreateMachineBasicBlock(LLVMBB);

  MachineFunction::iterator It = ++BB->getIterator();
  F->insert(It, TrueMBB);
  F->insert(It, DoneMBB);

  // Transfer the remainder of BB and its successor edges to DoneMBB.
  DoneMBB->splice(DoneMBB->begin(), BB, std::next(MI.getIterator()), BB->end());
  DoneMBB->transferSuccessorsAndUpdatePHIs(BB);

  // Connect the CFG edges.
  BB->addSuccessor(TrueMBB);
  BB->addSuccessor(DoneMBB);
  TrueMBB->addSuccessor(DoneMBB);

  // Create a virtual register for the `Eqz` result.
  unsigned EqzReg;
  EqzReg = MRI.createVirtualRegister(&WebAssembly::I32RegClass);

  // Erase the original `memory.fill`.
  MI.eraseFromParent();

  // Test if `Len` is zero.
  BuildMI(BB, DL, TII.get(Eqz), EqzReg).add(NoKillLen);

  // Insert a new `memory.copy`.
  BuildMI(TrueMBB, DL, TII.get(MemoryFill)).add(Mem).add(Dst).add(Val).add(Len);

  // Create the CFG triangle.
  BuildMI(BB, DL, TII.get(WebAssembly::BR_IF)).addMBB(DoneMBB).addReg(EqzReg);
  BuildMI(TrueMBB, DL, TII.get(WebAssembly::BR)).addMBB(DoneMBB);

  return DoneMBB;
}

static MachineBasicBlock *
LowerCallResults(MachineInstr &CallResults, DebugLoc DL, MachineBasicBlock *BB,
                 const WebAssemblySubtarget *Subtarget,
                 const TargetInstrInfo &TII) {
  MachineInstr &CallParams = *CallResults.getPrevNode();
  assert(CallParams.getOpcode() == WebAssembly::CALL_PARAMS);
  assert(CallResults.getOpcode() == WebAssembly::CALL_RESULTS ||
         CallResults.getOpcode() == WebAssembly::RET_CALL_RESULTS);

  bool IsIndirect =
      CallParams.getOperand(0).isReg() || CallParams.getOperand(0).isFI();
  bool IsRetCall = CallResults.getOpcode() == WebAssembly::RET_CALL_RESULTS;

  bool IsFuncrefCall = false;
  if (IsIndirect && CallParams.getOperand(0).isReg()) {
    Register Reg = CallParams.getOperand(0).getReg();
    const MachineFunction *MF = BB->getParent();
    const MachineRegisterInfo &MRI = MF->getRegInfo();
    const TargetRegisterClass *TRC = MRI.getRegClass(Reg);
    IsFuncrefCall = (TRC == &WebAssembly::FUNCREFRegClass);
    assert(!IsFuncrefCall || Subtarget->hasReferenceTypes());
  }

  unsigned CallOp;
  if (IsIndirect && IsRetCall) {
    CallOp = WebAssembly::RET_CALL_INDIRECT;
  } else if (IsIndirect) {
    CallOp = WebAssembly::CALL_INDIRECT;
  } else if (IsRetCall) {
    CallOp = WebAssembly::RET_CALL;
  } else {
    CallOp = WebAssembly::CALL;
  }

  MachineFunction &MF = *BB->getParent();
  const MCInstrDesc &MCID = TII.get(CallOp);
  MachineInstrBuilder MIB(MF, MF.CreateMachineInstr(MCID, DL));

  // Move the function pointer to the end of the arguments for indirect calls
  if (IsIndirect) {
    auto FnPtr = CallParams.getOperand(0);
    CallParams.removeOperand(0);

    // For funcrefs, call_indirect is done through __funcref_call_table and the
    // funcref is always installed in slot 0 of the table, therefore instead of
    // having the function pointer added at the end of the params list, a zero
    // (the index in
    // __funcref_call_table is added).
    if (IsFuncrefCall) {
      Register RegZero =
          MF.getRegInfo().createVirtualRegister(&WebAssembly::I32RegClass);
      MachineInstrBuilder MIBC0 =
          BuildMI(MF, DL, TII.get(WebAssembly::CONST_I32), RegZero).addImm(0);

      BB->insert(CallResults.getIterator(), MIBC0);
      MachineInstrBuilder(MF, CallParams).addReg(RegZero);
    } else
      CallParams.addOperand(FnPtr);
  }

  for (auto Def : CallResults.defs())
    MIB.add(Def);

  if (IsIndirect) {
    // Placeholder for the type index.
    // This gets replaced with the correct value in WebAssemblyMCInstLower.cpp
    MIB.addImm(0);
    // The table into which this call_indirect indexes.
    MCSymbolWasm *Table = IsFuncrefCall
                              ? WebAssembly::getOrCreateFuncrefCallTableSymbol(
                                    MF.getContext(), Subtarget)
                              : WebAssembly::getOrCreateFunctionTableSymbol(
                                    MF.getContext(), Subtarget);
    if (Subtarget->hasCallIndirectOverlong()) {
      MIB.addSym(Table);
    } else {
      // For the MVP there is at most one table whose number is 0, but we can't
      // write a table symbol or issue relocations.  Instead we just ensure the
      // table is live and write a zero.
      Table->setNoStrip();
      MIB.addImm(0);
    }
  }

  for (auto Use : CallParams.uses())
    MIB.add(Use);

  BB->insert(CallResults.getIterator(), MIB);
  CallParams.eraseFromParent();
  CallResults.eraseFromParent();

  // If this is a funcref call, to avoid hidden GC roots, we need to clear the
  // table slot with ref.null upon call_indirect return.
  //
  // This generates the following code, which comes right after a call_indirect
  // of a funcref:
  //
  //    i32.const 0
  //    ref.null func
  //    table.set __funcref_call_table
  if (IsIndirect && IsFuncrefCall) {
    MCSymbolWasm *Table = WebAssembly::getOrCreateFuncrefCallTableSymbol(
        MF.getContext(), Subtarget);
    Register RegZero =
        MF.getRegInfo().createVirtualRegister(&WebAssembly::I32RegClass);
    MachineInstr *Const0 =
        BuildMI(MF, DL, TII.get(WebAssembly::CONST_I32), RegZero).addImm(0);
    BB->insertAfter(MIB.getInstr()->getIterator(), Const0);

    Register RegFuncref =
        MF.getRegInfo().createVirtualRegister(&WebAssembly::FUNCREFRegClass);
    MachineInstr *RefNull =
        BuildMI(MF, DL, TII.get(WebAssembly::REF_NULL_FUNCREF), RegFuncref);
    BB->insertAfter(Const0->getIterator(), RefNull);

    MachineInstr *TableSet =
        BuildMI(MF, DL, TII.get(WebAssembly::TABLE_SET_FUNCREF))
            .addSym(Table)
            .addReg(RegZero)
            .addReg(RegFuncref);
    BB->insertAfter(RefNull->getIterator(), TableSet);
  }

  return BB;
}

MachineBasicBlock *WebAssemblyTargetLowering::EmitInstrWithCustomInserter(
    MachineInstr &MI, MachineBasicBlock *BB) const {
  const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
  DebugLoc DL = MI.getDebugLoc();

  switch (MI.getOpcode()) {
  default:
    llvm_unreachable("Unexpected instr type to insert");
  case WebAssembly::FP_TO_SINT_I32_F32:
    return LowerFPToInt(MI, DL, BB, TII, false, false, false,
                        WebAssembly::I32_TRUNC_S_F32);
  case WebAssembly::FP_TO_UINT_I32_F32:
    return LowerFPToInt(MI, DL, BB, TII, true, false, false,
                        WebAssembly::I32_TRUNC_U_F32);
  case WebAssembly::FP_TO_SINT_I64_F32:
    return LowerFPToInt(MI, DL, BB, TII, false, true, false,
                        WebAssembly::I64_TRUNC_S_F32);
  case WebAssembly::FP_TO_UINT_I64_F32:
    return LowerFPToInt(MI, DL, BB, TII, true, true, false,
                        WebAssembly::I64_TRUNC_U_F32);
  case WebAssembly::FP_TO_SINT_I32_F64:
    return LowerFPToInt(MI, DL, BB, TII, false, false, true,
                        WebAssembly::I32_TRUNC_S_F64);
  case WebAssembly::FP_TO_UINT_I32_F64:
    return LowerFPToInt(MI, DL, BB, TII, true, false, true,
                        WebAssembly::I32_TRUNC_U_F64);
  case WebAssembly::FP_TO_SINT_I64_F64:
    return LowerFPToInt(MI, DL, BB, TII, false, true, true,
                        WebAssembly::I64_TRUNC_S_F64);
  case WebAssembly::FP_TO_UINT_I64_F64:
    return LowerFPToInt(MI, DL, BB, TII, true, true, true,
                        WebAssembly::I64_TRUNC_U_F64);
  case WebAssembly::MEMCPY_A32:
    return LowerMemcpy(MI, DL, BB, TII, false);
  case WebAssembly::MEMCPY_A64:
    return LowerMemcpy(MI, DL, BB, TII, true);
  case WebAssembly::MEMSET_A32:
    return LowerMemset(MI, DL, BB, TII, false);
  case WebAssembly::MEMSET_A64:
    return LowerMemset(MI, DL, BB, TII, true);
  case WebAssembly::CALL_RESULTS:
  case WebAssembly::RET_CALL_RESULTS:
    return LowerCallResults(MI, DL, BB, Subtarget, TII);
  }
}

std::pair<unsigned, const TargetRegisterClass *>
WebAssemblyTargetLowering::getRegForInlineAsmConstraint(
    const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const {
  // First, see if this is a constraint that directly corresponds to a
  // WebAssembly register class.
  if (Constraint.size() == 1) {
    switch (Constraint[0]) {
    case 'r':
      assert(VT != MVT::iPTR && "Pointer MVT not expected here");
      if (Subtarget->hasSIMD128() && VT.isVector()) {
        if (VT.getSizeInBits() == 128)
          return std::make_pair(0U, &WebAssembly::V128RegClass);
      }
      if (VT.isInteger() && !VT.isVector()) {
        if (VT.getSizeInBits() <= 32)
          return std::make_pair(0U, &WebAssembly::I32RegClass);
        if (VT.getSizeInBits() <= 64)
          return std::make_pair(0U, &WebAssembly::I64RegClass);
      }
      if (VT.isFloatingPoint() && !VT.isVector()) {
        switch (VT.getSizeInBits()) {
        case 32:
          return std::make_pair(0U, &WebAssembly::F32RegClass);
        case 64:
          return std::make_pair(0U, &WebAssembly::F64RegClass);
        default:
          break;
        }
      }
      break;
    default:
      break;
    }
  }

  return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT);
}

bool WebAssemblyTargetLowering::isCheapToSpeculateCttz(Type *Ty) const {
  // Assume ctz is a relatively cheap operation.
  return true;
}

bool WebAssemblyTargetLowering::isCheapToSpeculateCtlz(Type *Ty) const {
  // Assume clz is a relatively cheap operation.
  return true;
}

bool WebAssemblyTargetLowering::isLegalAddressingMode(const DataLayout &DL,
                                                      const AddrMode &AM,
                                                      Type *Ty, unsigned AS,
                                                      Instruction *I) const {
  // WebAssembly offsets are added as unsigned without wrapping. The
  // isLegalAddressingMode gives us no way to determine if wrapping could be
  // happening, so we approximate this by accepting only non-negative offsets.
  if (AM.BaseOffs < 0)
    return false;

  // WebAssembly has no scale register operands.
  if (AM.Scale != 0)
    return false;

  // Everything else is legal.
  return true;
}

bool WebAssemblyTargetLowering::allowsMisalignedMemoryAccesses(
    EVT /*VT*/, unsigned /*AddrSpace*/, Align /*Align*/,
    MachineMemOperand::Flags /*Flags*/, unsigned *Fast) const {
  // WebAssembly supports unaligned accesses, though it should be declared
  // with the p2align attribute on loads and stores which do so, and there
  // may be a performance impact. We tell LLVM they're "fast" because
  // for the kinds of things that LLVM uses this for (merging adjacent stores
  // of constants, etc.), WebAssembly implementations will either want the
  // unaligned access or they'll split anyway.
  if (Fast)
    *Fast = 1;
  return true;
}

bool WebAssemblyTargetLowering::isIntDivCheap(EVT VT,
                                              AttributeList Attr) const {
  // The current thinking is that wasm engines will perform this optimization,
  // so we can save on code size.
  return true;
}

bool WebAssemblyTargetLowering::isVectorLoadExtDesirable(SDValue ExtVal) const {
  EVT ExtT = ExtVal.getValueType();
  SDValue N0 = peekThroughFreeze(ExtVal->getOperand(0));
  auto *Load = dyn_cast<LoadSDNode>(N0);
  if (!Load)
    return false;
  EVT MemT = Load->getValueType(0);
  return (ExtT == MVT::v8i16 && MemT == MVT::v8i8) ||
         (ExtT == MVT::v4i32 && MemT == MVT::v4i16) ||
         (ExtT == MVT::v2i64 && MemT == MVT::v2i32);
}

bool WebAssemblyTargetLowering::isOffsetFoldingLegal(
    const GlobalAddressSDNode *GA) const {
  // Wasm doesn't support function addresses with offsets
  const GlobalValue *GV = GA->getGlobal();
  return isa<Function>(GV) ? false : TargetLowering::isOffsetFoldingLegal(GA);
}

EVT WebAssemblyTargetLowering::getSetCCResultType(const DataLayout &DL,
                                                  LLVMContext &C,
                                                  EVT VT) const {
  if (VT.isVector()) {
    if (VT.getVectorElementType() == MVT::f16 && !Subtarget->hasFP16())
      return VT.changeElementType(C, MVT::i1);

    return VT.changeVectorElementTypeToInteger();
  }

  // So far, all branch instructions in Wasm take an I32 condition.
  // The default TargetLowering::getSetCCResultType returns the pointer size,
  // which would be useful to reduce instruction counts when testing
  // against 64-bit pointers/values if at some point Wasm supports that.
  return EVT::getIntegerVT(C, 32);
}

void WebAssemblyTargetLowering::getTgtMemIntrinsic(
    SmallVectorImpl<IntrinsicInfo> &Infos, const CallBase &I,
    MachineFunction &MF, unsigned Intrinsic) const {
  IntrinsicInfo Info;
  switch (Intrinsic) {
  case Intrinsic::wasm_memory_atomic_notify:
    Info.opc = ISD::INTRINSIC_W_CHAIN;
    Info.memVT = MVT::i32;
    Info.ptrVal = I.getArgOperand(0);
    Info.offset = 0;
    Info.align = Align(4);
    // atomic.notify instruction does not really load the memory specified with
    // this argument, but MachineMemOperand should either be load or store, so
    // we set this to a load.
    // FIXME Volatile isn't really correct, but currently all LLVM atomic
    // instructions are treated as volatiles in the backend, so we should be
    // consistent. The same applies for wasm_atomic_wait intrinsics too.
    Info.flags = MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad;
    Infos.push_back(Info);
    return;
  case Intrinsic::wasm_memory_atomic_wait32:
    Info.opc = ISD::INTRINSIC_W_CHAIN;
    Info.memVT = MVT::i32;
    Info.ptrVal = I.getArgOperand(0);
    Info.offset = 0;
    Info.align = Align(4);
    Info.flags = MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad;
    Infos.push_back(Info);
    return;
  case Intrinsic::wasm_memory_atomic_wait64:
    Info.opc = ISD::INTRINSIC_W_CHAIN;
    Info.memVT = MVT::i64;
    Info.ptrVal = I.getArgOperand(0);
    Info.offset = 0;
    Info.align = Align(8);
    Info.flags = MachineMemOperand::MOVolatile | MachineMemOperand::MOLoad;
    Infos.push_back(Info);
    return;
  case Intrinsic::wasm_loadf16_f32:
    Info.opc = ISD::INTRINSIC_W_CHAIN;
    Info.memVT = MVT::f16;
    Info.ptrVal = I.getArgOperand(0);
    Info.offset = 0;
    Info.align = Align(2);
    Info.flags = MachineMemOperand::MOLoad;
    Infos.push_back(Info);
    return;
  case Intrinsic::wasm_storef16_f32:
    Info.opc = ISD::INTRINSIC_VOID;
    Info.memVT = MVT::f16;
    Info.ptrVal = I.getArgOperand(1);
    Info.offset = 0;
    Info.align = Align(2);
    Info.flags = MachineMemOperand::MOStore;
    Infos.push_back(Info);
    return;
  default:
    return;
  }
}

void WebAssemblyTargetLowering::computeKnownBitsForTargetNode(
    const SDValue Op, KnownBits &Known, const APInt &DemandedElts,
    const SelectionDAG &DAG, unsigned Depth) const {
  switch (Op.getOpcode()) {
  default:
    break;
  case ISD::INTRINSIC_WO_CHAIN: {
    unsigned IntNo = Op.getConstantOperandVal(0);
    switch (IntNo) {
    default:
      break;
    case Intrinsic::wasm_bitmask: {
      unsigned BitWidth = Known.getBitWidth();
      EVT VT = Op.getOperand(1).getSimpleValueType();
      unsigned PossibleBits = VT.getVectorNumElements();
      APInt ZeroMask = APInt::getHighBitsSet(BitWidth, BitWidth - PossibleBits);
      Known.Zero |= ZeroMask;
      break;
    }
    }
    break;
  }
  case WebAssemblyISD::EXTEND_LOW_U:
  case WebAssemblyISD::EXTEND_HIGH_U: {
    // We know the high half, of each destination vector element, will be zero.
    SDValue SrcOp = Op.getOperand(0);
    EVT VT = SrcOp.getSimpleValueType();
    unsigned BitWidth = Known.getBitWidth();
    if (VT == MVT::v8i8 || VT == MVT::v16i8) {
      assert(BitWidth >= 8 && "Unexpected width!");
      APInt Mask = APInt::getHighBitsSet(BitWidth, BitWidth - 8);
      Known.Zero |= Mask;
    } else if (VT == MVT::v4i16 || VT == MVT::v8i16) {
      assert(BitWidth >= 16 && "Unexpected width!");
      APInt Mask = APInt::getHighBitsSet(BitWidth, BitWidth - 16);
      Known.Zero |= Mask;
    } else if (VT == MVT::v2i32 || VT == MVT::v4i32) {
      assert(BitWidth >= 32 && "Unexpected width!");
      APInt Mask = APInt::getHighBitsSet(BitWidth, BitWidth - 32);
      Known.Zero |= Mask;
    }
    break;
  }
  // For 128-bit addition if the upper bits are all zero then it's known that
  // the upper bits of the result will have all bits guaranteed zero except the
  // first.
  case WebAssemblyISD::I64_ADD128:
    if (Op.getResNo() == 1) {
      SDValue LHS_HI = Op.getOperand(1);
      SDValue RHS_HI = Op.getOperand(3);
      if (isNullConstant(LHS_HI) && isNullConstant(RHS_HI))
        Known.Zero.setBitsFrom(1);
    }
    break;
  }
}

TargetLoweringBase::LegalizeTypeAction
WebAssemblyTargetLowering::getPreferredVectorAction(MVT VT) const {
  if (VT.isFixedLengthVector()) {
    MVT EltVT = VT.getVectorElementType();
    // We have legal vector types with these lane types, so widening the
    // vector would let us use some of the lanes directly without having to
    // extend or truncate values.
    if (EltVT == MVT::i8 || EltVT == MVT::i16 || EltVT == MVT::i32 ||
        EltVT == MVT::i64 || EltVT == MVT::f32 || EltVT == MVT::f64)
      return TypeWidenVector;
  }

  return TargetLoweringBase::getPreferredVectorAction(VT);
}

bool WebAssemblyTargetLowering::isFMAFasterThanFMulAndFAdd(
    const MachineFunction &MF, EVT VT) const {
  if (!Subtarget->hasFP16() || !VT.isVector())
    return false;

  EVT ScalarVT = VT.getScalarType();
  if (!ScalarVT.isSimple())
    return false;

  return ScalarVT.getSimpleVT().SimpleTy == MVT::f16;
}

bool WebAssemblyTargetLowering::shouldSimplifyDemandedVectorElts(
    SDValue Op, const TargetLoweringOpt &TLO) const {
  // ISel process runs DAGCombiner after legalization; this step is called
  // SelectionDAG optimization phase. This post-legalization combining process
  // runs DAGCombiner on each node, and if there was a change to be made,
  // re-runs legalization again on it and its user nodes to make sure
  // everythiing is in a legalized state.
  //
  // The legalization calls lowering routines, and we do our custom lowering for
  // build_vectors (LowerBUILD_VECTOR), which converts undef vector elements
  // into zeros. But there is a set of routines in DAGCombiner that turns unused
  // (= not demanded) nodes into undef, among which SimplifyDemandedVectorElts
  // turns unused vector elements into undefs. But this routine does not work
  // with our custom LowerBUILD_VECTOR, which turns undefs into zeros. This
  // combination can result in a infinite loop, in which undefs are converted to
  // zeros in legalization and back to undefs in combining.
  //
  // So after DAG is legalized, we prevent SimplifyDemandedVectorElts from
  // running for build_vectors.
  if (Op.getOpcode() == ISD::BUILD_VECTOR && TLO.LegalOps && TLO.LegalTys)
    return false;
  return true;
}

//===----------------------------------------------------------------------===//
// WebAssembly Lowering private implementation.
//===----------------------------------------------------------------------===//

//===----------------------------------------------------------------------===//
// Lowering Code
//===----------------------------------------------------------------------===//

static void fail(const SDLoc &DL, SelectionDAG &DAG, const char *Msg) {
  MachineFunction &MF = DAG.getMachineFunction();
  DAG.getContext()->diagnose(
      DiagnosticInfoUnsupported(MF.getFunction(), Msg, DL.getDebugLoc()));
}

// Test whether the given calling convention is supported.
static bool callingConvSupported(CallingConv::ID CallConv) {
  // We currently support the language-independent target-independent
  // conventions. We don't yet have a way to annotate calls with properties like
  // "cold", and we don't have any call-clobbered registers, so these are mostly
  // all handled the same.
  return CallConv == CallingConv::C || CallConv == CallingConv::Fast ||
         CallConv == CallingConv::Cold ||
         CallConv == CallingConv::PreserveMost ||
         CallConv == CallingConv::PreserveAll ||
         CallConv == CallingConv::CXX_FAST_TLS ||
         CallConv == CallingConv::WASM_EmscriptenInvoke ||
         CallConv == CallingConv::Swift || CallConv == CallingConv::SwiftTail;
}

SDValue
WebAssemblyTargetLowering::LowerCall(CallLoweringInfo &CLI,
                                     SmallVectorImpl<SDValue> &InVals) const {
  SelectionDAG &DAG = CLI.DAG;
  SDLoc DL = CLI.DL;
  SDValue Chain = CLI.Chain;
  SDValue Callee = CLI.Callee;
  MachineFunction &MF = DAG.getMachineFunction();
  auto Layout = MF.getDataLayout();

  // A call through a funcref is expressed in IR as a call through the pointer
  // produced by the llvm.wasm.funcref.to_ptr intrinsic. Detect this here and
  // recover the underlying funcref value so the call can be lowered to a
  // table.set + call_indirect through the dedicated __funcref_call_table.
  bool IsFuncrefCall = false;
  if (Callee.getOpcode() == ISD::INTRINSIC_WO_CHAIN &&
      Callee.getConstantOperandVal(0) == Intrinsic::wasm_funcref_to_ptr) {
    Callee = Callee.getOperand(1);
    IsFuncrefCall = true;
  }

  CallingConv::ID CallConv = CLI.CallConv;
  if (!callingConvSupported(CallConv))
    fail(DL, DAG,
         "WebAssembly doesn't support language-specific or target-specific "
         "calling conventions yet");
  if (CLI.IsPatchPoint)
    fail(DL, DAG, "WebAssembly doesn't support patch point yet");

  if (CLI.IsTailCall) {
    auto NoTail = [&](const char *Msg) {
      if (CLI.CB && CLI.CB->isMustTailCall())
        fail(DL, DAG, Msg);
      CLI.IsTailCall = false;
    };

    if (!Subtarget->hasTailCall())
      NoTail("WebAssembly 'tail-call' feature not enabled");

    // Varargs calls cannot be tail calls because the buffer is on the stack
    if (CLI.IsVarArg)
      NoTail("WebAssembly does not support varargs tail calls");

    // Do not tail call unless caller and callee return types match
    const Function &F = MF.getFunction();
    const TargetMachine &TM = getTargetMachine();
    Type *RetTy = F.getReturnType();
    SmallVector<MVT, 4> CallerRetTys;
    SmallVector<MVT, 4> CalleeRetTys;
    computeLegalValueVTs(F, TM, RetTy, CallerRetTys);
    computeLegalValueVTs(F, TM, CLI.RetTy, CalleeRetTys);
    bool TypesMatch = CallerRetTys.size() == CalleeRetTys.size() &&
                      std::equal(CallerRetTys.begin(), CallerRetTys.end(),
                                 CalleeRetTys.begin());
    if (!TypesMatch)
      NoTail("WebAssembly tail call requires caller and callee return types to "
             "match");

    // If pointers to local stack values are passed, we cannot tail call
    if (CLI.CB) {
      for (auto &Arg : CLI.CB->args()) {
        Value *Val = Arg.get();
        // Trace the value back through pointer operations
        while (true) {
          Value *Src = Val->stripPointerCastsAndAliases();
          if (auto *GEP = dyn_cast<GetElementPtrInst>(Src))
            Src = GEP->getPointerOperand();
          if (Val == Src)
            break;
          Val = Src;
        }
        if (isa<AllocaInst>(Val)) {
          NoTail(
              "WebAssembly does not support tail calling with stack arguments");
          break;
        }
      }
    }
  }

  SmallVectorImpl<ISD::InputArg> &Ins = CLI.Ins;
  SmallVectorImpl<ISD::OutputArg> &Outs = CLI.Outs;
  SmallVectorImpl<SDValue> &OutVals = CLI.OutVals;

  // The generic code may have added an sret argument. If we're lowering an
  // invoke function, the ABI requires that the function pointer be the first
  // argument, so we may have to swap the arguments.
  if (CallConv == CallingConv::WASM_EmscriptenInvoke && Outs.size() >= 2 &&
      Outs[0].Flags.isSRet()) {
    std::swap(Outs[0], Outs[1]);
    std::swap(OutVals[0], OutVals[1]);
  }

  bool HasSwiftSelfArg = false;
  bool HasSwiftErrorArg = false;
  bool HasSwiftAsyncArg = false;
  unsigned NumFixedArgs = 0;
  for (unsigned I = 0; I < Outs.size(); ++I) {
    const ISD::OutputArg &Out = Outs[I];
    SDValue &OutVal = OutVals[I];
    HasSwiftSelfArg |= Out.Flags.isSwiftSelf();
    HasSwiftErrorArg |= Out.Flags.isSwiftError();
    HasSwiftAsyncArg |= Out.Flags.isSwiftAsync();
    if (Out.Flags.isNest())
      fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
    if (Out.Flags.isInAlloca())
      fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
    if (Out.Flags.isInConsecutiveRegs())
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
    if (Out.Flags.isInConsecutiveRegsLast())
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
    if (Out.Flags.isByVal() && Out.Flags.getByValSize() != 0) {
      auto &MFI = MF.getFrameInfo();
      int FI = MFI.CreateStackObject(Out.Flags.getByValSize(),
                                     Out.Flags.getNonZeroByValAlign(),
                                     /*isSS=*/false);
      SDValue SizeNode =
          DAG.getConstant(Out.Flags.getByValSize(), DL, MVT::i32);
      SDValue FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
      Align Alignment = Out.Flags.getNonZeroByValAlign();
      Chain = DAG.getMemcpy(Chain, DL, FINode, OutVal, SizeNode, Alignment,
                            Alignment,
                            /*isVolatile*/ false, /*AlwaysInline=*/false,
                            /*CI=*/nullptr, std::nullopt, MachinePointerInfo(),
                            MachinePointerInfo());
      OutVal = FINode;
    }
    // Count the number of fixed args *after* legalization.
    NumFixedArgs += !Out.Flags.isVarArg();
  }

  bool IsVarArg = CLI.IsVarArg;
  auto PtrVT = getPointerTy(Layout);

  // For swiftcc and swifttailcc, emit additional swiftself, swifterror, and
  // (for swifttailcc) swiftasync arguments if there aren't. These additional
  // arguments are also added for callee signature. They are necessary to match
  // callee and caller signature for indirect call.
  if (CallConv == CallingConv::Swift || CallConv == CallingConv::SwiftTail) {
    Type *PtrTy = PointerType::getUnqual(*DAG.getContext());
    if (!HasSwiftSelfArg) {
      NumFixedArgs++;
      ISD::ArgFlagsTy Flags;
      Flags.setSwiftSelf();
      ISD::OutputArg Arg(Flags, PtrVT, EVT(PtrVT), PtrTy, 0, 0);
      CLI.Outs.push_back(Arg);
      SDValue ArgVal = DAG.getUNDEF(PtrVT);
      CLI.OutVals.push_back(ArgVal);
    }
    if (!HasSwiftErrorArg) {
      NumFixedArgs++;
      ISD::ArgFlagsTy Flags;
      Flags.setSwiftError();
      ISD::OutputArg Arg(Flags, PtrVT, EVT(PtrVT), PtrTy, 0, 0);
      CLI.Outs.push_back(Arg);
      SDValue ArgVal = DAG.getUNDEF(PtrVT);
      CLI.OutVals.push_back(ArgVal);
    }
    if (CallConv == CallingConv::SwiftTail && !HasSwiftAsyncArg) {
      NumFixedArgs++;
      ISD::ArgFlagsTy Flags;
      Flags.setSwiftAsync();
      ISD::OutputArg Arg(Flags, PtrVT, EVT(PtrVT), PtrTy, 0, 0);
      CLI.Outs.push_back(Arg);
      SDValue ArgVal = DAG.getUNDEF(PtrVT);
      CLI.OutVals.push_back(ArgVal);
    }
  }

  // Analyze operands of the call, assigning locations to each operand.
  SmallVector<CCValAssign, 16> ArgLocs;
  CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext());

  if (IsVarArg) {
    // Outgoing non-fixed arguments are placed in a buffer. First
    // compute their offsets and the total amount of buffer space needed.
    for (unsigned I = NumFixedArgs; I < Outs.size(); ++I) {
      const ISD::OutputArg &Out = Outs[I];
      SDValue &Arg = OutVals[I];
      EVT VT = Arg.getValueType();
      assert(VT != MVT::iPTR && "Legalized args should be concrete");
      Type *Ty = VT.getTypeForEVT(*DAG.getContext());
      Align Alignment =
          std::max(Out.Flags.getNonZeroOrigAlign(), Layout.getABITypeAlign(Ty));
      unsigned Offset =
          CCInfo.AllocateStack(Layout.getTypeAllocSize(Ty), Alignment);
      CCInfo.addLoc(CCValAssign::getMem(ArgLocs.size(), VT.getSimpleVT(),
                                        Offset, VT.getSimpleVT(),
                                        CCValAssign::Full));
    }
  }

  unsigned NumBytes = CCInfo.getAlignedCallFrameSize();

  SDValue FINode;
  if (IsVarArg && NumBytes) {
    // For non-fixed arguments, next emit stores to store the argument values
    // to the stack buffer at the offsets computed above.
    MaybeAlign StackAlign = Layout.getStackAlignment();
    assert(StackAlign && "data layout string is missing stack alignment");
    int FI = MF.getFrameInfo().CreateStackObject(NumBytes, *StackAlign,
                                                 /*isSS=*/false);
    unsigned ValNo = 0;
    SmallVector<SDValue, 8> Chains;
    for (SDValue Arg : drop_begin(OutVals, NumFixedArgs)) {
      assert(ArgLocs[ValNo].getValNo() == ValNo &&
             "ArgLocs should remain in order and only hold varargs args");
      unsigned Offset = ArgLocs[ValNo++].getLocMemOffset();
      FINode = DAG.getFrameIndex(FI, getPointerTy(Layout));
      SDValue Add = DAG.getNode(ISD::ADD, DL, PtrVT, FINode,
                                DAG.getConstant(Offset, DL, PtrVT));
      Chains.push_back(
          DAG.getStore(Chain, DL, Arg, Add,
                       MachinePointerInfo::getFixedStack(MF, FI, Offset)));
    }
    if (!Chains.empty())
      Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains);
  } else if (IsVarArg) {
    FINode = DAG.getIntPtrConstant(0, DL);
  }

  if (Callee->getOpcode() == ISD::GlobalAddress) {
    // If the callee is a GlobalAddress node (quite common, every direct call
    // is) turn it into a TargetGlobalAddress node so that LowerGlobalAddress
    // doesn't at MO_GOT which is not needed for direct calls.
    GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Callee);
    Callee = DAG.getTargetGlobalAddress(GA->getGlobal(), DL,
                                        getPointerTy(DAG.getDataLayout()),
                                        GA->getOffset());
    Callee = DAG.getNode(WebAssemblyISD::Wrapper, DL,
                         getPointerTy(DAG.getDataLayout()), Callee);
  }

  // Compute the operands for the CALLn node.
  SmallVector<SDValue, 16> Ops;
  Ops.push_back(Chain);
  Ops.push_back(Callee);

  // Add all fixed arguments. Note that for non-varargs calls, NumFixedArgs
  // isn't reliable.
  Ops.append(OutVals.begin(),
             IsVarArg ? OutVals.begin() + NumFixedArgs : OutVals.end());
  // Add a pointer to the vararg buffer.
  if (IsVarArg)
    Ops.push_back(FINode);

  SmallVector<EVT, 8> InTys;
  for (const auto &In : Ins) {
    assert(!In.Flags.isByVal() && "byval is not valid for return values");
    assert(!In.Flags.isNest() && "nest is not valid for return values");
    if (In.Flags.isInAlloca())
      fail(DL, DAG, "WebAssembly hasn't implemented inalloca return values");
    if (In.Flags.isInConsecutiveRegs())
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs return values");
    if (In.Flags.isInConsecutiveRegsLast())
      fail(DL, DAG,
           "WebAssembly hasn't implemented cons regs last return values");
    // Ignore In.getNonZeroOrigAlign() because all our arguments are passed in
    // registers.
    InTys.push_back(In.VT);
  }

  // Lastly, if this is a call to a funcref we need to add an instruction
  // table.set to the chain and transform the call.
  if (IsFuncrefCall) {
    // In the absence of function references proposal where a funcref call is
    // lowered to call_ref, using reference types we generate a table.set to set
    // the funcref to a special table used solely for this purpose, followed by
    // a call_indirect. Here we just generate the table set, and return the
    // SDValue of the table.set so that LowerCall can finalize the lowering by
    // generating the call_indirect.
    SDValue Chain = Ops[0];

    MCSymbolWasm *Table = WebAssembly::getOrCreateFuncrefCallTableSymbol(
        MF.getContext(), Subtarget);
    SDValue Sym = DAG.getMCSymbol(Table, PtrVT);
    SDValue TableSlot = DAG.getConstant(0, DL, MVT::i32);
    SDValue TableSetOps[] = {Chain, Sym, TableSlot, Callee};
    SDValue TableSet = DAG.getMemIntrinsicNode(
        WebAssemblyISD::TABLE_SET, DL, DAG.getVTList(MVT::Other), TableSetOps,
        MVT::funcref, MachinePointerInfo(), Align(1),
        MachineMemOperand::MOStore);

    Ops[0] = TableSet; // The new chain is the TableSet itself
  }

  if (CLI.IsTailCall) {
    // ret_calls do not return values to the current frame
    SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
    return DAG.getNode(WebAssemblyISD::RET_CALL, DL, NodeTys, Ops);
  }

  InTys.push_back(MVT::Other);
  SDVTList InTyList = DAG.getVTList(InTys);
  SDValue Res = DAG.getNode(WebAssemblyISD::CALL, DL, InTyList, Ops);

  for (size_t I = 0; I < Ins.size(); ++I)
    InVals.push_back(Res.getValue(I));

  // Return the chain
  return Res.getValue(Ins.size());
}

bool WebAssemblyTargetLowering::CanLowerReturn(
    CallingConv::ID /*CallConv*/, MachineFunction & /*MF*/, bool /*IsVarArg*/,
    const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext & /*Context*/,
    const Type *RetTy) const {
  // WebAssembly can only handle returning tuples with multivalue enabled
  return WebAssembly::canLowerReturn(Outs.size(), Subtarget);
}

SDValue WebAssemblyTargetLowering::LowerReturn(
    SDValue Chain, CallingConv::ID CallConv, bool /*IsVarArg*/,
    const SmallVectorImpl<ISD::OutputArg> &Outs,
    const SmallVectorImpl<SDValue> &OutVals, const SDLoc &DL,
    SelectionDAG &DAG) const {
  assert(WebAssembly::canLowerReturn(Outs.size(), Subtarget) &&
         "MVP WebAssembly can only return up to one value");
  if (!callingConvSupported(CallConv))
    fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");

  SmallVector<SDValue, 4> RetOps(1, Chain);
  RetOps.append(OutVals.begin(), OutVals.end());
  Chain = DAG.getNode(WebAssemblyISD::RETURN, DL, MVT::Other, RetOps);

  // Record the number and types of the return values.
  for (const ISD::OutputArg &Out : Outs) {
    assert(!Out.Flags.isByVal() && "byval is not valid for return values");
    assert(!Out.Flags.isNest() && "nest is not valid for return values");
    assert(!Out.Flags.isVarArg() && "non-fixed return value is not valid");
    if (Out.Flags.isInAlloca())
      fail(DL, DAG, "WebAssembly hasn't implemented inalloca results");
    if (Out.Flags.isInConsecutiveRegs())
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs results");
    if (Out.Flags.isInConsecutiveRegsLast())
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs last results");
  }

  return Chain;
}

SDValue WebAssemblyTargetLowering::LowerFormalArguments(
    SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
    const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
    SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
  if (!callingConvSupported(CallConv))
    fail(DL, DAG, "WebAssembly doesn't support non-C calling conventions");

  MachineFunction &MF = DAG.getMachineFunction();
  auto *MFI = MF.getInfo<WebAssemblyFunctionInfo>();

  // Set up the incoming ARGUMENTS value, which serves to represent the liveness
  // of the incoming values before they're represented by virtual registers.
  MF.getRegInfo().addLiveIn(WebAssembly::ARGUMENTS);

  bool HasSwiftErrorArg = false;
  bool HasSwiftSelfArg = false;
  bool HasSwiftAsyncArg = false;
  for (const ISD::InputArg &In : Ins) {
    HasSwiftSelfArg |= In.Flags.isSwiftSelf();
    HasSwiftErrorArg |= In.Flags.isSwiftError();
    HasSwiftAsyncArg |= In.Flags.isSwiftAsync();
    if (In.Flags.isInAlloca())
      fail(DL, DAG, "WebAssembly hasn't implemented inalloca arguments");
    if (In.Flags.isNest())
      fail(DL, DAG, "WebAssembly hasn't implemented nest arguments");
    if (In.Flags.isInConsecutiveRegs())
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs arguments");
    if (In.Flags.isInConsecutiveRegsLast())
      fail(DL, DAG, "WebAssembly hasn't implemented cons regs last arguments");
    // Ignore In.getNonZeroOrigAlign() because all our arguments are passed in
    // registers.
    InVals.push_back(In.Used ? DAG.getNode(WebAssemblyISD::ARGUMENT, DL, In.VT,
                                           DAG.getTargetConstant(InVals.size(),
                                                                 DL, MVT::i32))
                             : DAG.getUNDEF(In.VT));

    // Record the number and types of arguments.
    MFI->addParam(In.VT);
  }

  // For swiftcc and swifttailcc, emit additional swiftself, swifterror, and
  // (for swifttailcc) swiftasync arguments if there aren't. These additional
  // arguments are also added for callee signature. They are necessary to match
  // callee and caller signature for indirect call.
  auto PtrVT = getPointerTy(MF.getDataLayout());
  if (CallConv == CallingConv::Swift || CallConv == CallingConv::SwiftTail) {
    if (!HasSwiftSelfArg) {
      MFI->addParam(PtrVT);
    }
    if (!HasSwiftErrorArg) {
      MFI->addParam(PtrVT);
    }
    if (CallConv == CallingConv::SwiftTail && !HasSwiftAsyncArg) {
      MFI->addParam(PtrVT);
    }
  }
  // Varargs are copied into a buffer allocated by the caller, and a pointer to
  // the buffer is passed as an argument.
  if (IsVarArg) {
    MVT PtrVT = getPointerTy(MF.getDataLayout());
    Register VarargVreg =
        MF.getRegInfo().createVirtualRegister(getRegClassFor(PtrVT));
    MFI->setVarargBufferVreg(VarargVreg);
    Chain = DAG.getCopyToReg(
        Chain, DL, VarargVreg,
        DAG.getNode(WebAssemblyISD::ARGUMENT, DL, PtrVT,
                    DAG.getTargetConstant(Ins.size(), DL, MVT::i32)));
    MFI->addParam(PtrVT);
  }

  // Record the number and types of arguments and results.
  SmallVector<MVT, 4> Params;
  SmallVector<MVT, 4> Results;
  computeSignatureVTs(MF.getFunction().getFunctionType(), &MF.getFunction(),
                      MF.getFunction(), DAG.getTarget(), Params, Results);
  for (MVT VT : Results)
    MFI->addResult(VT);
  // TODO: Use signatures in WebAssemblyMachineFunctionInfo too and unify
  // the param logic here with ComputeSignatureVTs
  assert(MFI->getParams().size() == Params.size() &&
         std::equal(MFI->getParams().begin(), MFI->getParams().end(),
                    Params.begin()));

  return Chain;
}

void WebAssemblyTargetLowering::ReplaceNodeResults(
    SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const {
  switch (N->getOpcode()) {
  case ISD::SIGN_EXTEND_INREG:
    // Do not add any results, signifying that N should not be custom lowered
    // after all. This happens because simd128 turns on custom lowering for
    // SIGN_EXTEND_INREG, but for non-vector sign extends the result might be an
    // illegal type.
    break;
  case ISD::ANY_EXTEND_VECTOR_INREG:
  case ISD::SIGN_EXTEND_VECTOR_INREG:
  case ISD::ZERO_EXTEND_VECTOR_INREG:
    // Do not add any results, signifying that N should not be custom lowered.
    // EXTEND_VECTOR_INREG is implemented for some vectors, but not all.
    break;
  case ISD::FP_ROUND: {
    EVT VT = N->getValueType(0);
    SDValue Src = N->getOperand(0);
    if (VT == MVT::v4f16 && Src.getValueType() == MVT::v4f32) {
      Results.push_back(
          DAG.getNode(WebAssemblyISD::DEMOTE_ZERO, SDLoc(N), MVT::v8f16, Src));
    }
    break;
  }
  case ISD::ADD:
  case ISD::SUB:
    Results.push_back(Replace128Op(N, DAG));
    break;
  default:
    llvm_unreachable(
        "ReplaceNodeResults not implemented for this op for WebAssembly!");
  }
}

//===----------------------------------------------------------------------===//
//  Custom lowering hooks.
//===----------------------------------------------------------------------===//

SDValue WebAssemblyTargetLowering::LowerOperation(SDValue Op,
                                                  SelectionDAG &DAG) const {
  SDLoc DL(Op);
  switch (Op.getOpcode()) {
  default:
    llvm_unreachable("unimplemented operation lowering");
    return SDValue();
  case ISD::FrameIndex:
    return LowerFrameIndex(Op, DAG);
  case ISD::GlobalAddress:
    return LowerGlobalAddress(Op, DAG);
  case ISD::GlobalTLSAddress:
    return LowerGlobalTLSAddress(Op, DAG);
  case ISD::ExternalSymbol:
    return LowerExternalSymbol(Op, DAG);
  case ISD::JumpTable:
    return LowerJumpTable(Op, DAG);
  case ISD::BR_JT:
    return LowerBR_JT(Op, DAG);
  case ISD::VASTART:
    return LowerVASTART(Op, DAG);
  case ISD::BlockAddress:
  case ISD::BRIND:
    fail(DL, DAG, "WebAssembly hasn't implemented computed gotos");
    return SDValue();
  case ISD::RETURNADDR:
    return LowerRETURNADDR(Op, DAG);
  case ISD::FRAMEADDR:
    return LowerFRAMEADDR(Op, DAG);
  case ISD::CopyToReg:
    return LowerCopyToReg(Op, DAG);
  case ISD::EXTRACT_VECTOR_ELT:
  case ISD::INSERT_VECTOR_ELT:
    return LowerAccessVectorElement(Op, DAG);
  case ISD::INTRINSIC_VOID:
  case ISD::INTRINSIC_WO_CHAIN:
  case ISD::INTRINSIC_W_CHAIN:
    return LowerIntrinsic(Op, DAG);
  case ISD::SIGN_EXTEND_INREG:
    return LowerSIGN_EXTEND_INREG(Op, DAG);
  case ISD::ZERO_EXTEND_VECTOR_INREG:
  case ISD::SIGN_EXTEND_VECTOR_INREG:
  case ISD::ANY_EXTEND_VECTOR_INREG:
    return LowerEXTEND_VECTOR_INREG(Op, DAG);
  case ISD::BUILD_VECTOR:
    return LowerBUILD_VECTOR(Op, DAG);
  case ISD::VECTOR_SHUFFLE:
    return LowerVECTOR_SHUFFLE(Op, DAG);
  case ISD::SETCC:
    return LowerSETCC(Op, DAG);
  case ISD::SHL:
  case ISD::SRA:
  case ISD::SRL:
    return LowerShift(Op, DAG);
  case ISD::FP_TO_SINT_SAT:
  case ISD::FP_TO_UINT_SAT:
    return LowerFP_TO_INT_SAT(Op, DAG);
  case ISD::FMINNUM:
  case ISD::FMINIMUMNUM:
    return LowerFMIN(Op, DAG);
  case ISD::FMAXNUM:
  case ISD::FMAXIMUMNUM:
    return LowerFMAX(Op, DAG);
  case ISD::LOAD:
    return LowerLoad(Op, DAG);
  case ISD::STORE:
    return LowerStore(Op, DAG);
  case ISD::CTPOP:
  case ISD::CTLZ:
  case ISD::CTTZ:
    return DAG.UnrollVectorOp(Op.getNode());
  case ISD::CLEAR_CACHE:
    report_fatal_error("llvm.clear_cache is not supported on wasm");
  case ISD::SMUL_LOHI:
  case ISD::UMUL_LOHI:
    return LowerMUL_LOHI(Op, DAG);
  case ISD::UADDO:
    return LowerUADDO(Op, DAG);
  }
}

static bool IsWebAssemblyGlobal(SDValue Op) {
  if (const GlobalAddressSDNode *GA = dyn_cast<GlobalAddressSDNode>(Op))
    return WebAssembly::isWasmVarAddressSpace(GA->getAddressSpace());

  return false;
}

static std::optional<unsigned> IsWebAssemblyLocal(SDValue Op,
                                                  SelectionDAG &DAG) {
  const FrameIndexSDNode *FI = dyn_cast<FrameIndexSDNode>(Op);
  if (!FI)
    return std::nullopt;

  auto &MF = DAG.getMachineFunction();
  return WebAssemblyFrameLowering::getLocalForStackObject(MF, FI->getIndex());
}

SDValue WebAssemblyTargetLowering::LowerStore(SDValue Op,
                                              SelectionDAG &DAG) const {
  SDLoc DL(Op);
  StoreSDNode *SN = cast<StoreSDNode>(Op.getNode());
  const SDValue &Value = SN->getValue();
  const SDValue &Base = SN->getBasePtr();
  const SDValue &Offset = SN->getOffset();

  if (IsWebAssemblyGlobal(Base)) {
    if (!Offset->isUndef())
      report_fatal_error("unexpected offset when storing to webassembly global",
                         false);

    SDVTList Tys = DAG.getVTList(MVT::Other);
    SDValue Ops[] = {SN->getChain(), Value, Base};
    return DAG.getMemIntrinsicNode(WebAssemblyISD::GLOBAL_SET, DL, Tys, Ops,
                                   SN->getMemoryVT(), SN->getMemOperand());
  }

  if (std::optional<unsigned> Local = IsWebAssemblyLocal(Base, DAG)) {
    if (!Offset->isUndef())
      report_fatal_error("unexpected offset when storing to webassembly local",
                         false);

    SDValue Idx = DAG.getTargetConstant(*Local, Base, MVT::i32);
    SDVTList Tys = DAG.getVTList(MVT::Other); // The chain.
    SDValue Ops[] = {SN->getChain(), Idx, Value};
    return DAG.getNode(WebAssemblyISD::LOCAL_SET, DL, Tys, Ops);
  }

  if (WebAssembly::isWasmVarAddressSpace(SN->getAddressSpace()))
    report_fatal_error(
        "Encountered an unlowerable store to the wasm_var address space",
        false);

  return Op;
}

SDValue WebAssemblyTargetLowering::LowerLoad(SDValue Op,
                                             SelectionDAG &DAG) const {
  SDLoc DL(Op);
  LoadSDNode *LN = cast<LoadSDNode>(Op.getNode());
  const SDValue &Base = LN->getBasePtr();
  const SDValue &Offset = LN->getOffset();

  if (IsWebAssemblyGlobal(Base)) {
    if (!Offset->isUndef())
      report_fatal_error(
          "unexpected offset when loading from webassembly global", false);

    SDVTList Tys = DAG.getVTList(LN->getValueType(0), MVT::Other);
    SDValue Ops[] = {LN->getChain(), Base};
    return DAG.getMemIntrinsicNode(WebAssemblyISD::GLOBAL_GET, DL, Tys, Ops,
                                   LN->getMemoryVT(), LN->getMemOperand());
  }

  if (std::optional<unsigned> Local = IsWebAssemblyLocal(Base, DAG)) {
    if (!Offset->isUndef())
      report_fatal_error(
          "unexpected offset when loading from webassembly local", false);

    SDValue Idx = DAG.getTargetConstant(*Local, Base, MVT::i32);
    EVT LocalVT = LN->getValueType(0);
    return DAG.getNode(WebAssemblyISD::LOCAL_GET, DL, {LocalVT, MVT::Other},
                       {LN->getChain(), Idx});
  }

  if (WebAssembly::isWasmVarAddressSpace(LN->getAddressSpace()))
    report_fatal_error(
        "Encountered an unlowerable load from the wasm_var address space",
        false);

  return Op;
}

SDValue WebAssemblyTargetLowering::LowerMUL_LOHI(SDValue Op,
                                                 SelectionDAG &DAG) const {
  assert(Subtarget->hasWideArithmetic());
  assert(Op.getValueType() == MVT::i64);
  SDLoc DL(Op);
  unsigned Opcode;
  switch (Op.getOpcode()) {
  case ISD::UMUL_LOHI:
    Opcode = WebAssemblyISD::I64_MUL_WIDE_U;
    break;
  case ISD::SMUL_LOHI:
    Opcode = WebAssemblyISD::I64_MUL_WIDE_S;
    break;
  default:
    llvm_unreachable("unexpected opcode");
  }
  SDValue LHS = Op.getOperand(0);
  SDValue RHS = Op.getOperand(1);
  SDValue Lo =
      DAG.getNode(Opcode, DL, DAG.getVTList(MVT::i64, MVT::i64), LHS, RHS);
  SDValue Hi(Lo.getNode(), 1);
  SDValue Ops[] = {Lo, Hi};
  return DAG.getMergeValues(Ops, DL);
}

// Lowers `UADDO` intrinsics to an `i64.add128` instruction when it's enabled.
//
// This enables generating a single wasm instruction for this operation where
// the upper half of both operands are constant zeros. The upper half of the
// result is then whether the overflow happened.
SDValue WebAssemblyTargetLowering::LowerUADDO(SDValue Op,
                                              SelectionDAG &DAG) const {
  assert(Subtarget->hasWideArithmetic());
  assert(Op.getValueType() == MVT::i64);
  assert(Op.getOpcode() == ISD::UADDO);
  SDLoc DL(Op);
  SDValue LHS = Op.getOperand(0);
  SDValue RHS = Op.getOperand(1);
  SDValue Zero = DAG.getConstant(0, DL, MVT::i64);
  SDValue Result =
      DAG.getNode(WebAssemblyISD::I64_ADD128, DL,
                  DAG.getVTList(MVT::i64, MVT::i64), LHS, Zero, RHS, Zero);
  SDValue CarryI64(Result.getNode(), 1);
  SDValue CarryI32 = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, CarryI64);
  SDValue Ops[] = {Result, CarryI32};
  return DAG.getMergeValues(Ops, DL);
}

SDValue WebAssemblyTargetLowering::Replace128Op(SDNode *N,
                                                SelectionDAG &DAG) const {
  assert(Subtarget->hasWideArithmetic());
  assert(N->getValueType(0) == MVT::i128);
  SDLoc DL(N);
  unsigned Opcode;
  switch (N->getOpcode()) {
  case ISD::ADD:
    Opcode = WebAssemblyISD::I64_ADD128;
    break;
  case ISD::SUB:
    Opcode = WebAssemblyISD::I64_SUB128;
    break;
  default:
    llvm_unreachable("unexpected opcode");
  }
  SDValue LHS = N->getOperand(0);
  SDValue RHS = N->getOperand(1);

  SDValue C0 = DAG.getConstant(0, DL, MVT::i64);
  SDValue C1 = DAG.getConstant(1, DL, MVT::i64);
  SDValue LHS_0 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i64, LHS, C0);
  SDValue LHS_1 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i64, LHS, C1);
  SDValue RHS_0 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i64, RHS, C0);
  SDValue RHS_1 = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i64, RHS, C1);
  SDValue Result_LO = DAG.getNode(Opcode, DL, DAG.getVTList(MVT::i64, MVT::i64),
                                  LHS_0, LHS_1, RHS_0, RHS_1);
  SDValue Result_HI(Result_LO.getNode(), 1);
  return DAG.getNode(ISD::BUILD_PAIR, DL, N->getVTList(), Result_LO, Result_HI);
}

SDValue WebAssemblyTargetLowering::LowerCopyToReg(SDValue Op,
                                                  SelectionDAG &DAG) const {
  SDValue Src = Op.getOperand(2);
  if (isa<FrameIndexSDNode>(Src.getNode())) {
    // CopyToReg nodes don't support FrameIndex operands. Other targets select
    // the FI to some LEA-like instruction, but since we don't have that, we
    // need to insert some kind of instruction that can take an FI operand and
    // produces a value usable by CopyToReg (i.e. in a vreg). So insert a dummy
    // local.copy between Op and its FI operand.
    SDValue Chain = Op.getOperand(0);
    SDLoc DL(Op);
    Register Reg = cast<RegisterSDNode>(Op.getOperand(1))->getReg();
    EVT VT = Src.getValueType();
    SDValue Copy(DAG.getMachineNode(VT == MVT::i32 ? WebAssembly::COPY_I32
                                                   : WebAssembly::COPY_I64,
                                    DL, VT, Src),
                 0);
    return Op.getNode()->getNumValues() == 1
               ? DAG.getCopyToReg(Chain, DL, Reg, Copy)
               : DAG.getCopyToReg(Chain, DL, Reg, Copy,
                                  Op.getNumOperands() == 4 ? Op.getOperand(3)
                                                           : SDValue());
  }
  return SDValue();
}

SDValue WebAssemblyTargetLowering::LowerFrameIndex(SDValue Op,
                                                   SelectionDAG &DAG) const {
  int FI = cast<FrameIndexSDNode>(Op)->getIndex();
  return DAG.getTargetFrameIndex(FI, Op.getValueType());
}

SDValue WebAssemblyTargetLowering::LowerRETURNADDR(SDValue Op,
                                                   SelectionDAG &DAG) const {
  SDLoc DL(Op);

  if (!Subtarget->getTargetTriple().isOSEmscripten()) {
    fail(DL, DAG,
         "Non-Emscripten WebAssembly hasn't implemented "
         "__builtin_return_address");
    return SDValue();
  }

  unsigned Depth = Op.getConstantOperandVal(0);
  MakeLibCallOptions CallOptions;
  return makeLibCall(DAG, RTLIB::RETURN_ADDRESS, Op.getValueType(),
                     {DAG.getConstant(Depth, DL, MVT::i32)}, CallOptions, DL)
      .first;
}

SDValue WebAssemblyTargetLowering::LowerFRAMEADDR(SDValue Op,
                                                  SelectionDAG &DAG) const {
  // Non-zero depths are not supported by WebAssembly currently. Use the
  // legalizer's default expansion, which is to return 0 (what this function is
  // documented to do).
  if (Op.getConstantOperandVal(0) > 0)
    return SDValue();

  DAG.getMachineFunction().getFrameInfo().setFrameAddressIsTaken(true);
  EVT VT = Op.getValueType();
  Register FP =
      Subtarget->getRegisterInfo()->getFrameRegister(DAG.getMachineFunction());
  return DAG.getCopyFromReg(DAG.getEntryNode(), SDLoc(Op), FP, VT);
}

SDValue
WebAssemblyTargetLowering::LowerGlobalTLSAddress(SDValue Op,
                                                 SelectionDAG &DAG) const {
  SDLoc DL(Op);
  const auto *GA = cast<GlobalAddressSDNode>(Op);

  MachineFunction &MF = DAG.getMachineFunction();
  if (!MF.getSubtarget<WebAssemblySubtarget>().hasBulkMemory())
    report_fatal_error("cannot use thread-local storage without bulk memory",
                       false);

  const GlobalValue *GV = GA->getGlobal();

  // Currently only Emscripten supports dynamic linking with threads. Therefore,
  // on other targets, if we have thread-local storage, only the local-exec
  // model is possible.
  auto model = Subtarget->getTargetTriple().isOSEmscripten()
                   ? GV->getThreadLocalMode()
                   : GlobalValue::LocalExecTLSModel;

  // Unsupported TLS modes
  assert(model != GlobalValue::NotThreadLocal);
  assert(model != GlobalValue::InitialExecTLSModel);

  if (model == GlobalValue::LocalExecTLSModel ||
      model == GlobalValue::LocalDynamicTLSModel ||
      (model == GlobalValue::GeneralDynamicTLSModel &&
       getTargetMachine().shouldAssumeDSOLocal(GV))) {
    // For DSO-local TLS variables we use offset from __tls_base, or
    // __wasm_get_tls_base() if using libcall thread context.

    MVT PtrVT = getPointerTy(DAG.getDataLayout());
    SDValue BaseAddr(WebAssembly::getTLSBase(DAG, DL, Subtarget), 0);

    SDValue TLSOffset = DAG.getTargetGlobalAddress(
        GV, DL, PtrVT, GA->getOffset(), WebAssemblyII::MO_TLS_BASE_REL);
    SDValue SymOffset =
        DAG.getNode(WebAssemblyISD::WrapperREL, DL, PtrVT, TLSOffset);

    return DAG.getNode(ISD::ADD, DL, PtrVT, BaseAddr, SymOffset);
  }

  assert(model == GlobalValue::GeneralDynamicTLSModel);

  EVT VT = Op.getValueType();
  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
                     DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT,
                                                GA->getOffset(),
                                                WebAssemblyII::MO_GOT_TLS));
}

SDValue WebAssemblyTargetLowering::LowerGlobalAddress(SDValue Op,
                                                      SelectionDAG &DAG) const {
  SDLoc DL(Op);
  const auto *GA = cast<GlobalAddressSDNode>(Op);
  EVT VT = Op.getValueType();
  assert(GA->getTargetFlags() == 0 &&
         "Unexpected target flags on generic GlobalAddressSDNode");
  if (!WebAssembly::isValidAddressSpace(GA->getAddressSpace()))
    fail(DL, DAG, "Invalid address space for WebAssembly target");

  unsigned OperandFlags = 0;
  const GlobalValue *GV = GA->getGlobal();
  // Since WebAssembly tables cannot yet be shared accross modules, we don't
  // need special treatment for tables in PIC mode.
  if (isPositionIndependent() &&
      !WebAssembly::isWebAssemblyTableType(GV->getValueType())) {
    if (getTargetMachine().shouldAssumeDSOLocal(GV)) {
      MachineFunction &MF = DAG.getMachineFunction();
      MVT PtrVT = getPointerTy(MF.getDataLayout());
      const char *BaseName;
      if (GV->getValueType()->isFunctionTy()) {
        BaseName = MF.createExternalSymbolName("__table_base");
        OperandFlags = WebAssemblyII::MO_TABLE_BASE_REL;
      } else {
        BaseName = MF.createExternalSymbolName("__memory_base");
        OperandFlags = WebAssemblyII::MO_MEMORY_BASE_REL;
      }
      SDValue BaseAddr =
          DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT,
                      DAG.getTargetExternalSymbol(BaseName, PtrVT));

      SDValue SymAddr = DAG.getNode(
          WebAssemblyISD::WrapperREL, DL, VT,
          DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT, GA->getOffset(),
                                     OperandFlags));

      return DAG.getNode(ISD::ADD, DL, VT, BaseAddr, SymAddr);
    }
    OperandFlags = WebAssemblyII::MO_GOT;
  }

  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
                     DAG.getTargetGlobalAddress(GA->getGlobal(), DL, VT,
                                                GA->getOffset(), OperandFlags));
}

SDValue
WebAssemblyTargetLowering::LowerExternalSymbol(SDValue Op,
                                               SelectionDAG &DAG) const {
  SDLoc DL(Op);
  const auto *ES = cast<ExternalSymbolSDNode>(Op);
  EVT VT = Op.getValueType();
  assert(ES->getTargetFlags() == 0 &&
         "Unexpected target flags on generic ExternalSymbolSDNode");
  return DAG.getNode(WebAssemblyISD::Wrapper, DL, VT,
                     DAG.getTargetExternalSymbol(ES->getSymbol(), VT));
}

SDValue WebAssemblyTargetLowering::LowerJumpTable(SDValue Op,
                                                  SelectionDAG &DAG) const {
  // There's no need for a Wrapper node because we always incorporate a jump
  // table operand into a BR_TABLE instruction, rather than ever
  // materializing it in a register.
  const JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
  return DAG.getTargetJumpTable(JT->getIndex(), Op.getValueType(),
                                JT->getTargetFlags());
}

SDValue WebAssemblyTargetLowering::LowerBR_JT(SDValue Op,
                                              SelectionDAG &DAG) const {
  SDLoc DL(Op);
  SDValue Chain = Op.getOperand(0);
  const auto *JT = cast<JumpTableSDNode>(Op.getOperand(1));
  SDValue Index = Op.getOperand(2);
  assert(JT->getTargetFlags() == 0 && "WebAssembly doesn't set target flags");

  SmallVector<SDValue, 8> Ops;
  Ops.push_back(Chain);
  Ops.push_back(Index);

  MachineJumpTableInfo *MJTI = DAG.getMachineFunction().getJumpTableInfo();
  const auto &MBBs = MJTI->getJumpTables()[JT->getIndex()].MBBs;

  // Add an operand for each case.
  for (auto *MBB : MBBs)
    Ops.push_back(DAG.getBasicBlock(MBB));

  // Add the first MBB as a dummy default target for now. This will be replaced
  // with the proper default target (and the preceding range check eliminated)
  // if possible by WebAssemblyFixBrTableDefaults.
  Ops.push_back(DAG.getBasicBlock(*MBBs.begin()));
  return DAG.getNode(WebAssemblyISD::BR_TABLE, DL, MVT::Other, Ops);
}

SDValue WebAssemblyTargetLowering::LowerVASTART(SDValue Op,
                                                SelectionDAG &DAG) const {
  SDLoc DL(Op);
  EVT PtrVT = getPointerTy(DAG.getMachineFunction().getDataLayout());

  auto *MFI = DAG.getMachineFunction().getInfo<WebAssemblyFunctionInfo>();
  const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();

  SDValue ArgN = DAG.getCopyFromReg(DAG.getEntryNode(), DL,
                                    MFI->getVarargBufferVreg(), PtrVT);
  return DAG.getStore(Op.getOperand(0), DL, ArgN, Op.getOperand(1),
                      MachinePointerInfo(SV));
}

SDValue WebAssemblyTargetLowering::LowerIntrinsic(SDValue Op,
                                                  SelectionDAG &DAG) const {
  MachineFunction &MF = DAG.getMachineFunction();
  unsigned IntNo;
  switch (Op.getOpcode()) {
  case ISD::INTRINSIC_VOID:
  case ISD::INTRINSIC_W_CHAIN:
    IntNo = Op.getConstantOperandVal(1);
    break;
  case ISD::INTRINSIC_WO_CHAIN:
    IntNo = Op.getConstantOperandVal(0);
    break;
  default:
    llvm_unreachable("Invalid intrinsic");
  }
  SDLoc DL(Op);

  switch (IntNo) {
  default:
    return SDValue(); // Don't custom lower most intrinsics.

  case Intrinsic::wasm_lsda: {
    auto PtrVT = getPointerTy(MF.getDataLayout());
    const char *SymName = MF.createExternalSymbolName(
        "GCC_except_table" + std::to_string(MF.getFunctionNumber()));
    if (isPositionIndependent()) {
      SDValue Node = DAG.getTargetExternalSymbol(
          SymName, PtrVT, WebAssemblyII::MO_MEMORY_BASE_REL);
      const char *BaseName = MF.createExternalSymbolName("__memory_base");
      SDValue BaseAddr =
          DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT,
                      DAG.getTargetExternalSymbol(BaseName, PtrVT));
      SDValue SymAddr =
          DAG.getNode(WebAssemblyISD::WrapperREL, DL, PtrVT, Node);
      return DAG.getNode(ISD::ADD, DL, PtrVT, BaseAddr, SymAddr);
    }
    SDValue Node = DAG.getTargetExternalSymbol(SymName, PtrVT);
    return DAG.getNode(WebAssemblyISD::Wrapper, DL, PtrVT, Node);
  }

  case Intrinsic::wasm_shuffle: {
    // Drop in-chain and replace undefs, but otherwise pass through unchanged
    SDValue Ops[18];
    size_t OpIdx = 0;
    Ops[OpIdx++] = Op.getOperand(1);
    Ops[OpIdx++] = Op.getOperand(2);
    while (OpIdx < 18) {
      const SDValue &MaskIdx = Op.getOperand(OpIdx + 1);
      if (MaskIdx.isUndef() || MaskIdx.getNode()->getAsZExtVal() >= 32) {
        bool isTarget = MaskIdx.getNode()->getOpcode() == ISD::TargetConstant;
        Ops[OpIdx++] = DAG.getConstant(0, DL, MVT::i32, isTarget);
      } else {
        Ops[OpIdx++] = MaskIdx;
      }
    }
    return DAG.getNode(WebAssemblyISD::SHUFFLE, DL, Op.getValueType(), Ops);
  }

  case Intrinsic::wasm_funcref_to_ptr: {
    // llvm.wasm.funcref.to_ptr only has a defined lowering when its result
    // feeds directly into an indirect call. Reaching here means the pointer
    // escapes a direct call. We haven't implemented conversion of a funcref
    // into a real function pointer so we crash if we get here.
    fail(DL, DAG,
         "a funcref can only be converted to a pointer to be directly called; "
         "the resulting pointer cannot otherwise be used");
    return DAG.getPOISON(Op.getValueType());
  }

  case Intrinsic::thread_pointer: {
    return SDValue(WebAssembly::getTLSBase(DAG, DL, Subtarget), 0);
  }
  }
}

SDValue
WebAssemblyTargetLowering::LowerSIGN_EXTEND_INREG(SDValue Op,
                                                  SelectionDAG &DAG) const {
  SDLoc DL(Op);
  // If sign extension operations are disabled, allow sext_inreg only if operand
  // is a vector extract of an i8 or i16 lane. SIMD does not depend on sign
  // extension operations, but allowing sext_inreg in this context lets us have
  // simple patterns to select extract_lane_s instructions. Expanding sext_inreg
  // everywhere would be simpler in this file, but would necessitate large and
  // brittle patterns to undo the expansion and select extract_lane_s
  // instructions.
  assert(!Subtarget->hasSignExt() && Subtarget->hasSIMD128());
  if (Op.getOperand(0).getOpcode() != ISD::EXTRACT_VECTOR_ELT)
    return SDValue();

  const SDValue &Extract = Op.getOperand(0);
  MVT VecT = Extract.getOperand(0).getSimpleValueType();
  if (VecT.getVectorElementType().getSizeInBits() > 32)
    return SDValue();
  MVT ExtractedLaneT =
      cast<VTSDNode>(Op.getOperand(1).getNode())->getVT().getSimpleVT();
  MVT ExtractedVecT =
      MVT::getVectorVT(ExtractedLaneT, 128 / ExtractedLaneT.getSizeInBits());
  if (ExtractedVecT == VecT)
    return Op;

  // Bitcast vector to appropriate type to ensure ISel pattern coverage
  const SDNode *Index = Extract.getOperand(1).getNode();
  if (!isa<ConstantSDNode>(Index))
    return SDValue();
  unsigned IndexVal = Index->getAsZExtVal();
  unsigned Scale =
      ExtractedVecT.getVectorNumElements() / VecT.getVectorNumElements();
  assert(Scale > 1);
  SDValue NewIndex =
      DAG.getConstant(IndexVal * Scale, DL, Index->getValueType(0));
  SDValue NewExtract = DAG.getNode(
      ISD::EXTRACT_VECTOR_ELT, DL, Extract.getValueType(),
      DAG.getBitcast(ExtractedVecT, Extract.getOperand(0)), NewIndex);
  return DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, Op.getValueType(), NewExtract,
                     Op.getOperand(1));
}

static SDValue GetExtendHigh(SDValue Op, unsigned UserOpc, EVT VT,
                             SelectionDAG &DAG) {
  SDValue Source = peekThroughBitcasts(Op);
  if (Source.getOpcode() != ISD::VECTOR_SHUFFLE)
    return SDValue();

  assert((UserOpc == WebAssemblyISD::EXTEND_LOW_U ||
          UserOpc == WebAssemblyISD::EXTEND_LOW_S) &&
         "expected extend_low");
  auto *Shuffle = cast<ShuffleVectorSDNode>(Source.getNode());

  ArrayRef<int> Mask = Shuffle->getMask();
  // Look for a shuffle which moves from the high half to the low half.
  size_t FirstIdx = Mask.size() / 2;
  for (size_t i = 0; i < Mask.size() / 2; ++i) {
    if (Mask[i] != static_cast<int>(FirstIdx + i)) {
      return SDValue();
    }
  }

  SDLoc DL(Op);
  unsigned Opc = UserOpc == WebAssemblyISD::EXTEND_LOW_S
                     ? WebAssemblyISD::EXTEND_HIGH_S
                     : WebAssemblyISD::EXTEND_HIGH_U;
  SDValue ShuffleSrc = Shuffle->getOperand(0);
  if (Op.getOpcode() == ISD::BITCAST)
    ShuffleSrc = DAG.getBitcast(Op.getValueType(), ShuffleSrc);

  return DAG.getNode(Opc, DL, VT, ShuffleSrc);
}

SDValue
WebAssemblyTargetLowering::LowerEXTEND_VECTOR_INREG(SDValue Op,
                                                    SelectionDAG &DAG) const {
  SDLoc DL(Op);
  EVT VT = Op.getValueType();
  SDValue Src = Op.getOperand(0);
  EVT SrcVT = Src.getValueType();

  if (SrcVT.getVectorElementType() == MVT::i1 ||
      SrcVT.getVectorElementType() == MVT::i64)
    return SDValue();

  assert(VT.getScalarSizeInBits() % SrcVT.getScalarSizeInBits() == 0 &&
         "Unexpected extension factor.");
  unsigned Scale = VT.getScalarSizeInBits() / SrcVT.getScalarSizeInBits();

  if (Scale != 2 && Scale != 4 && Scale != 8)
    return SDValue();

  unsigned Ext;
  switch (Op.getOpcode()) {
  default:
    llvm_unreachable("unexpected opcode");
  case ISD::ANY_EXTEND_VECTOR_INREG:
  case ISD::ZERO_EXTEND_VECTOR_INREG:
    Ext = WebAssemblyISD::EXTEND_LOW_U;
    break;
  case ISD::SIGN_EXTEND_VECTOR_INREG:
    Ext = WebAssemblyISD::EXTEND_LOW_S;
    break;
  }

  if (Scale == 2) {
    // See if we can use EXTEND_HIGH.
    if (auto ExtendHigh = GetExtendHigh(Op.getOperand(0), Ext, VT, DAG))
      return ExtendHigh;
  }

  SDValue Ret = Src;
  while (Scale != 1) {
    Ret = DAG.getNode(Ext, DL,
                      Ret.getValueType()
                          .widenIntegerVectorElementType(*DAG.getContext())
                          .getHalfNumVectorElementsVT(*DAG.getContext()),
                      Ret);
    Scale /= 2;
  }
  assert(Ret.getValueType() == VT);
  return Ret;
}

static SDValue LowerConvertLow(SDValue Op, SelectionDAG &DAG) {
  SDLoc DL(Op);
  if (Op.getValueType() != MVT::v2f64 && Op.getValueType() != MVT::v4f32)
    return SDValue();

  auto GetConvertedLane = [](SDValue Op, unsigned &Opcode, SDValue &SrcVec,
                             unsigned &Index) -> bool {
    switch (Op.getOpcode()) {
    case ISD::SINT_TO_FP:
      Opcode = WebAssemblyISD::CONVERT_LOW_S;
      break;
    case ISD::UINT_TO_FP:
      Opcode = WebAssemblyISD::CONVERT_LOW_U;
      break;
    case ISD::FP_EXTEND:
    case ISD::FP16_TO_FP:
      Opcode = WebAssemblyISD::PROMOTE_LOW;
      break;
    default:
      return false;
    }

    auto ExtractVector = Op.getOperand(0);
    if (ExtractVector.getOpcode() != ISD::EXTRACT_VECTOR_ELT)
      return false;

    if (!isa<ConstantSDNode>(ExtractVector.getOperand(1).getNode()))
      return false;

    SrcVec = ExtractVector.getOperand(0);
    Index = ExtractVector.getConstantOperandVal(1);
    return true;
  };

  unsigned NumLanes = Op.getValueType() == MVT::v2f64 ? 2 : 4;
  unsigned FirstOpcode = 0, SecondOpcode = 0, ThirdOpcode = 0, FourthOpcode = 0;
  unsigned FirstIndex = 0, SecondIndex = 0, ThirdIndex = 0, FourthIndex = 0;
  SDValue FirstSrcVec, SecondSrcVec, ThirdSrcVec, FourthSrcVec;

  if (!GetConvertedLane(Op.getOperand(0), FirstOpcode, FirstSrcVec,
                        FirstIndex) ||
      !GetConvertedLane(Op.getOperand(1), SecondOpcode, SecondSrcVec,
                        SecondIndex))
    return SDValue();

  // If we're converting to v4f32, check the third and fourth lanes, too.
  if (NumLanes == 4 && (!GetConvertedLane(Op.getOperand(2), ThirdOpcode,
                                          ThirdSrcVec, ThirdIndex) ||
                        !GetConvertedLane(Op.getOperand(3), FourthOpcode,
                                          FourthSrcVec, FourthIndex)))
    return SDValue();

  if (FirstOpcode != SecondOpcode)
    return SDValue();

  // TODO Add an optimization similar to the v2f64 below for shuffling the
  // vectors when the lanes are in the wrong order or come from different src
  // vectors.
  if (NumLanes == 4 &&
      (FirstOpcode != ThirdOpcode || FirstOpcode != FourthOpcode ||
       FirstSrcVec != SecondSrcVec || FirstSrcVec != ThirdSrcVec ||
       FirstSrcVec != FourthSrcVec || FirstIndex != 0 || SecondIndex != 1 ||
       ThirdIndex != 2 || FourthIndex != 3))
    return SDValue();

  MVT ExpectedSrcVT;
  switch (FirstOpcode) {
  case WebAssemblyISD::CONVERT_LOW_S:
  case WebAssemblyISD::CONVERT_LOW_U:
    ExpectedSrcVT = MVT::v4i32;
    break;
  case WebAssemblyISD::PROMOTE_LOW:
    ExpectedSrcVT = NumLanes == 2 ? MVT::v4f32 : MVT::v8i16;
    break;
  }
  if (FirstSrcVec.getValueType() != ExpectedSrcVT)
    return SDValue();

  auto Src = FirstSrcVec;
  if (NumLanes == 2 &&
      (FirstIndex != 0 || SecondIndex != 1 || FirstSrcVec != SecondSrcVec)) {
    // Shuffle the source vector so that the converted lanes are the low lanes.
    Src = DAG.getVectorShuffle(ExpectedSrcVT, DL, FirstSrcVec, SecondSrcVec,
                               {static_cast<int>(FirstIndex),
                                static_cast<int>(SecondIndex) + 4, -1, -1});
  }
  return DAG.getNode(FirstOpcode, DL, NumLanes == 2 ? MVT::v2f64 : MVT::v4f32,
                     Src);
}

SDValue WebAssemblyTargetLowering::LowerBUILD_VECTOR(SDValue Op,
                                                     SelectionDAG &DAG) const {
  MVT VT = Op.getSimpleValueType();
  if (VT == MVT::v8f16) {
    // BUILD_VECTOR can't handle FP16 operands since Wasm doesn't have a scaler
    // FP16 type, so cast them to I16s.
    MVT IVT = VT.changeVectorElementType(MVT::i16);
    SmallVector<SDValue, 8> NewOps;
    for (unsigned I = 0, E = Op.getNumOperands(); I < E; ++I)
      NewOps.push_back(DAG.getBitcast(MVT::i16, Op.getOperand(I)));
    SDValue Res = DAG.getNode(ISD::BUILD_VECTOR, SDLoc(), IVT, NewOps);
    return DAG.getBitcast(VT, Res);
  }

  if (auto ConvertLow = LowerConvertLow(Op, DAG))
    return ConvertLow;

  SDLoc DL(Op);
  const EVT VecT = Op.getValueType();
  const EVT LaneT = Op.getOperand(0).getValueType();
  const size_t Lanes = Op.getNumOperands();
  bool CanSwizzle = VecT == MVT::v16i8;

  // BUILD_VECTORs are lowered to the instruction that initializes the highest
  // possible number of lanes at once followed by a sequence of replace_lane
  // instructions to individually initialize any remaining lanes.

  // TODO: Tune this. For example, lanewise swizzling is very expensive, so
  // swizzled lanes should be given greater weight.

  // TODO: Investigate looping rather than always extracting/replacing specific
  // lanes to fill gaps.

  auto IsConstant = [](const SDValue &V) {
    return V.getOpcode() == ISD::Constant || V.getOpcode() == ISD::ConstantFP;
  };

  // Returns the source vector and index vector pair if they exist. Checks for:
  //   (extract_vector_elt
  //     $src,
  //     (sign_extend_inreg (extract_vector_elt $indices, $i))
  //   )
  auto GetSwizzleSrcs = [](size_t I, const SDValue &Lane) {
    auto Bail = std::make_pair(SDValue(), SDValue());
    if (Lane->getOpcode() != ISD::EXTRACT_VECTOR_ELT)
      return Bail;
    const SDValue &SwizzleSrc = Lane->getOperand(0);
    const SDValue &IndexExt = Lane->getOperand(1);
    if (IndexExt->getOpcode() != ISD::SIGN_EXTEND_INREG)
      return Bail;
    const SDValue &Index = IndexExt->getOperand(0);
    if (Index->getOpcode() != ISD::EXTRACT_VECTOR_ELT)
      return Bail;
    const SDValue &SwizzleIndices = Index->getOperand(0);
    if (SwizzleSrc.getValueType() != MVT::v16i8 ||
        SwizzleIndices.getValueType() != MVT::v16i8 ||
        Index->getOperand(1)->getOpcode() != ISD::Constant ||
        Index->getConstantOperandVal(1) != I)
      return Bail;
    return std::make_pair(SwizzleSrc, SwizzleIndices);
  };

  // If the lane is extracted from another vector at a constant index, return
  // that vector. The source vector must not have more lanes than the dest
  // because the shufflevector indices are in terms of the destination lanes and
  // would not be able to address the smaller individual source lanes.
  auto GetShuffleSrc = [&](const SDValue &Lane) {
    if (Lane->getOpcode() != ISD::EXTRACT_VECTOR_ELT)
      return SDValue();
    if (!isa<ConstantSDNode>(Lane->getOperand(1).getNode()))
      return SDValue();
    if (Lane->getOperand(0).getValueType().getVectorNumElements() >
        VecT.getVectorNumElements())
      return SDValue();
    return Lane->getOperand(0);
  };

  using ValueEntry = std::pair<SDValue, size_t>;
  SmallVector<ValueEntry, 16> SplatValueCounts;

  using SwizzleEntry = std::pair<std::pair<SDValue, SDValue>, size_t>;
  SmallVector<SwizzleEntry, 16> SwizzleCounts;

  using ShuffleEntry = std::pair<SDValue, size_t>;
  SmallVector<ShuffleEntry, 16> ShuffleCounts;

  auto AddCount = [](auto &Counts, const auto &Val) {
    auto CountIt =
        llvm::find_if(Counts, [&Val](auto E) { return E.first == Val; });
    if (CountIt == Counts.end()) {
      Counts.emplace_back(Val, 1);
    } else {
      CountIt->second++;
    }
  };

  auto GetMostCommon = [](auto &Counts) {
    auto CommonIt = llvm::max_element(Counts, llvm::less_second());
    assert(CommonIt != Counts.end() && "Unexpected all-undef build_vector");
    return *CommonIt;
  };

  size_t NumConstantLanes = 0;

  // Count eligible lanes for each type of vector creation op
  for (size_t I = 0; I < Lanes; ++I) {
    const SDValue &Lane = Op->getOperand(I);
    if (Lane.isUndef())
      continue;

    AddCount(SplatValueCounts, Lane);

    if (IsConstant(Lane))
      NumConstantLanes++;
    if (auto ShuffleSrc = GetShuffleSrc(Lane))
      AddCount(ShuffleCounts, ShuffleSrc);
    if (CanSwizzle) {
      auto SwizzleSrcs = GetSwizzleSrcs(I, Lane);
      if (SwizzleSrcs.first)
        AddCount(SwizzleCounts, SwizzleSrcs);
    }
  }

  SDValue SplatValue;
  size_t NumSplatLanes;
  std::tie(SplatValue, NumSplatLanes) = GetMostCommon(SplatValueCounts);

  SDValue SwizzleSrc;
  SDValue SwizzleIndices;
  size_t NumSwizzleLanes = 0;
  if (SwizzleCounts.size())
    std::forward_as_tuple(std::tie(SwizzleSrc, SwizzleIndices),
                          NumSwizzleLanes) = GetMostCommon(SwizzleCounts);

  // Shuffles can draw from up to two vectors, so find the two most common
  // sources.
  SDValue ShuffleSrc1, ShuffleSrc2;
  size_t NumShuffleLanes = 0;
  if (ShuffleCounts.size()) {
    std::tie(ShuffleSrc1, NumShuffleLanes) = GetMostCommon(ShuffleCounts);
    llvm::erase_if(ShuffleCounts,
                   [&](const auto &Pair) { return Pair.first == ShuffleSrc1; });
  }
  if (ShuffleCounts.size()) {
    size_t AdditionalShuffleLanes;
    std::tie(ShuffleSrc2, AdditionalShuffleLanes) =
        GetMostCommon(ShuffleCounts);
    NumShuffleLanes += AdditionalShuffleLanes;
  }

  // Predicate returning true if the lane is properly initialized by the
  // original instruction
  std::function<bool(size_t, const SDValue &)> IsLaneConstructed;
  SDValue Result;
  // Prefer swizzles over shuffles over vector consts over splats
  if (NumSwizzleLanes >= NumShuffleLanes &&
      NumSwizzleLanes >= NumConstantLanes && NumSwizzleLanes >= NumSplatLanes) {
    Result = DAG.getNode(WebAssemblyISD::SWIZZLE, DL, VecT, SwizzleSrc,
                         SwizzleIndices);
    auto Swizzled = std::make_pair(SwizzleSrc, SwizzleIndices);
    IsLaneConstructed = [&, Swizzled](size_t I, const SDValue &Lane) {
      return Swizzled == GetSwizzleSrcs(I, Lane);
    };
  } else if (NumShuffleLanes >= NumConstantLanes &&
             NumShuffleLanes >= NumSplatLanes) {
    size_t DestLaneSize = VecT.getVectorElementType().getFixedSizeInBits() / 8;
    size_t DestLaneCount = VecT.getVectorNumElements();
    size_t Scale1 = 1;
    size_t Scale2 = 1;
    SDValue Src1 = ShuffleSrc1;
    SDValue Src2 = ShuffleSrc2 ? ShuffleSrc2 : DAG.getUNDEF(VecT);
    if (Src1.getValueType() != VecT) {
      size_t LaneSize =
          Src1.getValueType().getVectorElementType().getFixedSizeInBits() / 8;
      assert(LaneSize > DestLaneSize);
      Scale1 = LaneSize / DestLaneSize;
      Src1 = DAG.getBitcast(VecT, Src1);
    }
    if (Src2.getValueType() != VecT) {
      size_t LaneSize =
          Src2.getValueType().getVectorElementType().getFixedSizeInBits() / 8;
      assert(LaneSize > DestLaneSize);
      Scale2 = LaneSize / DestLaneSize;
      Src2 = DAG.getBitcast(VecT, Src2);
    }

    int Mask[16];
    assert(DestLaneCount <= 16);
    for (size_t I = 0; I < DestLaneCount; ++I) {
      const SDValue &Lane = Op->getOperand(I);
      SDValue Src = GetShuffleSrc(Lane);
      if (Src == ShuffleSrc1) {
        Mask[I] = Lane->getConstantOperandVal(1) * Scale1;
      } else if (Src && Src == ShuffleSrc2) {
        Mask[I] = DestLaneCount + Lane->getConstantOperandVal(1) * Scale2;
      } else {
        Mask[I] = -1;
      }
    }
    ArrayRef<int> MaskRef(Mask, DestLaneCount);
    Result = DAG.getVectorShuffle(VecT, DL, Src1, Src2, MaskRef);
    IsLaneConstructed = [&](size_t, const SDValue &Lane) {
      auto Src = GetShuffleSrc(Lane);
      return Src == ShuffleSrc1 || (Src && Src == ShuffleSrc2);
    };
  } else if (NumConstantLanes >= NumSplatLanes) {
    SmallVector<SDValue, 16> ConstLanes;
    for (const SDValue &Lane : Op->op_values()) {
      if (IsConstant(Lane)) {
        // Values may need to be fixed so that they will sign extend to be
        // within the expected range during ISel. Check whether the value is in
        // bounds based on the lane bit width and if it is out of bounds, lop
        // off the extra bits.
        uint64_t LaneBits = 128 / Lanes;
        if (auto *Const = dyn_cast<ConstantSDNode>(Lane.getNode())) {
          ConstLanes.push_back(DAG.getConstant(
              Const->getAPIntValue().trunc(LaneBits).getZExtValue(),
              SDLoc(Lane), LaneT));
        } else {
          ConstLanes.push_back(Lane);
        }
      } else if (LaneT.isFloatingPoint()) {
        ConstLanes.push_back(DAG.getConstantFP(0, DL, LaneT));
      } else {
        ConstLanes.push_back(DAG.getConstant(0, DL, LaneT));
      }
    }
    Result = DAG.getBuildVector(VecT, DL, ConstLanes);
    IsLaneConstructed = [&IsConstant](size_t _, const SDValue &Lane) {
      return IsConstant(Lane);
    };
  } else {
    size_t DestLaneSize = VecT.getVectorElementType().getFixedSizeInBits();
    if (NumSplatLanes == 1 && Op->getOperand(0) == SplatValue &&
        (DestLaneSize == 32 || DestLaneSize == 64)) {
      // Could be selected to load_zero.
      Result = DAG.getNode(ISD::SCALAR_TO_VECTOR, DL, VecT, SplatValue);
    } else {
      // Use a splat (which might be selected as a load splat)
      Result = DAG.getSplatBuildVector(VecT, DL, SplatValue);
    }
    IsLaneConstructed = [&SplatValue](size_t _, const SDValue &Lane) {
      return Lane == SplatValue;
    };
  }

  assert(Result);
  assert(IsLaneConstructed);

  // Add replace_lane instructions for any unhandled values
  for (size_t I = 0; I < Lanes; ++I) {
    const SDValue &Lane = Op->getOperand(I);
    if (!Lane.isUndef() && !IsLaneConstructed(I, Lane))
      Result = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, VecT, Result, Lane,
                           DAG.getConstant(I, DL, MVT::i32));
  }

  return Result;
}

SDValue
WebAssemblyTargetLowering::LowerVECTOR_SHUFFLE(SDValue Op,
                                               SelectionDAG &DAG) const {
  SDLoc DL(Op);
  ArrayRef<int> Mask = cast<ShuffleVectorSDNode>(Op.getNode())->getMask();
  MVT VecType = Op.getOperand(0).getSimpleValueType();
  assert(VecType.is128BitVector() && "Unexpected shuffle vector type");
  size_t LaneBytes = VecType.getVectorElementType().getSizeInBits() / 8;

  // Space for two vector args and sixteen mask indices
  SDValue Ops[18];
  size_t OpIdx = 0;
  Ops[OpIdx++] = Op.getOperand(0);
  Ops[OpIdx++] = Op.getOperand(1);

  // Expand mask indices to byte indices and materialize them as operands
  for (int M : Mask) {
    for (size_t J = 0; J < LaneBytes; ++J) {
      // Lower undefs (represented by -1 in mask) to {0..J}, which use a
      // whole lane of vector input, to allow further reduction at VM. E.g.
      // match an 8x16 byte shuffle to an equivalent cheaper 32x4 shuffle.
      uint64_t ByteIndex = M == -1 ? J : (uint64_t)M * LaneBytes + J;
      Ops[OpIdx++] = DAG.getConstant(ByteIndex, DL, MVT::i32);
    }
  }

  return DAG.getNode(WebAssemblyISD::SHUFFLE, DL, Op.getValueType(), Ops);
}

SDValue WebAssemblyTargetLowering::LowerSETCC(SDValue Op,
                                              SelectionDAG &DAG) const {
  SDLoc DL(Op);
  // The legalizer does not know how to expand the unsupported comparison modes
  // of i64x2 vectors, so we manually unroll them here.
  assert(Op->getOperand(0)->getSimpleValueType(0) == MVT::v2i64);
  SmallVector<SDValue, 2> LHS, RHS;
  DAG.ExtractVectorElements(Op->getOperand(0), LHS);
  DAG.ExtractVectorElements(Op->getOperand(1), RHS);
  const SDValue &CC = Op->getOperand(2);
  auto MakeLane = [&](unsigned I) {
    return DAG.getNode(ISD::SELECT_CC, DL, MVT::i64, LHS[I], RHS[I],
                       DAG.getConstant(uint64_t(-1), DL, MVT::i64),
                       DAG.getConstant(uint64_t(0), DL, MVT::i64), CC);
  };
  return DAG.getBuildVector(Op->getValueType(0), DL,
                            {MakeLane(0), MakeLane(1)});
}

SDValue
WebAssemblyTargetLowering::LowerAccessVectorElement(SDValue Op,
                                                    SelectionDAG &DAG) const {
  // Allow constant lane indices, expand variable lane indices
  SDNode *IdxNode = Op.getOperand(Op.getNumOperands() - 1).getNode();
  if (isa<ConstantSDNode>(IdxNode)) {
    // Ensure the index type is i32 to match the tablegen patterns
    uint64_t Idx = IdxNode->getAsZExtVal();
    SmallVector<SDValue, 3> Ops(Op.getNode()->ops());
    Ops[Op.getNumOperands() - 1] =
        DAG.getConstant(Idx, SDLoc(IdxNode), MVT::i32);
    return DAG.getNode(Op.getOpcode(), SDLoc(Op), Op.getValueType(), Ops);
  }
  // Perform default expansion
  return SDValue();
}

static SDValue unrollVectorShift(SDValue Op, SelectionDAG &DAG) {
  EVT LaneT = Op.getSimpleValueType().getVectorElementType();
  // 32-bit and 64-bit unrolled shifts will have proper semantics
  if (LaneT.bitsGE(MVT::i32))
    return DAG.UnrollVectorOp(Op.getNode());
  // Otherwise mask the shift value to get proper semantics from 32-bit shift
  SDLoc DL(Op);
  size_t NumLanes = Op.getSimpleValueType().getVectorNumElements();
  SDValue Mask = DAG.getConstant(LaneT.getSizeInBits() - 1, DL, MVT::i32);
  unsigned ShiftOpcode = Op.getOpcode();
  SmallVector<SDValue, 16> ShiftedElements;
  DAG.ExtractVectorElements(Op.getOperand(0), ShiftedElements, 0, 0, MVT::i32);
  SmallVector<SDValue, 16> ShiftElements;
  DAG.ExtractVectorElements(Op.getOperand(1), ShiftElements, 0, 0, MVT::i32);
  SmallVector<SDValue, 16> UnrolledOps;
  for (size_t i = 0; i < NumLanes; ++i) {
    SDValue MaskedShiftValue =
        DAG.getNode(ISD::AND, DL, MVT::i32, ShiftElements[i], Mask);
    SDValue ShiftedValue = ShiftedElements[i];
    if (ShiftOpcode == ISD::SRA)
      ShiftedValue = DAG.getNode(ISD::SIGN_EXTEND_INREG, DL, MVT::i32,
                                 ShiftedValue, DAG.getValueType(LaneT));
    UnrolledOps.push_back(
        DAG.getNode(ShiftOpcode, DL, MVT::i32, ShiftedValue, MaskedShiftValue));
  }
  return DAG.getBuildVector(Op.getValueType(), DL, UnrolledOps);
}

SDValue WebAssemblyTargetLowering::LowerShift(SDValue Op,
                                              SelectionDAG &DAG) const {
  SDLoc DL(Op);
  // Only manually lower vector shifts
  assert(Op.getSimpleValueType().isVector());

  uint64_t LaneBits = Op.getValueType().getScalarSizeInBits();
  auto ShiftVal = Op.getOperand(1);

  // Try to skip bitmask operation since it is implied inside shift instruction
  auto SkipImpliedMask = [](SDValue MaskOp, uint64_t MaskBits) {
    if (MaskOp.getOpcode() != ISD::AND)
      return MaskOp;
    SDValue LHS = MaskOp.getOperand(0);
    SDValue RHS = MaskOp.getOperand(1);
    if (MaskOp.getValueType().isVector()) {
      APInt MaskVal;
      if (!ISD::isConstantSplatVector(RHS.getNode(), MaskVal))
        std::swap(LHS, RHS);

      if (ISD::isConstantSplatVector(RHS.getNode(), MaskVal) &&
          MaskVal == MaskBits)
        MaskOp = LHS;
    } else {
      if (!isa<ConstantSDNode>(RHS.getNode()))
        std::swap(LHS, RHS);

      auto ConstantRHS = dyn_cast<ConstantSDNode>(RHS.getNode());
      if (ConstantRHS && ConstantRHS->getAPIntValue() == MaskBits)
        MaskOp = LHS;
    }

    return MaskOp;
  };

  // Skip vector and operation
  ShiftVal = SkipImpliedMask(ShiftVal, LaneBits - 1);
  ShiftVal = DAG.getSplatValue(ShiftVal);
  if (!ShiftVal)
    return unrollVectorShift(Op, DAG);

  // Skip scalar and operation
  ShiftVal = SkipImpliedMask(ShiftVal, LaneBits - 1);
  // Use anyext because none of the high bits can affect the shift
  ShiftVal = DAG.getAnyExtOrTrunc(ShiftVal, DL, MVT::i32);

  unsigned Opcode;
  switch (Op.getOpcode()) {
  case ISD::SHL:
    Opcode = WebAssemblyISD::VEC_SHL;
    break;
  case ISD::SRA:
    Opcode = WebAssemblyISD::VEC_SHR_S;
    break;
  case ISD::SRL:
    Opcode = WebAssemblyISD::VEC_SHR_U;
    break;
  default:
    llvm_unreachable("unexpected opcode");
  }

  return DAG.getNode(Opcode, DL, Op.getValueType(), Op.getOperand(0), ShiftVal);
}

SDValue WebAssemblyTargetLowering::LowerFP_TO_INT_SAT(SDValue Op,
                                                      SelectionDAG &DAG) const {
  EVT ResT = Op.getValueType();
  EVT SatVT = cast<VTSDNode>(Op.getOperand(1))->getVT();

  if ((ResT == MVT::i32 || ResT == MVT::i64) &&
      (SatVT == MVT::i32 || SatVT == MVT::i64))
    return Op;

  if (ResT == MVT::v4i32 && SatVT == MVT::i32)
    return Op;

  if (ResT == MVT::v8i16 && SatVT == MVT::i16)
    return Op;

  return SDValue();
}

static bool HasNoSignedZerosOrNaNs(SDValue Op, SelectionDAG &DAG) {
  return (Op->getFlags().hasNoNaNs() ||
          (DAG.isKnownNeverNaN(Op->getOperand(0)) &&
           DAG.isKnownNeverNaN(Op->getOperand(1)))) &&
         (Op->getFlags().hasNoSignedZeros() ||
          DAG.isKnownNeverLogicalZero(Op->getOperand(0)) ||
          DAG.isKnownNeverLogicalZero(Op->getOperand(1)));
}

SDValue WebAssemblyTargetLowering::LowerFMIN(SDValue Op,
                                             SelectionDAG &DAG) const {
  if (Subtarget->hasRelaxedSIMD() && HasNoSignedZerosOrNaNs(Op, DAG)) {
    return DAG.getNode(WebAssemblyISD::RELAXED_FMIN, SDLoc(Op),
                       Op.getValueType(), Op.getOperand(0), Op.getOperand(1));
  }
  return SDValue();
}

SDValue WebAssemblyTargetLowering::LowerFMAX(SDValue Op,
                                             SelectionDAG &DAG) const {
  if (Subtarget->hasRelaxedSIMD() && HasNoSignedZerosOrNaNs(Op, DAG)) {
    return DAG.getNode(WebAssemblyISD::RELAXED_FMAX, SDLoc(Op),
                       Op.getValueType(), Op.getOperand(0), Op.getOperand(1));
  }
  return SDValue();
}

//===----------------------------------------------------------------------===//
//   Custom DAG combine hooks
//===----------------------------------------------------------------------===//
static SDValue
performVECTOR_SHUFFLECombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) {
  auto &DAG = DCI.DAG;
  auto Shuffle = cast<ShuffleVectorSDNode>(N);

  // Hoist vector bitcasts that don't change the number of lanes out of unary
  // shuffles, where they are less likely to get in the way of other combines.
  // (shuffle (vNxT1 (bitcast (vNxT0 x))), undef, mask) ->
  //  (vNxT1 (bitcast (vNxT0 (shuffle x, undef, mask))))
  SDValue Bitcast = N->getOperand(0);
  if (Bitcast.getOpcode() != ISD::BITCAST)
    return SDValue();
  if (!N->getOperand(1).isUndef())
    return SDValue();
  SDValue CastOp = Bitcast.getOperand(0);
  EVT SrcType = CastOp.getValueType();
  EVT DstType = Bitcast.getValueType();
  if (!SrcType.is128BitVector() ||
      SrcType.getVectorNumElements() != DstType.getVectorNumElements())
    return SDValue();
  SDValue NewShuffle = DAG.getVectorShuffle(
      SrcType, SDLoc(N), CastOp, DAG.getUNDEF(SrcType), Shuffle->getMask());
  return DAG.getBitcast(DstType, NewShuffle);
}

/// Convert ({u,s}itofp vec) --> ({u,s}itofp ({s,z}ext vec)) so it doesn't get
/// split up into scalar instructions during legalization, and the vector
/// extending instructions are selected in performVectorExtendCombine below.
static SDValue
performVectorExtendToFPCombine(SDNode *N,
                               TargetLowering::DAGCombinerInfo &DCI) {
  auto &DAG = DCI.DAG;
  assert(N->getOpcode() == ISD::UINT_TO_FP ||
         N->getOpcode() == ISD::SINT_TO_FP);

  EVT InVT = N->getOperand(0)->getValueType(0);
  EVT ResVT = N->getValueType(0);
  MVT ExtVT;
  if (ResVT == MVT::v4f32 && (InVT == MVT::v4i16 || InVT == MVT::v4i8))
    ExtVT = MVT::v4i32;
  else if (ResVT == MVT::v2f64 && (InVT == MVT::v2i16 || InVT == MVT::v2i8))
    ExtVT = MVT::v2i32;
  else
    return SDValue();

  unsigned Op =
      N->getOpcode() == ISD::UINT_TO_FP ? ISD::ZERO_EXTEND : ISD::SIGN_EXTEND;
  SDValue Conv = DAG.getNode(Op, SDLoc(N), ExtVT, N->getOperand(0));
  return DAG.getNode(N->getOpcode(), SDLoc(N), ResVT, Conv);
}

static SDValue
performVectorNonNegToFPCombine(SDNode *N,
                               TargetLowering::DAGCombinerInfo &DCI) {
  auto &DAG = DCI.DAG;

  SDNodeFlags Flags = N->getFlags();
  SDValue Op0 = N->getOperand(0);
  EVT VT = N->getValueType(0);

  // Optimize uitofp to sitofp when the sign bit is known to be zero.
  // Depending on the target (runtime) backend, this might be performance
  // neutral (e.g. AArch64) or a significant improvement (e.g. x86_64).
  if (VT.isVector() && (Flags.hasNonNeg() || DAG.SignBitIsZero(Op0))) {
    return DAG.getNode(ISD::SINT_TO_FP, SDLoc(N), VT, Op0);
  }

  return SDValue();
}

static SDValue
performVectorExtendCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) {
  auto &DAG = DCI.DAG;
  assert(N->getOpcode() == ISD::SIGN_EXTEND ||
         N->getOpcode() == ISD::ZERO_EXTEND);

  EVT ResVT = N->getValueType(0);
  bool IsSext = N->getOpcode() == ISD::SIGN_EXTEND;
  SDLoc DL(N);

  if (ResVT == MVT::v16i32 && N->getOperand(0)->getValueType(0) == MVT::v16i8) {
    // Use a tree of extend low/high to split and extend the input in two
    // layers to avoid doing several shuffles and even more extends.
    unsigned LowOp =
        IsSext ? WebAssemblyISD::EXTEND_LOW_S : WebAssemblyISD::EXTEND_LOW_U;
    unsigned HighOp =
        IsSext ? WebAssemblyISD::EXTEND_HIGH_S : WebAssemblyISD::EXTEND_HIGH_U;
    SDValue Input = N->getOperand(0);
    SDValue LowHalf = DAG.getNode(LowOp, DL, MVT::v8i16, Input);
    SDValue HighHalf = DAG.getNode(HighOp, DL, MVT::v8i16, Input);
    SDValue Subvectors[] = {
        DAG.getNode(LowOp, DL, MVT::v4i32, LowHalf),
        DAG.getNode(HighOp, DL, MVT::v4i32, LowHalf),
        DAG.getNode(LowOp, DL, MVT::v4i32, HighHalf),
        DAG.getNode(HighOp, DL, MVT::v4i32, HighHalf),
    };
    return DAG.getNode(ISD::CONCAT_VECTORS, DL, ResVT, Subvectors);
  }

  // Combine ({s,z}ext (extract_subvector src, i)) into a widening operation if
  // possible before the extract_subvector can be expanded.
  auto Extract = N->getOperand(0);
  if (Extract.getOpcode() != ISD::EXTRACT_SUBVECTOR)
    return SDValue();
  auto Source = Extract.getOperand(0);
  auto *IndexNode = dyn_cast<ConstantSDNode>(Extract.getOperand(1));
  if (IndexNode == nullptr)
    return SDValue();
  auto Index = IndexNode->getZExtValue();

  // Only v8i8, v4i16, and v2i32 extracts can be widened, and only if the
  // extracted subvector is the low or high half of its source.
  if (ResVT == MVT::v8i16) {
    if (Extract.getValueType() != MVT::v8i8 ||
        Source.getValueType() != MVT::v16i8 || (Index != 0 && Index != 8))
      return SDValue();
  } else if (ResVT == MVT::v4i32) {
    if (Extract.getValueType() != MVT::v4i16 ||
        Source.getValueType() != MVT::v8i16 || (Index != 0 && Index != 4))
      return SDValue();
  } else if (ResVT == MVT::v2i64) {
    if (Extract.getValueType() != MVT::v2i32 ||
        Source.getValueType() != MVT::v4i32 || (Index != 0 && Index != 2))
      return SDValue();
  } else {
    return SDValue();
  }

  bool IsLow = Index == 0;

  unsigned Op = IsSext ? (IsLow ? WebAssemblyISD::EXTEND_LOW_S
                                : WebAssemblyISD::EXTEND_HIGH_S)
                       : (IsLow ? WebAssemblyISD::EXTEND_LOW_U
                                : WebAssemblyISD::EXTEND_HIGH_U);

  return DAG.getNode(Op, DL, ResVT, Source);
}

static SDValue
performVectorTruncZeroCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI) {
  auto &DAG = DCI.DAG;

  auto GetWasmConversionOp = [](unsigned Op) {
    switch (Op) {
    case ISD::FP_TO_SINT_SAT:
      return WebAssemblyISD::TRUNC_SAT_ZERO_S;
    case ISD::FP_TO_UINT_SAT:
      return WebAssemblyISD::TRUNC_SAT_ZERO_U;
    case ISD::FP_ROUND:
      return WebAssemblyISD::DEMOTE_ZERO;
    }
    llvm_unreachable("unexpected op");
  };

  auto IsZeroSplat = [](SDValue SplatVal) {
    auto *Splat = dyn_cast<BuildVectorSDNode>(SplatVal.getNode());
    APInt SplatValue, SplatUndef;
    unsigned SplatBitSize;
    bool HasAnyUndefs;
    // Endianness doesn't matter in this context because we are looking for
    // an all-zero value.
    return Splat &&
           Splat->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
                                  HasAnyUndefs) &&
           SplatValue == 0;
  };

  if (N->getOpcode() == ISD::CONCAT_VECTORS) {
    // Combine this:
    //
    //   (concat_vectors (v2i32 (fp_to_{s,u}int_sat $x, 32)), (v2i32 (splat 0)))
    //
    // into (i32x4.trunc_sat_f64x2_zero_{s,u} $x).
    //
    // Or this:
    //
    //   (concat_vectors ({v2f32, v4f16} (fp_round ({v2f64, v4f32} $x))),
    //                     ({v2f32, v4f16} (splat 0)))
    //
    // into ({f32x4, f16x8}.demote_zero_{f64x2, f32x4} $x).
    EVT ResVT;
    EVT ExpectedConversionType;
    auto Conversion = N->getOperand(0);
    auto ConversionOp = Conversion.getOpcode();
    switch (ConversionOp) {
    case ISD::FP_TO_SINT_SAT:
    case ISD::FP_TO_UINT_SAT:
      ResVT = MVT::v4i32;
      ExpectedConversionType = MVT::v2i32;
      break;
    case ISD::FP_ROUND:
      if (Conversion.getValueType() == MVT::v2f32) {
        ResVT = MVT::v4f32;
        ExpectedConversionType = MVT::v2f32;
      } else if (Conversion.getValueType() == MVT::v4f16) {
        ResVT = MVT::v8f16;
        ExpectedConversionType = MVT::v4f16;
      } else {
        return SDValue();
      }
      break;
    default:
      return SDValue();
    }

    if (N->getValueType(0) != ResVT)
      return SDValue();

    if (Conversion.getValueType() != ExpectedConversionType)
      return SDValue();

    auto Source = Conversion.getOperand(0);
    if (!((Source.getValueType() == MVT::v2f64 && ResVT == MVT::v4f32) ||
          (Source.getValueType() == MVT::v2f64 && ResVT == MVT::v4i32) ||
          (Source.getValueType() == MVT::v4f32 && ResVT == MVT::v8f16)))
      return SDValue();

    if (!IsZeroSplat(N->getOperand(1)) ||
        N->getOperand(1).getValueType() != ExpectedConversionType)
      return SDValue();

    unsigned Op = GetWasmConversionOp(ConversionOp);
    return DAG.getNode(Op, SDLoc(N), ResVT, Source);
  }

  // Combine this:
  //
  //   (fp_to_{s,u}int_sat (concat_vectors $x, (v2f64 (splat 0))), 32)
  //
  // into (i32x4.trunc_sat_f64x2_zero_{s,u} $x).
  //
  // Or this:
  //
  //   ({v4f32, v8f16} (fp_round (concat_vectors $x,
  //                               ({v2f64, v4f32} (splat 0)))))
  //
  // into ({f32x4, f16x8}.demote_zero_{f64x2, f32x4} $x).
  EVT ResVT;
  auto ConversionOp = N->getOpcode();
  switch (ConversionOp) {
  case ISD::FP_TO_SINT_SAT:
  case ISD::FP_TO_UINT_SAT:
    ResVT = MVT::v4i32;
    break;
  case ISD::FP_ROUND:
    ResVT = N->getValueType(0);
    break;
  default:
    llvm_unreachable("unexpected op");
  }

  if (N->getValueType(0) != ResVT)
    return SDValue();

  auto Concat = N->getOperand(0);
  if (Concat.getOpcode() != ISD::CONCAT_VECTORS)
    return SDValue();
  EVT ConcatVT = Concat.getValueType();
  EVT SourceVT = Concat.getOperand(0).getValueType();

  if (!IsZeroSplat(Concat.getOperand(1)))
    return SDValue();

  if (ConversionOp == ISD::FP_ROUND) {
    bool IsF64ToF32 =
        ConcatVT == MVT::v4f64 && SourceVT == MVT::v2f64 && ResVT == MVT::v4f32;
    bool IsF32ToF16 =
        ConcatVT == MVT::v8f32 && SourceVT == MVT::v4f32 && ResVT == MVT::v8f16;
    if (!(IsF64ToF32 || IsF32ToF16))
      return SDValue();
  } else {
    if (ConcatVT != MVT::v4f64 || SourceVT != MVT::v2f64 || ResVT != MVT::v4i32)
      return SDValue();
  }

  unsigned Op = GetWasmConversionOp(ConversionOp);
  return DAG.getNode(Op, SDLoc(N), ResVT, Concat.getOperand(0));
}

// Helper to extract VectorWidth bits from Vec, starting from IdxVal.
static SDValue extractSubVector(SDValue Vec, unsigned IdxVal, SelectionDAG &DAG,
                                const SDLoc &DL, unsigned VectorWidth) {
  EVT VT = Vec.getValueType();
  EVT ElVT = VT.getVectorElementType();
  unsigned Factor = VT.getSizeInBits() / VectorWidth;
  EVT ResultVT = EVT::getVectorVT(*DAG.getContext(), ElVT,
                                  VT.getVectorNumElements() / Factor);

  // Extract the relevant VectorWidth bits.  Generate an EXTRACT_SUBVECTOR
  unsigned ElemsPerChunk = VectorWidth / ElVT.getSizeInBits();
  assert(isPowerOf2_32(ElemsPerChunk) && "Elements per chunk not power of 2");

  // This is the index of the first element of the VectorWidth-bit chunk
  // we want. Since ElemsPerChunk is a power of 2 just need to clear bits.
  IdxVal &= ~(ElemsPerChunk - 1);

  // If the input is a buildvector just emit a smaller one.
  if (Vec.getOpcode() == ISD::BUILD_VECTOR)
    return DAG.getBuildVector(ResultVT, DL,
                              Vec->ops().slice(IdxVal, ElemsPerChunk));

  SDValue VecIdx = DAG.getIntPtrConstant(IdxVal, DL);
  return DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, ResultVT, Vec, VecIdx);
}

// Helper to recursively truncate vector elements in half with NARROW_U. DstVT
// is the expected destination value type after recursion. In is the initial
// input. Note that the input should have enough leading zero bits to prevent
// NARROW_U from saturating results.
static SDValue truncateVectorWithNARROW(EVT DstVT, SDValue In, const SDLoc &DL,
                                        SelectionDAG &DAG) {
  EVT SrcVT = In.getValueType();

  // No truncation required, we might get here due to recursive calls.
  if (SrcVT == DstVT)
    return In;

  unsigned SrcSizeInBits = SrcVT.getSizeInBits();
  unsigned NumElems = SrcVT.getVectorNumElements();
  if (!isPowerOf2_32(NumElems))
    return SDValue();
  assert(DstVT.getVectorNumElements() == NumElems && "Illegal truncation");
  assert(SrcSizeInBits > DstVT.getSizeInBits() && "Illegal truncation");

  LLVMContext &Ctx = *DAG.getContext();
  EVT PackedSVT = EVT::getIntegerVT(Ctx, SrcVT.getScalarSizeInBits() / 2);

  // Narrow to the largest type possible:
  // vXi64/vXi32 -> i16x8.narrow_i32x4_u and vXi16 -> i8x16.narrow_i16x8_u.
  EVT InVT = MVT::i16, OutVT = MVT::i8;
  if (SrcVT.getScalarSizeInBits() > 16) {
    InVT = MVT::i32;
    OutVT = MVT::i16;
  }
  unsigned SubSizeInBits = SrcSizeInBits / 2;
  InVT = EVT::getVectorVT(Ctx, InVT, SubSizeInBits / InVT.getSizeInBits());
  OutVT = EVT::getVectorVT(Ctx, OutVT, SubSizeInBits / OutVT.getSizeInBits());

  // Split lower/upper subvectors.
  SDValue Lo = extractSubVector(In, 0, DAG, DL, SubSizeInBits);
  SDValue Hi = extractSubVector(In, NumElems / 2, DAG, DL, SubSizeInBits);

  // 256bit -> 128bit truncate - Narrow lower/upper 128-bit subvectors.
  if (SrcVT.is256BitVector() && DstVT.is128BitVector()) {
    Lo = DAG.getBitcast(InVT, Lo);
    Hi = DAG.getBitcast(InVT, Hi);
    SDValue Res = DAG.getNode(WebAssemblyISD::NARROW_U, DL, OutVT, Lo, Hi);
    return DAG.getBitcast(DstVT, Res);
  }

  // Recursively narrow lower/upper subvectors, concat result and narrow again.
  EVT PackedVT = EVT::getVectorVT(Ctx, PackedSVT, NumElems / 2);
  Lo = truncateVectorWithNARROW(PackedVT, Lo, DL, DAG);
  Hi = truncateVectorWithNARROW(PackedVT, Hi, DL, DAG);

  PackedVT = EVT::getVectorVT(Ctx, PackedSVT, NumElems);
  SDValue Res = DAG.getNode(ISD::CONCAT_VECTORS, DL, PackedVT, Lo, Hi);
  return truncateVectorWithNARROW(DstVT, Res, DL, DAG);
}

static SDValue performTruncateCombine(SDNode *N,
                                      TargetLowering::DAGCombinerInfo &DCI) {
  auto &DAG = DCI.DAG;

  SDValue In = N->getOperand(0);
  EVT InVT = In.getValueType();
  if (!InVT.isSimple())
    return SDValue();

  EVT OutVT = N->getValueType(0);
  if (!OutVT.isVector())
    return SDValue();

  EVT OutSVT = OutVT.getVectorElementType();
  EVT InSVT = InVT.getVectorElementType();
  // Currently only cover truncate to v16i8 or v8i16.
  if (!((InSVT == MVT::i16 || InSVT == MVT::i32 || InSVT == MVT::i64) &&
        (OutSVT == MVT::i8 || OutSVT == MVT::i16) && OutVT.is128BitVector()))
    return SDValue();

  SDLoc DL(N);
  APInt Mask = APInt::getLowBitsSet(InVT.getScalarSizeInBits(),
                                    OutVT.getScalarSizeInBits());
  In = DAG.getNode(ISD::AND, DL, InVT, In, DAG.getConstant(Mask, DL, InVT));
  return truncateVectorWithNARROW(OutVT, In, DL, DAG);
}

static SDValue performBitcastCombine(SDNode *N,
                                     TargetLowering::DAGCombinerInfo &DCI) {
  using namespace llvm::SDPatternMatch;
  auto &DAG = DCI.DAG;
  SDLoc DL(N);
  SDValue Src = N->getOperand(0);
  EVT VT = N->getValueType(0);
  EVT SrcVT = Src.getValueType();

  if (!(DCI.isBeforeLegalize() && VT.isScalarInteger() &&
        SrcVT.isFixedLengthVectorOf(MVT::i1)))
    return SDValue();

  unsigned NumElts = SrcVT.getVectorNumElements();
  EVT Width = MVT::getIntegerVT(128 / NumElts);

  // bitcast <N x i1> to iN, where N = 2, 4, 8, 16 (legal)
  //   ==> bitmask
  if (NumElts == 2 || NumElts == 4 || NumElts == 8 || NumElts == 16) {
    return DAG.getZExtOrTrunc(
        DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
                    {DAG.getConstant(Intrinsic::wasm_bitmask, DL, MVT::i32),
                     DAG.getSExtOrTrunc(N->getOperand(0), DL,
                                        SrcVT.changeVectorElementType(
                                            *DAG.getContext(), Width))}),
        DL, VT);
  }

  // bitcast <N x i1>(setcc ...) to concat iN, where N = 32 and 64 (illegal)
  if (NumElts == 32 || NumElts == 64) {
    SDValue Concat, SetCCVector;
    ISD::CondCode SetCond;

    if (!sd_match(N, m_BitCast(m_c_SetCC(m_Value(Concat), m_Value(SetCCVector),
                                         m_CondCode(SetCond)))))
      return SDValue();
    if (Concat.getOpcode() != ISD::CONCAT_VECTORS)
      return SDValue();

    // Reconstruct the wide bitmask from each CONCAT_VECTORS operand.
    // Derive the per-chunk mask/integer types from the actual operand type
    // instead of hardcoding v16i1 / i16 for every chunk.
    EVT ConcatOperandVT = Concat.getOperand(0).getValueType();
    unsigned ConcatOperandNumElts = ConcatOperandVT.getVectorNumElements();

    EVT ConcatOperandMaskVT =
        EVT::getVectorVT(*DAG.getContext(), MVT::i1,
                         ElementCount::getFixed(ConcatOperandNumElts));
    EVT ConcatOperandBitmaskVT =
        EVT::getIntegerVT(*DAG.getContext(), ConcatOperandNumElts);
    EVT ReturnVT = N->getValueType(0);
    SDValue ReconstructedBitmask = DAG.getConstant(0, DL, ReturnVT);
    // Example:
    //   v32i16 = concat(v8i16, v8i16, v8i16, v8i16)
    //     -> v8i1 + v8i1 + v8i1 + v8i1
    //     -> i8   + i8   + i8   + i8
    //     -> reconstructed i32 bitmask
    for (size_t I = 0; I < Concat->ops().size(); ++I) {
      SDValue ConcatOperand = Concat.getOperand(I);
      assert(ConcatOperand.getValueType() == ConcatOperandVT &&
             "concat_vectors operands must have the same type");

      SDValue SetCCVectorOperand =
          extractSubVector(SetCCVector, I * ConcatOperandNumElts, DAG, DL, 128);
      if (!SetCCVectorOperand ||
          SetCCVectorOperand.getValueType() != ConcatOperandVT)
        return SDValue();

      // Build the per-chunk mask using the correct chunk type:
      //   v16i8 -> v16i1 -> i16
      //   v8i16 -> v8i1  -> i8
      //   v4i32 -> v4i1  -> i4
      //   v2i64 -> v2i1  -> i2
      SDValue ConcatOperandMask = DAG.getSetCC(
          DL, ConcatOperandMaskVT, ConcatOperand, SetCCVectorOperand, SetCond);
      SDValue ConcatOperandBitmask =
          DAG.getBitcast(ConcatOperandBitmaskVT, ConcatOperandMask);
      SDValue ExtendedConcatOperandBitmask =
          DAG.getZExtOrTrunc(ConcatOperandBitmask, DL, ReturnVT);

      // Shift the previously reconstructed bits to make room for this chunk.
      if (I != 0) {
        ReconstructedBitmask = DAG.getNode(
            ISD::SHL, DL, ReturnVT, ReconstructedBitmask,
            DAG.getShiftAmountConstant(ConcatOperandNumElts, ReturnVT, DL));
      }

      // Merge disjoint partial bitmasks with OR.
      ReconstructedBitmask =
          DAG.getNode(ISD::OR, DL, ReturnVT, ReconstructedBitmask,
                      ExtendedConcatOperandBitmask);
    }

    return ReconstructedBitmask;
  }

  return SDValue();
}

static SDValue performBitmaskCombine(SDNode *N, SelectionDAG &DAG) {
  // bitmask (setcc <X>, 0, setlt) => bitmask X
  assert(N->getOpcode() == ISD::INTRINSIC_WO_CHAIN);
  using namespace llvm::SDPatternMatch;

  if (N->getConstantOperandVal(0) != Intrinsic::wasm_bitmask)
    return SDValue();

  SDValue LHS;
  if (!sd_match(N->getOperand(1), m_c_SetCC(m_Value(LHS), m_Zero(),
                                            m_SpecificCondCode(ISD::SETLT))))
    return SDValue();

  SDLoc DL(N);
  return DAG.getNode(
      ISD::INTRINSIC_WO_CHAIN, DL, N->getValueType(0),
      {DAG.getConstant(Intrinsic::wasm_bitmask, DL, MVT::i32), LHS});
}

static SDValue performAnyAllCombine(SDNode *N, SelectionDAG &DAG) {
  // any_true (setcc <X>, 0, eq) => (not (all_true X))
  // all_true (setcc <X>, 0, eq) => (not (any_true X))
  // any_true (setcc <X>, 0, ne) => (any_true X)
  // all_true (setcc <X>, 0, ne) => (all_true X)
  assert(N->getOpcode() == ISD::INTRINSIC_WO_CHAIN);
  using namespace llvm::SDPatternMatch;

  SDValue LHS;
  if (N->getNumOperands() < 2 ||
      !sd_match(N->getOperand(1),
                m_c_SetCC(m_Value(LHS), m_Zero(), m_CondCode())))
    return SDValue();
  EVT LT = LHS.getValueType();
  if (LT.getScalarSizeInBits() > 128 / LT.getVectorNumElements())
    return SDValue();

  auto CombineSetCC = [&N, &DAG](Intrinsic::WASMIntrinsics InPre,
                                 ISD::CondCode SetType,
                                 Intrinsic::WASMIntrinsics InPost) {
    if (N->getConstantOperandVal(0) != InPre)
      return SDValue();

    SDValue LHS;
    if (!sd_match(N->getOperand(1), m_c_SetCC(m_Value(LHS), m_Zero(),
                                              m_SpecificCondCode(SetType))))
      return SDValue();

    SDLoc DL(N);
    SDValue Ret = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
                              {DAG.getConstant(InPost, DL, MVT::i32), LHS});
    if (SetType == ISD::SETEQ)
      Ret = DAG.getNode(ISD::XOR, DL, MVT::i32, Ret,
                        DAG.getConstant(1, DL, MVT::i32));
    return DAG.getZExtOrTrunc(Ret, DL, N->getValueType(0));
  };

  if (SDValue AnyTrueEQ = CombineSetCC(Intrinsic::wasm_anytrue, ISD::SETEQ,
                                       Intrinsic::wasm_alltrue))
    return AnyTrueEQ;
  if (SDValue AllTrueEQ = CombineSetCC(Intrinsic::wasm_alltrue, ISD::SETEQ,
                                       Intrinsic::wasm_anytrue))
    return AllTrueEQ;
  if (SDValue AnyTrueNE = CombineSetCC(Intrinsic::wasm_anytrue, ISD::SETNE,
                                       Intrinsic::wasm_anytrue))
    return AnyTrueNE;
  if (SDValue AllTrueNE = CombineSetCC(Intrinsic::wasm_alltrue, ISD::SETNE,
                                       Intrinsic::wasm_alltrue))
    return AllTrueNE;

  return SDValue();
}

struct MaskReduceInfo {
  Intrinsic::ID IID;
  unsigned WideCombineOpcode;
  bool Invert;
};

static SDValue combineSmallMaskReduction(SDNode *N, EVT FromVT,
                                         unsigned NumElts,
                                         const MaskReduceInfo &Info,
                                         SelectionDAG &DAG) {
  EVT VecVT = FromVT.changeVectorElementType(*DAG.getContext(),
                                             MVT::getIntegerVT(128 / NumElts));
  assert(VecVT.getSizeInBits() == 128 &&
         "mask reduction should be widened to a 128-bit vector");

  SDLoc DL(N);
  SDValue Mask = N->getOperand(0)->getOperand(0);
  SDValue Ret = DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
                            {DAG.getConstant(Info.IID, DL, MVT::i32),
                             DAG.getSExtOrTrunc(Mask, DL, VecVT)});
  if (Info.Invert)
    Ret = DAG.getNode(ISD::XOR, DL, MVT::i32, Ret,
                      DAG.getConstant(1, DL, MVT::i32));
  return DAG.getZExtOrTrunc(Ret, DL, N->getValueType(0));
}

static SDValue combineWideMaskReduction(SDNode *N, SDValue Mask, EVT MaskVT,
                                        unsigned NumElts,
                                        const MaskReduceInfo &Info,
                                        SelectionDAG &DAG) {
  assert((NumElts == 32 || NumElts == 64) &&
         "combineWideMaskReduction is only for wide masks");
  assert(MaskVT.isFixedLengthVector() &&
         MaskVT.getVectorElementType() == MVT::i1);
  SDLoc DL(N);
  unsigned ChunkElts = 16;
  EVT ChunkMaskVT = EVT::getVectorVT(*DAG.getContext(), MVT::i1,
                                     ElementCount::getFixed(ChunkElts));
  EVT LegalVecVT = ChunkMaskVT.changeVectorElementType(
      *DAG.getContext(), MVT::getIntegerVT(128 / ChunkElts));

  SmallVector<SDValue, 4> ChunkResults;
  // Split the wide mask into v16i1 chunks and reduce each chunk separately.
  // For example:
  //   v32i1:  [0..15] [16..31]
  //              |       |
  //              v       v
  //            chunk0  chunk1
  //
  //   v64i1:  [0..15] [16..31] [32..47] [48..63]
  //              |       |       |       |
  //              v       v       v       v
  //            chunk0  chunk1  chunk2  chunk3
  //
  //   each chunk:
  //     v16i1 -> v16i8 -> wasm_anytrue/alltrue -> i32 0/1
  for (unsigned I = 0; I < NumElts; I += ChunkElts) {
    SDValue ChunkMask = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, ChunkMaskVT,
                                    Mask, DAG.getVectorIdxConstant(I, DL));
    SDValue LegalMask = DAG.getSExtOrTrunc(ChunkMask, DL, LegalVecVT);
    SDValue Reduced =
        DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
                    DAG.getConstant(Info.IID, DL, MVT::i32), LegalMask);
    ChunkResults.push_back(Reduced);
  }

  SDValue Acc = ChunkResults[0];
  for (unsigned I = 1; I < ChunkResults.size(); ++I)
    Acc =
        DAG.getNode(Info.WideCombineOpcode, DL, MVT::i32, Acc, ChunkResults[I]);

  if (Info.Invert)
    Acc = DAG.getNode(ISD::XOR, DL, MVT::i32, Acc,
                      DAG.getConstant(1, DL, MVT::i32));

  return DAG.getZExtOrTrunc(Acc, DL, N->getValueType(0));
}

static std::optional<MaskReduceInfo> classifyMaskReduction(SDNode *N) {
  auto *C = dyn_cast<ConstantSDNode>(N->getOperand(1));
  if (!C)
    return std::nullopt;

  ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();

  // setcc (bitcast mask), 0, ne  -> any_true(mask)
  if (C->isZero() && CC == ISD::SETNE)
    return MaskReduceInfo{Intrinsic::wasm_anytrue, ISD::OR, false};

  // setcc (bitcast mask), 0, eq  -> !any_true(mask)
  if (C->isZero() && CC == ISD::SETEQ)
    return MaskReduceInfo{Intrinsic::wasm_anytrue, ISD::OR, true};

  // setcc (bitcast mask), -1, eq -> all_true(mask)
  if (C->isAllOnes() && CC == ISD::SETEQ)
    return MaskReduceInfo{Intrinsic::wasm_alltrue, ISD::AND, false};

  // setcc (bitcast mask), -1, ne -> !all_true(mask)
  if (C->isAllOnes() && CC == ISD::SETNE)
    return MaskReduceInfo{Intrinsic::wasm_alltrue, ISD::AND, true};

  return std::nullopt;
}

/// Try to convert a i128 comparison to a v16i8 comparison before type
/// legalization splits it up into chunks
static SDValue
combineVectorSizedSetCCEquality(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
                                const WebAssemblySubtarget *Subtarget) {

  SDLoc DL(N);
  SDValue X = N->getOperand(0);
  SDValue Y = N->getOperand(1);
  EVT VT = N->getValueType(0);
  EVT OpVT = X.getValueType();

  SelectionDAG &DAG = DCI.DAG;
  if (DCI.DAG.getMachineFunction().getFunction().hasFnAttribute(
          Attribute::NoImplicitFloat))
    return SDValue();

  ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
  // We're looking for an oversized integer equality comparison with SIMD
  if (!OpVT.isScalarInteger() || !OpVT.isByteSized() || OpVT != MVT::i128 ||
      !Subtarget->hasSIMD128() || !isIntEqualitySetCC(CC))
    return SDValue();

  // Don't perform this combine if constructing the vector will be expensive.
  auto IsVectorBitCastCheap = [](SDValue X) {
    X = peekThroughBitcasts(X);
    return isa<ConstantSDNode>(X) || X.getOpcode() == ISD::LOAD;
  };

  if (!IsVectorBitCastCheap(X) || !IsVectorBitCastCheap(Y))
    return SDValue();

  SDValue VecX = DAG.getBitcast(MVT::v16i8, X);
  SDValue VecY = DAG.getBitcast(MVT::v16i8, Y);
  SDValue Cmp = DAG.getSetCC(DL, MVT::v16i8, VecX, VecY, CC);

  SDValue Intr =
      DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, MVT::i32,
                  {DAG.getConstant(CC == ISD::SETEQ ? Intrinsic::wasm_alltrue
                                                    : Intrinsic::wasm_anytrue,
                                   DL, MVT::i32),
                   Cmp});

  return DAG.getSetCC(DL, VT, Intr, DAG.getConstant(0, DL, MVT::i32),
                      ISD::SETNE);
}

static SDValue performSETCCCombine(SDNode *N,
                                   TargetLowering::DAGCombinerInfo &DCI,
                                   const WebAssemblySubtarget *Subtarget) {
  if (!DCI.isBeforeLegalize())
    return SDValue();

  EVT VT = N->getValueType(0);
  if (!VT.isScalarInteger())
    return SDValue();

  if (SDValue V = combineVectorSizedSetCCEquality(N, DCI, Subtarget))
    return V;

  SDValue LHS = N->getOperand(0);
  if (LHS->getOpcode() != ISD::BITCAST)
    return SDValue();

  EVT FromVT = LHS->getOperand(0).getValueType();
  if (!FromVT.isFixedLengthVectorOf(MVT::i1))
    return SDValue();

  unsigned NumElts = FromVT.getVectorNumElements();
  auto Info = classifyMaskReduction(N);
  if (!Info)
    return SDValue();

  auto &DAG = DCI.DAG;
  if (NumElts == 2 || NumElts == 4 || NumElts == 8 || NumElts == 16)
    return combineSmallMaskReduction(N, FromVT, NumElts, *Info, DAG);

  if (NumElts == 32 || NumElts == 64)
    return combineWideMaskReduction(N, LHS.getOperand(0), FromVT, NumElts,
                                    *Info, DAG);

  return SDValue();
}

static SDValue TryWideExtMulCombine(SDNode *N, SelectionDAG &DAG) {
  EVT VT = N->getValueType(0);
  if (VT != MVT::v8i32 && VT != MVT::v16i32)
    return SDValue();

  // Mul with extending inputs.
  SDValue LHS = N->getOperand(0);
  SDValue RHS = N->getOperand(1);
  if (LHS.getOpcode() != RHS.getOpcode())
    return SDValue();

  if (LHS.getOpcode() != ISD::SIGN_EXTEND &&
      LHS.getOpcode() != ISD::ZERO_EXTEND)
    return SDValue();

  if (LHS->getOperand(0).getValueType() != RHS->getOperand(0).getValueType())
    return SDValue();

  EVT FromVT = LHS->getOperand(0).getValueType();
  EVT EltTy = FromVT.getVectorElementType();
  if (EltTy != MVT::i8)
    return SDValue();

  // For an input DAG that looks like this
  // %a = input_type
  // %b = input_type
  // %lhs = extend %a to output_type
  // %rhs = extend %b to output_type
  // %mul = mul %lhs, %rhs

  // input_type | output_type | instructions
  // v16i8      | v16i32      | %low = i16x8.extmul_low_i8x16_ %a, %b
  //            |             | %high = i16x8.extmul_high_i8x16_, %a, %b
  //            |             | %low_low = i32x4.ext_low_i16x8_ %low
  //            |             | %low_high = i32x4.ext_high_i16x8_ %low
  //            |             | %high_low = i32x4.ext_low_i16x8_ %high
  //            |             | %high_high = i32x4.ext_high_i16x8_ %high
  //            |             | %res = concat_vector(...)
  // v8i8       | v8i32       | %low = i16x8.extmul_low_i8x16_ %a, %b
  //            |             | %low_low = i32x4.ext_low_i16x8_ %low
  //            |             | %low_high = i32x4.ext_high_i16x8_ %low
  //            |             | %res = concat_vector(%low_low, %low_high)

  SDLoc DL(N);
  unsigned NumElts = VT.getVectorNumElements();
  SDValue ExtendInLHS = LHS->getOperand(0);
  SDValue ExtendInRHS = RHS->getOperand(0);
  bool IsSigned = LHS->getOpcode() == ISD::SIGN_EXTEND;
  unsigned ExtendLowOpc =
      IsSigned ? WebAssemblyISD::EXTEND_LOW_S : WebAssemblyISD::EXTEND_LOW_U;
  unsigned ExtendHighOpc =
      IsSigned ? WebAssemblyISD::EXTEND_HIGH_S : WebAssemblyISD::EXTEND_HIGH_U;

  auto GetExtendLow = [&DAG, &DL, &ExtendLowOpc](EVT VT, SDValue Op) {
    return DAG.getNode(ExtendLowOpc, DL, VT, Op);
  };
  auto GetExtendHigh = [&DAG, &DL, &ExtendHighOpc](EVT VT, SDValue Op) {
    return DAG.getNode(ExtendHighOpc, DL, VT, Op);
  };

  if (NumElts == 16) {
    SDValue LowLHS = GetExtendLow(MVT::v8i16, ExtendInLHS);
    SDValue LowRHS = GetExtendLow(MVT::v8i16, ExtendInRHS);
    SDValue MulLow = DAG.getNode(ISD::MUL, DL, MVT::v8i16, LowLHS, LowRHS);
    SDValue HighLHS = GetExtendHigh(MVT::v8i16, ExtendInLHS);
    SDValue HighRHS = GetExtendHigh(MVT::v8i16, ExtendInRHS);
    SDValue MulHigh = DAG.getNode(ISD::MUL, DL, MVT::v8i16, HighLHS, HighRHS);
    SDValue SubVectors[] = {
        GetExtendLow(MVT::v4i32, MulLow),
        GetExtendHigh(MVT::v4i32, MulLow),
        GetExtendLow(MVT::v4i32, MulHigh),
        GetExtendHigh(MVT::v4i32, MulHigh),
    };
    return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, SubVectors);
  } else {
    assert(NumElts == 8);
    SDValue LowLHS = DAG.getNode(LHS->getOpcode(), DL, MVT::v8i16, ExtendInLHS);
    SDValue LowRHS = DAG.getNode(RHS->getOpcode(), DL, MVT::v8i16, ExtendInRHS);
    SDValue MulLow = DAG.getNode(ISD::MUL, DL, MVT::v8i16, LowLHS, LowRHS);
    SDValue Lo = GetExtendLow(MVT::v4i32, MulLow);
    SDValue Hi = GetExtendHigh(MVT::v4i32, MulLow);
    return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, Lo, Hi);
  }
  return SDValue();
}

static SDValue performMulCombine(SDNode *N,
                                 TargetLowering::DAGCombinerInfo &DCI) {
  assert(N->getOpcode() == ISD::MUL);
  EVT VT = N->getValueType(0);
  if (!VT.isVector())
    return SDValue();

  if (auto Res = TryWideExtMulCombine(N, DCI.DAG))
    return Res;

  // We don't natively support v16i8 or v8i8 mul, but we do support v8i16. So,
  // extend them to v8i16.
  if (VT != MVT::v8i8 && VT != MVT::v16i8)
    return SDValue();

  SDLoc DL(N);
  SelectionDAG &DAG = DCI.DAG;
  SDValue LHS = N->getOperand(0);
  SDValue RHS = N->getOperand(1);
  EVT MulVT = MVT::v8i16;

  if (VT == MVT::v8i8) {
    SDValue PromotedLHS = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v16i8, LHS,
                                      DAG.getUNDEF(MVT::v8i8));
    SDValue PromotedRHS = DAG.getNode(ISD::CONCAT_VECTORS, DL, MVT::v16i8, RHS,
                                      DAG.getUNDEF(MVT::v8i8));
    SDValue LowLHS =
        DAG.getNode(WebAssemblyISD::EXTEND_LOW_U, DL, MulVT, PromotedLHS);
    SDValue LowRHS =
        DAG.getNode(WebAssemblyISD::EXTEND_LOW_U, DL, MulVT, PromotedRHS);
    SDValue MulLow = DAG.getBitcast(
        MVT::v16i8, DAG.getNode(ISD::MUL, DL, MulVT, LowLHS, LowRHS));
    // Take the low byte of each lane.
    SDValue Shuffle = DAG.getVectorShuffle(
        MVT::v16i8, DL, MulLow, DAG.getUNDEF(MVT::v16i8),
        {0, 2, 4, 6, 8, 10, 12, 14, -1, -1, -1, -1, -1, -1, -1, -1});
    return extractSubVector(Shuffle, 0, DAG, DL, 64);
  } else {
    assert(VT == MVT::v16i8 && "Expected v16i8");
    SDValue LowLHS = DAG.getNode(WebAssemblyISD::EXTEND_LOW_U, DL, MulVT, LHS);
    SDValue LowRHS = DAG.getNode(WebAssemblyISD::EXTEND_LOW_U, DL, MulVT, RHS);
    SDValue HighLHS =
        DAG.getNode(WebAssemblyISD::EXTEND_HIGH_U, DL, MulVT, LHS);
    SDValue HighRHS =
        DAG.getNode(WebAssemblyISD::EXTEND_HIGH_U, DL, MulVT, RHS);

    SDValue MulLow =
        DAG.getBitcast(VT, DAG.getNode(ISD::MUL, DL, MulVT, LowLHS, LowRHS));
    SDValue MulHigh =
        DAG.getBitcast(VT, DAG.getNode(ISD::MUL, DL, MulVT, HighLHS, HighRHS));

    // Take the low byte of each lane.
    return DAG.getVectorShuffle(
        VT, DL, MulLow, MulHigh,
        {0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30});
  }
}

SDValue DoubleVectorWidth(SDValue In, unsigned RequiredNumElems,
                          SelectionDAG &DAG) {
  SDLoc DL(In);
  LLVMContext &Ctx = *DAG.getContext();
  EVT InVT = In.getValueType();
  unsigned NumElems = InVT.getVectorNumElements() * 2;
  EVT OutVT = EVT::getVectorVT(Ctx, InVT.getVectorElementType(), NumElems);
  SDValue Concat =
      DAG.getNode(ISD::CONCAT_VECTORS, DL, OutVT, In, DAG.getPOISON(InVT));
  if (NumElems < RequiredNumElems) {
    return DoubleVectorWidth(Concat, RequiredNumElems, DAG);
  }
  return Concat;
}

SDValue performConvertFPCombine(SDNode *N, SelectionDAG &DAG) {
  EVT OutVT = N->getValueType(0);
  if (!OutVT.isVector())
    return SDValue();

  EVT OutElTy = OutVT.getVectorElementType();
  if (OutElTy != MVT::i8 && OutElTy != MVT::i16)
    return SDValue();

  unsigned NumElems = OutVT.getVectorNumElements();
  if (!isPowerOf2_32(NumElems))
    return SDValue();

  EVT FPVT = N->getOperand(0)->getValueType(0);
  if (FPVT.getVectorElementType() != MVT::f32)
    return SDValue();

  SDLoc DL(N);

  // First, convert to i32.
  LLVMContext &Ctx = *DAG.getContext();
  EVT IntVT = EVT::getVectorVT(Ctx, MVT::i32, NumElems);
  SDValue ToInt = DAG.getNode(N->getOpcode(), DL, IntVT, N->getOperand(0));
  APInt Mask = APInt::getLowBitsSet(IntVT.getScalarSizeInBits(),
                                    OutVT.getScalarSizeInBits());
  // Mask out the top MSBs.
  SDValue Masked =
      DAG.getNode(ISD::AND, DL, IntVT, ToInt, DAG.getConstant(Mask, DL, IntVT));

  if (OutVT.getSizeInBits() < 128) {
    // Create a wide enough vector that we can use narrow.
    EVT NarrowedVT = OutElTy == MVT::i8 ? MVT::v16i8 : MVT::v8i16;
    unsigned NumRequiredElems = NarrowedVT.getVectorNumElements();
    SDValue WideVector = DoubleVectorWidth(Masked, NumRequiredElems, DAG);
    SDValue Trunc = truncateVectorWithNARROW(NarrowedVT, WideVector, DL, DAG);
    return DAG.getBitcast(
        OutVT, extractSubVector(Trunc, 0, DAG, DL, OutVT.getSizeInBits()));
  } else {
    return truncateVectorWithNARROW(OutVT, Masked, DL, DAG);
  }
  return SDValue();
}

// Wide vector shift operations such as v8i32 with sign-extended
// operands cause Type Legalizer crashes because the target-specific
// extension nodes cannot be directly mapped to the 256-bit size.
//
// To resolve the crash and optimize performance, we intercept the
// illegal v8i32 shift in DAGCombine. We convert the shift amounts
// into multipliers and manually split the vector into two v4i32 halves.
//
// Before: t1: v8i32 = shl (sign_extend v8i16), const_vec
// After : t2: v4i32 = mul (ext_low_s v8i16), (ext_low_s narrow_vec)
//         t3: v4i32 = mul (ext_high_s v8i16), (ext_high_s narrow_vec)
//         t4: v8i32 = concat_vectors t2, t3
static SDValue performShiftCombine(SDNode *N,
                                   TargetLowering::DAGCombinerInfo &DCI) {
  SelectionDAG &DAG = DCI.DAG;
  assert(N->getOpcode() == ISD::SHL);
  EVT VT = N->getValueType(0);
  if (VT != MVT::v8i32)
    return SDValue();

  SDValue LHS = N->getOperand(0);
  SDValue RHS = N->getOperand(1);
  unsigned ExtOpc = LHS.getOpcode();
  if (ExtOpc != ISD::SIGN_EXTEND && ExtOpc != ISD::ZERO_EXTEND)
    return SDValue();

  if (RHS.getOpcode() != ISD::BUILD_VECTOR)
    return SDValue();

  SDLoc DL(N);
  SDValue ExtendIn = LHS.getOperand(0);
  EVT FromVT = ExtendIn.getValueType();
  if (FromVT != MVT::v8i16)
    return SDValue();

  unsigned NumElts = VT.getVectorNumElements();
  unsigned BitWidth = FromVT.getScalarSizeInBits();
  bool IsSigned = (ExtOpc == ISD::SIGN_EXTEND);
  unsigned MaxValidShift = IsSigned ? (BitWidth - 1) : BitWidth;
  SmallVector<SDValue, 16> MulConsts;
  for (unsigned I = 0; I < NumElts; ++I) {
    auto *C = dyn_cast<ConstantSDNode>(RHS.getOperand(I));
    if (!C)
      return SDValue();

    const APInt &ShiftAmt = C->getAPIntValue();
    if (ShiftAmt.uge(MaxValidShift))
      return SDValue();

    APInt MulAmt = APInt::getOneBitSet(BitWidth, ShiftAmt.getZExtValue());
    MulConsts.push_back(DAG.getConstant(MulAmt, DL, FromVT.getScalarType(),
                                        /*isTarget=*/false, /*isOpaque=*/true));
  }

  SDValue NarrowConst = DAG.getBuildVector(FromVT, DL, MulConsts);
  unsigned ExtLowOpc =
      IsSigned ? WebAssemblyISD::EXTEND_LOW_S : WebAssemblyISD::EXTEND_LOW_U;
  unsigned ExtHighOpc =
      IsSigned ? WebAssemblyISD::EXTEND_HIGH_S : WebAssemblyISD::EXTEND_HIGH_U;

  EVT HalfVT = MVT::v4i32;
  SDValue LHSLo = DAG.getNode(ExtLowOpc, DL, HalfVT, ExtendIn);
  SDValue LHSHi = DAG.getNode(ExtHighOpc, DL, HalfVT, ExtendIn);
  SDValue RHSLo = DAG.getNode(ExtLowOpc, DL, HalfVT, NarrowConst);
  SDValue RHSHi = DAG.getNode(ExtHighOpc, DL, HalfVT, NarrowConst);
  SDValue MulLo = DAG.getNode(ISD::MUL, DL, HalfVT, LHSLo, RHSLo);
  SDValue MulHi = DAG.getNode(ISD::MUL, DL, HalfVT, LHSHi, RHSHi);
  return DAG.getNode(ISD::CONCAT_VECTORS, DL, VT, MulLo, MulHi);
}

static SDValue performMinMaxF128Combine(SDNode *N, SelectionDAG &DAG) {
  if (N->getValueType(0) != MVT::f128)
    return SDValue();

  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
  switch (N->getOpcode()) {
  // wasi-libc and emscripten do not currently define fminimuml and fmaximuml.
  case ISD::FMINIMUM:
  case ISD::FMAXIMUM:
    return TLI.expandFMINIMUM_FMAXIMUM(N, DAG);

  // wasi-libc and emscripten do not currently define fminimum_numl and
  // fmaximum_numl.
  case ISD::FMINIMUMNUM:
  case ISD::FMAXIMUMNUM:
    return TLI.expandFMINIMUMNUM_FMAXIMUMNUM(N, DAG);

  default:
    return SDValue();
  }
}

SDValue
WebAssemblyTargetLowering::PerformDAGCombine(SDNode *N,
                                             DAGCombinerInfo &DCI) const {
  switch (N->getOpcode()) {
  default:
    return SDValue();
  case ISD::BITCAST:
    return performBitcastCombine(N, DCI);
  case ISD::SETCC:
    return performSETCCCombine(N, DCI, Subtarget);
  case ISD::VECTOR_SHUFFLE:
    return performVECTOR_SHUFFLECombine(N, DCI);
  case ISD::SIGN_EXTEND:
  case ISD::ZERO_EXTEND:
    return performVectorExtendCombine(N, DCI);
  case ISD::UINT_TO_FP:
    if (auto ExtCombine = performVectorExtendToFPCombine(N, DCI))
      return ExtCombine;
    return performVectorNonNegToFPCombine(N, DCI);
  case ISD::SINT_TO_FP:
    return performVectorExtendToFPCombine(N, DCI);
  case ISD::FP_TO_SINT_SAT:
  case ISD::FP_TO_UINT_SAT:
  case ISD::FP_ROUND:
  case ISD::CONCAT_VECTORS:
    return performVectorTruncZeroCombine(N, DCI);
  case ISD::FP_TO_SINT:
  case ISD::FP_TO_UINT:
    return performConvertFPCombine(N, DCI.DAG);
  case ISD::TRUNCATE:
    return performTruncateCombine(N, DCI);
  case ISD::INTRINSIC_WO_CHAIN: {
    if (SDValue V = performBitmaskCombine(N, DCI.DAG))
      return V;
    return performAnyAllCombine(N, DCI.DAG);
  }
  case ISD::MUL:
    return performMulCombine(N, DCI);
  case ISD::SHL:
    return performShiftCombine(N, DCI);
  case ISD::FMINIMUM:
  case ISD::FMAXIMUM:
  case ISD::FMINIMUMNUM:
  case ISD::FMAXIMUMNUM:
    return performMinMaxF128Combine(N, DCI.DAG);
  }
}
