brintos

brintos / llvm-project-archived public Read only

0
0
Text · 42.8 KiB · 9d8e09c Raw
1471 lines · cpp
1//===-- WebAssemblyFastISel.cpp - WebAssembly FastISel implementation -----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8///9/// \file10/// This file defines the WebAssembly-specific support for the FastISel11/// class. Some of the target-specific code is generated by tablegen in the file12/// WebAssemblyGenFastISel.inc, which is #included here.13///14/// TODO: kill flags15///16//===----------------------------------------------------------------------===//17 18#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"19#include "Utils/WebAssemblyTypeUtilities.h"20#include "WebAssemblyMachineFunctionInfo.h"21#include "WebAssemblySubtarget.h"22#include "WebAssemblyUtilities.h"23#include "llvm/Analysis/BranchProbabilityInfo.h"24#include "llvm/CodeGen/FastISel.h"25#include "llvm/CodeGen/FunctionLoweringInfo.h"26#include "llvm/CodeGen/MachineConstantPool.h"27#include "llvm/CodeGen/MachineFrameInfo.h"28#include "llvm/CodeGen/MachineInstrBuilder.h"29#include "llvm/CodeGen/MachineModuleInfo.h"30#include "llvm/CodeGen/MachineRegisterInfo.h"31#include "llvm/IR/DataLayout.h"32#include "llvm/IR/DerivedTypes.h"33#include "llvm/IR/Function.h"34#include "llvm/IR/GetElementPtrTypeIterator.h"35#include "llvm/IR/GlobalVariable.h"36#include "llvm/IR/Instructions.h"37#include "llvm/IR/Operator.h"38 39using namespace llvm;40 41#define DEBUG_TYPE "wasm-fastisel"42 43namespace {44 45class WebAssemblyFastISel final : public FastISel {46  // All possible address modes.47  class Address {48  public:49    enum BaseKind { RegBase, FrameIndexBase };50 51  private:52    BaseKind Kind = RegBase;53    union {54      unsigned Reg;55      int FI;56    } Base;57 58    // Whether the base has been determined yet59    bool IsBaseSet = false;60 61    int64_t Offset = 0;62 63    const GlobalValue *GV = nullptr;64 65  public:66    // Innocuous defaults for our address.67    Address() { Base.Reg = 0; }68    void setKind(BaseKind K) {69      assert(!isSet() && "Can't change kind with non-zero base");70      Kind = K;71    }72    BaseKind getKind() const { return Kind; }73    bool isRegBase() const { return Kind == RegBase; }74    bool isFIBase() const { return Kind == FrameIndexBase; }75    void setReg(unsigned Reg) {76      assert(isRegBase() && "Invalid base register access!");77      assert(!IsBaseSet && "Base cannot be reset");78      Base.Reg = Reg;79      IsBaseSet = true;80    }81    unsigned getReg() const {82      assert(isRegBase() && "Invalid base register access!");83      return Base.Reg;84    }85    void setFI(unsigned FI) {86      assert(isFIBase() && "Invalid base frame index access!");87      assert(!IsBaseSet && "Base cannot be reset");88      Base.FI = FI;89      IsBaseSet = true;90    }91    unsigned getFI() const {92      assert(isFIBase() && "Invalid base frame index access!");93      return Base.FI;94    }95 96    void setOffset(int64_t NewOffset) {97      assert(NewOffset >= 0 && "Offsets must be non-negative");98      Offset = NewOffset;99    }100    int64_t getOffset() const { return Offset; }101    void setGlobalValue(const GlobalValue *G) { GV = G; }102    const GlobalValue *getGlobalValue() const { return GV; }103    bool isSet() const { return IsBaseSet; }104  };105 106  /// Keep a pointer to the WebAssemblySubtarget around so that we can make the107  /// right decision when generating code for different targets.108  const WebAssemblySubtarget *Subtarget;109  LLVMContext *Context;110 111private:112  // Utility helper routines113  MVT::SimpleValueType getSimpleType(Type *Ty) {114    EVT VT = TLI.getValueType(DL, Ty, /*AllowUnknown=*/true);115    return VT.isSimple() ? VT.getSimpleVT().SimpleTy116                         : MVT::INVALID_SIMPLE_VALUE_TYPE;117  }118  MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {119    switch (VT) {120    case MVT::i1:121    case MVT::i8:122    case MVT::i16:123      return MVT::i32;124    case MVT::i32:125    case MVT::i64:126    case MVT::f32:127    case MVT::f64:128      return VT;129    case MVT::funcref:130    case MVT::externref:131      if (Subtarget->hasReferenceTypes())132        return VT;133      break;134    case MVT::exnref:135      if (Subtarget->hasReferenceTypes() && Subtarget->hasExceptionHandling())136        return VT;137      break;138    case MVT::f16:139      return MVT::f32;140    case MVT::v16i8:141    case MVT::v8i16:142    case MVT::v4i32:143    case MVT::v4f32:144    case MVT::v2i64:145    case MVT::v2f64:146      if (Subtarget->hasSIMD128())147        return VT;148      break;149    default:150      break;151    }152    return MVT::INVALID_SIMPLE_VALUE_TYPE;153  }154  bool computeAddress(const Value *Obj, Address &Addr);155  void materializeLoadStoreOperands(Address &Addr);156  void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,157                            MachineMemOperand *MMO);158  unsigned maskI1Value(unsigned Reg, const Value *V);159  unsigned getRegForI1Value(const Value *V, const BasicBlock *BB, bool &Not);160  unsigned zeroExtendToI32(unsigned Reg, const Value *V,161                           MVT::SimpleValueType From);162  unsigned signExtendToI32(unsigned Reg, const Value *V,163                           MVT::SimpleValueType From);164  unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,165                      MVT::SimpleValueType To);166  unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,167                      MVT::SimpleValueType To);168  unsigned getRegForUnsignedValue(const Value *V);169  unsigned getRegForSignedValue(const Value *V);170  unsigned getRegForPromotedValue(const Value *V, bool IsSigned);171  unsigned notValue(unsigned Reg);172  unsigned copyValue(unsigned Reg);173 174  // Backend specific FastISel code.175  Register fastMaterializeAlloca(const AllocaInst *AI) override;176  Register fastMaterializeConstant(const Constant *C) override;177  bool fastLowerArguments() override;178 179  // Selection routines.180  bool selectCall(const Instruction *I);181  bool selectSelect(const Instruction *I);182  bool selectTrunc(const Instruction *I);183  bool selectZExt(const Instruction *I);184  bool selectSExt(const Instruction *I);185  bool selectICmp(const Instruction *I);186  bool selectFCmp(const Instruction *I);187  bool selectBitCast(const Instruction *I);188  bool selectLoad(const Instruction *I);189  bool selectStore(const Instruction *I);190  bool selectBr(const Instruction *I);191  bool selectRet(const Instruction *I);192  bool selectUnreachable(const Instruction *I);193 194public:195  // Backend specific FastISel code.196  WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo,197                      const TargetLibraryInfo *LibInfo)198      : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {199    Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>();200    Context = &FuncInfo.Fn->getContext();201  }202 203  bool fastSelectInstruction(const Instruction *I) override;204 205#include "WebAssemblyGenFastISel.inc"206};207 208} // end anonymous namespace209 210bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {211  const User *U = nullptr;212  unsigned Opcode = Instruction::UserOp1;213  if (const auto *I = dyn_cast<Instruction>(Obj)) {214    // Don't walk into other basic blocks unless the object is an alloca from215    // another block, otherwise it may not have a virtual register assigned.216    if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||217        FuncInfo.getMBB(I->getParent()) == FuncInfo.MBB) {218      Opcode = I->getOpcode();219      U = I;220    }221  } else if (const auto *C = dyn_cast<ConstantExpr>(Obj)) {222    Opcode = C->getOpcode();223    U = C;224  }225 226  if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))227    if (Ty->getAddressSpace() > 255)228      // Fast instruction selection doesn't support the special229      // address spaces.230      return false;231 232  if (const auto *GV = dyn_cast<GlobalValue>(Obj)) {233    if (TLI.isPositionIndependent())234      return false;235    if (Addr.getGlobalValue())236      return false;237    if (GV->isThreadLocal())238      return false;239    Addr.setGlobalValue(GV);240    return true;241  }242 243  switch (Opcode) {244  default:245    break;246  case Instruction::BitCast: {247    // Look through bitcasts.248    return computeAddress(U->getOperand(0), Addr);249  }250  case Instruction::IntToPtr: {251    // Look past no-op inttoptrs.252    if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==253        TLI.getPointerTy(DL))254      return computeAddress(U->getOperand(0), Addr);255    break;256  }257  case Instruction::PtrToInt: {258    // Look past no-op ptrtoints.259    if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))260      return computeAddress(U->getOperand(0), Addr);261    break;262  }263  case Instruction::GetElementPtr: {264    Address SavedAddr = Addr;265    uint64_t TmpOffset = Addr.getOffset();266    // Non-inbounds geps can wrap; wasm's offsets can't.267    if (!cast<GEPOperator>(U)->isInBounds())268      goto unsupported_gep;269    // Iterate through the GEP folding the constants into offsets where270    // we can.271    for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);272         GTI != E; ++GTI) {273      const Value *Op = GTI.getOperand();274      if (StructType *STy = GTI.getStructTypeOrNull()) {275        const StructLayout *SL = DL.getStructLayout(STy);276        unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();277        TmpOffset += SL->getElementOffset(Idx);278      } else {279        uint64_t S = GTI.getSequentialElementStride(DL);280        for (;;) {281          if (const auto *CI = dyn_cast<ConstantInt>(Op)) {282            // Constant-offset addressing.283            TmpOffset += CI->getSExtValue() * S;284            break;285          }286          if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {287            // An unscaled add of a register. Set it as the new base.288            Register Reg = getRegForValue(Op);289            if (Reg == 0)290              return false;291            Addr.setReg(Reg);292            break;293          }294          if (canFoldAddIntoGEP(U, Op)) {295            // A compatible add with a constant operand. Fold the constant.296            auto *CI = cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));297            TmpOffset += CI->getSExtValue() * S;298            // Iterate on the other operand.299            Op = cast<AddOperator>(Op)->getOperand(0);300            continue;301          }302          // Unsupported303          goto unsupported_gep;304        }305      }306    }307    // Don't fold in negative offsets.308    if (int64_t(TmpOffset) >= 0) {309      // Try to grab the base operand now.310      Addr.setOffset(TmpOffset);311      if (computeAddress(U->getOperand(0), Addr))312        return true;313    }314    // We failed, restore everything and try the other options.315    Addr = SavedAddr;316  unsupported_gep:317    break;318  }319  case Instruction::Alloca: {320    const auto *AI = cast<AllocaInst>(Obj);321    DenseMap<const AllocaInst *, int>::iterator SI =322        FuncInfo.StaticAllocaMap.find(AI);323    if (SI != FuncInfo.StaticAllocaMap.end()) {324      if (Addr.isSet()) {325        return false;326      }327      Addr.setKind(Address::FrameIndexBase);328      Addr.setFI(SI->second);329      return true;330    }331    break;332  }333  case Instruction::Add: {334    // We should not fold operands into an offset when 'nuw' (no unsigned wrap)335    // is not present, because the address calculation does not wrap.336    if (auto *OFBinOp = dyn_cast<OverflowingBinaryOperator>(U))337      if (!OFBinOp->hasNoUnsignedWrap())338        break;339 340    // Adds of constants are common and easy enough.341    const Value *LHS = U->getOperand(0);342    const Value *RHS = U->getOperand(1);343 344    if (isa<ConstantInt>(LHS))345      std::swap(LHS, RHS);346 347    if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {348      uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();349      if (int64_t(TmpOffset) >= 0) {350        Addr.setOffset(TmpOffset);351        return computeAddress(LHS, Addr);352      }353    }354 355    Address Backup = Addr;356    if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))357      return true;358    Addr = Backup;359 360    break;361  }362  case Instruction::Sub: {363    // We should not fold operands into an offset when 'nuw' (no unsigned wrap)364    // is not present, because the address calculation does not wrap.365    if (auto *OFBinOp = dyn_cast<OverflowingBinaryOperator>(U))366      if (!OFBinOp->hasNoUnsignedWrap())367        break;368 369    // Subs of constants are common and easy enough.370    const Value *LHS = U->getOperand(0);371    const Value *RHS = U->getOperand(1);372 373    if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {374      int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();375      if (TmpOffset >= 0) {376        Addr.setOffset(TmpOffset);377        return computeAddress(LHS, Addr);378      }379    }380    break;381  }382  }383  if (Addr.isSet()) {384    return false;385  }386  Register Reg = getRegForValue(Obj);387  if (Reg == 0)388    return false;389  Addr.setReg(Reg);390  return Addr.getReg() != 0;391}392 393void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {394  if (Addr.isRegBase()) {395    unsigned Reg = Addr.getReg();396    if (Reg == 0) {397      Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass398                                                   : &WebAssembly::I32RegClass);399      unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64400                                            : WebAssembly::CONST_I32;401      BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), Reg)402          .addImm(0);403      Addr.setReg(Reg);404    }405  }406}407 408void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,409                                               const MachineInstrBuilder &MIB,410                                               MachineMemOperand *MMO) {411  // Set the alignment operand (this is rewritten in SetP2AlignOperands).412  // TODO: Disable SetP2AlignOperands for FastISel and just do it here.413  MIB.addImm(0);414 415  if (const GlobalValue *GV = Addr.getGlobalValue())416    MIB.addGlobalAddress(GV, Addr.getOffset());417  else418    MIB.addImm(Addr.getOffset());419 420  if (Addr.isRegBase())421    MIB.addReg(Addr.getReg());422  else423    MIB.addFrameIndex(Addr.getFI());424 425  MIB.addMemOperand(MMO);426}427 428unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {429  return zeroExtendToI32(Reg, V, MVT::i1);430}431 432unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V,433                                               const BasicBlock *BB,434                                               bool &Not) {435  if (const auto *ICmp = dyn_cast<ICmpInst>(V))436    if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))437      if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32) &&438          ICmp->getParent() == BB) {439        Not = ICmp->isTrueWhenEqual();440        return getRegForValue(ICmp->getOperand(0));441      }442 443  Not = false;444  Register Reg = getRegForValue(V);445  if (Reg == 0)446    return 0;447  return maskI1Value(Reg, V);448}449 450unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,451                                              MVT::SimpleValueType From) {452  if (Reg == 0)453    return 0;454 455  switch (From) {456  case MVT::i1:457    // If the value is naturally an i1, we don't need to mask it. We only know458    // if a value is naturally an i1 if it is definitely lowered by FastISel,459    // not a DAG ISel fallback.460    if (V != nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr())461      return copyValue(Reg);462    break;463  case MVT::i8:464  case MVT::i16:465    break;466  case MVT::i32:467    return copyValue(Reg);468  default:469    return 0;470  }471 472  Register Imm = createResultReg(&WebAssembly::I32RegClass);473  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,474          TII.get(WebAssembly::CONST_I32), Imm)475      .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));476 477  Register Result = createResultReg(&WebAssembly::I32RegClass);478  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,479          TII.get(WebAssembly::AND_I32), Result)480      .addReg(Reg)481      .addReg(Imm);482 483  return Result;484}485 486unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,487                                              MVT::SimpleValueType From) {488  if (Reg == 0)489    return 0;490 491  switch (From) {492  case MVT::i1:493  case MVT::i8:494  case MVT::i16:495    break;496  case MVT::i32:497    return copyValue(Reg);498  default:499    return 0;500  }501 502  Register Imm = createResultReg(&WebAssembly::I32RegClass);503  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,504          TII.get(WebAssembly::CONST_I32), Imm)505      .addImm(32 - MVT(From).getSizeInBits());506 507  Register Left = createResultReg(&WebAssembly::I32RegClass);508  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,509          TII.get(WebAssembly::SHL_I32), Left)510      .addReg(Reg)511      .addReg(Imm);512 513  Register Right = createResultReg(&WebAssembly::I32RegClass);514  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,515          TII.get(WebAssembly::SHR_S_I32), Right)516      .addReg(Left)517      .addReg(Imm);518 519  return Right;520}521 522unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,523                                         MVT::SimpleValueType From,524                                         MVT::SimpleValueType To) {525  if (To == MVT::i64) {526    if (From == MVT::i64)527      return copyValue(Reg);528 529    Reg = zeroExtendToI32(Reg, V, From);530 531    Register Result = createResultReg(&WebAssembly::I64RegClass);532    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,533            TII.get(WebAssembly::I64_EXTEND_U_I32), Result)534        .addReg(Reg);535    return Result;536  }537 538  if (To == MVT::i32)539    return zeroExtendToI32(Reg, V, From);540 541  return 0;542}543 544unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,545                                         MVT::SimpleValueType From,546                                         MVT::SimpleValueType To) {547  if (To == MVT::i64) {548    if (From == MVT::i64)549      return copyValue(Reg);550 551    Reg = signExtendToI32(Reg, V, From);552 553    Register Result = createResultReg(&WebAssembly::I64RegClass);554    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,555            TII.get(WebAssembly::I64_EXTEND_S_I32), Result)556        .addReg(Reg);557    return Result;558  }559 560  if (To == MVT::i32)561    return signExtendToI32(Reg, V, From);562 563  return 0;564}565 566unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {567  MVT::SimpleValueType From = getSimpleType(V->getType());568  MVT::SimpleValueType To = getLegalType(From);569  Register VReg = getRegForValue(V);570  if (VReg == 0)571    return 0;572  if (From == To)573    return VReg;574  return zeroExtend(VReg, V, From, To);575}576 577unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {578  MVT::SimpleValueType From = getSimpleType(V->getType());579  MVT::SimpleValueType To = getLegalType(From);580  Register VReg = getRegForValue(V);581  if (VReg == 0)582    return 0;583  if (From == To)584    return VReg;585  return signExtend(VReg, V, From, To);586}587 588unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,589                                                     bool IsSigned) {590  return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);591}592 593unsigned WebAssemblyFastISel::notValue(unsigned Reg) {594  assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);595 596  Register NotReg = createResultReg(&WebAssembly::I32RegClass);597  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,598          TII.get(WebAssembly::EQZ_I32), NotReg)599      .addReg(Reg);600  return NotReg;601}602 603unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {604  Register ResultReg = createResultReg(MRI.getRegClass(Reg));605  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(WebAssembly::COPY),606          ResultReg)607      .addReg(Reg);608  return ResultReg;609}610 611Register WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {612  DenseMap<const AllocaInst *, int>::iterator SI =613      FuncInfo.StaticAllocaMap.find(AI);614 615  if (SI != FuncInfo.StaticAllocaMap.end()) {616    Register ResultReg =617        createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass618                                               : &WebAssembly::I32RegClass);619    unsigned Opc =620        Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;621    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)622        .addFrameIndex(SI->second);623    return ResultReg;624  }625 626  return Register();627}628 629Register WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {630  if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {631    if (TLI.isPositionIndependent())632      return Register();633    if (GV->isThreadLocal())634      return Register();635    Register ResultReg =636        createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass637                                               : &WebAssembly::I32RegClass);638    unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64639                                          : WebAssembly::CONST_I32;640    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)641        .addGlobalAddress(GV);642    return ResultReg;643  }644 645  // Let target-independent code handle it.646  return Register();647}648 649bool WebAssemblyFastISel::fastLowerArguments() {650  if (!FuncInfo.CanLowerReturn)651    return false;652 653  const Function *F = FuncInfo.Fn;654  if (F->isVarArg())655    return false;656 657  if (FuncInfo.Fn->getCallingConv() == CallingConv::Swift)658    return false;659 660  unsigned I = 0;661  for (auto const &Arg : F->args()) {662    const AttributeList &Attrs = F->getAttributes();663    if (Attrs.hasParamAttr(I, Attribute::ByVal) ||664        Attrs.hasParamAttr(I, Attribute::SwiftSelf) ||665        Attrs.hasParamAttr(I, Attribute::SwiftError) ||666        Attrs.hasParamAttr(I, Attribute::InAlloca) ||667        Attrs.hasParamAttr(I, Attribute::Nest))668      return false;669 670    Type *ArgTy = Arg.getType();671    if (ArgTy->isStructTy() || ArgTy->isArrayTy())672      return false;673    if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())674      return false;675 676    unsigned Opc;677    const TargetRegisterClass *RC;678    switch (getSimpleType(ArgTy)) {679    case MVT::i1:680    case MVT::i8:681    case MVT::i16:682    case MVT::i32:683      Opc = WebAssembly::ARGUMENT_i32;684      RC = &WebAssembly::I32RegClass;685      break;686    case MVT::i64:687      Opc = WebAssembly::ARGUMENT_i64;688      RC = &WebAssembly::I64RegClass;689      break;690    case MVT::f32:691      Opc = WebAssembly::ARGUMENT_f32;692      RC = &WebAssembly::F32RegClass;693      break;694    case MVT::f64:695      Opc = WebAssembly::ARGUMENT_f64;696      RC = &WebAssembly::F64RegClass;697      break;698    case MVT::v16i8:699      Opc = WebAssembly::ARGUMENT_v16i8;700      RC = &WebAssembly::V128RegClass;701      break;702    case MVT::v8i16:703      Opc = WebAssembly::ARGUMENT_v8i16;704      RC = &WebAssembly::V128RegClass;705      break;706    case MVT::v4i32:707      Opc = WebAssembly::ARGUMENT_v4i32;708      RC = &WebAssembly::V128RegClass;709      break;710    case MVT::v2i64:711      Opc = WebAssembly::ARGUMENT_v2i64;712      RC = &WebAssembly::V128RegClass;713      break;714    case MVT::v4f32:715      Opc = WebAssembly::ARGUMENT_v4f32;716      RC = &WebAssembly::V128RegClass;717      break;718    case MVT::v2f64:719      Opc = WebAssembly::ARGUMENT_v2f64;720      RC = &WebAssembly::V128RegClass;721      break;722    case MVT::funcref:723      Opc = WebAssembly::ARGUMENT_funcref;724      RC = &WebAssembly::FUNCREFRegClass;725      break;726    case MVT::externref:727      Opc = WebAssembly::ARGUMENT_externref;728      RC = &WebAssembly::EXTERNREFRegClass;729      break;730    case MVT::exnref:731      Opc = WebAssembly::ARGUMENT_exnref;732      RC = &WebAssembly::EXNREFRegClass;733      break;734    default:735      return false;736    }737    Register ResultReg = createResultReg(RC);738    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)739        .addImm(I);740    updateValueMap(&Arg, ResultReg);741 742    ++I;743  }744 745  MRI.addLiveIn(WebAssembly::ARGUMENTS);746 747  auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();748  for (auto const &Arg : F->args()) {749    MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType()));750    if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {751      MFI->clearParamsAndResults();752      return false;753    }754    MFI->addParam(ArgTy);755  }756 757  if (!F->getReturnType()->isVoidTy()) {758    MVT::SimpleValueType RetTy =759        getLegalType(getSimpleType(F->getReturnType()));760    if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {761      MFI->clearParamsAndResults();762      return false;763    }764    MFI->addResult(RetTy);765  }766 767  return true;768}769 770bool WebAssemblyFastISel::selectCall(const Instruction *I) {771  const auto *Call = cast<CallInst>(I);772 773  // TODO: Support tail calls in FastISel774  if (Call->isMustTailCall() || Call->isInlineAsm() ||775      Call->getFunctionType()->isVarArg())776    return false;777 778  Function *Func = Call->getCalledFunction();779  if (Func && Func->isIntrinsic())780    return false;781 782  if (Call->getCallingConv() == CallingConv::Swift)783    return false;784 785  bool IsDirect = Func != nullptr;786  if (!IsDirect && isa<ConstantExpr>(Call->getCalledOperand()))787    return false;788 789  FunctionType *FuncTy = Call->getFunctionType();790  unsigned Opc = IsDirect ? WebAssembly::CALL : WebAssembly::CALL_INDIRECT;791  bool IsVoid = FuncTy->getReturnType()->isVoidTy();792  unsigned ResultReg;793  if (!IsVoid) {794    if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())795      return false;796 797    MVT::SimpleValueType RetTy = getSimpleType(Call->getType());798    switch (RetTy) {799    case MVT::i1:800    case MVT::i8:801    case MVT::i16:802    case MVT::i32:803      ResultReg = createResultReg(&WebAssembly::I32RegClass);804      break;805    case MVT::i64:806      ResultReg = createResultReg(&WebAssembly::I64RegClass);807      break;808    case MVT::f32:809      ResultReg = createResultReg(&WebAssembly::F32RegClass);810      break;811    case MVT::f64:812      ResultReg = createResultReg(&WebAssembly::F64RegClass);813      break;814    case MVT::v16i8:815      ResultReg = createResultReg(&WebAssembly::V128RegClass);816      break;817    case MVT::v8i16:818      ResultReg = createResultReg(&WebAssembly::V128RegClass);819      break;820    case MVT::v4i32:821      ResultReg = createResultReg(&WebAssembly::V128RegClass);822      break;823    case MVT::v2i64:824      ResultReg = createResultReg(&WebAssembly::V128RegClass);825      break;826    case MVT::v4f32:827      ResultReg = createResultReg(&WebAssembly::V128RegClass);828      break;829    case MVT::v2f64:830      ResultReg = createResultReg(&WebAssembly::V128RegClass);831      break;832    case MVT::funcref:833      ResultReg = createResultReg(&WebAssembly::FUNCREFRegClass);834      break;835    case MVT::externref:836      ResultReg = createResultReg(&WebAssembly::EXTERNREFRegClass);837      break;838    case MVT::exnref:839      ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);840      break;841    default:842      return false;843    }844  }845 846  SmallVector<unsigned, 8> Args;847  for (unsigned I = 0, E = Call->arg_size(); I < E; ++I) {848    Value *V = Call->getArgOperand(I);849    MVT::SimpleValueType ArgTy = getSimpleType(V->getType());850    if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)851      return false;852 853    const AttributeList &Attrs = Call->getAttributes();854    if (Attrs.hasParamAttr(I, Attribute::ByVal) ||855        Attrs.hasParamAttr(I, Attribute::SwiftSelf) ||856        Attrs.hasParamAttr(I, Attribute::SwiftError) ||857        Attrs.hasParamAttr(I, Attribute::InAlloca) ||858        Attrs.hasParamAttr(I, Attribute::Nest))859      return false;860 861    unsigned Reg;862 863    if (Call->paramHasAttr(I, Attribute::SExt))864      Reg = getRegForSignedValue(V);865    else if (Call->paramHasAttr(I, Attribute::ZExt))866      Reg = getRegForUnsignedValue(V);867    else868      Reg = getRegForValue(V);869 870    if (Reg == 0)871      return false;872 873    Args.push_back(Reg);874  }875 876  unsigned CalleeReg = 0;877  if (!IsDirect) {878    CalleeReg = getRegForValue(Call->getCalledOperand());879    if (!CalleeReg)880      return false;881  }882 883  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc));884 885  if (!IsVoid)886    MIB.addReg(ResultReg, RegState::Define);887 888  if (IsDirect) {889    MIB.addGlobalAddress(Func);890  } else {891    // Placeholder for the type index.892    MIB.addImm(0);893    // The table into which this call_indirect indexes.894    MCSymbolWasm *Table = WebAssembly::getOrCreateFunctionTableSymbol(895        MF->getContext(), Subtarget);896    if (Subtarget->hasCallIndirectOverlong()) {897      MIB.addSym(Table);898    } else {899      // Otherwise for the MVP there is at most one table whose number is 0, but900      // we can't write a table symbol or issue relocations.  Instead we just901      // ensure the table is live.902      Table->setNoStrip();903      MIB.addImm(0);904    }905  }906 907  for (unsigned ArgReg : Args)908    MIB.addReg(ArgReg);909 910  if (!IsDirect)911    MIB.addReg(CalleeReg);912 913  if (!IsVoid)914    updateValueMap(Call, ResultReg);915 916  diagnoseDontCall(*Call);917  return true;918}919 920bool WebAssemblyFastISel::selectSelect(const Instruction *I) {921  const auto *Select = cast<SelectInst>(I);922 923  bool Not;924  unsigned CondReg =925      getRegForI1Value(Select->getCondition(), I->getParent(), Not);926  if (CondReg == 0)927    return false;928 929  Register TrueReg = getRegForValue(Select->getTrueValue());930  if (TrueReg == 0)931    return false;932 933  Register FalseReg = getRegForValue(Select->getFalseValue());934  if (FalseReg == 0)935    return false;936 937  if (Not)938    std::swap(TrueReg, FalseReg);939 940  unsigned Opc;941  const TargetRegisterClass *RC;942  switch (getSimpleType(Select->getType())) {943  case MVT::i1:944  case MVT::i8:945  case MVT::i16:946  case MVT::i32:947    Opc = WebAssembly::SELECT_I32;948    RC = &WebAssembly::I32RegClass;949    break;950  case MVT::i64:951    Opc = WebAssembly::SELECT_I64;952    RC = &WebAssembly::I64RegClass;953    break;954  case MVT::f32:955    Opc = WebAssembly::SELECT_F32;956    RC = &WebAssembly::F32RegClass;957    break;958  case MVT::f64:959    Opc = WebAssembly::SELECT_F64;960    RC = &WebAssembly::F64RegClass;961    break;962  case MVT::funcref:963    Opc = WebAssembly::SELECT_FUNCREF;964    RC = &WebAssembly::FUNCREFRegClass;965    break;966  case MVT::externref:967    Opc = WebAssembly::SELECT_EXTERNREF;968    RC = &WebAssembly::EXTERNREFRegClass;969    break;970  case MVT::exnref:971    Opc = WebAssembly::SELECT_EXNREF;972    RC = &WebAssembly::EXNREFRegClass;973    break;974  default:975    return false;976  }977 978  Register ResultReg = createResultReg(RC);979  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)980      .addReg(TrueReg)981      .addReg(FalseReg)982      .addReg(CondReg);983 984  updateValueMap(Select, ResultReg);985  return true;986}987 988bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {989  const auto *Trunc = cast<TruncInst>(I);990 991  const Value *Op = Trunc->getOperand(0);992  MVT::SimpleValueType From = getSimpleType(Op->getType());993  MVT::SimpleValueType To = getLegalType(getSimpleType(Trunc->getType()));994  Register In = getRegForValue(Op);995  if (In == 0)996    return false;997 998  auto Truncate = [&](Register Reg) -> unsigned {999    if (From == MVT::i64) {1000      if (To == MVT::i64)1001        return copyValue(Reg);1002 1003      if (To == MVT::i1 || To == MVT::i8 || To == MVT::i16 || To == MVT::i32) {1004        Register Result = createResultReg(&WebAssembly::I32RegClass);1005        BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,1006                TII.get(WebAssembly::I32_WRAP_I64), Result)1007            .addReg(Reg);1008        return Result;1009      }1010    }1011 1012    if (From == MVT::i32)1013      return copyValue(Reg);1014 1015    return 0;1016  };1017 1018  unsigned Reg = Truncate(In);1019  if (Reg == 0)1020    return false;1021 1022  updateValueMap(Trunc, Reg);1023  return true;1024}1025 1026bool WebAssemblyFastISel::selectZExt(const Instruction *I) {1027  const auto *ZExt = cast<ZExtInst>(I);1028 1029  const Value *Op = ZExt->getOperand(0);1030  MVT::SimpleValueType From = getSimpleType(Op->getType());1031  MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));1032  Register In = getRegForValue(Op);1033  if (In == 0)1034    return false;1035  unsigned Reg = zeroExtend(In, Op, From, To);1036  if (Reg == 0)1037    return false;1038 1039  updateValueMap(ZExt, Reg);1040  return true;1041}1042 1043bool WebAssemblyFastISel::selectSExt(const Instruction *I) {1044  const auto *SExt = cast<SExtInst>(I);1045 1046  const Value *Op = SExt->getOperand(0);1047  MVT::SimpleValueType From = getSimpleType(Op->getType());1048  MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));1049  Register In = getRegForValue(Op);1050  if (In == 0)1051    return false;1052  unsigned Reg = signExtend(In, Op, From, To);1053  if (Reg == 0)1054    return false;1055 1056  updateValueMap(SExt, Reg);1057  return true;1058}1059 1060bool WebAssemblyFastISel::selectICmp(const Instruction *I) {1061  const auto *ICmp = cast<ICmpInst>(I);1062 1063  bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;1064  unsigned Opc;1065  bool IsSigned = false;1066  switch (ICmp->getPredicate()) {1067  case ICmpInst::ICMP_EQ:1068    Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;1069    break;1070  case ICmpInst::ICMP_NE:1071    Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;1072    break;1073  case ICmpInst::ICMP_UGT:1074    Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;1075    break;1076  case ICmpInst::ICMP_UGE:1077    Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;1078    break;1079  case ICmpInst::ICMP_ULT:1080    Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;1081    break;1082  case ICmpInst::ICMP_ULE:1083    Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;1084    break;1085  case ICmpInst::ICMP_SGT:1086    Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;1087    IsSigned = true;1088    break;1089  case ICmpInst::ICMP_SGE:1090    Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;1091    IsSigned = true;1092    break;1093  case ICmpInst::ICMP_SLT:1094    Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;1095    IsSigned = true;1096    break;1097  case ICmpInst::ICMP_SLE:1098    Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;1099    IsSigned = true;1100    break;1101  default:1102    return false;1103  }1104 1105  unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);1106  if (LHS == 0)1107    return false;1108 1109  unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);1110  if (RHS == 0)1111    return false;1112 1113  Register ResultReg = createResultReg(&WebAssembly::I32RegClass);1114  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)1115      .addReg(LHS)1116      .addReg(RHS);1117  updateValueMap(ICmp, ResultReg);1118  return true;1119}1120 1121bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {1122  const auto *FCmp = cast<FCmpInst>(I);1123 1124  Register LHS = getRegForValue(FCmp->getOperand(0));1125  if (LHS == 0)1126    return false;1127 1128  Register RHS = getRegForValue(FCmp->getOperand(1));1129  if (RHS == 0)1130    return false;1131 1132  bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;1133  unsigned Opc;1134  bool Not = false;1135  switch (FCmp->getPredicate()) {1136  case FCmpInst::FCMP_OEQ:1137    Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;1138    break;1139  case FCmpInst::FCMP_UNE:1140    Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;1141    break;1142  case FCmpInst::FCMP_OGT:1143    Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;1144    break;1145  case FCmpInst::FCMP_OGE:1146    Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;1147    break;1148  case FCmpInst::FCMP_OLT:1149    Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;1150    break;1151  case FCmpInst::FCMP_OLE:1152    Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;1153    break;1154  case FCmpInst::FCMP_UGT:1155    Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;1156    Not = true;1157    break;1158  case FCmpInst::FCMP_UGE:1159    Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;1160    Not = true;1161    break;1162  case FCmpInst::FCMP_ULT:1163    Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;1164    Not = true;1165    break;1166  case FCmpInst::FCMP_ULE:1167    Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;1168    Not = true;1169    break;1170  default:1171    return false;1172  }1173 1174  Register ResultReg = createResultReg(&WebAssembly::I32RegClass);1175  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc), ResultReg)1176      .addReg(LHS)1177      .addReg(RHS);1178 1179  if (Not)1180    ResultReg = notValue(ResultReg);1181 1182  updateValueMap(FCmp, ResultReg);1183  return true;1184}1185 1186bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {1187  // Target-independent code can handle this, except it doesn't set the dead1188  // flag on the ARGUMENTS clobber, so we have to do that manually in order1189  // to satisfy code that expects this of isBitcast() instructions.1190  EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());1191  EVT RetVT = TLI.getValueType(DL, I->getType());1192  if (!VT.isSimple() || !RetVT.isSimple())1193    return false;1194 1195  Register In = getRegForValue(I->getOperand(0));1196  if (In == 0)1197    return false;1198 1199  if (VT == RetVT) {1200    // No-op bitcast.1201    updateValueMap(I, In);1202    return true;1203  }1204 1205  Register Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),1206                                        In);1207  if (!Reg)1208    return false;1209  MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;1210  --Iter;1211  assert(Iter->isBitcast());1212  Iter->setPhysRegsDeadExcept(ArrayRef<Register>(), TRI);1213  updateValueMap(I, Reg);1214  return true;1215}1216 1217bool WebAssemblyFastISel::selectLoad(const Instruction *I) {1218  const auto *Load = cast<LoadInst>(I);1219  if (Load->isAtomic())1220    return false;1221  if (!WebAssembly::isDefaultAddressSpace(Load->getPointerAddressSpace()))1222    return false;1223  if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())1224    return false;1225 1226  Address Addr;1227  if (!computeAddress(Load->getPointerOperand(), Addr))1228    return false;1229 1230  // TODO: Fold a following sign-/zero-extend into the load instruction.1231 1232  unsigned Opc;1233  const TargetRegisterClass *RC;1234  bool A64 = Subtarget->hasAddr64();1235  switch (getSimpleType(Load->getType())) {1236  case MVT::i1:1237  case MVT::i8:1238    Opc = A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;1239    RC = &WebAssembly::I32RegClass;1240    break;1241  case MVT::i16:1242    Opc = A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;1243    RC = &WebAssembly::I32RegClass;1244    break;1245  case MVT::i32:1246    Opc = A64 ? WebAssembly::LOAD_I32_A64 : WebAssembly::LOAD_I32_A32;1247    RC = &WebAssembly::I32RegClass;1248    break;1249  case MVT::i64:1250    Opc = A64 ? WebAssembly::LOAD_I64_A64 : WebAssembly::LOAD_I64_A32;1251    RC = &WebAssembly::I64RegClass;1252    break;1253  case MVT::f32:1254    Opc = A64 ? WebAssembly::LOAD_F32_A64 : WebAssembly::LOAD_F32_A32;1255    RC = &WebAssembly::F32RegClass;1256    break;1257  case MVT::f64:1258    Opc = A64 ? WebAssembly::LOAD_F64_A64 : WebAssembly::LOAD_F64_A32;1259    RC = &WebAssembly::F64RegClass;1260    break;1261  default:1262    return false;1263  }1264 1265  materializeLoadStoreOperands(Addr);1266 1267  Register ResultReg = createResultReg(RC);1268  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc),1269                     ResultReg);1270 1271  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));1272 1273  updateValueMap(Load, ResultReg);1274  return true;1275}1276 1277bool WebAssemblyFastISel::selectStore(const Instruction *I) {1278  const auto *Store = cast<StoreInst>(I);1279  if (Store->isAtomic())1280    return false;1281  if (!WebAssembly::isDefaultAddressSpace(Store->getPointerAddressSpace()))1282    return false;1283  if (!Subtarget->hasSIMD128() &&1284      Store->getValueOperand()->getType()->isVectorTy())1285    return false;1286 1287  Address Addr;1288  if (!computeAddress(Store->getPointerOperand(), Addr))1289    return false;1290 1291  unsigned Opc;1292  bool VTIsi1 = false;1293  bool A64 = Subtarget->hasAddr64();1294  switch (getSimpleType(Store->getValueOperand()->getType())) {1295  case MVT::i1:1296    VTIsi1 = true;1297    [[fallthrough]];1298  case MVT::i8:1299    Opc = A64 ? WebAssembly::STORE8_I32_A64 : WebAssembly::STORE8_I32_A32;1300    break;1301  case MVT::i16:1302    Opc = A64 ? WebAssembly::STORE16_I32_A64 : WebAssembly::STORE16_I32_A32;1303    break;1304  case MVT::i32:1305    Opc = A64 ? WebAssembly::STORE_I32_A64 : WebAssembly::STORE_I32_A32;1306    break;1307  case MVT::i64:1308    Opc = A64 ? WebAssembly::STORE_I64_A64 : WebAssembly::STORE_I64_A32;1309    break;1310  case MVT::f32:1311    Opc = A64 ? WebAssembly::STORE_F32_A64 : WebAssembly::STORE_F32_A32;1312    break;1313  case MVT::f64:1314    Opc = A64 ? WebAssembly::STORE_F64_A64 : WebAssembly::STORE_F64_A32;1315    break;1316  default:1317    return false;1318  }1319 1320  materializeLoadStoreOperands(Addr);1321 1322  Register ValueReg = getRegForValue(Store->getValueOperand());1323  if (ValueReg == 0)1324    return false;1325  if (VTIsi1)1326    ValueReg = maskI1Value(ValueReg, Store->getValueOperand());1327 1328  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc));1329 1330  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));1331 1332  MIB.addReg(ValueReg);1333  return true;1334}1335 1336bool WebAssemblyFastISel::selectBr(const Instruction *I) {1337  const auto *Br = cast<BranchInst>(I);1338  if (Br->isUnconditional()) {1339    MachineBasicBlock *MSucc = FuncInfo.getMBB(Br->getSuccessor(0));1340    fastEmitBranch(MSucc, Br->getDebugLoc());1341    return true;1342  }1343 1344  MachineBasicBlock *TBB = FuncInfo.getMBB(Br->getSuccessor(0));1345  MachineBasicBlock *FBB = FuncInfo.getMBB(Br->getSuccessor(1));1346 1347  bool Not;1348  unsigned CondReg = getRegForI1Value(Br->getCondition(), Br->getParent(), Not);1349  if (CondReg == 0)1350    return false;1351 1352  unsigned Opc = WebAssembly::BR_IF;1353  if (Not)1354    Opc = WebAssembly::BR_UNLESS;1355 1356  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD, TII.get(Opc))1357      .addMBB(TBB)1358      .addReg(CondReg);1359 1360  finishCondBranch(Br->getParent(), TBB, FBB);1361  return true;1362}1363 1364bool WebAssemblyFastISel::selectRet(const Instruction *I) {1365  if (!FuncInfo.CanLowerReturn)1366    return false;1367 1368  const auto *Ret = cast<ReturnInst>(I);1369 1370  if (Ret->getNumOperands() == 0) {1371    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,1372            TII.get(WebAssembly::RETURN));1373    return true;1374  }1375 1376  // TODO: support multiple return in FastISel1377  if (Ret->getNumOperands() > 1)1378    return false;1379 1380  Value *RV = Ret->getOperand(0);1381  if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())1382    return false;1383 1384  switch (getSimpleType(RV->getType())) {1385  case MVT::i1:1386  case MVT::i8:1387  case MVT::i16:1388  case MVT::i32:1389  case MVT::i64:1390  case MVT::f32:1391  case MVT::f64:1392  case MVT::v16i8:1393  case MVT::v8i16:1394  case MVT::v4i32:1395  case MVT::v2i64:1396  case MVT::v4f32:1397  case MVT::v2f64:1398  case MVT::funcref:1399  case MVT::externref:1400  case MVT::exnref:1401    break;1402  default:1403    return false;1404  }1405 1406  unsigned Reg;1407  if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::SExt))1408    Reg = getRegForSignedValue(RV);1409  else if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::ZExt))1410    Reg = getRegForUnsignedValue(RV);1411  else1412    Reg = getRegForValue(RV);1413 1414  if (Reg == 0)1415    return false;1416 1417  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,1418          TII.get(WebAssembly::RETURN))1419      .addReg(Reg);1420  return true;1421}1422 1423bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {1424  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, MIMD,1425          TII.get(WebAssembly::UNREACHABLE));1426  return true;1427}1428 1429bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {1430  switch (I->getOpcode()) {1431  case Instruction::Call:1432    if (selectCall(I))1433      return true;1434    break;1435  case Instruction::Select:1436    return selectSelect(I);1437  case Instruction::Trunc:1438    return selectTrunc(I);1439  case Instruction::ZExt:1440    return selectZExt(I);1441  case Instruction::SExt:1442    return selectSExt(I);1443  case Instruction::ICmp:1444    return selectICmp(I);1445  case Instruction::FCmp:1446    return selectFCmp(I);1447  case Instruction::BitCast:1448    return selectBitCast(I);1449  case Instruction::Load:1450    return selectLoad(I);1451  case Instruction::Store:1452    return selectStore(I);1453  case Instruction::Br:1454    return selectBr(I);1455  case Instruction::Ret:1456    return selectRet(I);1457  case Instruction::Unreachable:1458    return selectUnreachable(I);1459  default:1460    break;1461  }1462 1463  // Fall back to target-independent instruction selection.1464  return selectOperator(I, I->getOpcode());1465}1466 1467FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,1468                                      const TargetLibraryInfo *LibInfo) {1469  return new WebAssemblyFastISel(FuncInfo, LibInfo);1470}1471