LCOV - code coverage report
Current view: top level - lib/Target/WebAssembly - WebAssemblyFastISel.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 484 636 76.1 %
Date: 2018-10-20 13:21:21 Functions: 29 44 65.9 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13