diff options
Diffstat (limited to 'contrib/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp')
| -rw-r--r-- | contrib/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp | 1417 | 
1 files changed, 0 insertions, 1417 deletions
diff --git a/contrib/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp b/contrib/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp deleted file mode 100644 index 2552e9150833..000000000000 --- a/contrib/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp +++ /dev/null @@ -1,1417 +0,0 @@ -//===-- WebAssemblyFastISel.cpp - WebAssembly FastISel 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 defines the WebAssembly-specific support for the FastISel -/// class. Some of the target-specific code is generated by tablegen in the file -/// WebAssemblyGenFastISel.inc, which is #included here. -/// -/// TODO: kill flags -/// -//===----------------------------------------------------------------------===// - -#include "MCTargetDesc/WebAssemblyMCTargetDesc.h" -#include "WebAssembly.h" -#include "WebAssemblyMachineFunctionInfo.h" -#include "WebAssemblySubtarget.h" -#include "WebAssemblyTargetMachine.h" -#include "llvm/Analysis/BranchProbabilityInfo.h" -#include "llvm/CodeGen/FastISel.h" -#include "llvm/CodeGen/FunctionLoweringInfo.h" -#include "llvm/CodeGen/MachineConstantPool.h" -#include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/DerivedTypes.h" -#include "llvm/IR/Function.h" -#include "llvm/IR/GetElementPtrTypeIterator.h" -#include "llvm/IR/GlobalAlias.h" -#include "llvm/IR/GlobalVariable.h" -#include "llvm/IR/Instructions.h" -#include "llvm/IR/IntrinsicInst.h" -#include "llvm/IR/Operator.h" -#include "llvm/IR/PatternMatch.h" - -using namespace llvm; -using namespace PatternMatch; - -#define DEBUG_TYPE "wasm-fastisel" - -namespace { - -class WebAssemblyFastISel final : public FastISel { -  // All possible address modes. -  class Address { -  public: -    using BaseKind = enum { RegBase, FrameIndexBase }; - -  private: -    BaseKind Kind = RegBase; -    union { -      unsigned Reg; -      int FI; -    } Base; - -    int64_t Offset = 0; - -    const GlobalValue *GV = nullptr; - -  public: -    // Innocuous defaults for our address. -    Address() { Base.Reg = 0; } -    void setKind(BaseKind K) { -      assert(!isSet() && "Can't change kind with non-zero base"); -      Kind = K; -    } -    BaseKind getKind() const { return Kind; } -    bool isRegBase() const { return Kind == RegBase; } -    bool isFIBase() const { return Kind == FrameIndexBase; } -    void setReg(unsigned Reg) { -      assert(isRegBase() && "Invalid base register access!"); -      assert(Base.Reg == 0 && "Overwriting non-zero register"); -      Base.Reg = Reg; -    } -    unsigned getReg() const { -      assert(isRegBase() && "Invalid base register access!"); -      return Base.Reg; -    } -    void setFI(unsigned FI) { -      assert(isFIBase() && "Invalid base frame index access!"); -      assert(Base.FI == 0 && "Overwriting non-zero frame index"); -      Base.FI = FI; -    } -    unsigned getFI() const { -      assert(isFIBase() && "Invalid base frame index access!"); -      return Base.FI; -    } - -    void setOffset(int64_t NewOffset) { -      assert(NewOffset >= 0 && "Offsets must be non-negative"); -      Offset = NewOffset; -    } -    int64_t getOffset() const { return Offset; } -    void setGlobalValue(const GlobalValue *G) { GV = G; } -    const GlobalValue *getGlobalValue() const { return GV; } -    bool isSet() const { -      if (isRegBase()) { -        return Base.Reg != 0; -      } else { -        return Base.FI != 0; -      } -    } -  }; - -  /// Keep a pointer to the WebAssemblySubtarget around so that we can make the -  /// right decision when generating code for different targets. -  const WebAssemblySubtarget *Subtarget; -  LLVMContext *Context; - -private: -  // Utility helper routines -  MVT::SimpleValueType getSimpleType(Type *Ty) { -    EVT VT = TLI.getValueType(DL, Ty, /*AllowUnknown=*/true); -    return VT.isSimple() ? VT.getSimpleVT().SimpleTy -                         : MVT::INVALID_SIMPLE_VALUE_TYPE; -  } -  MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) { -    switch (VT) { -    case MVT::i1: -    case MVT::i8: -    case MVT::i16: -      return MVT::i32; -    case MVT::i32: -    case MVT::i64: -    case MVT::f32: -    case MVT::f64: -    case MVT::exnref: -      return VT; -    case MVT::f16: -      return MVT::f32; -    case MVT::v16i8: -    case MVT::v8i16: -    case MVT::v4i32: -    case MVT::v4f32: -      if (Subtarget->hasSIMD128()) -        return VT; -      break; -    case MVT::v2i64: -    case MVT::v2f64: -      if (Subtarget->hasUnimplementedSIMD128()) -        return VT; -      break; -    default: -      break; -    } -    return MVT::INVALID_SIMPLE_VALUE_TYPE; -  } -  bool computeAddress(const Value *Obj, Address &Addr); -  void materializeLoadStoreOperands(Address &Addr); -  void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB, -                            MachineMemOperand *MMO); -  unsigned maskI1Value(unsigned Reg, const Value *V); -  unsigned getRegForI1Value(const Value *V, bool &Not); -  unsigned zeroExtendToI32(unsigned Reg, const Value *V, -                           MVT::SimpleValueType From); -  unsigned signExtendToI32(unsigned Reg, const Value *V, -                           MVT::SimpleValueType From); -  unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From, -                      MVT::SimpleValueType To); -  unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From, -                      MVT::SimpleValueType To); -  unsigned getRegForUnsignedValue(const Value *V); -  unsigned getRegForSignedValue(const Value *V); -  unsigned getRegForPromotedValue(const Value *V, bool IsSigned); -  unsigned notValue(unsigned Reg); -  unsigned copyValue(unsigned Reg); - -  // Backend specific FastISel code. -  unsigned fastMaterializeAlloca(const AllocaInst *AI) override; -  unsigned fastMaterializeConstant(const Constant *C) override; -  bool fastLowerArguments() override; - -  // Selection routines. -  bool selectCall(const Instruction *I); -  bool selectSelect(const Instruction *I); -  bool selectTrunc(const Instruction *I); -  bool selectZExt(const Instruction *I); -  bool selectSExt(const Instruction *I); -  bool selectICmp(const Instruction *I); -  bool selectFCmp(const Instruction *I); -  bool selectBitCast(const Instruction *I); -  bool selectLoad(const Instruction *I); -  bool selectStore(const Instruction *I); -  bool selectBr(const Instruction *I); -  bool selectRet(const Instruction *I); -  bool selectUnreachable(const Instruction *I); - -public: -  // Backend specific FastISel code. -  WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo, -                      const TargetLibraryInfo *LibInfo) -      : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) { -    Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>(); -    Context = &FuncInfo.Fn->getContext(); -  } - -  bool fastSelectInstruction(const Instruction *I) override; - -#include "WebAssemblyGenFastISel.inc" -}; - -} // end anonymous namespace - -bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) { -  const User *U = nullptr; -  unsigned Opcode = Instruction::UserOp1; -  if (const auto *I = dyn_cast<Instruction>(Obj)) { -    // Don't walk into other basic blocks unless the object is an alloca from -    // another block, otherwise it may not have a virtual register assigned. -    if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) || -        FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) { -      Opcode = I->getOpcode(); -      U = I; -    } -  } else if (const auto *C = dyn_cast<ConstantExpr>(Obj)) { -    Opcode = C->getOpcode(); -    U = C; -  } - -  if (auto *Ty = dyn_cast<PointerType>(Obj->getType())) -    if (Ty->getAddressSpace() > 255) -      // Fast instruction selection doesn't support the special -      // address spaces. -      return false; - -  if (const auto *GV = dyn_cast<GlobalValue>(Obj)) { -    if (TLI.isPositionIndependent()) -      return false; -    if (Addr.getGlobalValue()) -      return false; -    if (GV->isThreadLocal()) -      return false; -    Addr.setGlobalValue(GV); -    return true; -  } - -  switch (Opcode) { -  default: -    break; -  case Instruction::BitCast: { -    // Look through bitcasts. -    return computeAddress(U->getOperand(0), Addr); -  } -  case Instruction::IntToPtr: { -    // Look past no-op inttoptrs. -    if (TLI.getValueType(DL, U->getOperand(0)->getType()) == -        TLI.getPointerTy(DL)) -      return computeAddress(U->getOperand(0), Addr); -    break; -  } -  case Instruction::PtrToInt: { -    // Look past no-op ptrtoints. -    if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL)) -      return computeAddress(U->getOperand(0), Addr); -    break; -  } -  case Instruction::GetElementPtr: { -    Address SavedAddr = Addr; -    uint64_t TmpOffset = Addr.getOffset(); -    // Non-inbounds geps can wrap; wasm's offsets can't. -    if (!cast<GEPOperator>(U)->isInBounds()) -      goto unsupported_gep; -    // Iterate through the GEP folding the constants into offsets where -    // we can. -    for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U); -         GTI != E; ++GTI) { -      const Value *Op = GTI.getOperand(); -      if (StructType *STy = GTI.getStructTypeOrNull()) { -        const StructLayout *SL = DL.getStructLayout(STy); -        unsigned Idx = cast<ConstantInt>(Op)->getZExtValue(); -        TmpOffset += SL->getElementOffset(Idx); -      } else { -        uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType()); -        for (;;) { -          if (const auto *CI = dyn_cast<ConstantInt>(Op)) { -            // Constant-offset addressing. -            TmpOffset += CI->getSExtValue() * S; -            break; -          } -          if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) { -            // An unscaled add of a register. Set it as the new base. -            unsigned Reg = getRegForValue(Op); -            if (Reg == 0) -              return false; -            Addr.setReg(Reg); -            break; -          } -          if (canFoldAddIntoGEP(U, Op)) { -            // A compatible add with a constant operand. Fold the constant. -            auto *CI = cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1)); -            TmpOffset += CI->getSExtValue() * S; -            // Iterate on the other operand. -            Op = cast<AddOperator>(Op)->getOperand(0); -            continue; -          } -          // Unsupported -          goto unsupported_gep; -        } -      } -    } -    // Don't fold in negative offsets. -    if (int64_t(TmpOffset) >= 0) { -      // Try to grab the base operand now. -      Addr.setOffset(TmpOffset); -      if (computeAddress(U->getOperand(0), Addr)) -        return true; -    } -    // We failed, restore everything and try the other options. -    Addr = SavedAddr; -  unsupported_gep: -    break; -  } -  case Instruction::Alloca: { -    const auto *AI = cast<AllocaInst>(Obj); -    DenseMap<const AllocaInst *, int>::iterator SI = -        FuncInfo.StaticAllocaMap.find(AI); -    if (SI != FuncInfo.StaticAllocaMap.end()) { -      if (Addr.isSet()) { -        return false; -      } -      Addr.setKind(Address::FrameIndexBase); -      Addr.setFI(SI->second); -      return true; -    } -    break; -  } -  case Instruction::Add: { -    // Adds of constants are common and easy enough. -    const Value *LHS = U->getOperand(0); -    const Value *RHS = U->getOperand(1); - -    if (isa<ConstantInt>(LHS)) -      std::swap(LHS, RHS); - -    if (const auto *CI = dyn_cast<ConstantInt>(RHS)) { -      uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue(); -      if (int64_t(TmpOffset) >= 0) { -        Addr.setOffset(TmpOffset); -        return computeAddress(LHS, Addr); -      } -    } - -    Address Backup = Addr; -    if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr)) -      return true; -    Addr = Backup; - -    break; -  } -  case Instruction::Sub: { -    // Subs of constants are common and easy enough. -    const Value *LHS = U->getOperand(0); -    const Value *RHS = U->getOperand(1); - -    if (const auto *CI = dyn_cast<ConstantInt>(RHS)) { -      int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue(); -      if (TmpOffset >= 0) { -        Addr.setOffset(TmpOffset); -        return computeAddress(LHS, Addr); -      } -    } -    break; -  } -  } -  if (Addr.isSet()) { -    return false; -  } -  unsigned Reg = getRegForValue(Obj); -  if (Reg == 0) -    return false; -  Addr.setReg(Reg); -  return Addr.getReg() != 0; -} - -void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) { -  if (Addr.isRegBase()) { -    unsigned Reg = Addr.getReg(); -    if (Reg == 0) { -      Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass -                                                   : &WebAssembly::I32RegClass); -      unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64 -                                            : WebAssembly::CONST_I32; -      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg) -          .addImm(0); -      Addr.setReg(Reg); -    } -  } -} - -void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr, -                                               const MachineInstrBuilder &MIB, -                                               MachineMemOperand *MMO) { -  // Set the alignment operand (this is rewritten in SetP2AlignOperands). -  // TODO: Disable SetP2AlignOperands for FastISel and just do it here. -  MIB.addImm(0); - -  if (const GlobalValue *GV = Addr.getGlobalValue()) -    MIB.addGlobalAddress(GV, Addr.getOffset()); -  else -    MIB.addImm(Addr.getOffset()); - -  if (Addr.isRegBase()) -    MIB.addReg(Addr.getReg()); -  else -    MIB.addFrameIndex(Addr.getFI()); - -  MIB.addMemOperand(MMO); -} - -unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) { -  return zeroExtendToI32(Reg, V, MVT::i1); -} - -unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) { -  if (const auto *ICmp = dyn_cast<ICmpInst>(V)) -    if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1))) -      if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) { -        Not = ICmp->isTrueWhenEqual(); -        return getRegForValue(ICmp->getOperand(0)); -      } - -  Value *NotV; -  if (match(V, m_Not(m_Value(NotV))) && V->getType()->isIntegerTy(32)) { -    Not = true; -    return getRegForValue(NotV); -  } - -  Not = false; -  unsigned Reg = getRegForValue(V); -  if (Reg == 0) -    return 0; -  return maskI1Value(Reg, V); -} - -unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V, -                                              MVT::SimpleValueType From) { -  if (Reg == 0) -    return 0; - -  switch (From) { -  case MVT::i1: -    // If the value is naturally an i1, we don't need to mask it. We only know -    // if a value is naturally an i1 if it is definitely lowered by FastISel, -    // not a DAG ISel fallback. -    if (V != nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr()) -      return copyValue(Reg); -    break; -  case MVT::i8: -  case MVT::i16: -    break; -  case MVT::i32: -    return copyValue(Reg); -  default: -    return 0; -  } - -  unsigned Imm = createResultReg(&WebAssembly::I32RegClass); -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, -          TII.get(WebAssembly::CONST_I32), Imm) -      .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits())); - -  unsigned Result = createResultReg(&WebAssembly::I32RegClass); -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, -          TII.get(WebAssembly::AND_I32), Result) -      .addReg(Reg) -      .addReg(Imm); - -  return Result; -} - -unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V, -                                              MVT::SimpleValueType From) { -  if (Reg == 0) -    return 0; - -  switch (From) { -  case MVT::i1: -  case MVT::i8: -  case MVT::i16: -    break; -  case MVT::i32: -    return copyValue(Reg); -  default: -    return 0; -  } - -  unsigned Imm = createResultReg(&WebAssembly::I32RegClass); -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, -          TII.get(WebAssembly::CONST_I32), Imm) -      .addImm(32 - MVT(From).getSizeInBits()); - -  unsigned Left = createResultReg(&WebAssembly::I32RegClass); -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, -          TII.get(WebAssembly::SHL_I32), Left) -      .addReg(Reg) -      .addReg(Imm); - -  unsigned Right = createResultReg(&WebAssembly::I32RegClass); -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, -          TII.get(WebAssembly::SHR_S_I32), Right) -      .addReg(Left) -      .addReg(Imm); - -  return Right; -} - -unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V, -                                         MVT::SimpleValueType From, -                                         MVT::SimpleValueType To) { -  if (To == MVT::i64) { -    if (From == MVT::i64) -      return copyValue(Reg); - -    Reg = zeroExtendToI32(Reg, V, From); - -    unsigned Result = createResultReg(&WebAssembly::I64RegClass); -    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, -            TII.get(WebAssembly::I64_EXTEND_U_I32), Result) -        .addReg(Reg); -    return Result; -  } - -  if (To == MVT::i32) -    return zeroExtendToI32(Reg, V, From); - -  return 0; -} - -unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V, -                                         MVT::SimpleValueType From, -                                         MVT::SimpleValueType To) { -  if (To == MVT::i64) { -    if (From == MVT::i64) -      return copyValue(Reg); - -    Reg = signExtendToI32(Reg, V, From); - -    unsigned Result = createResultReg(&WebAssembly::I64RegClass); -    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, -            TII.get(WebAssembly::I64_EXTEND_S_I32), Result) -        .addReg(Reg); -    return Result; -  } - -  if (To == MVT::i32) -    return signExtendToI32(Reg, V, From); - -  return 0; -} - -unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) { -  MVT::SimpleValueType From = getSimpleType(V->getType()); -  MVT::SimpleValueType To = getLegalType(From); -  unsigned VReg = getRegForValue(V); -  if (VReg == 0) -    return 0; -  return zeroExtend(VReg, V, From, To); -} - -unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) { -  MVT::SimpleValueType From = getSimpleType(V->getType()); -  MVT::SimpleValueType To = getLegalType(From); -  unsigned VReg = getRegForValue(V); -  if (VReg == 0) -    return 0; -  return signExtend(VReg, V, From, To); -} - -unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V, -                                                     bool IsSigned) { -  return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V); -} - -unsigned WebAssemblyFastISel::notValue(unsigned Reg) { -  assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass); - -  unsigned NotReg = createResultReg(&WebAssembly::I32RegClass); -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, -          TII.get(WebAssembly::EQZ_I32), NotReg) -      .addReg(Reg); -  return NotReg; -} - -unsigned WebAssemblyFastISel::copyValue(unsigned Reg) { -  unsigned ResultReg = createResultReg(MRI.getRegClass(Reg)); -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY), -          ResultReg) -      .addReg(Reg); -  return ResultReg; -} - -unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) { -  DenseMap<const AllocaInst *, int>::iterator SI = -      FuncInfo.StaticAllocaMap.find(AI); - -  if (SI != FuncInfo.StaticAllocaMap.end()) { -    unsigned ResultReg = -        createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass -                                               : &WebAssembly::I32RegClass); -    unsigned Opc = -        Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32; -    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) -        .addFrameIndex(SI->second); -    return ResultReg; -  } - -  return 0; -} - -unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) { -  if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) { -    if (TLI.isPositionIndependent()) -      return 0; -    if (GV->isThreadLocal()) -      return 0; -    unsigned ResultReg = -        createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass -                                               : &WebAssembly::I32RegClass); -    unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64 -                                          : WebAssembly::CONST_I32; -    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) -        .addGlobalAddress(GV); -    return ResultReg; -  } - -  // Let target-independent code handle it. -  return 0; -} - -bool WebAssemblyFastISel::fastLowerArguments() { -  if (!FuncInfo.CanLowerReturn) -    return false; - -  const Function *F = FuncInfo.Fn; -  if (F->isVarArg()) -    return false; - -  unsigned I = 0; -  for (auto const &Arg : F->args()) { -    const AttributeList &Attrs = F->getAttributes(); -    if (Attrs.hasParamAttribute(I, Attribute::ByVal) || -        Attrs.hasParamAttribute(I, Attribute::SwiftSelf) || -        Attrs.hasParamAttribute(I, Attribute::SwiftError) || -        Attrs.hasParamAttribute(I, Attribute::InAlloca) || -        Attrs.hasParamAttribute(I, Attribute::Nest)) -      return false; - -    Type *ArgTy = Arg.getType(); -    if (ArgTy->isStructTy() || ArgTy->isArrayTy()) -      return false; -    if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy()) -      return false; - -    unsigned Opc; -    const TargetRegisterClass *RC; -    switch (getSimpleType(ArgTy)) { -    case MVT::i1: -    case MVT::i8: -    case MVT::i16: -    case MVT::i32: -      Opc = WebAssembly::ARGUMENT_i32; -      RC = &WebAssembly::I32RegClass; -      break; -    case MVT::i64: -      Opc = WebAssembly::ARGUMENT_i64; -      RC = &WebAssembly::I64RegClass; -      break; -    case MVT::f32: -      Opc = WebAssembly::ARGUMENT_f32; -      RC = &WebAssembly::F32RegClass; -      break; -    case MVT::f64: -      Opc = WebAssembly::ARGUMENT_f64; -      RC = &WebAssembly::F64RegClass; -      break; -    case MVT::v16i8: -      Opc = WebAssembly::ARGUMENT_v16i8; -      RC = &WebAssembly::V128RegClass; -      break; -    case MVT::v8i16: -      Opc = WebAssembly::ARGUMENT_v8i16; -      RC = &WebAssembly::V128RegClass; -      break; -    case MVT::v4i32: -      Opc = WebAssembly::ARGUMENT_v4i32; -      RC = &WebAssembly::V128RegClass; -      break; -    case MVT::v2i64: -      Opc = WebAssembly::ARGUMENT_v2i64; -      RC = &WebAssembly::V128RegClass; -      break; -    case MVT::v4f32: -      Opc = WebAssembly::ARGUMENT_v4f32; -      RC = &WebAssembly::V128RegClass; -      break; -    case MVT::v2f64: -      Opc = WebAssembly::ARGUMENT_v2f64; -      RC = &WebAssembly::V128RegClass; -      break; -    case MVT::exnref: -      Opc = WebAssembly::ARGUMENT_exnref; -      RC = &WebAssembly::EXNREFRegClass; -      break; -    default: -      return false; -    } -    unsigned ResultReg = createResultReg(RC); -    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) -        .addImm(I); -    updateValueMap(&Arg, ResultReg); - -    ++I; -  } - -  MRI.addLiveIn(WebAssembly::ARGUMENTS); - -  auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>(); -  for (auto const &Arg : F->args()) { -    MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType())); -    if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) { -      MFI->clearParamsAndResults(); -      return false; -    } -    MFI->addParam(ArgTy); -  } - -  if (!F->getReturnType()->isVoidTy()) { -    MVT::SimpleValueType RetTy = -        getLegalType(getSimpleType(F->getReturnType())); -    if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) { -      MFI->clearParamsAndResults(); -      return false; -    } -    MFI->addResult(RetTy); -  } - -  return true; -} - -bool WebAssemblyFastISel::selectCall(const Instruction *I) { -  const auto *Call = cast<CallInst>(I); - -  // TODO: Support tail calls in FastISel -  if (Call->isMustTailCall() || Call->isInlineAsm() || -      Call->getFunctionType()->isVarArg()) -    return false; - -  Function *Func = Call->getCalledFunction(); -  if (Func && Func->isIntrinsic()) -    return false; - -  bool IsDirect = Func != nullptr; -  if (!IsDirect && isa<ConstantExpr>(Call->getCalledValue())) -    return false; - -  FunctionType *FuncTy = Call->getFunctionType(); -  unsigned Opc; -  bool IsVoid = FuncTy->getReturnType()->isVoidTy(); -  unsigned ResultReg; -  if (IsVoid) { -    Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID; -  } else { -    if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy()) -      return false; - -    MVT::SimpleValueType RetTy = getSimpleType(Call->getType()); -    switch (RetTy) { -    case MVT::i1: -    case MVT::i8: -    case MVT::i16: -    case MVT::i32: -      Opc = IsDirect ? WebAssembly::CALL_i32 : WebAssembly::PCALL_INDIRECT_i32; -      ResultReg = createResultReg(&WebAssembly::I32RegClass); -      break; -    case MVT::i64: -      Opc = IsDirect ? WebAssembly::CALL_i64 : WebAssembly::PCALL_INDIRECT_i64; -      ResultReg = createResultReg(&WebAssembly::I64RegClass); -      break; -    case MVT::f32: -      Opc = IsDirect ? WebAssembly::CALL_f32 : WebAssembly::PCALL_INDIRECT_f32; -      ResultReg = createResultReg(&WebAssembly::F32RegClass); -      break; -    case MVT::f64: -      Opc = IsDirect ? WebAssembly::CALL_f64 : WebAssembly::PCALL_INDIRECT_f64; -      ResultReg = createResultReg(&WebAssembly::F64RegClass); -      break; -    case MVT::v16i8: -      Opc = IsDirect ? WebAssembly::CALL_v16i8 -                     : WebAssembly::PCALL_INDIRECT_v16i8; -      ResultReg = createResultReg(&WebAssembly::V128RegClass); -      break; -    case MVT::v8i16: -      Opc = IsDirect ? WebAssembly::CALL_v8i16 -                     : WebAssembly::PCALL_INDIRECT_v8i16; -      ResultReg = createResultReg(&WebAssembly::V128RegClass); -      break; -    case MVT::v4i32: -      Opc = IsDirect ? WebAssembly::CALL_v4i32 -                     : WebAssembly::PCALL_INDIRECT_v4i32; -      ResultReg = createResultReg(&WebAssembly::V128RegClass); -      break; -    case MVT::v2i64: -      Opc = IsDirect ? WebAssembly::CALL_v2i64 -                     : WebAssembly::PCALL_INDIRECT_v2i64; -      ResultReg = createResultReg(&WebAssembly::V128RegClass); -      break; -    case MVT::v4f32: -      Opc = IsDirect ? WebAssembly::CALL_v4f32 -                     : WebAssembly::PCALL_INDIRECT_v4f32; -      ResultReg = createResultReg(&WebAssembly::V128RegClass); -      break; -    case MVT::v2f64: -      Opc = IsDirect ? WebAssembly::CALL_v2f64 -                     : WebAssembly::PCALL_INDIRECT_v2f64; -      ResultReg = createResultReg(&WebAssembly::V128RegClass); -      break; -    case MVT::exnref: -      Opc = IsDirect ? WebAssembly::CALL_exnref -                     : WebAssembly::PCALL_INDIRECT_exnref; -      ResultReg = createResultReg(&WebAssembly::EXNREFRegClass); -      break; -    default: -      return false; -    } -  } - -  SmallVector<unsigned, 8> Args; -  for (unsigned I = 0, E = Call->getNumArgOperands(); I < E; ++I) { -    Value *V = Call->getArgOperand(I); -    MVT::SimpleValueType ArgTy = getSimpleType(V->getType()); -    if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) -      return false; - -    const AttributeList &Attrs = Call->getAttributes(); -    if (Attrs.hasParamAttribute(I, Attribute::ByVal) || -        Attrs.hasParamAttribute(I, Attribute::SwiftSelf) || -        Attrs.hasParamAttribute(I, Attribute::SwiftError) || -        Attrs.hasParamAttribute(I, Attribute::InAlloca) || -        Attrs.hasParamAttribute(I, Attribute::Nest)) -      return false; - -    unsigned Reg; - -    if (Attrs.hasParamAttribute(I, Attribute::SExt)) -      Reg = getRegForSignedValue(V); -    else if (Attrs.hasParamAttribute(I, Attribute::ZExt)) -      Reg = getRegForUnsignedValue(V); -    else -      Reg = getRegForValue(V); - -    if (Reg == 0) -      return false; - -    Args.push_back(Reg); -  } - -  unsigned CalleeReg = 0; -  if (!IsDirect) { -    CalleeReg = getRegForValue(Call->getCalledValue()); -    if (!CalleeReg) -      return false; -  } - -  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)); - -  if (!IsVoid) -    MIB.addReg(ResultReg, RegState::Define); - -  if (IsDirect) -    MIB.addGlobalAddress(Func); -  else -    MIB.addReg(CalleeReg); - -  for (unsigned ArgReg : Args) -    MIB.addReg(ArgReg); - -  if (!IsVoid) -    updateValueMap(Call, ResultReg); -  return true; -} - -bool WebAssemblyFastISel::selectSelect(const Instruction *I) { -  const auto *Select = cast<SelectInst>(I); - -  bool Not; -  unsigned CondReg = getRegForI1Value(Select->getCondition(), Not); -  if (CondReg == 0) -    return false; - -  unsigned TrueReg = getRegForValue(Select->getTrueValue()); -  if (TrueReg == 0) -    return false; - -  unsigned FalseReg = getRegForValue(Select->getFalseValue()); -  if (FalseReg == 0) -    return false; - -  if (Not) -    std::swap(TrueReg, FalseReg); - -  unsigned Opc; -  const TargetRegisterClass *RC; -  switch (getSimpleType(Select->getType())) { -  case MVT::i1: -  case MVT::i8: -  case MVT::i16: -  case MVT::i32: -    Opc = WebAssembly::SELECT_I32; -    RC = &WebAssembly::I32RegClass; -    break; -  case MVT::i64: -    Opc = WebAssembly::SELECT_I64; -    RC = &WebAssembly::I64RegClass; -    break; -  case MVT::f32: -    Opc = WebAssembly::SELECT_F32; -    RC = &WebAssembly::F32RegClass; -    break; -  case MVT::f64: -    Opc = WebAssembly::SELECT_F64; -    RC = &WebAssembly::F64RegClass; -    break; -  case MVT::exnref: -    Opc = WebAssembly::SELECT_EXNREF; -    RC = &WebAssembly::EXNREFRegClass; -    break; -  default: -    return false; -  } - -  unsigned ResultReg = createResultReg(RC); -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) -      .addReg(TrueReg) -      .addReg(FalseReg) -      .addReg(CondReg); - -  updateValueMap(Select, ResultReg); -  return true; -} - -bool WebAssemblyFastISel::selectTrunc(const Instruction *I) { -  const auto *Trunc = cast<TruncInst>(I); - -  unsigned Reg = getRegForValue(Trunc->getOperand(0)); -  if (Reg == 0) -    return false; - -  if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) { -    unsigned Result = createResultReg(&WebAssembly::I32RegClass); -    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, -            TII.get(WebAssembly::I32_WRAP_I64), Result) -        .addReg(Reg); -    Reg = Result; -  } - -  updateValueMap(Trunc, Reg); -  return true; -} - -bool WebAssemblyFastISel::selectZExt(const Instruction *I) { -  const auto *ZExt = cast<ZExtInst>(I); - -  const Value *Op = ZExt->getOperand(0); -  MVT::SimpleValueType From = getSimpleType(Op->getType()); -  MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType())); -  unsigned In = getRegForValue(Op); -  if (In == 0) -    return false; -  unsigned Reg = zeroExtend(In, Op, From, To); -  if (Reg == 0) -    return false; - -  updateValueMap(ZExt, Reg); -  return true; -} - -bool WebAssemblyFastISel::selectSExt(const Instruction *I) { -  const auto *SExt = cast<SExtInst>(I); - -  const Value *Op = SExt->getOperand(0); -  MVT::SimpleValueType From = getSimpleType(Op->getType()); -  MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType())); -  unsigned In = getRegForValue(Op); -  if (In == 0) -    return false; -  unsigned Reg = signExtend(In, Op, From, To); -  if (Reg == 0) -    return false; - -  updateValueMap(SExt, Reg); -  return true; -} - -bool WebAssemblyFastISel::selectICmp(const Instruction *I) { -  const auto *ICmp = cast<ICmpInst>(I); - -  bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64; -  unsigned Opc; -  bool IsSigned = false; -  switch (ICmp->getPredicate()) { -  case ICmpInst::ICMP_EQ: -    Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64; -    break; -  case ICmpInst::ICMP_NE: -    Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64; -    break; -  case ICmpInst::ICMP_UGT: -    Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64; -    break; -  case ICmpInst::ICMP_UGE: -    Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64; -    break; -  case ICmpInst::ICMP_ULT: -    Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64; -    break; -  case ICmpInst::ICMP_ULE: -    Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64; -    break; -  case ICmpInst::ICMP_SGT: -    Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64; -    IsSigned = true; -    break; -  case ICmpInst::ICMP_SGE: -    Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64; -    IsSigned = true; -    break; -  case ICmpInst::ICMP_SLT: -    Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64; -    IsSigned = true; -    break; -  case ICmpInst::ICMP_SLE: -    Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64; -    IsSigned = true; -    break; -  default: -    return false; -  } - -  unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned); -  if (LHS == 0) -    return false; - -  unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned); -  if (RHS == 0) -    return false; - -  unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass); -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) -      .addReg(LHS) -      .addReg(RHS); -  updateValueMap(ICmp, ResultReg); -  return true; -} - -bool WebAssemblyFastISel::selectFCmp(const Instruction *I) { -  const auto *FCmp = cast<FCmpInst>(I); - -  unsigned LHS = getRegForValue(FCmp->getOperand(0)); -  if (LHS == 0) -    return false; - -  unsigned RHS = getRegForValue(FCmp->getOperand(1)); -  if (RHS == 0) -    return false; - -  bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64; -  unsigned Opc; -  bool Not = false; -  switch (FCmp->getPredicate()) { -  case FCmpInst::FCMP_OEQ: -    Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64; -    break; -  case FCmpInst::FCMP_UNE: -    Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64; -    break; -  case FCmpInst::FCMP_OGT: -    Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64; -    break; -  case FCmpInst::FCMP_OGE: -    Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64; -    break; -  case FCmpInst::FCMP_OLT: -    Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64; -    break; -  case FCmpInst::FCMP_OLE: -    Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64; -    break; -  case FCmpInst::FCMP_UGT: -    Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64; -    Not = true; -    break; -  case FCmpInst::FCMP_UGE: -    Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64; -    Not = true; -    break; -  case FCmpInst::FCMP_ULT: -    Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64; -    Not = true; -    break; -  case FCmpInst::FCMP_ULE: -    Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64; -    Not = true; -    break; -  default: -    return false; -  } - -  unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass); -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) -      .addReg(LHS) -      .addReg(RHS); - -  if (Not) -    ResultReg = notValue(ResultReg); - -  updateValueMap(FCmp, ResultReg); -  return true; -} - -bool WebAssemblyFastISel::selectBitCast(const Instruction *I) { -  // Target-independent code can handle this, except it doesn't set the dead -  // flag on the ARGUMENTS clobber, so we have to do that manually in order -  // to satisfy code that expects this of isBitcast() instructions. -  EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType()); -  EVT RetVT = TLI.getValueType(DL, I->getType()); -  if (!VT.isSimple() || !RetVT.isSimple()) -    return false; - -  unsigned In = getRegForValue(I->getOperand(0)); -  if (In == 0) -    return false; - -  if (VT == RetVT) { -    // No-op bitcast. -    updateValueMap(I, In); -    return true; -  } - -  unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(), -                                        In, I->getOperand(0)->hasOneUse()); -  if (!Reg) -    return false; -  MachineBasicBlock::iterator Iter = FuncInfo.InsertPt; -  --Iter; -  assert(Iter->isBitcast()); -  Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI); -  updateValueMap(I, Reg); -  return true; -} - -bool WebAssemblyFastISel::selectLoad(const Instruction *I) { -  const auto *Load = cast<LoadInst>(I); -  if (Load->isAtomic()) -    return false; -  if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy()) -    return false; - -  Address Addr; -  if (!computeAddress(Load->getPointerOperand(), Addr)) -    return false; - -  // TODO: Fold a following sign-/zero-extend into the load instruction. - -  unsigned Opc; -  const TargetRegisterClass *RC; -  switch (getSimpleType(Load->getType())) { -  case MVT::i1: -  case MVT::i8: -    Opc = WebAssembly::LOAD8_U_I32; -    RC = &WebAssembly::I32RegClass; -    break; -  case MVT::i16: -    Opc = WebAssembly::LOAD16_U_I32; -    RC = &WebAssembly::I32RegClass; -    break; -  case MVT::i32: -    Opc = WebAssembly::LOAD_I32; -    RC = &WebAssembly::I32RegClass; -    break; -  case MVT::i64: -    Opc = WebAssembly::LOAD_I64; -    RC = &WebAssembly::I64RegClass; -    break; -  case MVT::f32: -    Opc = WebAssembly::LOAD_F32; -    RC = &WebAssembly::F32RegClass; -    break; -  case MVT::f64: -    Opc = WebAssembly::LOAD_F64; -    RC = &WebAssembly::F64RegClass; -    break; -  default: -    return false; -  } - -  materializeLoadStoreOperands(Addr); - -  unsigned ResultReg = createResultReg(RC); -  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), -                     ResultReg); - -  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load)); - -  updateValueMap(Load, ResultReg); -  return true; -} - -bool WebAssemblyFastISel::selectStore(const Instruction *I) { -  const auto *Store = cast<StoreInst>(I); -  if (Store->isAtomic()) -    return false; -  if (!Subtarget->hasSIMD128() && -      Store->getValueOperand()->getType()->isVectorTy()) -    return false; - -  Address Addr; -  if (!computeAddress(Store->getPointerOperand(), Addr)) -    return false; - -  unsigned Opc; -  bool VTIsi1 = false; -  switch (getSimpleType(Store->getValueOperand()->getType())) { -  case MVT::i1: -    VTIsi1 = true; -    LLVM_FALLTHROUGH; -  case MVT::i8: -    Opc = WebAssembly::STORE8_I32; -    break; -  case MVT::i16: -    Opc = WebAssembly::STORE16_I32; -    break; -  case MVT::i32: -    Opc = WebAssembly::STORE_I32; -    break; -  case MVT::i64: -    Opc = WebAssembly::STORE_I64; -    break; -  case MVT::f32: -    Opc = WebAssembly::STORE_F32; -    break; -  case MVT::f64: -    Opc = WebAssembly::STORE_F64; -    break; -  default: -    return false; -  } - -  materializeLoadStoreOperands(Addr); - -  unsigned ValueReg = getRegForValue(Store->getValueOperand()); -  if (ValueReg == 0) -    return false; -  if (VTIsi1) -    ValueReg = maskI1Value(ValueReg, Store->getValueOperand()); - -  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)); - -  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store)); - -  MIB.addReg(ValueReg); -  return true; -} - -bool WebAssemblyFastISel::selectBr(const Instruction *I) { -  const auto *Br = cast<BranchInst>(I); -  if (Br->isUnconditional()) { -    MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)]; -    fastEmitBranch(MSucc, Br->getDebugLoc()); -    return true; -  } - -  MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)]; -  MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)]; - -  bool Not; -  unsigned CondReg = getRegForI1Value(Br->getCondition(), Not); -  if (CondReg == 0) -    return false; - -  unsigned Opc = WebAssembly::BR_IF; -  if (Not) -    Opc = WebAssembly::BR_UNLESS; - -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)) -      .addMBB(TBB) -      .addReg(CondReg); - -  finishCondBranch(Br->getParent(), TBB, FBB); -  return true; -} - -bool WebAssemblyFastISel::selectRet(const Instruction *I) { -  if (!FuncInfo.CanLowerReturn) -    return false; - -  const auto *Ret = cast<ReturnInst>(I); - -  if (Ret->getNumOperands() == 0) { -    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, -            TII.get(WebAssembly::RETURN_VOID)); -    return true; -  } - -  Value *RV = Ret->getOperand(0); -  if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy()) -    return false; - -  unsigned Opc; -  switch (getSimpleType(RV->getType())) { -  case MVT::i1: -  case MVT::i8: -  case MVT::i16: -  case MVT::i32: -    Opc = WebAssembly::RETURN_I32; -    break; -  case MVT::i64: -    Opc = WebAssembly::RETURN_I64; -    break; -  case MVT::f32: -    Opc = WebAssembly::RETURN_F32; -    break; -  case MVT::f64: -    Opc = WebAssembly::RETURN_F64; -    break; -  case MVT::v16i8: -    Opc = WebAssembly::RETURN_v16i8; -    break; -  case MVT::v8i16: -    Opc = WebAssembly::RETURN_v8i16; -    break; -  case MVT::v4i32: -    Opc = WebAssembly::RETURN_v4i32; -    break; -  case MVT::v2i64: -    Opc = WebAssembly::RETURN_v2i64; -    break; -  case MVT::v4f32: -    Opc = WebAssembly::RETURN_v4f32; -    break; -  case MVT::v2f64: -    Opc = WebAssembly::RETURN_v2f64; -    break; -  case MVT::exnref: -    Opc = WebAssembly::RETURN_EXNREF; -    break; -  default: -    return false; -  } - -  unsigned Reg; -  if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt)) -    Reg = getRegForSignedValue(RV); -  else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt)) -    Reg = getRegForUnsignedValue(RV); -  else -    Reg = getRegForValue(RV); - -  if (Reg == 0) -    return false; - -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg); -  return true; -} - -bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) { -  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, -          TII.get(WebAssembly::UNREACHABLE)); -  return true; -} - -bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) { -  switch (I->getOpcode()) { -  case Instruction::Call: -    if (selectCall(I)) -      return true; -    break; -  case Instruction::Select: -    return selectSelect(I); -  case Instruction::Trunc: -    return selectTrunc(I); -  case Instruction::ZExt: -    return selectZExt(I); -  case Instruction::SExt: -    return selectSExt(I); -  case Instruction::ICmp: -    return selectICmp(I); -  case Instruction::FCmp: -    return selectFCmp(I); -  case Instruction::BitCast: -    return selectBitCast(I); -  case Instruction::Load: -    return selectLoad(I); -  case Instruction::Store: -    return selectStore(I); -  case Instruction::Br: -    return selectBr(I); -  case Instruction::Ret: -    return selectRet(I); -  case Instruction::Unreachable: -    return selectUnreachable(I); -  default: -    break; -  } - -  // Fall back to target-independent instruction selection. -  return selectOperator(I, I->getOpcode()); -} - -FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo, -                                      const TargetLibraryInfo *LibInfo) { -  return new WebAssemblyFastISel(FuncInfo, LibInfo); -}  | 
