17b63484bSDan Gohman //===-- WebAssemblyFastISel.cpp - WebAssembly FastISel implementation -----===//
27b63484bSDan Gohman //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67b63484bSDan Gohman //
77b63484bSDan Gohman //===----------------------------------------------------------------------===//
87b63484bSDan Gohman ///
97b63484bSDan Gohman /// \file
105f8f34e4SAdrian Prantl /// This file defines the WebAssembly-specific support for the FastISel
117b63484bSDan Gohman /// class. Some of the target-specific code is generated by tablegen in the file
127b63484bSDan Gohman /// WebAssemblyGenFastISel.inc, which is #included here.
137b63484bSDan Gohman ///
1433e694a8SDan Gohman /// TODO: kill flags
1533e694a8SDan Gohman ///
167b63484bSDan Gohman //===----------------------------------------------------------------------===//
177b63484bSDan Gohman 
187b63484bSDan Gohman #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
19*864767abSPaulo Matos #include "Utils/WebAssemblyTypeUtilities.h"
200b2bc69bSHeejin Ahn #include "Utils/WebAssemblyUtilities.h"
216bda14b3SChandler Carruth #include "WebAssembly.h"
2233e694a8SDan Gohman #include "WebAssemblyMachineFunctionInfo.h"
237b63484bSDan Gohman #include "WebAssemblySubtarget.h"
247b63484bSDan Gohman #include "WebAssemblyTargetMachine.h"
257b63484bSDan Gohman #include "llvm/Analysis/BranchProbabilityInfo.h"
267b63484bSDan Gohman #include "llvm/CodeGen/FastISel.h"
277b63484bSDan Gohman #include "llvm/CodeGen/FunctionLoweringInfo.h"
287b63484bSDan Gohman #include "llvm/CodeGen/MachineConstantPool.h"
297b63484bSDan Gohman #include "llvm/CodeGen/MachineFrameInfo.h"
307b63484bSDan Gohman #include "llvm/CodeGen/MachineInstrBuilder.h"
319ad83fd6SAndy Wingo #include "llvm/CodeGen/MachineModuleInfo.h"
327b63484bSDan Gohman #include "llvm/CodeGen/MachineRegisterInfo.h"
337b63484bSDan Gohman #include "llvm/IR/DataLayout.h"
347b63484bSDan Gohman #include "llvm/IR/DerivedTypes.h"
357b63484bSDan Gohman #include "llvm/IR/Function.h"
367b63484bSDan Gohman #include "llvm/IR/GetElementPtrTypeIterator.h"
377b63484bSDan Gohman #include "llvm/IR/GlobalAlias.h"
387b63484bSDan Gohman #include "llvm/IR/GlobalVariable.h"
397b63484bSDan Gohman #include "llvm/IR/Instructions.h"
407b63484bSDan Gohman #include "llvm/IR/IntrinsicInst.h"
417b63484bSDan Gohman #include "llvm/IR/Operator.h"
4247a52a05SSanjay Patel #include "llvm/IR/PatternMatch.h"
4347a52a05SSanjay Patel 
447b63484bSDan Gohman using namespace llvm;
4547a52a05SSanjay Patel using namespace PatternMatch;
467b63484bSDan Gohman 
477b63484bSDan Gohman #define DEBUG_TYPE "wasm-fastisel"
487b63484bSDan Gohman 
497b63484bSDan Gohman namespace {
507b63484bSDan Gohman 
517b63484bSDan Gohman class WebAssemblyFastISel final : public FastISel {
522e64438aSDan Gohman   // All possible address modes.
532e64438aSDan Gohman   class Address {
542e64438aSDan Gohman   public:
5518c56a07SHeejin Ahn     using BaseKind = enum { RegBase, FrameIndexBase };
562e64438aSDan Gohman 
572e64438aSDan Gohman   private:
5818c56a07SHeejin Ahn     BaseKind Kind = RegBase;
592e64438aSDan Gohman     union {
602e64438aSDan Gohman       unsigned Reg;
612e64438aSDan Gohman       int FI;
622e64438aSDan Gohman     } Base;
632e64438aSDan Gohman 
64cc612c29SThomas Lively     // Whether the base has been determined yet
65cc612c29SThomas Lively     bool IsBaseSet = false;
66cc612c29SThomas Lively 
6718c56a07SHeejin Ahn     int64_t Offset = 0;
682e64438aSDan Gohman 
6918c56a07SHeejin Ahn     const GlobalValue *GV = nullptr;
702e64438aSDan Gohman 
712e64438aSDan Gohman   public:
722e64438aSDan Gohman     // Innocuous defaults for our address.
Address()7318c56a07SHeejin Ahn     Address() { Base.Reg = 0; }
setKind(BaseKind K)74a31ec61cSJacob Gravelle     void setKind(BaseKind K) {
75a31ec61cSJacob Gravelle       assert(!isSet() && "Can't change kind with non-zero base");
76a31ec61cSJacob Gravelle       Kind = K;
77a31ec61cSJacob Gravelle     }
getKind() const782e64438aSDan Gohman     BaseKind getKind() const { return Kind; }
isRegBase() const792e64438aSDan Gohman     bool isRegBase() const { return Kind == RegBase; }
isFIBase() const802e64438aSDan Gohman     bool isFIBase() const { return Kind == FrameIndexBase; }
setReg(unsigned Reg)812e64438aSDan Gohman     void setReg(unsigned Reg) {
822e64438aSDan Gohman       assert(isRegBase() && "Invalid base register access!");
83cc612c29SThomas Lively       assert(!IsBaseSet && "Base cannot be reset");
842e64438aSDan Gohman       Base.Reg = Reg;
85cc612c29SThomas Lively       IsBaseSet = true;
862e64438aSDan Gohman     }
getReg() const872e64438aSDan Gohman     unsigned getReg() const {
882e64438aSDan Gohman       assert(isRegBase() && "Invalid base register access!");
892e64438aSDan Gohman       return Base.Reg;
902e64438aSDan Gohman     }
setFI(unsigned FI)912e64438aSDan Gohman     void setFI(unsigned FI) {
922e64438aSDan Gohman       assert(isFIBase() && "Invalid base frame index access!");
93cc612c29SThomas Lively       assert(!IsBaseSet && "Base cannot be reset");
942e64438aSDan Gohman       Base.FI = FI;
95cc612c29SThomas Lively       IsBaseSet = true;
962e64438aSDan Gohman     }
getFI() const972e64438aSDan Gohman     unsigned getFI() const {
982e64438aSDan Gohman       assert(isFIBase() && "Invalid base frame index access!");
992e64438aSDan Gohman       return Base.FI;
1002e64438aSDan Gohman     }
1012e64438aSDan Gohman 
setOffset(int64_t NewOffset)10218c56a07SHeejin Ahn     void setOffset(int64_t NewOffset) {
10318c56a07SHeejin Ahn       assert(NewOffset >= 0 && "Offsets must be non-negative");
10418c56a07SHeejin Ahn       Offset = NewOffset;
105728926acSDan Gohman     }
getOffset() const1062e64438aSDan Gohman     int64_t getOffset() const { return Offset; }
setGlobalValue(const GlobalValue * G)1072e64438aSDan Gohman     void setGlobalValue(const GlobalValue *G) { GV = G; }
getGlobalValue() const1082e64438aSDan Gohman     const GlobalValue *getGlobalValue() const { return GV; }
isSet() const109cc612c29SThomas Lively     bool isSet() const { return IsBaseSet; }
1102e64438aSDan Gohman   };
1112e64438aSDan Gohman 
1127b63484bSDan Gohman   /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
1137b63484bSDan Gohman   /// right decision when generating code for different targets.
1147b63484bSDan Gohman   const WebAssemblySubtarget *Subtarget;
1157b63484bSDan Gohman   LLVMContext *Context;
1167b63484bSDan Gohman 
1177b63484bSDan Gohman private:
1182e64438aSDan Gohman   // Utility helper routines
getSimpleType(Type * Ty)1193a5ce733SDan Gohman   MVT::SimpleValueType getSimpleType(Type *Ty) {
12049a3ad21SRui Ueyama     EVT VT = TLI.getValueType(DL, Ty, /*AllowUnknown=*/true);
121f208f631SHeejin Ahn     return VT.isSimple() ? VT.getSimpleVT().SimpleTy
122f208f631SHeejin Ahn                          : MVT::INVALID_SIMPLE_VALUE_TYPE;
1233a5ce733SDan Gohman   }
getLegalType(MVT::SimpleValueType VT)1243a5ce733SDan Gohman   MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
1253a5ce733SDan Gohman     switch (VT) {
1263a5ce733SDan Gohman     case MVT::i1:
1273a5ce733SDan Gohman     case MVT::i8:
1283a5ce733SDan Gohman     case MVT::i16:
1293a5ce733SDan Gohman       return MVT::i32;
13033e694a8SDan Gohman     case MVT::i32:
1313a5ce733SDan Gohman     case MVT::i64:
13233e694a8SDan Gohman     case MVT::f32:
13333e694a8SDan Gohman     case MVT::f64:
13446667a10SPaulo Matos       return VT;
13569e2797eSPaulo Matos     case MVT::funcref:
13669e2797eSPaulo Matos     case MVT::externref:
13746667a10SPaulo Matos       if (Subtarget->hasReferenceTypes())
13833e694a8SDan Gohman         return VT;
13946667a10SPaulo Matos       break;
1406999c4fdSDan Gohman     case MVT::f16:
1416999c4fdSDan Gohman       return MVT::f32;
14239bf39f3SDerek Schuff     case MVT::v16i8:
14339bf39f3SDerek Schuff     case MVT::v8i16:
14439bf39f3SDerek Schuff     case MVT::v4i32:
14539bf39f3SDerek Schuff     case MVT::v4f32:
146b6dac89cSThomas Lively     case MVT::v2i64:
147b6dac89cSThomas Lively     case MVT::v2f64:
1488638c897SThomas Lively       if (Subtarget->hasSIMD128())
149b6dac89cSThomas Lively         return VT;
150b6dac89cSThomas Lively       break;
1513a5ce733SDan Gohman     default:
1523a5ce733SDan Gohman       break;
1533a5ce733SDan Gohman     }
1543a5ce733SDan Gohman     return MVT::INVALID_SIMPLE_VALUE_TYPE;
1553a5ce733SDan Gohman   }
1562e64438aSDan Gohman   bool computeAddress(const Value *Obj, Address &Addr);
1579da81421SSam Clegg   void materializeLoadStoreOperands(Address &Addr);
1582e64438aSDan Gohman   void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
1592e64438aSDan Gohman                             MachineMemOperand *MMO);
1603a5ce733SDan Gohman   unsigned maskI1Value(unsigned Reg, const Value *V);
16116086d47SNikita Popov   unsigned getRegForI1Value(const Value *V, const BasicBlock *BB, bool &Not);
1623a5ce733SDan Gohman   unsigned zeroExtendToI32(unsigned Reg, const Value *V,
1633a5ce733SDan Gohman                            MVT::SimpleValueType From);
1643a5ce733SDan Gohman   unsigned signExtendToI32(unsigned Reg, const Value *V,
1653a5ce733SDan Gohman                            MVT::SimpleValueType From);
166f208f631SHeejin Ahn   unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
1673a5ce733SDan Gohman                       MVT::SimpleValueType To);
168f208f631SHeejin Ahn   unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
1693a5ce733SDan Gohman                       MVT::SimpleValueType To);
1703a5ce733SDan Gohman   unsigned getRegForUnsignedValue(const Value *V);
1713a5ce733SDan Gohman   unsigned getRegForSignedValue(const Value *V);
1723a5ce733SDan Gohman   unsigned getRegForPromotedValue(const Value *V, bool IsSigned);
1733a5ce733SDan Gohman   unsigned notValue(unsigned Reg);
17433e694a8SDan Gohman   unsigned copyValue(unsigned Reg);
1752e64438aSDan Gohman 
1762e64438aSDan Gohman   // Backend specific FastISel code.
1772e64438aSDan Gohman   unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
1782e64438aSDan Gohman   unsigned fastMaterializeConstant(const Constant *C) override;
17933e694a8SDan Gohman   bool fastLowerArguments() override;
1802e64438aSDan Gohman 
1812e64438aSDan Gohman   // Selection routines.
18233e694a8SDan Gohman   bool selectCall(const Instruction *I);
18333e694a8SDan Gohman   bool selectSelect(const Instruction *I);
18433e694a8SDan Gohman   bool selectTrunc(const Instruction *I);
1853a5ce733SDan Gohman   bool selectZExt(const Instruction *I);
1863a5ce733SDan Gohman   bool selectSExt(const Instruction *I);
1873a5ce733SDan Gohman   bool selectICmp(const Instruction *I);
1883a5ce733SDan Gohman   bool selectFCmp(const Instruction *I);
1892e64438aSDan Gohman   bool selectBitCast(const Instruction *I);
1902e64438aSDan Gohman   bool selectLoad(const Instruction *I);
1912e64438aSDan Gohman   bool selectStore(const Instruction *I);
1922e64438aSDan Gohman   bool selectBr(const Instruction *I);
1932e64438aSDan Gohman   bool selectRet(const Instruction *I);
1942e64438aSDan Gohman   bool selectUnreachable(const Instruction *I);
1952e64438aSDan Gohman 
1967b63484bSDan Gohman public:
1977b63484bSDan Gohman   // Backend specific FastISel code.
WebAssemblyFastISel(FunctionLoweringInfo & FuncInfo,const TargetLibraryInfo * LibInfo)1987b63484bSDan Gohman   WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo,
1997b63484bSDan Gohman                       const TargetLibraryInfo *LibInfo)
2007b63484bSDan Gohman       : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
2017b63484bSDan Gohman     Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>();
2027b63484bSDan Gohman     Context = &FuncInfo.Fn->getContext();
2037b63484bSDan Gohman   }
2047b63484bSDan Gohman 
2057b63484bSDan Gohman   bool fastSelectInstruction(const Instruction *I) override;
2067b63484bSDan Gohman 
2077b63484bSDan Gohman #include "WebAssemblyGenFastISel.inc"
2087b63484bSDan Gohman };
2097b63484bSDan Gohman 
2107b63484bSDan Gohman } // end anonymous namespace
2117b63484bSDan Gohman 
computeAddress(const Value * Obj,Address & Addr)2122e64438aSDan Gohman bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {
2132e64438aSDan Gohman   const User *U = nullptr;
2142e64438aSDan Gohman   unsigned Opcode = Instruction::UserOp1;
21518c56a07SHeejin Ahn   if (const auto *I = dyn_cast<Instruction>(Obj)) {
2162e64438aSDan Gohman     // Don't walk into other basic blocks unless the object is an alloca from
2172e64438aSDan Gohman     // another block, otherwise it may not have a virtual register assigned.
2182e64438aSDan Gohman     if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
2192e64438aSDan Gohman         FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
2202e64438aSDan Gohman       Opcode = I->getOpcode();
2212e64438aSDan Gohman       U = I;
2222e64438aSDan Gohman     }
22318c56a07SHeejin Ahn   } else if (const auto *C = dyn_cast<ConstantExpr>(Obj)) {
2242e64438aSDan Gohman     Opcode = C->getOpcode();
2252e64438aSDan Gohman     U = C;
2262e64438aSDan Gohman   }
2272e64438aSDan Gohman 
2282e64438aSDan Gohman   if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
2292e64438aSDan Gohman     if (Ty->getAddressSpace() > 255)
2302e64438aSDan Gohman       // Fast instruction selection doesn't support the special
2312e64438aSDan Gohman       // address spaces.
2322e64438aSDan Gohman       return false;
2332e64438aSDan Gohman 
23418c56a07SHeejin Ahn   if (const auto *GV = dyn_cast<GlobalValue>(Obj)) {
2359da81421SSam Clegg     if (TLI.isPositionIndependent())
2369da81421SSam Clegg       return false;
2372e64438aSDan Gohman     if (Addr.getGlobalValue())
2382e64438aSDan Gohman       return false;
23942bba4b8SGuanzhong Chen     if (GV->isThreadLocal())
24042bba4b8SGuanzhong Chen       return false;
2412e64438aSDan Gohman     Addr.setGlobalValue(GV);
2422e64438aSDan Gohman     return true;
2432e64438aSDan Gohman   }
2442e64438aSDan Gohman 
2452e64438aSDan Gohman   switch (Opcode) {
2467b63484bSDan Gohman   default:
2477b63484bSDan Gohman     break;
2482e64438aSDan Gohman   case Instruction::BitCast: {
2492e64438aSDan Gohman     // Look through bitcasts.
2502e64438aSDan Gohman     return computeAddress(U->getOperand(0), Addr);
2512e64438aSDan Gohman   }
2522e64438aSDan Gohman   case Instruction::IntToPtr: {
2532e64438aSDan Gohman     // Look past no-op inttoptrs.
2542e64438aSDan Gohman     if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
2552e64438aSDan Gohman         TLI.getPointerTy(DL))
2562e64438aSDan Gohman       return computeAddress(U->getOperand(0), Addr);
2572e64438aSDan Gohman     break;
2582e64438aSDan Gohman   }
2592e64438aSDan Gohman   case Instruction::PtrToInt: {
2602e64438aSDan Gohman     // Look past no-op ptrtoints.
2612e64438aSDan Gohman     if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
2622e64438aSDan Gohman       return computeAddress(U->getOperand(0), Addr);
2632e64438aSDan Gohman     break;
2642e64438aSDan Gohman   }
2652e64438aSDan Gohman   case Instruction::GetElementPtr: {
2662e64438aSDan Gohman     Address SavedAddr = Addr;
2672e64438aSDan Gohman     uint64_t TmpOffset = Addr.getOffset();
268728926acSDan Gohman     // Non-inbounds geps can wrap; wasm's offsets can't.
269728926acSDan Gohman     if (!cast<GEPOperator>(U)->isInBounds())
270728926acSDan Gohman       goto unsupported_gep;
2712e64438aSDan Gohman     // Iterate through the GEP folding the constants into offsets where
2722e64438aSDan Gohman     // we can.
2732e64438aSDan Gohman     for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
2742e64438aSDan Gohman          GTI != E; ++GTI) {
2752e64438aSDan Gohman       const Value *Op = GTI.getOperand();
276ab85225bSPeter Collingbourne       if (StructType *STy = GTI.getStructTypeOrNull()) {
2772e64438aSDan Gohman         const StructLayout *SL = DL.getStructLayout(STy);
2782e64438aSDan Gohman         unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
2792e64438aSDan Gohman         TmpOffset += SL->getElementOffset(Idx);
2802e64438aSDan Gohman       } else {
2812e64438aSDan Gohman         uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
2822e64438aSDan Gohman         for (;;) {
28318c56a07SHeejin Ahn           if (const auto *CI = dyn_cast<ConstantInt>(Op)) {
2842e64438aSDan Gohman             // Constant-offset addressing.
2852e64438aSDan Gohman             TmpOffset += CI->getSExtValue() * S;
2862e64438aSDan Gohman             break;
2872e64438aSDan Gohman           }
28833e694a8SDan Gohman           if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
28933e694a8SDan Gohman             // An unscaled add of a register. Set it as the new base.
290d6b07348SJim Lin             Register Reg = getRegForValue(Op);
2913ff73cfbSDan Gohman             if (Reg == 0)
2923ff73cfbSDan Gohman               return false;
2933ff73cfbSDan Gohman             Addr.setReg(Reg);
29433e694a8SDan Gohman             break;
29533e694a8SDan Gohman           }
2962e64438aSDan Gohman           if (canFoldAddIntoGEP(U, Op)) {
2972e64438aSDan Gohman             // A compatible add with a constant operand. Fold the constant.
29818c56a07SHeejin Ahn             auto *CI = cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
2992e64438aSDan Gohman             TmpOffset += CI->getSExtValue() * S;
3002e64438aSDan Gohman             // Iterate on the other operand.
3012e64438aSDan Gohman             Op = cast<AddOperator>(Op)->getOperand(0);
3022e64438aSDan Gohman             continue;
3032e64438aSDan Gohman           }
3042e64438aSDan Gohman           // Unsupported
3052e64438aSDan Gohman           goto unsupported_gep;
3062e64438aSDan Gohman         }
3072e64438aSDan Gohman       }
3082e64438aSDan Gohman     }
309728926acSDan Gohman     // Don't fold in negative offsets.
310728926acSDan Gohman     if (int64_t(TmpOffset) >= 0) {
3112e64438aSDan Gohman       // Try to grab the base operand now.
3122e64438aSDan Gohman       Addr.setOffset(TmpOffset);
3132e64438aSDan Gohman       if (computeAddress(U->getOperand(0), Addr))
3142e64438aSDan Gohman         return true;
315728926acSDan Gohman     }
3162e64438aSDan Gohman     // We failed, restore everything and try the other options.
3172e64438aSDan Gohman     Addr = SavedAddr;
3182e64438aSDan Gohman   unsupported_gep:
3192e64438aSDan Gohman     break;
3202e64438aSDan Gohman   }
3212e64438aSDan Gohman   case Instruction::Alloca: {
32218c56a07SHeejin Ahn     const auto *AI = cast<AllocaInst>(Obj);
3232e64438aSDan Gohman     DenseMap<const AllocaInst *, int>::iterator SI =
3242e64438aSDan Gohman         FuncInfo.StaticAllocaMap.find(AI);
3252e64438aSDan Gohman     if (SI != FuncInfo.StaticAllocaMap.end()) {
326a31ec61cSJacob Gravelle       if (Addr.isSet()) {
327a31ec61cSJacob Gravelle         return false;
328a31ec61cSJacob Gravelle       }
3292e64438aSDan Gohman       Addr.setKind(Address::FrameIndexBase);
3302e64438aSDan Gohman       Addr.setFI(SI->second);
3312e64438aSDan Gohman       return true;
3322e64438aSDan Gohman     }
3332e64438aSDan Gohman     break;
3342e64438aSDan Gohman   }
3352e64438aSDan Gohman   case Instruction::Add: {
3362e64438aSDan Gohman     // Adds of constants are common and easy enough.
3372e64438aSDan Gohman     const Value *LHS = U->getOperand(0);
3382e64438aSDan Gohman     const Value *RHS = U->getOperand(1);
3392e64438aSDan Gohman 
3402e64438aSDan Gohman     if (isa<ConstantInt>(LHS))
3412e64438aSDan Gohman       std::swap(LHS, RHS);
3422e64438aSDan Gohman 
34318c56a07SHeejin Ahn     if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
344728926acSDan Gohman       uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
345728926acSDan Gohman       if (int64_t(TmpOffset) >= 0) {
346728926acSDan Gohman         Addr.setOffset(TmpOffset);
3472e64438aSDan Gohman         return computeAddress(LHS, Addr);
3482e64438aSDan Gohman       }
349728926acSDan Gohman     }
3502e64438aSDan Gohman 
3512e64438aSDan Gohman     Address Backup = Addr;
3522e64438aSDan Gohman     if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
3532e64438aSDan Gohman       return true;
3542e64438aSDan Gohman     Addr = Backup;
3552e64438aSDan Gohman 
3562e64438aSDan Gohman     break;
3572e64438aSDan Gohman   }
3582e64438aSDan Gohman   case Instruction::Sub: {
3592e64438aSDan Gohman     // Subs of constants are common and easy enough.
3602e64438aSDan Gohman     const Value *LHS = U->getOperand(0);
3612e64438aSDan Gohman     const Value *RHS = U->getOperand(1);
3622e64438aSDan Gohman 
36318c56a07SHeejin Ahn     if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
364728926acSDan Gohman       int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
365728926acSDan Gohman       if (TmpOffset >= 0) {
366728926acSDan Gohman         Addr.setOffset(TmpOffset);
3672e64438aSDan Gohman         return computeAddress(LHS, Addr);
3682e64438aSDan Gohman       }
369728926acSDan Gohman     }
3702e64438aSDan Gohman     break;
3712e64438aSDan Gohman   }
3722e64438aSDan Gohman   }
373a31ec61cSJacob Gravelle   if (Addr.isSet()) {
374a31ec61cSJacob Gravelle     return false;
375a31ec61cSJacob Gravelle   }
376d6b07348SJim Lin   Register Reg = getRegForValue(Obj);
3773ff73cfbSDan Gohman   if (Reg == 0)
3783ff73cfbSDan Gohman     return false;
3793ff73cfbSDan Gohman   Addr.setReg(Reg);
3802e64438aSDan Gohman   return Addr.getReg() != 0;
3812e64438aSDan Gohman }
3822e64438aSDan Gohman 
materializeLoadStoreOperands(Address & Addr)3839da81421SSam Clegg void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
3842e64438aSDan Gohman   if (Addr.isRegBase()) {
3852e64438aSDan Gohman     unsigned Reg = Addr.getReg();
3862e64438aSDan Gohman     if (Reg == 0) {
387f208f631SHeejin Ahn       Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
388f208f631SHeejin Ahn                                                    : &WebAssembly::I32RegClass);
389f208f631SHeejin Ahn       unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
390f208f631SHeejin Ahn                                             : WebAssembly::CONST_I32;
3912e64438aSDan Gohman       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
3922e64438aSDan Gohman           .addImm(0);
3932e64438aSDan Gohman       Addr.setReg(Reg);
3942e64438aSDan Gohman     }
3952e64438aSDan Gohman   }
3962e64438aSDan Gohman }
3972e64438aSDan Gohman 
addLoadStoreOperands(const Address & Addr,const MachineInstrBuilder & MIB,MachineMemOperand * MMO)3982e64438aSDan Gohman void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
3992e64438aSDan Gohman                                                const MachineInstrBuilder &MIB,
4002e64438aSDan Gohman                                                MachineMemOperand *MMO) {
40148abaa9cSDan Gohman   // Set the alignment operand (this is rewritten in SetP2AlignOperands).
40248abaa9cSDan Gohman   // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
40348abaa9cSDan Gohman   MIB.addImm(0);
40448abaa9cSDan Gohman 
4052e64438aSDan Gohman   if (const GlobalValue *GV = Addr.getGlobalValue())
4062e64438aSDan Gohman     MIB.addGlobalAddress(GV, Addr.getOffset());
4072e64438aSDan Gohman   else
4082e64438aSDan Gohman     MIB.addImm(Addr.getOffset());
4092e64438aSDan Gohman 
4102e64438aSDan Gohman   if (Addr.isRegBase())
4112e64438aSDan Gohman     MIB.addReg(Addr.getReg());
4122e64438aSDan Gohman   else
4132e64438aSDan Gohman     MIB.addFrameIndex(Addr.getFI());
4142e64438aSDan Gohman 
4152e64438aSDan Gohman   MIB.addMemOperand(MMO);
4162e64438aSDan Gohman }
4172e64438aSDan Gohman 
maskI1Value(unsigned Reg,const Value * V)4183a5ce733SDan Gohman unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
4193a5ce733SDan Gohman   return zeroExtendToI32(Reg, V, MVT::i1);
4202e64438aSDan Gohman }
4212e64438aSDan Gohman 
getRegForI1Value(const Value * V,const BasicBlock * BB,bool & Not)42216086d47SNikita Popov unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V,
42316086d47SNikita Popov                                                const BasicBlock *BB,
42416086d47SNikita Popov                                                bool &Not) {
42518c56a07SHeejin Ahn   if (const auto *ICmp = dyn_cast<ICmpInst>(V))
42633e694a8SDan Gohman     if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
42716086d47SNikita Popov       if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32) &&
42816086d47SNikita Popov           ICmp->getParent() == BB) {
42933e694a8SDan Gohman         Not = ICmp->isTrueWhenEqual();
43033e694a8SDan Gohman         return getRegForValue(ICmp->getOperand(0));
43133e694a8SDan Gohman       }
43233e694a8SDan Gohman 
43333e694a8SDan Gohman   Not = false;
434d6b07348SJim Lin   Register Reg = getRegForValue(V);
4353ff73cfbSDan Gohman   if (Reg == 0)
4363ff73cfbSDan Gohman     return 0;
4373ff73cfbSDan Gohman   return maskI1Value(Reg, V);
4383a5ce733SDan Gohman }
4393a5ce733SDan Gohman 
zeroExtendToI32(unsigned Reg,const Value * V,MVT::SimpleValueType From)4403a5ce733SDan Gohman unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
4413a5ce733SDan Gohman                                               MVT::SimpleValueType From) {
442732636d9SDerek Schuff   if (Reg == 0)
443732636d9SDerek Schuff     return 0;
444732636d9SDerek Schuff 
4453a5ce733SDan Gohman   switch (From) {
4463a5ce733SDan Gohman   case MVT::i1:
4472a47e03eSThomas Lively     // If the value is naturally an i1, we don't need to mask it. We only know
4482a47e03eSThomas Lively     // if a value is naturally an i1 if it is definitely lowered by FastISel,
4492a47e03eSThomas Lively     // not a DAG ISel fallback.
4502a47e03eSThomas Lively     if (V != nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr())
45133e694a8SDan Gohman       return copyValue(Reg);
4524dc0b1acSReid Kleckner     break;
45333e694a8SDan Gohman   case MVT::i8:
45433e694a8SDan Gohman   case MVT::i16:
4553a5ce733SDan Gohman     break;
4563a5ce733SDan Gohman   case MVT::i32:
45733e694a8SDan Gohman     return copyValue(Reg);
4583a5ce733SDan Gohman   default:
4593a5ce733SDan Gohman     return 0;
4603a5ce733SDan Gohman   }
4613a5ce733SDan Gohman 
462d6b07348SJim Lin   Register Imm = createResultReg(&WebAssembly::I32RegClass);
4633a5ce733SDan Gohman   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4643a5ce733SDan Gohman           TII.get(WebAssembly::CONST_I32), Imm)
4653a5ce733SDan Gohman       .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
4663a5ce733SDan Gohman 
467d6b07348SJim Lin   Register Result = createResultReg(&WebAssembly::I32RegClass);
4683a5ce733SDan Gohman   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4693a5ce733SDan Gohman           TII.get(WebAssembly::AND_I32), Result)
4703a5ce733SDan Gohman       .addReg(Reg)
4713a5ce733SDan Gohman       .addReg(Imm);
4723a5ce733SDan Gohman 
4733a5ce733SDan Gohman   return Result;
4743a5ce733SDan Gohman }
4753a5ce733SDan Gohman 
signExtendToI32(unsigned Reg,const Value * V,MVT::SimpleValueType From)4763a5ce733SDan Gohman unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
4773a5ce733SDan Gohman                                               MVT::SimpleValueType From) {
478732636d9SDerek Schuff   if (Reg == 0)
479732636d9SDerek Schuff     return 0;
480732636d9SDerek Schuff 
4813a5ce733SDan Gohman   switch (From) {
4823a5ce733SDan Gohman   case MVT::i1:
4833a5ce733SDan Gohman   case MVT::i8:
4843a5ce733SDan Gohman   case MVT::i16:
4853a5ce733SDan Gohman     break;
4863a5ce733SDan Gohman   case MVT::i32:
48733e694a8SDan Gohman     return copyValue(Reg);
4883a5ce733SDan Gohman   default:
48933e694a8SDan Gohman     return 0;
4903a5ce733SDan Gohman   }
4913a5ce733SDan Gohman 
492d6b07348SJim Lin   Register Imm = createResultReg(&WebAssembly::I32RegClass);
4933a5ce733SDan Gohman   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4943a5ce733SDan Gohman           TII.get(WebAssembly::CONST_I32), Imm)
4953a5ce733SDan Gohman       .addImm(32 - MVT(From).getSizeInBits());
4963a5ce733SDan Gohman 
497d6b07348SJim Lin   Register Left = createResultReg(&WebAssembly::I32RegClass);
4983a5ce733SDan Gohman   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4993a5ce733SDan Gohman           TII.get(WebAssembly::SHL_I32), Left)
5003a5ce733SDan Gohman       .addReg(Reg)
5013a5ce733SDan Gohman       .addReg(Imm);
5023a5ce733SDan Gohman 
503d6b07348SJim Lin   Register Right = createResultReg(&WebAssembly::I32RegClass);
5043a5ce733SDan Gohman   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
5053a5ce733SDan Gohman           TII.get(WebAssembly::SHR_S_I32), Right)
5063a5ce733SDan Gohman       .addReg(Left)
5073a5ce733SDan Gohman       .addReg(Imm);
5083a5ce733SDan Gohman 
5093a5ce733SDan Gohman   return Right;
5103a5ce733SDan Gohman }
5113a5ce733SDan Gohman 
zeroExtend(unsigned Reg,const Value * V,MVT::SimpleValueType From,MVT::SimpleValueType To)5123a5ce733SDan Gohman unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
5133a5ce733SDan Gohman                                          MVT::SimpleValueType From,
5143a5ce733SDan Gohman                                          MVT::SimpleValueType To) {
5153a5ce733SDan Gohman   if (To == MVT::i64) {
5163a5ce733SDan Gohman     if (From == MVT::i64)
51733e694a8SDan Gohman       return copyValue(Reg);
5183a5ce733SDan Gohman 
5193a5ce733SDan Gohman     Reg = zeroExtendToI32(Reg, V, From);
5203a5ce733SDan Gohman 
521d6b07348SJim Lin     Register Result = createResultReg(&WebAssembly::I64RegClass);
5223a5ce733SDan Gohman     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
5233a5ce733SDan Gohman             TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
5243a5ce733SDan Gohman         .addReg(Reg);
5253a5ce733SDan Gohman     return Result;
5263a5ce733SDan Gohman   }
5273a5ce733SDan Gohman 
528323dc634SNikita Popov   if (To == MVT::i32)
5293a5ce733SDan Gohman     return zeroExtendToI32(Reg, V, From);
530323dc634SNikita Popov 
531323dc634SNikita Popov   return 0;
5323a5ce733SDan Gohman }
5333a5ce733SDan Gohman 
signExtend(unsigned Reg,const Value * V,MVT::SimpleValueType From,MVT::SimpleValueType To)5343a5ce733SDan Gohman unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
5353a5ce733SDan Gohman                                          MVT::SimpleValueType From,
5363a5ce733SDan Gohman                                          MVT::SimpleValueType To) {
5373a5ce733SDan Gohman   if (To == MVT::i64) {
5383a5ce733SDan Gohman     if (From == MVT::i64)
53933e694a8SDan Gohman       return copyValue(Reg);
5403a5ce733SDan Gohman 
5413a5ce733SDan Gohman     Reg = signExtendToI32(Reg, V, From);
5423a5ce733SDan Gohman 
543d6b07348SJim Lin     Register Result = createResultReg(&WebAssembly::I64RegClass);
5443a5ce733SDan Gohman     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
5453a5ce733SDan Gohman             TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
5463a5ce733SDan Gohman         .addReg(Reg);
5473a5ce733SDan Gohman     return Result;
5483a5ce733SDan Gohman   }
5493a5ce733SDan Gohman 
550323dc634SNikita Popov   if (To == MVT::i32)
5513a5ce733SDan Gohman     return signExtendToI32(Reg, V, From);
552323dc634SNikita Popov 
553323dc634SNikita Popov   return 0;
5543a5ce733SDan Gohman }
5553a5ce733SDan Gohman 
getRegForUnsignedValue(const Value * V)5563a5ce733SDan Gohman unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
5573a5ce733SDan Gohman   MVT::SimpleValueType From = getSimpleType(V->getType());
5583a5ce733SDan Gohman   MVT::SimpleValueType To = getLegalType(From);
559d6b07348SJim Lin   Register VReg = getRegForValue(V);
5603ff73cfbSDan Gohman   if (VReg == 0)
5613ff73cfbSDan Gohman     return 0;
5623ff73cfbSDan Gohman   return zeroExtend(VReg, V, From, To);
5633a5ce733SDan Gohman }
5643a5ce733SDan Gohman 
getRegForSignedValue(const Value * V)5653a5ce733SDan Gohman unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
5663a5ce733SDan Gohman   MVT::SimpleValueType From = getSimpleType(V->getType());
5673a5ce733SDan Gohman   MVT::SimpleValueType To = getLegalType(From);
568d6b07348SJim Lin   Register VReg = getRegForValue(V);
5693ff73cfbSDan Gohman   if (VReg == 0)
5703ff73cfbSDan Gohman     return 0;
5713ff73cfbSDan Gohman   return signExtend(VReg, V, From, To);
5723a5ce733SDan Gohman }
5733a5ce733SDan Gohman 
getRegForPromotedValue(const Value * V,bool IsSigned)5743a5ce733SDan Gohman unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
5753a5ce733SDan Gohman                                                      bool IsSigned) {
576f208f631SHeejin Ahn   return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
5773a5ce733SDan Gohman }
5783a5ce733SDan Gohman 
notValue(unsigned Reg)5793a5ce733SDan Gohman unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
58033e694a8SDan Gohman   assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
58133e694a8SDan Gohman 
582d6b07348SJim Lin   Register NotReg = createResultReg(&WebAssembly::I32RegClass);
5833a5ce733SDan Gohman   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
5843a5ce733SDan Gohman           TII.get(WebAssembly::EQZ_I32), NotReg)
5853a5ce733SDan Gohman       .addReg(Reg);
5863a5ce733SDan Gohman   return NotReg;
5872e64438aSDan Gohman }
5882e64438aSDan Gohman 
copyValue(unsigned Reg)58933e694a8SDan Gohman unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
590d6b07348SJim Lin   Register ResultReg = createResultReg(MRI.getRegClass(Reg));
591f208f631SHeejin Ahn   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
592f208f631SHeejin Ahn           ResultReg)
59333e694a8SDan Gohman       .addReg(Reg);
59433e694a8SDan Gohman   return ResultReg;
59533e694a8SDan Gohman }
59633e694a8SDan Gohman 
fastMaterializeAlloca(const AllocaInst * AI)5972e64438aSDan Gohman unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
5982e64438aSDan Gohman   DenseMap<const AllocaInst *, int>::iterator SI =
5992e64438aSDan Gohman       FuncInfo.StaticAllocaMap.find(AI);
6002e64438aSDan Gohman 
6012e64438aSDan Gohman   if (SI != FuncInfo.StaticAllocaMap.end()) {
602d6b07348SJim Lin     Register ResultReg =
603f208f631SHeejin Ahn         createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
604f208f631SHeejin Ahn                                                : &WebAssembly::I32RegClass);
605f208f631SHeejin Ahn     unsigned Opc =
606f208f631SHeejin Ahn         Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
6072e64438aSDan Gohman     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
6082e64438aSDan Gohman         .addFrameIndex(SI->second);
6092e64438aSDan Gohman     return ResultReg;
6102e64438aSDan Gohman   }
6112e64438aSDan Gohman 
6122e64438aSDan Gohman   return 0;
6132e64438aSDan Gohman }
6142e64438aSDan Gohman 
fastMaterializeConstant(const Constant * C)6152e64438aSDan Gohman unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
616492f7529SSam Clegg   if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
617492f7529SSam Clegg     if (TLI.isPositionIndependent())
618492f7529SSam Clegg       return 0;
61942bba4b8SGuanzhong Chen     if (GV->isThreadLocal())
62042bba4b8SGuanzhong Chen       return 0;
621d6b07348SJim Lin     Register ResultReg =
622f208f631SHeejin Ahn         createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
623f208f631SHeejin Ahn                                                : &WebAssembly::I32RegClass);
624f208f631SHeejin Ahn     unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
625f208f631SHeejin Ahn                                           : WebAssembly::CONST_I32;
62633e694a8SDan Gohman     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
6272e64438aSDan Gohman         .addGlobalAddress(GV);
62833e694a8SDan Gohman     return ResultReg;
6292e64438aSDan Gohman   }
6302e64438aSDan Gohman 
6312e64438aSDan Gohman   // Let target-independent code handle it.
6322e64438aSDan Gohman   return 0;
6332e64438aSDan Gohman }
6342e64438aSDan Gohman 
fastLowerArguments()63533e694a8SDan Gohman bool WebAssemblyFastISel::fastLowerArguments() {
63633e694a8SDan Gohman   if (!FuncInfo.CanLowerReturn)
63733e694a8SDan Gohman     return false;
63833e694a8SDan Gohman 
63933e694a8SDan Gohman   const Function *F = FuncInfo.Fn;
64033e694a8SDan Gohman   if (F->isVarArg())
64133e694a8SDan Gohman     return false;
64233e694a8SDan Gohman 
64308670d43SYuta Saito   if (FuncInfo.Fn->getCallingConv() == CallingConv::Swift)
64408670d43SYuta Saito     return false;
64508670d43SYuta Saito 
64618c56a07SHeejin Ahn   unsigned I = 0;
64733e694a8SDan Gohman   for (auto const &Arg : F->args()) {
648b518054bSReid Kleckner     const AttributeList &Attrs = F->getAttributes();
649a0c42ca5SArthur Eubanks     if (Attrs.hasParamAttr(I, Attribute::ByVal) ||
650a0c42ca5SArthur Eubanks         Attrs.hasParamAttr(I, Attribute::SwiftSelf) ||
651a0c42ca5SArthur Eubanks         Attrs.hasParamAttr(I, Attribute::SwiftError) ||
652a0c42ca5SArthur Eubanks         Attrs.hasParamAttr(I, Attribute::InAlloca) ||
653a0c42ca5SArthur Eubanks         Attrs.hasParamAttr(I, Attribute::Nest))
65433e694a8SDan Gohman       return false;
65533e694a8SDan Gohman 
65633e694a8SDan Gohman     Type *ArgTy = Arg.getType();
65739bf39f3SDerek Schuff     if (ArgTy->isStructTy() || ArgTy->isArrayTy())
65839bf39f3SDerek Schuff       return false;
65939bf39f3SDerek Schuff     if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
66033e694a8SDan Gohman       return false;
66133e694a8SDan Gohman 
66233e694a8SDan Gohman     unsigned Opc;
66333e694a8SDan Gohman     const TargetRegisterClass *RC;
66433e694a8SDan Gohman     switch (getSimpleType(ArgTy)) {
66533e694a8SDan Gohman     case MVT::i1:
66633e694a8SDan Gohman     case MVT::i8:
66733e694a8SDan Gohman     case MVT::i16:
66833e694a8SDan Gohman     case MVT::i32:
6690ff82ac1SThomas Lively       Opc = WebAssembly::ARGUMENT_i32;
67033e694a8SDan Gohman       RC = &WebAssembly::I32RegClass;
67133e694a8SDan Gohman       break;
67233e694a8SDan Gohman     case MVT::i64:
6730ff82ac1SThomas Lively       Opc = WebAssembly::ARGUMENT_i64;
67433e694a8SDan Gohman       RC = &WebAssembly::I64RegClass;
67533e694a8SDan Gohman       break;
67633e694a8SDan Gohman     case MVT::f32:
6770ff82ac1SThomas Lively       Opc = WebAssembly::ARGUMENT_f32;
67833e694a8SDan Gohman       RC = &WebAssembly::F32RegClass;
67933e694a8SDan Gohman       break;
68033e694a8SDan Gohman     case MVT::f64:
6810ff82ac1SThomas Lively       Opc = WebAssembly::ARGUMENT_f64;
68233e694a8SDan Gohman       RC = &WebAssembly::F64RegClass;
68333e694a8SDan Gohman       break;
68439bf39f3SDerek Schuff     case MVT::v16i8:
68539bf39f3SDerek Schuff       Opc = WebAssembly::ARGUMENT_v16i8;
68639bf39f3SDerek Schuff       RC = &WebAssembly::V128RegClass;
68739bf39f3SDerek Schuff       break;
68839bf39f3SDerek Schuff     case MVT::v8i16:
68939bf39f3SDerek Schuff       Opc = WebAssembly::ARGUMENT_v8i16;
69039bf39f3SDerek Schuff       RC = &WebAssembly::V128RegClass;
69139bf39f3SDerek Schuff       break;
69239bf39f3SDerek Schuff     case MVT::v4i32:
69339bf39f3SDerek Schuff       Opc = WebAssembly::ARGUMENT_v4i32;
69439bf39f3SDerek Schuff       RC = &WebAssembly::V128RegClass;
69539bf39f3SDerek Schuff       break;
69651ed131eSDerek Schuff     case MVT::v2i64:
69751ed131eSDerek Schuff       Opc = WebAssembly::ARGUMENT_v2i64;
69851ed131eSDerek Schuff       RC = &WebAssembly::V128RegClass;
69951ed131eSDerek Schuff       break;
70039bf39f3SDerek Schuff     case MVT::v4f32:
70139bf39f3SDerek Schuff       Opc = WebAssembly::ARGUMENT_v4f32;
70239bf39f3SDerek Schuff       RC = &WebAssembly::V128RegClass;
70339bf39f3SDerek Schuff       break;
70451ed131eSDerek Schuff     case MVT::v2f64:
70551ed131eSDerek Schuff       Opc = WebAssembly::ARGUMENT_v2f64;
70651ed131eSDerek Schuff       RC = &WebAssembly::V128RegClass;
70751ed131eSDerek Schuff       break;
70860653e24SHeejin Ahn     case MVT::funcref:
70960653e24SHeejin Ahn       Opc = WebAssembly::ARGUMENT_funcref;
71060653e24SHeejin Ahn       RC = &WebAssembly::FUNCREFRegClass;
71160653e24SHeejin Ahn       break;
71260653e24SHeejin Ahn     case MVT::externref:
71360653e24SHeejin Ahn       Opc = WebAssembly::ARGUMENT_externref;
71460653e24SHeejin Ahn       RC = &WebAssembly::EXTERNREFRegClass;
71560653e24SHeejin Ahn       break;
71633e694a8SDan Gohman     default:
71733e694a8SDan Gohman       return false;
71833e694a8SDan Gohman     }
719d6b07348SJim Lin     Register ResultReg = createResultReg(RC);
72033e694a8SDan Gohman     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
72118c56a07SHeejin Ahn         .addImm(I);
72233e694a8SDan Gohman     updateValueMap(&Arg, ResultReg);
72333e694a8SDan Gohman 
72418c56a07SHeejin Ahn     ++I;
72533e694a8SDan Gohman   }
72633e694a8SDan Gohman 
72733e694a8SDan Gohman   MRI.addLiveIn(WebAssembly::ARGUMENTS);
72833e694a8SDan Gohman 
72933e694a8SDan Gohman   auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
730b8184827SDan Gohman   for (auto const &Arg : F->args()) {
731b8184827SDan Gohman     MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType()));
732b8184827SDan Gohman     if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
733b8184827SDan Gohman       MFI->clearParamsAndResults();
734b8184827SDan Gohman       return false;
735b8184827SDan Gohman     }
736b8184827SDan Gohman     MFI->addParam(ArgTy);
737b8184827SDan Gohman   }
73833e694a8SDan Gohman 
7394576dc06SDan Gohman   if (!F->getReturnType()->isVoidTy()) {
740f208f631SHeejin Ahn     MVT::SimpleValueType RetTy =
741f208f631SHeejin Ahn         getLegalType(getSimpleType(F->getReturnType()));
742b8184827SDan Gohman     if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
743b8184827SDan Gohman       MFI->clearParamsAndResults();
7444576dc06SDan Gohman       return false;
745b8184827SDan Gohman     }
746b8184827SDan Gohman     MFI->addResult(RetTy);
7474576dc06SDan Gohman   }
7486055fbaeSDan Gohman 
74933e694a8SDan Gohman   return true;
75033e694a8SDan Gohman }
75133e694a8SDan Gohman 
selectCall(const Instruction * I)75233e694a8SDan Gohman bool WebAssemblyFastISel::selectCall(const Instruction *I) {
75318c56a07SHeejin Ahn   const auto *Call = cast<CallInst>(I);
75433e694a8SDan Gohman 
755a1d97a96SThomas Lively   // TODO: Support tail calls in FastISel
75633e694a8SDan Gohman   if (Call->isMustTailCall() || Call->isInlineAsm() ||
75733e694a8SDan Gohman       Call->getFunctionType()->isVarArg())
75833e694a8SDan Gohman     return false;
75933e694a8SDan Gohman 
76033e694a8SDan Gohman   Function *Func = Call->getCalledFunction();
76133e694a8SDan Gohman   if (Func && Func->isIntrinsic())
76233e694a8SDan Gohman     return false;
76333e694a8SDan Gohman 
76408670d43SYuta Saito   if (Call->getCallingConv() == CallingConv::Swift)
76508670d43SYuta Saito     return false;
76608670d43SYuta Saito 
767690b76e1SJacob Gravelle   bool IsDirect = Func != nullptr;
768a58b62b4SCraig Topper   if (!IsDirect && isa<ConstantExpr>(Call->getCalledOperand()))
769690b76e1SJacob Gravelle     return false;
770690b76e1SJacob Gravelle 
77133e694a8SDan Gohman   FunctionType *FuncTy = Call->getFunctionType();
772ca9ba764SThomas Lively   unsigned Opc = IsDirect ? WebAssembly::CALL : WebAssembly::CALL_INDIRECT;
77333e694a8SDan Gohman   bool IsVoid = FuncTy->getReturnType()->isVoidTy();
77433e694a8SDan Gohman   unsigned ResultReg;
775ca9ba764SThomas Lively   if (!IsVoid) {
77639bf39f3SDerek Schuff     if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
77739bf39f3SDerek Schuff       return false;
77839bf39f3SDerek Schuff 
77933e694a8SDan Gohman     MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
78033e694a8SDan Gohman     switch (RetTy) {
78133e694a8SDan Gohman     case MVT::i1:
78233e694a8SDan Gohman     case MVT::i8:
78333e694a8SDan Gohman     case MVT::i16:
78433e694a8SDan Gohman     case MVT::i32:
78533e694a8SDan Gohman       ResultReg = createResultReg(&WebAssembly::I32RegClass);
78633e694a8SDan Gohman       break;
78733e694a8SDan Gohman     case MVT::i64:
78833e694a8SDan Gohman       ResultReg = createResultReg(&WebAssembly::I64RegClass);
78933e694a8SDan Gohman       break;
79033e694a8SDan Gohman     case MVT::f32:
79133e694a8SDan Gohman       ResultReg = createResultReg(&WebAssembly::F32RegClass);
79233e694a8SDan Gohman       break;
79333e694a8SDan Gohman     case MVT::f64:
79433e694a8SDan Gohman       ResultReg = createResultReg(&WebAssembly::F64RegClass);
79533e694a8SDan Gohman       break;
79639bf39f3SDerek Schuff     case MVT::v16i8:
79739bf39f3SDerek Schuff       ResultReg = createResultReg(&WebAssembly::V128RegClass);
79839bf39f3SDerek Schuff       break;
79939bf39f3SDerek Schuff     case MVT::v8i16:
80039bf39f3SDerek Schuff       ResultReg = createResultReg(&WebAssembly::V128RegClass);
80139bf39f3SDerek Schuff       break;
80239bf39f3SDerek Schuff     case MVT::v4i32:
80339bf39f3SDerek Schuff       ResultReg = createResultReg(&WebAssembly::V128RegClass);
80439bf39f3SDerek Schuff       break;
80551ed131eSDerek Schuff     case MVT::v2i64:
80651ed131eSDerek Schuff       ResultReg = createResultReg(&WebAssembly::V128RegClass);
80751ed131eSDerek Schuff       break;
80839bf39f3SDerek Schuff     case MVT::v4f32:
80939bf39f3SDerek Schuff       ResultReg = createResultReg(&WebAssembly::V128RegClass);
81039bf39f3SDerek Schuff       break;
81151ed131eSDerek Schuff     case MVT::v2f64:
81251ed131eSDerek Schuff       ResultReg = createResultReg(&WebAssembly::V128RegClass);
81351ed131eSDerek Schuff       break;
81469e2797eSPaulo Matos     case MVT::funcref:
81569e2797eSPaulo Matos       ResultReg = createResultReg(&WebAssembly::FUNCREFRegClass);
81669e2797eSPaulo Matos       break;
81769e2797eSPaulo Matos     case MVT::externref:
81869e2797eSPaulo Matos       ResultReg = createResultReg(&WebAssembly::EXTERNREFRegClass);
81969e2797eSPaulo Matos       break;
82033e694a8SDan Gohman     default:
82133e694a8SDan Gohman       return false;
82233e694a8SDan Gohman     }
82333e694a8SDan Gohman   }
82433e694a8SDan Gohman 
82533e694a8SDan Gohman   SmallVector<unsigned, 8> Args;
826c1e32b3fSKazu Hirata   for (unsigned I = 0, E = Call->arg_size(); I < E; ++I) {
82718c56a07SHeejin Ahn     Value *V = Call->getArgOperand(I);
82833e694a8SDan Gohman     MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
82933e694a8SDan Gohman     if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
83033e694a8SDan Gohman       return false;
83133e694a8SDan Gohman 
832b518054bSReid Kleckner     const AttributeList &Attrs = Call->getAttributes();
833a0c42ca5SArthur Eubanks     if (Attrs.hasParamAttr(I, Attribute::ByVal) ||
834a0c42ca5SArthur Eubanks         Attrs.hasParamAttr(I, Attribute::SwiftSelf) ||
835a0c42ca5SArthur Eubanks         Attrs.hasParamAttr(I, Attribute::SwiftError) ||
836a0c42ca5SArthur Eubanks         Attrs.hasParamAttr(I, Attribute::InAlloca) ||
837a0c42ca5SArthur Eubanks         Attrs.hasParamAttr(I, Attribute::Nest))
83833e694a8SDan Gohman       return false;
83933e694a8SDan Gohman 
84033e694a8SDan Gohman     unsigned Reg;
84133e694a8SDan Gohman 
842a0c42ca5SArthur Eubanks     if (Attrs.hasParamAttr(I, Attribute::SExt))
84333e694a8SDan Gohman       Reg = getRegForSignedValue(V);
844a0c42ca5SArthur Eubanks     else if (Attrs.hasParamAttr(I, Attribute::ZExt))
84533e694a8SDan Gohman       Reg = getRegForUnsignedValue(V);
84633e694a8SDan Gohman     else
84733e694a8SDan Gohman       Reg = getRegForValue(V);
84833e694a8SDan Gohman 
84933e694a8SDan Gohman     if (Reg == 0)
85033e694a8SDan Gohman       return false;
85133e694a8SDan Gohman 
85233e694a8SDan Gohman     Args.push_back(Reg);
85333e694a8SDan Gohman   }
85433e694a8SDan Gohman 
855a2725279SSam Clegg   unsigned CalleeReg = 0;
856a2725279SSam Clegg   if (!IsDirect) {
857a58b62b4SCraig Topper     CalleeReg = getRegForValue(Call->getCalledOperand());
858a2725279SSam Clegg     if (!CalleeReg)
859a2725279SSam Clegg       return false;
860a2725279SSam Clegg   }
861a2725279SSam Clegg 
86233e694a8SDan Gohman   auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
86333e694a8SDan Gohman 
86433e694a8SDan Gohman   if (!IsVoid)
86533e694a8SDan Gohman     MIB.addReg(ResultReg, RegState::Define);
86633e694a8SDan Gohman 
867ca9ba764SThomas Lively   if (IsDirect) {
86833e694a8SDan Gohman     MIB.addGlobalAddress(Func);
869ca9ba764SThomas Lively   } else {
8704307069dSAndy Wingo     // Placeholder for the type index.
871ca9ba764SThomas Lively     MIB.addImm(0);
8722632ba6aSAndy Wingo     // The table into which this call_indirect indexes.
8732632ba6aSAndy Wingo     MCSymbolWasm *Table = WebAssembly::getOrCreateFunctionTableSymbol(
8742632ba6aSAndy Wingo         MF->getMMI().getContext(), Subtarget);
8752632ba6aSAndy Wingo     if (Subtarget->hasReferenceTypes()) {
8762632ba6aSAndy Wingo       MIB.addSym(Table);
8772632ba6aSAndy Wingo     } else {
8782632ba6aSAndy Wingo       // Otherwise for the MVP there is at most one table whose number is 0, but
8792632ba6aSAndy Wingo       // we can't write a table symbol or issue relocations.  Instead we just
8802632ba6aSAndy Wingo       // ensure the table is live.
8812632ba6aSAndy Wingo       Table->setNoStrip();
88296ef4f30SSam Clegg       MIB.addImm(0);
8832632ba6aSAndy Wingo     }
884275c6af7SWouter van Oortmerssen     // See if we must truncate the function pointer.
885275c6af7SWouter van Oortmerssen     // CALL_INDIRECT takes an i32, but in wasm64 we represent function pointers
886275c6af7SWouter van Oortmerssen     // as 64-bit for uniformity with other pointer types.
887275c6af7SWouter van Oortmerssen     // See also: WebAssemblyISelLowering.cpp: LowerCallResults
888275c6af7SWouter van Oortmerssen     if (Subtarget->hasAddr64()) {
889275c6af7SWouter van Oortmerssen       auto Wrap = BuildMI(*FuncInfo.MBB, std::prev(FuncInfo.InsertPt), DbgLoc,
890275c6af7SWouter van Oortmerssen                           TII.get(WebAssembly::I32_WRAP_I64));
891d6b07348SJim Lin       Register Reg32 = createResultReg(&WebAssembly::I32RegClass);
892275c6af7SWouter van Oortmerssen       Wrap.addReg(Reg32, RegState::Define);
893275c6af7SWouter van Oortmerssen       Wrap.addReg(CalleeReg);
894275c6af7SWouter van Oortmerssen       CalleeReg = Reg32;
895275c6af7SWouter van Oortmerssen     }
896ca9ba764SThomas Lively   }
89733e694a8SDan Gohman 
89833e694a8SDan Gohman   for (unsigned ArgReg : Args)
89933e694a8SDan Gohman     MIB.addReg(ArgReg);
90033e694a8SDan Gohman 
901ca9ba764SThomas Lively   if (!IsDirect)
902ca9ba764SThomas Lively     MIB.addReg(CalleeReg);
903ca9ba764SThomas Lively 
90433e694a8SDan Gohman   if (!IsVoid)
90533e694a8SDan Gohman     updateValueMap(Call, ResultReg);
90633e694a8SDan Gohman   return true;
90733e694a8SDan Gohman }
90833e694a8SDan Gohman 
selectSelect(const Instruction * I)90933e694a8SDan Gohman bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
91018c56a07SHeejin Ahn   const auto *Select = cast<SelectInst>(I);
91133e694a8SDan Gohman 
91233e694a8SDan Gohman   bool Not;
91316086d47SNikita Popov   unsigned CondReg =
91416086d47SNikita Popov       getRegForI1Value(Select->getCondition(), I->getParent(), Not);
91533e694a8SDan Gohman   if (CondReg == 0)
91633e694a8SDan Gohman     return false;
91733e694a8SDan Gohman 
918d6b07348SJim Lin   Register TrueReg = getRegForValue(Select->getTrueValue());
91933e694a8SDan Gohman   if (TrueReg == 0)
92033e694a8SDan Gohman     return false;
92133e694a8SDan Gohman 
922d6b07348SJim Lin   Register FalseReg = getRegForValue(Select->getFalseValue());
92333e694a8SDan Gohman   if (FalseReg == 0)
92433e694a8SDan Gohman     return false;
92533e694a8SDan Gohman 
92633e694a8SDan Gohman   if (Not)
92733e694a8SDan Gohman     std::swap(TrueReg, FalseReg);
92833e694a8SDan Gohman 
92933e694a8SDan Gohman   unsigned Opc;
93033e694a8SDan Gohman   const TargetRegisterClass *RC;
93133e694a8SDan Gohman   switch (getSimpleType(Select->getType())) {
93233e694a8SDan Gohman   case MVT::i1:
93333e694a8SDan Gohman   case MVT::i8:
93433e694a8SDan Gohman   case MVT::i16:
93533e694a8SDan Gohman   case MVT::i32:
93633e694a8SDan Gohman     Opc = WebAssembly::SELECT_I32;
93733e694a8SDan Gohman     RC = &WebAssembly::I32RegClass;
93833e694a8SDan Gohman     break;
93933e694a8SDan Gohman   case MVT::i64:
94033e694a8SDan Gohman     Opc = WebAssembly::SELECT_I64;
94133e694a8SDan Gohman     RC = &WebAssembly::I64RegClass;
94233e694a8SDan Gohman     break;
94333e694a8SDan Gohman   case MVT::f32:
94433e694a8SDan Gohman     Opc = WebAssembly::SELECT_F32;
94533e694a8SDan Gohman     RC = &WebAssembly::F32RegClass;
94633e694a8SDan Gohman     break;
94733e694a8SDan Gohman   case MVT::f64:
94833e694a8SDan Gohman     Opc = WebAssembly::SELECT_F64;
94933e694a8SDan Gohman     RC = &WebAssembly::F64RegClass;
95033e694a8SDan Gohman     break;
95160653e24SHeejin Ahn   case MVT::funcref:
95260653e24SHeejin Ahn     Opc = WebAssembly::SELECT_FUNCREF;
95360653e24SHeejin Ahn     RC = &WebAssembly::FUNCREFRegClass;
95460653e24SHeejin Ahn     break;
95560653e24SHeejin Ahn   case MVT::externref:
95660653e24SHeejin Ahn     Opc = WebAssembly::SELECT_EXTERNREF;
95760653e24SHeejin Ahn     RC = &WebAssembly::EXTERNREFRegClass;
95860653e24SHeejin Ahn     break;
95933e694a8SDan Gohman   default:
96033e694a8SDan Gohman     return false;
96133e694a8SDan Gohman   }
96233e694a8SDan Gohman 
963d6b07348SJim Lin   Register ResultReg = createResultReg(RC);
96433e694a8SDan Gohman   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
96533e694a8SDan Gohman       .addReg(TrueReg)
96633e694a8SDan Gohman       .addReg(FalseReg)
96733e694a8SDan Gohman       .addReg(CondReg);
96833e694a8SDan Gohman 
96933e694a8SDan Gohman   updateValueMap(Select, ResultReg);
97033e694a8SDan Gohman   return true;
97133e694a8SDan Gohman }
97233e694a8SDan Gohman 
selectTrunc(const Instruction * I)97333e694a8SDan Gohman bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
97418c56a07SHeejin Ahn   const auto *Trunc = cast<TruncInst>(I);
97533e694a8SDan Gohman 
976d6b07348SJim Lin   Register Reg = getRegForValue(Trunc->getOperand(0));
97733e694a8SDan Gohman   if (Reg == 0)
97833e694a8SDan Gohman     return false;
97933e694a8SDan Gohman 
98033e694a8SDan Gohman   if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
981d6b07348SJim Lin     Register Result = createResultReg(&WebAssembly::I32RegClass);
98233e694a8SDan Gohman     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
98333e694a8SDan Gohman             TII.get(WebAssembly::I32_WRAP_I64), Result)
98433e694a8SDan Gohman         .addReg(Reg);
98533e694a8SDan Gohman     Reg = Result;
98633e694a8SDan Gohman   }
98733e694a8SDan Gohman 
98833e694a8SDan Gohman   updateValueMap(Trunc, Reg);
98933e694a8SDan Gohman   return true;
99033e694a8SDan Gohman }
99133e694a8SDan Gohman 
selectZExt(const Instruction * I)9923a5ce733SDan Gohman bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
99318c56a07SHeejin Ahn   const auto *ZExt = cast<ZExtInst>(I);
9943a5ce733SDan Gohman 
99533e694a8SDan Gohman   const Value *Op = ZExt->getOperand(0);
99633e694a8SDan Gohman   MVT::SimpleValueType From = getSimpleType(Op->getType());
99733e694a8SDan Gohman   MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
998d6b07348SJim Lin   Register In = getRegForValue(Op);
9993ff73cfbSDan Gohman   if (In == 0)
10003ff73cfbSDan Gohman     return false;
10013ff73cfbSDan Gohman   unsigned Reg = zeroExtend(In, Op, From, To);
10023a5ce733SDan Gohman   if (Reg == 0)
10033a5ce733SDan Gohman     return false;
10043a5ce733SDan Gohman 
10053a5ce733SDan Gohman   updateValueMap(ZExt, Reg);
10063a5ce733SDan Gohman   return true;
10073a5ce733SDan Gohman }
10083a5ce733SDan Gohman 
selectSExt(const Instruction * I)10093a5ce733SDan Gohman bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
101018c56a07SHeejin Ahn   const auto *SExt = cast<SExtInst>(I);
10113a5ce733SDan Gohman 
101233e694a8SDan Gohman   const Value *Op = SExt->getOperand(0);
101333e694a8SDan Gohman   MVT::SimpleValueType From = getSimpleType(Op->getType());
101433e694a8SDan Gohman   MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
1015d6b07348SJim Lin   Register In = getRegForValue(Op);
10163ff73cfbSDan Gohman   if (In == 0)
10173ff73cfbSDan Gohman     return false;
10183ff73cfbSDan Gohman   unsigned Reg = signExtend(In, Op, From, To);
10193a5ce733SDan Gohman   if (Reg == 0)
10203a5ce733SDan Gohman     return false;
10213a5ce733SDan Gohman 
10223a5ce733SDan Gohman   updateValueMap(SExt, Reg);
10233a5ce733SDan Gohman   return true;
10243a5ce733SDan Gohman }
10253a5ce733SDan Gohman 
selectICmp(const Instruction * I)10263a5ce733SDan Gohman bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
102718c56a07SHeejin Ahn   const auto *ICmp = cast<ICmpInst>(I);
10283a5ce733SDan Gohman 
10293a5ce733SDan Gohman   bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
10303a5ce733SDan Gohman   unsigned Opc;
103118c56a07SHeejin Ahn   bool IsSigned = false;
10323a5ce733SDan Gohman   switch (ICmp->getPredicate()) {
10333a5ce733SDan Gohman   case ICmpInst::ICMP_EQ:
10343a5ce733SDan Gohman     Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
10353a5ce733SDan Gohman     break;
10363a5ce733SDan Gohman   case ICmpInst::ICMP_NE:
10373a5ce733SDan Gohman     Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
10383a5ce733SDan Gohman     break;
10393a5ce733SDan Gohman   case ICmpInst::ICMP_UGT:
10403a5ce733SDan Gohman     Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
10413a5ce733SDan Gohman     break;
10423a5ce733SDan Gohman   case ICmpInst::ICMP_UGE:
10433a5ce733SDan Gohman     Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
10443a5ce733SDan Gohman     break;
10453a5ce733SDan Gohman   case ICmpInst::ICMP_ULT:
10463a5ce733SDan Gohman     Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
10473a5ce733SDan Gohman     break;
10483a5ce733SDan Gohman   case ICmpInst::ICMP_ULE:
10493a5ce733SDan Gohman     Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
10503a5ce733SDan Gohman     break;
10513a5ce733SDan Gohman   case ICmpInst::ICMP_SGT:
10523a5ce733SDan Gohman     Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
105318c56a07SHeejin Ahn     IsSigned = true;
10543a5ce733SDan Gohman     break;
10553a5ce733SDan Gohman   case ICmpInst::ICMP_SGE:
10563a5ce733SDan Gohman     Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
105718c56a07SHeejin Ahn     IsSigned = true;
10583a5ce733SDan Gohman     break;
10593a5ce733SDan Gohman   case ICmpInst::ICMP_SLT:
10603a5ce733SDan Gohman     Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
106118c56a07SHeejin Ahn     IsSigned = true;
10623a5ce733SDan Gohman     break;
10633a5ce733SDan Gohman   case ICmpInst::ICMP_SLE:
10643a5ce733SDan Gohman     Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
106518c56a07SHeejin Ahn     IsSigned = true;
10663a5ce733SDan Gohman     break;
1067f208f631SHeejin Ahn   default:
1068f208f631SHeejin Ahn     return false;
10693a5ce733SDan Gohman   }
10703a5ce733SDan Gohman 
107118c56a07SHeejin Ahn   unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
10723a5ce733SDan Gohman   if (LHS == 0)
10733a5ce733SDan Gohman     return false;
10743a5ce733SDan Gohman 
107518c56a07SHeejin Ahn   unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
10763a5ce733SDan Gohman   if (RHS == 0)
10773a5ce733SDan Gohman     return false;
10783a5ce733SDan Gohman 
1079d6b07348SJim Lin   Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
10803a5ce733SDan Gohman   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
10813a5ce733SDan Gohman       .addReg(LHS)
10823a5ce733SDan Gohman       .addReg(RHS);
10833a5ce733SDan Gohman   updateValueMap(ICmp, ResultReg);
10843a5ce733SDan Gohman   return true;
10853a5ce733SDan Gohman }
10863a5ce733SDan Gohman 
selectFCmp(const Instruction * I)10873a5ce733SDan Gohman bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
108818c56a07SHeejin Ahn   const auto *FCmp = cast<FCmpInst>(I);
10893a5ce733SDan Gohman 
1090d6b07348SJim Lin   Register LHS = getRegForValue(FCmp->getOperand(0));
10913a5ce733SDan Gohman   if (LHS == 0)
10923a5ce733SDan Gohman     return false;
10933a5ce733SDan Gohman 
1094d6b07348SJim Lin   Register RHS = getRegForValue(FCmp->getOperand(1));
10953a5ce733SDan Gohman   if (RHS == 0)
10963a5ce733SDan Gohman     return false;
10973a5ce733SDan Gohman 
10983a5ce733SDan Gohman   bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
10993a5ce733SDan Gohman   unsigned Opc;
11003a5ce733SDan Gohman   bool Not = false;
11013a5ce733SDan Gohman   switch (FCmp->getPredicate()) {
11023a5ce733SDan Gohman   case FCmpInst::FCMP_OEQ:
11033a5ce733SDan Gohman     Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
11043a5ce733SDan Gohman     break;
11053a5ce733SDan Gohman   case FCmpInst::FCMP_UNE:
11063a5ce733SDan Gohman     Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
11073a5ce733SDan Gohman     break;
11083a5ce733SDan Gohman   case FCmpInst::FCMP_OGT:
11093a5ce733SDan Gohman     Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
11103a5ce733SDan Gohman     break;
11113a5ce733SDan Gohman   case FCmpInst::FCMP_OGE:
11123a5ce733SDan Gohman     Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
11133a5ce733SDan Gohman     break;
11143a5ce733SDan Gohman   case FCmpInst::FCMP_OLT:
11153a5ce733SDan Gohman     Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
11163a5ce733SDan Gohman     break;
11173a5ce733SDan Gohman   case FCmpInst::FCMP_OLE:
11183a5ce733SDan Gohman     Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
11193a5ce733SDan Gohman     break;
11203a5ce733SDan Gohman   case FCmpInst::FCMP_UGT:
11213a5ce733SDan Gohman     Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
11223a5ce733SDan Gohman     Not = true;
11233a5ce733SDan Gohman     break;
11243a5ce733SDan Gohman   case FCmpInst::FCMP_UGE:
11253a5ce733SDan Gohman     Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
11263a5ce733SDan Gohman     Not = true;
11273a5ce733SDan Gohman     break;
11283a5ce733SDan Gohman   case FCmpInst::FCMP_ULT:
11293a5ce733SDan Gohman     Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
11303a5ce733SDan Gohman     Not = true;
11313a5ce733SDan Gohman     break;
11323a5ce733SDan Gohman   case FCmpInst::FCMP_ULE:
11333a5ce733SDan Gohman     Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
11343a5ce733SDan Gohman     Not = true;
11353a5ce733SDan Gohman     break;
11363a5ce733SDan Gohman   default:
11373a5ce733SDan Gohman     return false;
11383a5ce733SDan Gohman   }
11393a5ce733SDan Gohman 
1140d6b07348SJim Lin   Register ResultReg = createResultReg(&WebAssembly::I32RegClass);
11413a5ce733SDan Gohman   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
11423a5ce733SDan Gohman       .addReg(LHS)
11433a5ce733SDan Gohman       .addReg(RHS);
11443a5ce733SDan Gohman 
11453a5ce733SDan Gohman   if (Not)
11463a5ce733SDan Gohman     ResultReg = notValue(ResultReg);
11473a5ce733SDan Gohman 
11483a5ce733SDan Gohman   updateValueMap(FCmp, ResultReg);
11493a5ce733SDan Gohman   return true;
11503a5ce733SDan Gohman }
11513a5ce733SDan Gohman 
selectBitCast(const Instruction * I)11522e64438aSDan Gohman bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
11532e64438aSDan Gohman   // Target-independent code can handle this, except it doesn't set the dead
11542e64438aSDan Gohman   // flag on the ARGUMENTS clobber, so we have to do that manually in order
11552e64438aSDan Gohman   // to satisfy code that expects this of isBitcast() instructions.
11562e64438aSDan Gohman   EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
11572e64438aSDan Gohman   EVT RetVT = TLI.getValueType(DL, I->getType());
11582e64438aSDan Gohman   if (!VT.isSimple() || !RetVT.isSimple())
11592e64438aSDan Gohman     return false;
116033e694a8SDan Gohman 
1161d6b07348SJim Lin   Register In = getRegForValue(I->getOperand(0));
11623ff73cfbSDan Gohman   if (In == 0)
11633ff73cfbSDan Gohman     return false;
11643ff73cfbSDan Gohman 
116533e694a8SDan Gohman   if (VT == RetVT) {
116633e694a8SDan Gohman     // No-op bitcast.
11673ff73cfbSDan Gohman     updateValueMap(I, In);
116833e694a8SDan Gohman     return true;
116933e694a8SDan Gohman   }
117033e694a8SDan Gohman 
1171f4d3113aSMatt Arsenault   Register Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
117266506582SNikita Popov                                         In);
11732e64438aSDan Gohman   if (!Reg)
11742e64438aSDan Gohman     return false;
11752e64438aSDan Gohman   MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
11762e64438aSDan Gohman   --Iter;
11772e64438aSDan Gohman   assert(Iter->isBitcast());
1178f4d3113aSMatt Arsenault   Iter->setPhysRegsDeadExcept(ArrayRef<Register>(), TRI);
11792e64438aSDan Gohman   updateValueMap(I, Reg);
11802e64438aSDan Gohman   return true;
11812e64438aSDan Gohman }
11822e64438aSDan Gohman 
selectLoad(const Instruction * I)11832e64438aSDan Gohman bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
118418c56a07SHeejin Ahn   const auto *Load = cast<LoadInst>(I);
11852e64438aSDan Gohman   if (Load->isAtomic())
11862e64438aSDan Gohman     return false;
1187d7086af2SPaulo Matos   if (!WebAssembly::isDefaultAddressSpace(Load->getPointerAddressSpace()))
1188d7086af2SPaulo Matos     return false;
118939bf39f3SDerek Schuff   if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
119039bf39f3SDerek Schuff     return false;
11912e64438aSDan Gohman 
11922e64438aSDan Gohman   Address Addr;
11932e64438aSDan Gohman   if (!computeAddress(Load->getPointerOperand(), Addr))
11942e64438aSDan Gohman     return false;
11952e64438aSDan Gohman 
11962e64438aSDan Gohman   // TODO: Fold a following sign-/zero-extend into the load instruction.
11972e64438aSDan Gohman 
11982e64438aSDan Gohman   unsigned Opc;
11992e64438aSDan Gohman   const TargetRegisterClass *RC;
1200d9e0bbd1SWouter van Oortmerssen   bool A64 = Subtarget->hasAddr64();
12013a5ce733SDan Gohman   switch (getSimpleType(Load->getType())) {
12023a5ce733SDan Gohman   case MVT::i1:
12033a5ce733SDan Gohman   case MVT::i8:
1204d9e0bbd1SWouter van Oortmerssen     Opc = A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
12052e64438aSDan Gohman     RC = &WebAssembly::I32RegClass;
12062e64438aSDan Gohman     break;
12073a5ce733SDan Gohman   case MVT::i16:
1208d9e0bbd1SWouter van Oortmerssen     Opc = A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;
12092e64438aSDan Gohman     RC = &WebAssembly::I32RegClass;
12102e64438aSDan Gohman     break;
12113a5ce733SDan Gohman   case MVT::i32:
1212d9e0bbd1SWouter van Oortmerssen     Opc = A64 ? WebAssembly::LOAD_I32_A64 : WebAssembly::LOAD_I32_A32;
12132e64438aSDan Gohman     RC = &WebAssembly::I32RegClass;
12142e64438aSDan Gohman     break;
12153a5ce733SDan Gohman   case MVT::i64:
1216d9e0bbd1SWouter van Oortmerssen     Opc = A64 ? WebAssembly::LOAD_I64_A64 : WebAssembly::LOAD_I64_A32;
12172e64438aSDan Gohman     RC = &WebAssembly::I64RegClass;
12182e64438aSDan Gohman     break;
12193a5ce733SDan Gohman   case MVT::f32:
1220d9e0bbd1SWouter van Oortmerssen     Opc = A64 ? WebAssembly::LOAD_F32_A64 : WebAssembly::LOAD_F32_A32;
12212e64438aSDan Gohman     RC = &WebAssembly::F32RegClass;
12222e64438aSDan Gohman     break;
12233a5ce733SDan Gohman   case MVT::f64:
1224d9e0bbd1SWouter van Oortmerssen     Opc = A64 ? WebAssembly::LOAD_F64_A64 : WebAssembly::LOAD_F64_A32;
12252e64438aSDan Gohman     RC = &WebAssembly::F64RegClass;
12262e64438aSDan Gohman     break;
12273a5ce733SDan Gohman   default:
12283a5ce733SDan Gohman     return false;
12292e64438aSDan Gohman   }
12302e64438aSDan Gohman 
12319da81421SSam Clegg   materializeLoadStoreOperands(Addr);
12322e64438aSDan Gohman 
1233d6b07348SJim Lin   Register ResultReg = createResultReg(RC);
12342e64438aSDan Gohman   auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
12352e64438aSDan Gohman                      ResultReg);
12362e64438aSDan Gohman 
12372e64438aSDan Gohman   addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
12382e64438aSDan Gohman 
12392e64438aSDan Gohman   updateValueMap(Load, ResultReg);
12402e64438aSDan Gohman   return true;
12412e64438aSDan Gohman }
12422e64438aSDan Gohman 
selectStore(const Instruction * I)12432e64438aSDan Gohman bool WebAssemblyFastISel::selectStore(const Instruction *I) {
124418c56a07SHeejin Ahn   const auto *Store = cast<StoreInst>(I);
12452e64438aSDan Gohman   if (Store->isAtomic())
12462e64438aSDan Gohman     return false;
1247d7086af2SPaulo Matos   if (!WebAssembly::isDefaultAddressSpace(Store->getPointerAddressSpace()))
1248d7086af2SPaulo Matos     return false;
124939bf39f3SDerek Schuff   if (!Subtarget->hasSIMD128() &&
125039bf39f3SDerek Schuff       Store->getValueOperand()->getType()->isVectorTy())
125139bf39f3SDerek Schuff     return false;
12522e64438aSDan Gohman 
12532e64438aSDan Gohman   Address Addr;
12542e64438aSDan Gohman   if (!computeAddress(Store->getPointerOperand(), Addr))
12552e64438aSDan Gohman     return false;
12562e64438aSDan Gohman 
12572e64438aSDan Gohman   unsigned Opc;
12582e64438aSDan Gohman   bool VTIsi1 = false;
1259d9e0bbd1SWouter van Oortmerssen   bool A64 = Subtarget->hasAddr64();
12603a5ce733SDan Gohman   switch (getSimpleType(Store->getValueOperand()->getType())) {
12613a5ce733SDan Gohman   case MVT::i1:
12622e64438aSDan Gohman     VTIsi1 = true;
1263861bec2bSDan Gohman     LLVM_FALLTHROUGH;
12643a5ce733SDan Gohman   case MVT::i8:
1265d9e0bbd1SWouter van Oortmerssen     Opc = A64 ? WebAssembly::STORE8_I32_A64 : WebAssembly::STORE8_I32_A32;
12662e64438aSDan Gohman     break;
12673a5ce733SDan Gohman   case MVT::i16:
1268d9e0bbd1SWouter van Oortmerssen     Opc = A64 ? WebAssembly::STORE16_I32_A64 : WebAssembly::STORE16_I32_A32;
12692e64438aSDan Gohman     break;
12703a5ce733SDan Gohman   case MVT::i32:
1271d9e0bbd1SWouter van Oortmerssen     Opc = A64 ? WebAssembly::STORE_I32_A64 : WebAssembly::STORE_I32_A32;
12722e64438aSDan Gohman     break;
12733a5ce733SDan Gohman   case MVT::i64:
1274d9e0bbd1SWouter van Oortmerssen     Opc = A64 ? WebAssembly::STORE_I64_A64 : WebAssembly::STORE_I64_A32;
12752e64438aSDan Gohman     break;
12763a5ce733SDan Gohman   case MVT::f32:
1277d9e0bbd1SWouter van Oortmerssen     Opc = A64 ? WebAssembly::STORE_F32_A64 : WebAssembly::STORE_F32_A32;
12782e64438aSDan Gohman     break;
12793a5ce733SDan Gohman   case MVT::f64:
1280d9e0bbd1SWouter van Oortmerssen     Opc = A64 ? WebAssembly::STORE_F64_A64 : WebAssembly::STORE_F64_A32;
12812e64438aSDan Gohman     break;
1282f208f631SHeejin Ahn   default:
1283f208f631SHeejin Ahn     return false;
12842e64438aSDan Gohman   }
12852e64438aSDan Gohman 
12869da81421SSam Clegg   materializeLoadStoreOperands(Addr);
12872e64438aSDan Gohman 
1288d6b07348SJim Lin   Register ValueReg = getRegForValue(Store->getValueOperand());
1289732636d9SDerek Schuff   if (ValueReg == 0)
1290732636d9SDerek Schuff     return false;
12912e64438aSDan Gohman   if (VTIsi1)
12923a5ce733SDan Gohman     ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
12932e64438aSDan Gohman 
12947f1bdb2eSDan Gohman   auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
12952e64438aSDan Gohman 
12962e64438aSDan Gohman   addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
12972e64438aSDan Gohman 
12982e64438aSDan Gohman   MIB.addReg(ValueReg);
12992e64438aSDan Gohman   return true;
13002e64438aSDan Gohman }
13012e64438aSDan Gohman 
selectBr(const Instruction * I)13022e64438aSDan Gohman bool WebAssemblyFastISel::selectBr(const Instruction *I) {
130318c56a07SHeejin Ahn   const auto *Br = cast<BranchInst>(I);
13042e64438aSDan Gohman   if (Br->isUnconditional()) {
13052e64438aSDan Gohman     MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
13062e64438aSDan Gohman     fastEmitBranch(MSucc, Br->getDebugLoc());
13072e64438aSDan Gohman     return true;
13082e64438aSDan Gohman   }
13092e64438aSDan Gohman 
13102e64438aSDan Gohman   MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
13112e64438aSDan Gohman   MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
13122e64438aSDan Gohman 
131333e694a8SDan Gohman   bool Not;
131416086d47SNikita Popov   unsigned CondReg = getRegForI1Value(Br->getCondition(), Br->getParent(), Not);
1315732636d9SDerek Schuff   if (CondReg == 0)
1316732636d9SDerek Schuff     return false;
13172e64438aSDan Gohman 
131833e694a8SDan Gohman   unsigned Opc = WebAssembly::BR_IF;
131933e694a8SDan Gohman   if (Not)
132033e694a8SDan Gohman     Opc = WebAssembly::BR_UNLESS;
132133e694a8SDan Gohman 
13222e64438aSDan Gohman   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
13232e64438aSDan Gohman       .addMBB(TBB)
13242e64438aSDan Gohman       .addReg(CondReg);
13252e64438aSDan Gohman 
13262e64438aSDan Gohman   finishCondBranch(Br->getParent(), TBB, FBB);
13272e64438aSDan Gohman   return true;
13282e64438aSDan Gohman }
13292e64438aSDan Gohman 
selectRet(const Instruction * I)13302e64438aSDan Gohman bool WebAssemblyFastISel::selectRet(const Instruction *I) {
13312e64438aSDan Gohman   if (!FuncInfo.CanLowerReturn)
13322e64438aSDan Gohman     return false;
13332e64438aSDan Gohman 
133418c56a07SHeejin Ahn   const auto *Ret = cast<ReturnInst>(I);
13352e64438aSDan Gohman 
13362e64438aSDan Gohman   if (Ret->getNumOperands() == 0) {
13372e64438aSDan Gohman     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
133800f9e5aaSThomas Lively             TII.get(WebAssembly::RETURN));
13392e64438aSDan Gohman     return true;
13402e64438aSDan Gohman   }
13412e64438aSDan Gohman 
134200f9e5aaSThomas Lively   // TODO: support multiple return in FastISel
134300f9e5aaSThomas Lively   if (Ret->getNumOperands() > 1)
134400f9e5aaSThomas Lively     return false;
134500f9e5aaSThomas Lively 
13462e64438aSDan Gohman   Value *RV = Ret->getOperand(0);
134739bf39f3SDerek Schuff   if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
134839bf39f3SDerek Schuff     return false;
134939bf39f3SDerek Schuff 
13503a5ce733SDan Gohman   switch (getSimpleType(RV->getType())) {
1351f208f631SHeejin Ahn   case MVT::i1:
1352f208f631SHeejin Ahn   case MVT::i8:
1353f208f631SHeejin Ahn   case MVT::i16:
1354f208f631SHeejin Ahn   case MVT::i32:
13553a5ce733SDan Gohman   case MVT::i64:
135639bf39f3SDerek Schuff   case MVT::f32:
135739bf39f3SDerek Schuff   case MVT::f64:
135839bf39f3SDerek Schuff   case MVT::v16i8:
135939bf39f3SDerek Schuff   case MVT::v8i16:
136039bf39f3SDerek Schuff   case MVT::v4i32:
136151ed131eSDerek Schuff   case MVT::v2i64:
136239bf39f3SDerek Schuff   case MVT::v4f32:
136351ed131eSDerek Schuff   case MVT::v2f64:
136460653e24SHeejin Ahn   case MVT::funcref:
136560653e24SHeejin Ahn   case MVT::externref:
13660de58729SHeejin Ahn     break;
1367f208f631SHeejin Ahn   default:
1368f208f631SHeejin Ahn     return false;
13692e64438aSDan Gohman   }
13702e64438aSDan Gohman 
137133e694a8SDan Gohman   unsigned Reg;
1372d7593ebaSArthur Eubanks   if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::SExt))
137333e694a8SDan Gohman     Reg = getRegForSignedValue(RV);
1374d7593ebaSArthur Eubanks   else if (FuncInfo.Fn->getAttributes().hasRetAttr(Attribute::ZExt))
137533e694a8SDan Gohman     Reg = getRegForUnsignedValue(RV);
137633e694a8SDan Gohman   else
137733e694a8SDan Gohman     Reg = getRegForValue(RV);
137833e694a8SDan Gohman 
1379732636d9SDerek Schuff   if (Reg == 0)
1380732636d9SDerek Schuff     return false;
1381732636d9SDerek Schuff 
138200f9e5aaSThomas Lively   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
138300f9e5aaSThomas Lively           TII.get(WebAssembly::RETURN))
138400f9e5aaSThomas Lively       .addReg(Reg);
13852e64438aSDan Gohman   return true;
13862e64438aSDan Gohman }
13872e64438aSDan Gohman 
selectUnreachable(const Instruction * I)13882e64438aSDan Gohman bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
13892e64438aSDan Gohman   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
13902e64438aSDan Gohman           TII.get(WebAssembly::UNREACHABLE));
13912e64438aSDan Gohman   return true;
13922e64438aSDan Gohman }
13932e64438aSDan Gohman 
fastSelectInstruction(const Instruction * I)13942e64438aSDan Gohman bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
13952e64438aSDan Gohman   switch (I->getOpcode()) {
139633e694a8SDan Gohman   case Instruction::Call:
139733e694a8SDan Gohman     if (selectCall(I))
139833e694a8SDan Gohman       return true;
139933e694a8SDan Gohman     break;
1400f208f631SHeejin Ahn   case Instruction::Select:
1401f208f631SHeejin Ahn     return selectSelect(I);
1402f208f631SHeejin Ahn   case Instruction::Trunc:
1403f208f631SHeejin Ahn     return selectTrunc(I);
1404f208f631SHeejin Ahn   case Instruction::ZExt:
1405f208f631SHeejin Ahn     return selectZExt(I);
1406f208f631SHeejin Ahn   case Instruction::SExt:
1407f208f631SHeejin Ahn     return selectSExt(I);
1408f208f631SHeejin Ahn   case Instruction::ICmp:
1409f208f631SHeejin Ahn     return selectICmp(I);
1410f208f631SHeejin Ahn   case Instruction::FCmp:
1411f208f631SHeejin Ahn     return selectFCmp(I);
1412f208f631SHeejin Ahn   case Instruction::BitCast:
1413f208f631SHeejin Ahn     return selectBitCast(I);
1414f208f631SHeejin Ahn   case Instruction::Load:
1415f208f631SHeejin Ahn     return selectLoad(I);
1416f208f631SHeejin Ahn   case Instruction::Store:
1417f208f631SHeejin Ahn     return selectStore(I);
1418f208f631SHeejin Ahn   case Instruction::Br:
1419f208f631SHeejin Ahn     return selectBr(I);
1420f208f631SHeejin Ahn   case Instruction::Ret:
1421f208f631SHeejin Ahn     return selectRet(I);
1422f208f631SHeejin Ahn   case Instruction::Unreachable:
1423f208f631SHeejin Ahn     return selectUnreachable(I);
1424f208f631SHeejin Ahn   default:
1425f208f631SHeejin Ahn     break;
14267b63484bSDan Gohman   }
14277b63484bSDan Gohman 
14287b63484bSDan Gohman   // Fall back to target-independent instruction selection.
14297b63484bSDan Gohman   return selectOperator(I, I->getOpcode());
14307b63484bSDan Gohman }
14317b63484bSDan Gohman 
createFastISel(FunctionLoweringInfo & FuncInfo,const TargetLibraryInfo * LibInfo)14327b63484bSDan Gohman FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,
14337b63484bSDan Gohman                                       const TargetLibraryInfo *LibInfo) {
14347b63484bSDan Gohman   return new WebAssemblyFastISel(FuncInfo, LibInfo);
14357b63484bSDan Gohman }
1436