xref: /freebsd/contrib/llvm-project/llvm/lib/Target/WebAssembly/WebAssemblyFastISel.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
10b57cec5SDimitry Andric //===-- WebAssemblyFastISel.cpp - WebAssembly FastISel implementation -----===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric ///
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// This file defines the WebAssembly-specific support for the FastISel
110b57cec5SDimitry Andric /// class. Some of the target-specific code is generated by tablegen in the file
120b57cec5SDimitry Andric /// WebAssemblyGenFastISel.inc, which is #included here.
130b57cec5SDimitry Andric ///
140b57cec5SDimitry Andric /// TODO: kill flags
150b57cec5SDimitry Andric ///
160b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
19*fe6060f1SDimitry Andric #include "Utils/WebAssemblyUtilities.h"
200b57cec5SDimitry Andric #include "WebAssembly.h"
210b57cec5SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
220b57cec5SDimitry Andric #include "WebAssemblySubtarget.h"
230b57cec5SDimitry Andric #include "WebAssemblyTargetMachine.h"
240b57cec5SDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h"
250b57cec5SDimitry Andric #include "llvm/CodeGen/FastISel.h"
260b57cec5SDimitry Andric #include "llvm/CodeGen/FunctionLoweringInfo.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
30e8d8bef9SDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
310b57cec5SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
320b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
330b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
340b57cec5SDimitry Andric #include "llvm/IR/Function.h"
350b57cec5SDimitry Andric #include "llvm/IR/GetElementPtrTypeIterator.h"
360b57cec5SDimitry Andric #include "llvm/IR/GlobalAlias.h"
370b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
380b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
390b57cec5SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
400b57cec5SDimitry Andric #include "llvm/IR/Operator.h"
410b57cec5SDimitry Andric #include "llvm/IR/PatternMatch.h"
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric using namespace llvm;
440b57cec5SDimitry Andric using namespace PatternMatch;
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric #define DEBUG_TYPE "wasm-fastisel"
470b57cec5SDimitry Andric 
480b57cec5SDimitry Andric namespace {
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric class WebAssemblyFastISel final : public FastISel {
510b57cec5SDimitry Andric   // All possible address modes.
520b57cec5SDimitry Andric   class Address {
530b57cec5SDimitry Andric   public:
540b57cec5SDimitry Andric     using BaseKind = enum { RegBase, FrameIndexBase };
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   private:
570b57cec5SDimitry Andric     BaseKind Kind = RegBase;
580b57cec5SDimitry Andric     union {
590b57cec5SDimitry Andric       unsigned Reg;
600b57cec5SDimitry Andric       int FI;
610b57cec5SDimitry Andric     } Base;
620b57cec5SDimitry Andric 
63eaeb601bSDimitry Andric     // Whether the base has been determined yet
64eaeb601bSDimitry Andric     bool IsBaseSet = false;
65eaeb601bSDimitry Andric 
660b57cec5SDimitry Andric     int64_t Offset = 0;
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric     const GlobalValue *GV = nullptr;
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   public:
710b57cec5SDimitry Andric     // Innocuous defaults for our address.
720b57cec5SDimitry Andric     Address() { Base.Reg = 0; }
730b57cec5SDimitry Andric     void setKind(BaseKind K) {
740b57cec5SDimitry Andric       assert(!isSet() && "Can't change kind with non-zero base");
750b57cec5SDimitry Andric       Kind = K;
760b57cec5SDimitry Andric     }
770b57cec5SDimitry Andric     BaseKind getKind() const { return Kind; }
780b57cec5SDimitry Andric     bool isRegBase() const { return Kind == RegBase; }
790b57cec5SDimitry Andric     bool isFIBase() const { return Kind == FrameIndexBase; }
800b57cec5SDimitry Andric     void setReg(unsigned Reg) {
810b57cec5SDimitry Andric       assert(isRegBase() && "Invalid base register access!");
82eaeb601bSDimitry Andric       assert(!IsBaseSet && "Base cannot be reset");
830b57cec5SDimitry Andric       Base.Reg = Reg;
84eaeb601bSDimitry Andric       IsBaseSet = true;
850b57cec5SDimitry Andric     }
860b57cec5SDimitry Andric     unsigned getReg() const {
870b57cec5SDimitry Andric       assert(isRegBase() && "Invalid base register access!");
880b57cec5SDimitry Andric       return Base.Reg;
890b57cec5SDimitry Andric     }
900b57cec5SDimitry Andric     void setFI(unsigned FI) {
910b57cec5SDimitry Andric       assert(isFIBase() && "Invalid base frame index access!");
92eaeb601bSDimitry Andric       assert(!IsBaseSet && "Base cannot be reset");
930b57cec5SDimitry Andric       Base.FI = FI;
94eaeb601bSDimitry Andric       IsBaseSet = true;
950b57cec5SDimitry Andric     }
960b57cec5SDimitry Andric     unsigned getFI() const {
970b57cec5SDimitry Andric       assert(isFIBase() && "Invalid base frame index access!");
980b57cec5SDimitry Andric       return Base.FI;
990b57cec5SDimitry Andric     }
1000b57cec5SDimitry Andric 
1010b57cec5SDimitry Andric     void setOffset(int64_t NewOffset) {
1020b57cec5SDimitry Andric       assert(NewOffset >= 0 && "Offsets must be non-negative");
1030b57cec5SDimitry Andric       Offset = NewOffset;
1040b57cec5SDimitry Andric     }
1050b57cec5SDimitry Andric     int64_t getOffset() const { return Offset; }
1060b57cec5SDimitry Andric     void setGlobalValue(const GlobalValue *G) { GV = G; }
1070b57cec5SDimitry Andric     const GlobalValue *getGlobalValue() const { return GV; }
108eaeb601bSDimitry Andric     bool isSet() const { return IsBaseSet; }
1090b57cec5SDimitry Andric   };
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
1120b57cec5SDimitry Andric   /// right decision when generating code for different targets.
1130b57cec5SDimitry Andric   const WebAssemblySubtarget *Subtarget;
1140b57cec5SDimitry Andric   LLVMContext *Context;
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric private:
1170b57cec5SDimitry Andric   // Utility helper routines
1180b57cec5SDimitry Andric   MVT::SimpleValueType getSimpleType(Type *Ty) {
1190b57cec5SDimitry Andric     EVT VT = TLI.getValueType(DL, Ty, /*AllowUnknown=*/true);
1200b57cec5SDimitry Andric     return VT.isSimple() ? VT.getSimpleVT().SimpleTy
1210b57cec5SDimitry Andric                          : MVT::INVALID_SIMPLE_VALUE_TYPE;
1220b57cec5SDimitry Andric   }
1230b57cec5SDimitry Andric   MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
1240b57cec5SDimitry Andric     switch (VT) {
1250b57cec5SDimitry Andric     case MVT::i1:
1260b57cec5SDimitry Andric     case MVT::i8:
1270b57cec5SDimitry Andric     case MVT::i16:
1280b57cec5SDimitry Andric       return MVT::i32;
1290b57cec5SDimitry Andric     case MVT::i32:
1300b57cec5SDimitry Andric     case MVT::i64:
1310b57cec5SDimitry Andric     case MVT::f32:
1320b57cec5SDimitry Andric     case MVT::f64:
133*fe6060f1SDimitry Andric       return VT;
134e8d8bef9SDimitry Andric     case MVT::funcref:
135e8d8bef9SDimitry Andric     case MVT::externref:
136*fe6060f1SDimitry Andric       if (Subtarget->hasReferenceTypes())
1370b57cec5SDimitry Andric         return VT;
138*fe6060f1SDimitry Andric       break;
1390b57cec5SDimitry Andric     case MVT::f16:
1400b57cec5SDimitry Andric       return MVT::f32;
1410b57cec5SDimitry Andric     case MVT::v16i8:
1420b57cec5SDimitry Andric     case MVT::v8i16:
1430b57cec5SDimitry Andric     case MVT::v4i32:
1440b57cec5SDimitry Andric     case MVT::v4f32:
1450b57cec5SDimitry Andric     case MVT::v2i64:
1460b57cec5SDimitry Andric     case MVT::v2f64:
147*fe6060f1SDimitry Andric       if (Subtarget->hasSIMD128())
1480b57cec5SDimitry Andric         return VT;
1490b57cec5SDimitry Andric       break;
1500b57cec5SDimitry Andric     default:
1510b57cec5SDimitry Andric       break;
1520b57cec5SDimitry Andric     }
1530b57cec5SDimitry Andric     return MVT::INVALID_SIMPLE_VALUE_TYPE;
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric   bool computeAddress(const Value *Obj, Address &Addr);
1560b57cec5SDimitry Andric   void materializeLoadStoreOperands(Address &Addr);
1570b57cec5SDimitry Andric   void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
1580b57cec5SDimitry Andric                             MachineMemOperand *MMO);
1590b57cec5SDimitry Andric   unsigned maskI1Value(unsigned Reg, const Value *V);
1600b57cec5SDimitry Andric   unsigned getRegForI1Value(const Value *V, bool &Not);
1610b57cec5SDimitry Andric   unsigned zeroExtendToI32(unsigned Reg, const Value *V,
1620b57cec5SDimitry Andric                            MVT::SimpleValueType From);
1630b57cec5SDimitry Andric   unsigned signExtendToI32(unsigned Reg, const Value *V,
1640b57cec5SDimitry Andric                            MVT::SimpleValueType From);
1650b57cec5SDimitry Andric   unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
1660b57cec5SDimitry Andric                       MVT::SimpleValueType To);
1670b57cec5SDimitry Andric   unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
1680b57cec5SDimitry Andric                       MVT::SimpleValueType To);
1690b57cec5SDimitry Andric   unsigned getRegForUnsignedValue(const Value *V);
1700b57cec5SDimitry Andric   unsigned getRegForSignedValue(const Value *V);
1710b57cec5SDimitry Andric   unsigned getRegForPromotedValue(const Value *V, bool IsSigned);
1720b57cec5SDimitry Andric   unsigned notValue(unsigned Reg);
1730b57cec5SDimitry Andric   unsigned copyValue(unsigned Reg);
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   // Backend specific FastISel code.
1760b57cec5SDimitry Andric   unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
1770b57cec5SDimitry Andric   unsigned fastMaterializeConstant(const Constant *C) override;
1780b57cec5SDimitry Andric   bool fastLowerArguments() override;
1790b57cec5SDimitry Andric 
1800b57cec5SDimitry Andric   // Selection routines.
1810b57cec5SDimitry Andric   bool selectCall(const Instruction *I);
1820b57cec5SDimitry Andric   bool selectSelect(const Instruction *I);
1830b57cec5SDimitry Andric   bool selectTrunc(const Instruction *I);
1840b57cec5SDimitry Andric   bool selectZExt(const Instruction *I);
1850b57cec5SDimitry Andric   bool selectSExt(const Instruction *I);
1860b57cec5SDimitry Andric   bool selectICmp(const Instruction *I);
1870b57cec5SDimitry Andric   bool selectFCmp(const Instruction *I);
1880b57cec5SDimitry Andric   bool selectBitCast(const Instruction *I);
1890b57cec5SDimitry Andric   bool selectLoad(const Instruction *I);
1900b57cec5SDimitry Andric   bool selectStore(const Instruction *I);
1910b57cec5SDimitry Andric   bool selectBr(const Instruction *I);
1920b57cec5SDimitry Andric   bool selectRet(const Instruction *I);
1930b57cec5SDimitry Andric   bool selectUnreachable(const Instruction *I);
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric public:
1960b57cec5SDimitry Andric   // Backend specific FastISel code.
1970b57cec5SDimitry Andric   WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo,
1980b57cec5SDimitry Andric                       const TargetLibraryInfo *LibInfo)
1990b57cec5SDimitry Andric       : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
2000b57cec5SDimitry Andric     Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>();
2010b57cec5SDimitry Andric     Context = &FuncInfo.Fn->getContext();
2020b57cec5SDimitry Andric   }
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric   bool fastSelectInstruction(const Instruction *I) override;
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric #include "WebAssemblyGenFastISel.inc"
2070b57cec5SDimitry Andric };
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric } // end anonymous namespace
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {
2120b57cec5SDimitry Andric   const User *U = nullptr;
2130b57cec5SDimitry Andric   unsigned Opcode = Instruction::UserOp1;
2140b57cec5SDimitry Andric   if (const auto *I = dyn_cast<Instruction>(Obj)) {
2150b57cec5SDimitry Andric     // Don't walk into other basic blocks unless the object is an alloca from
2160b57cec5SDimitry Andric     // another block, otherwise it may not have a virtual register assigned.
2170b57cec5SDimitry Andric     if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
2180b57cec5SDimitry Andric         FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
2190b57cec5SDimitry Andric       Opcode = I->getOpcode();
2200b57cec5SDimitry Andric       U = I;
2210b57cec5SDimitry Andric     }
2220b57cec5SDimitry Andric   } else if (const auto *C = dyn_cast<ConstantExpr>(Obj)) {
2230b57cec5SDimitry Andric     Opcode = C->getOpcode();
2240b57cec5SDimitry Andric     U = C;
2250b57cec5SDimitry Andric   }
2260b57cec5SDimitry Andric 
2270b57cec5SDimitry Andric   if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
2280b57cec5SDimitry Andric     if (Ty->getAddressSpace() > 255)
2290b57cec5SDimitry Andric       // Fast instruction selection doesn't support the special
2300b57cec5SDimitry Andric       // address spaces.
2310b57cec5SDimitry Andric       return false;
2320b57cec5SDimitry Andric 
2330b57cec5SDimitry Andric   if (const auto *GV = dyn_cast<GlobalValue>(Obj)) {
2340b57cec5SDimitry Andric     if (TLI.isPositionIndependent())
2350b57cec5SDimitry Andric       return false;
2360b57cec5SDimitry Andric     if (Addr.getGlobalValue())
2370b57cec5SDimitry Andric       return false;
2380b57cec5SDimitry Andric     if (GV->isThreadLocal())
2390b57cec5SDimitry Andric       return false;
2400b57cec5SDimitry Andric     Addr.setGlobalValue(GV);
2410b57cec5SDimitry Andric     return true;
2420b57cec5SDimitry Andric   }
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   switch (Opcode) {
2450b57cec5SDimitry Andric   default:
2460b57cec5SDimitry Andric     break;
2470b57cec5SDimitry Andric   case Instruction::BitCast: {
2480b57cec5SDimitry Andric     // Look through bitcasts.
2490b57cec5SDimitry Andric     return computeAddress(U->getOperand(0), Addr);
2500b57cec5SDimitry Andric   }
2510b57cec5SDimitry Andric   case Instruction::IntToPtr: {
2520b57cec5SDimitry Andric     // Look past no-op inttoptrs.
2530b57cec5SDimitry Andric     if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
2540b57cec5SDimitry Andric         TLI.getPointerTy(DL))
2550b57cec5SDimitry Andric       return computeAddress(U->getOperand(0), Addr);
2560b57cec5SDimitry Andric     break;
2570b57cec5SDimitry Andric   }
2580b57cec5SDimitry Andric   case Instruction::PtrToInt: {
2590b57cec5SDimitry Andric     // Look past no-op ptrtoints.
2600b57cec5SDimitry Andric     if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
2610b57cec5SDimitry Andric       return computeAddress(U->getOperand(0), Addr);
2620b57cec5SDimitry Andric     break;
2630b57cec5SDimitry Andric   }
2640b57cec5SDimitry Andric   case Instruction::GetElementPtr: {
2650b57cec5SDimitry Andric     Address SavedAddr = Addr;
2660b57cec5SDimitry Andric     uint64_t TmpOffset = Addr.getOffset();
2670b57cec5SDimitry Andric     // Non-inbounds geps can wrap; wasm's offsets can't.
2680b57cec5SDimitry Andric     if (!cast<GEPOperator>(U)->isInBounds())
2690b57cec5SDimitry Andric       goto unsupported_gep;
2700b57cec5SDimitry Andric     // Iterate through the GEP folding the constants into offsets where
2710b57cec5SDimitry Andric     // we can.
2720b57cec5SDimitry Andric     for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
2730b57cec5SDimitry Andric          GTI != E; ++GTI) {
2740b57cec5SDimitry Andric       const Value *Op = GTI.getOperand();
2750b57cec5SDimitry Andric       if (StructType *STy = GTI.getStructTypeOrNull()) {
2760b57cec5SDimitry Andric         const StructLayout *SL = DL.getStructLayout(STy);
2770b57cec5SDimitry Andric         unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
2780b57cec5SDimitry Andric         TmpOffset += SL->getElementOffset(Idx);
2790b57cec5SDimitry Andric       } else {
2800b57cec5SDimitry Andric         uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
2810b57cec5SDimitry Andric         for (;;) {
2820b57cec5SDimitry Andric           if (const auto *CI = dyn_cast<ConstantInt>(Op)) {
2830b57cec5SDimitry Andric             // Constant-offset addressing.
2840b57cec5SDimitry Andric             TmpOffset += CI->getSExtValue() * S;
2850b57cec5SDimitry Andric             break;
2860b57cec5SDimitry Andric           }
2870b57cec5SDimitry Andric           if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
2880b57cec5SDimitry Andric             // An unscaled add of a register. Set it as the new base.
2890b57cec5SDimitry Andric             unsigned Reg = getRegForValue(Op);
2900b57cec5SDimitry Andric             if (Reg == 0)
2910b57cec5SDimitry Andric               return false;
2920b57cec5SDimitry Andric             Addr.setReg(Reg);
2930b57cec5SDimitry Andric             break;
2940b57cec5SDimitry Andric           }
2950b57cec5SDimitry Andric           if (canFoldAddIntoGEP(U, Op)) {
2960b57cec5SDimitry Andric             // A compatible add with a constant operand. Fold the constant.
2970b57cec5SDimitry Andric             auto *CI = cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
2980b57cec5SDimitry Andric             TmpOffset += CI->getSExtValue() * S;
2990b57cec5SDimitry Andric             // Iterate on the other operand.
3000b57cec5SDimitry Andric             Op = cast<AddOperator>(Op)->getOperand(0);
3010b57cec5SDimitry Andric             continue;
3020b57cec5SDimitry Andric           }
3030b57cec5SDimitry Andric           // Unsupported
3040b57cec5SDimitry Andric           goto unsupported_gep;
3050b57cec5SDimitry Andric         }
3060b57cec5SDimitry Andric       }
3070b57cec5SDimitry Andric     }
3080b57cec5SDimitry Andric     // Don't fold in negative offsets.
3090b57cec5SDimitry Andric     if (int64_t(TmpOffset) >= 0) {
3100b57cec5SDimitry Andric       // Try to grab the base operand now.
3110b57cec5SDimitry Andric       Addr.setOffset(TmpOffset);
3120b57cec5SDimitry Andric       if (computeAddress(U->getOperand(0), Addr))
3130b57cec5SDimitry Andric         return true;
3140b57cec5SDimitry Andric     }
3150b57cec5SDimitry Andric     // We failed, restore everything and try the other options.
3160b57cec5SDimitry Andric     Addr = SavedAddr;
3170b57cec5SDimitry Andric   unsupported_gep:
3180b57cec5SDimitry Andric     break;
3190b57cec5SDimitry Andric   }
3200b57cec5SDimitry Andric   case Instruction::Alloca: {
3210b57cec5SDimitry Andric     const auto *AI = cast<AllocaInst>(Obj);
3220b57cec5SDimitry Andric     DenseMap<const AllocaInst *, int>::iterator SI =
3230b57cec5SDimitry Andric         FuncInfo.StaticAllocaMap.find(AI);
3240b57cec5SDimitry Andric     if (SI != FuncInfo.StaticAllocaMap.end()) {
3250b57cec5SDimitry Andric       if (Addr.isSet()) {
3260b57cec5SDimitry Andric         return false;
3270b57cec5SDimitry Andric       }
3280b57cec5SDimitry Andric       Addr.setKind(Address::FrameIndexBase);
3290b57cec5SDimitry Andric       Addr.setFI(SI->second);
3300b57cec5SDimitry Andric       return true;
3310b57cec5SDimitry Andric     }
3320b57cec5SDimitry Andric     break;
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric   case Instruction::Add: {
3350b57cec5SDimitry Andric     // Adds of constants are common and easy enough.
3360b57cec5SDimitry Andric     const Value *LHS = U->getOperand(0);
3370b57cec5SDimitry Andric     const Value *RHS = U->getOperand(1);
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric     if (isa<ConstantInt>(LHS))
3400b57cec5SDimitry Andric       std::swap(LHS, RHS);
3410b57cec5SDimitry Andric 
3420b57cec5SDimitry Andric     if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
3430b57cec5SDimitry Andric       uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
3440b57cec5SDimitry Andric       if (int64_t(TmpOffset) >= 0) {
3450b57cec5SDimitry Andric         Addr.setOffset(TmpOffset);
3460b57cec5SDimitry Andric         return computeAddress(LHS, Addr);
3470b57cec5SDimitry Andric       }
3480b57cec5SDimitry Andric     }
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric     Address Backup = Addr;
3510b57cec5SDimitry Andric     if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
3520b57cec5SDimitry Andric       return true;
3530b57cec5SDimitry Andric     Addr = Backup;
3540b57cec5SDimitry Andric 
3550b57cec5SDimitry Andric     break;
3560b57cec5SDimitry Andric   }
3570b57cec5SDimitry Andric   case Instruction::Sub: {
3580b57cec5SDimitry Andric     // Subs of constants are common and easy enough.
3590b57cec5SDimitry Andric     const Value *LHS = U->getOperand(0);
3600b57cec5SDimitry Andric     const Value *RHS = U->getOperand(1);
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric     if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
3630b57cec5SDimitry Andric       int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
3640b57cec5SDimitry Andric       if (TmpOffset >= 0) {
3650b57cec5SDimitry Andric         Addr.setOffset(TmpOffset);
3660b57cec5SDimitry Andric         return computeAddress(LHS, Addr);
3670b57cec5SDimitry Andric       }
3680b57cec5SDimitry Andric     }
3690b57cec5SDimitry Andric     break;
3700b57cec5SDimitry Andric   }
3710b57cec5SDimitry Andric   }
3720b57cec5SDimitry Andric   if (Addr.isSet()) {
3730b57cec5SDimitry Andric     return false;
3740b57cec5SDimitry Andric   }
3750b57cec5SDimitry Andric   unsigned Reg = getRegForValue(Obj);
3760b57cec5SDimitry Andric   if (Reg == 0)
3770b57cec5SDimitry Andric     return false;
3780b57cec5SDimitry Andric   Addr.setReg(Reg);
3790b57cec5SDimitry Andric   return Addr.getReg() != 0;
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
3830b57cec5SDimitry Andric   if (Addr.isRegBase()) {
3840b57cec5SDimitry Andric     unsigned Reg = Addr.getReg();
3850b57cec5SDimitry Andric     if (Reg == 0) {
3860b57cec5SDimitry Andric       Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
3870b57cec5SDimitry Andric                                                    : &WebAssembly::I32RegClass);
3880b57cec5SDimitry Andric       unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
3890b57cec5SDimitry Andric                                             : WebAssembly::CONST_I32;
3900b57cec5SDimitry Andric       BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
3910b57cec5SDimitry Andric           .addImm(0);
3920b57cec5SDimitry Andric       Addr.setReg(Reg);
3930b57cec5SDimitry Andric     }
3940b57cec5SDimitry Andric   }
3950b57cec5SDimitry Andric }
3960b57cec5SDimitry Andric 
3970b57cec5SDimitry Andric void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
3980b57cec5SDimitry Andric                                                const MachineInstrBuilder &MIB,
3990b57cec5SDimitry Andric                                                MachineMemOperand *MMO) {
4000b57cec5SDimitry Andric   // Set the alignment operand (this is rewritten in SetP2AlignOperands).
4010b57cec5SDimitry Andric   // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
4020b57cec5SDimitry Andric   MIB.addImm(0);
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric   if (const GlobalValue *GV = Addr.getGlobalValue())
4050b57cec5SDimitry Andric     MIB.addGlobalAddress(GV, Addr.getOffset());
4060b57cec5SDimitry Andric   else
4070b57cec5SDimitry Andric     MIB.addImm(Addr.getOffset());
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric   if (Addr.isRegBase())
4100b57cec5SDimitry Andric     MIB.addReg(Addr.getReg());
4110b57cec5SDimitry Andric   else
4120b57cec5SDimitry Andric     MIB.addFrameIndex(Addr.getFI());
4130b57cec5SDimitry Andric 
4140b57cec5SDimitry Andric   MIB.addMemOperand(MMO);
4150b57cec5SDimitry Andric }
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
4180b57cec5SDimitry Andric   return zeroExtendToI32(Reg, V, MVT::i1);
4190b57cec5SDimitry Andric }
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
4220b57cec5SDimitry Andric   if (const auto *ICmp = dyn_cast<ICmpInst>(V))
4230b57cec5SDimitry Andric     if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
4240b57cec5SDimitry Andric       if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
4250b57cec5SDimitry Andric         Not = ICmp->isTrueWhenEqual();
4260b57cec5SDimitry Andric         return getRegForValue(ICmp->getOperand(0));
4270b57cec5SDimitry Andric       }
4280b57cec5SDimitry Andric 
4290b57cec5SDimitry Andric   Value *NotV;
4300b57cec5SDimitry Andric   if (match(V, m_Not(m_Value(NotV))) && V->getType()->isIntegerTy(32)) {
4310b57cec5SDimitry Andric     Not = true;
4320b57cec5SDimitry Andric     return getRegForValue(NotV);
4330b57cec5SDimitry Andric   }
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   Not = false;
4360b57cec5SDimitry Andric   unsigned Reg = getRegForValue(V);
4370b57cec5SDimitry Andric   if (Reg == 0)
4380b57cec5SDimitry Andric     return 0;
4390b57cec5SDimitry Andric   return maskI1Value(Reg, V);
4400b57cec5SDimitry Andric }
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
4430b57cec5SDimitry Andric                                               MVT::SimpleValueType From) {
4440b57cec5SDimitry Andric   if (Reg == 0)
4450b57cec5SDimitry Andric     return 0;
4460b57cec5SDimitry Andric 
4470b57cec5SDimitry Andric   switch (From) {
4480b57cec5SDimitry Andric   case MVT::i1:
4490b57cec5SDimitry Andric     // If the value is naturally an i1, we don't need to mask it. We only know
4500b57cec5SDimitry Andric     // if a value is naturally an i1 if it is definitely lowered by FastISel,
4510b57cec5SDimitry Andric     // not a DAG ISel fallback.
4520b57cec5SDimitry Andric     if (V != nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr())
4530b57cec5SDimitry Andric       return copyValue(Reg);
4540b57cec5SDimitry Andric     break;
4550b57cec5SDimitry Andric   case MVT::i8:
4560b57cec5SDimitry Andric   case MVT::i16:
4570b57cec5SDimitry Andric     break;
4580b57cec5SDimitry Andric   case MVT::i32:
4590b57cec5SDimitry Andric     return copyValue(Reg);
4600b57cec5SDimitry Andric   default:
4610b57cec5SDimitry Andric     return 0;
4620b57cec5SDimitry Andric   }
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric   unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
4650b57cec5SDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4660b57cec5SDimitry Andric           TII.get(WebAssembly::CONST_I32), Imm)
4670b57cec5SDimitry Andric       .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
4680b57cec5SDimitry Andric 
4690b57cec5SDimitry Andric   unsigned Result = createResultReg(&WebAssembly::I32RegClass);
4700b57cec5SDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4710b57cec5SDimitry Andric           TII.get(WebAssembly::AND_I32), Result)
4720b57cec5SDimitry Andric       .addReg(Reg)
4730b57cec5SDimitry Andric       .addReg(Imm);
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric   return Result;
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
4790b57cec5SDimitry Andric                                               MVT::SimpleValueType From) {
4800b57cec5SDimitry Andric   if (Reg == 0)
4810b57cec5SDimitry Andric     return 0;
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   switch (From) {
4840b57cec5SDimitry Andric   case MVT::i1:
4850b57cec5SDimitry Andric   case MVT::i8:
4860b57cec5SDimitry Andric   case MVT::i16:
4870b57cec5SDimitry Andric     break;
4880b57cec5SDimitry Andric   case MVT::i32:
4890b57cec5SDimitry Andric     return copyValue(Reg);
4900b57cec5SDimitry Andric   default:
4910b57cec5SDimitry Andric     return 0;
4920b57cec5SDimitry Andric   }
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric   unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
4950b57cec5SDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4960b57cec5SDimitry Andric           TII.get(WebAssembly::CONST_I32), Imm)
4970b57cec5SDimitry Andric       .addImm(32 - MVT(From).getSizeInBits());
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric   unsigned Left = createResultReg(&WebAssembly::I32RegClass);
5000b57cec5SDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
5010b57cec5SDimitry Andric           TII.get(WebAssembly::SHL_I32), Left)
5020b57cec5SDimitry Andric       .addReg(Reg)
5030b57cec5SDimitry Andric       .addReg(Imm);
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric   unsigned Right = createResultReg(&WebAssembly::I32RegClass);
5060b57cec5SDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
5070b57cec5SDimitry Andric           TII.get(WebAssembly::SHR_S_I32), Right)
5080b57cec5SDimitry Andric       .addReg(Left)
5090b57cec5SDimitry Andric       .addReg(Imm);
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric   return Right;
5120b57cec5SDimitry Andric }
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
5150b57cec5SDimitry Andric                                          MVT::SimpleValueType From,
5160b57cec5SDimitry Andric                                          MVT::SimpleValueType To) {
5170b57cec5SDimitry Andric   if (To == MVT::i64) {
5180b57cec5SDimitry Andric     if (From == MVT::i64)
5190b57cec5SDimitry Andric       return copyValue(Reg);
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric     Reg = zeroExtendToI32(Reg, V, From);
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric     unsigned Result = createResultReg(&WebAssembly::I64RegClass);
5240b57cec5SDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
5250b57cec5SDimitry Andric             TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
5260b57cec5SDimitry Andric         .addReg(Reg);
5270b57cec5SDimitry Andric     return Result;
5280b57cec5SDimitry Andric   }
5290b57cec5SDimitry Andric 
5300b57cec5SDimitry Andric   if (To == MVT::i32)
5310b57cec5SDimitry Andric     return zeroExtendToI32(Reg, V, From);
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric   return 0;
5340b57cec5SDimitry Andric }
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
5370b57cec5SDimitry Andric                                          MVT::SimpleValueType From,
5380b57cec5SDimitry Andric                                          MVT::SimpleValueType To) {
5390b57cec5SDimitry Andric   if (To == MVT::i64) {
5400b57cec5SDimitry Andric     if (From == MVT::i64)
5410b57cec5SDimitry Andric       return copyValue(Reg);
5420b57cec5SDimitry Andric 
5430b57cec5SDimitry Andric     Reg = signExtendToI32(Reg, V, From);
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric     unsigned Result = createResultReg(&WebAssembly::I64RegClass);
5460b57cec5SDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
5470b57cec5SDimitry Andric             TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
5480b57cec5SDimitry Andric         .addReg(Reg);
5490b57cec5SDimitry Andric     return Result;
5500b57cec5SDimitry Andric   }
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   if (To == MVT::i32)
5530b57cec5SDimitry Andric     return signExtendToI32(Reg, V, From);
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric   return 0;
5560b57cec5SDimitry Andric }
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
5590b57cec5SDimitry Andric   MVT::SimpleValueType From = getSimpleType(V->getType());
5600b57cec5SDimitry Andric   MVT::SimpleValueType To = getLegalType(From);
5610b57cec5SDimitry Andric   unsigned VReg = getRegForValue(V);
5620b57cec5SDimitry Andric   if (VReg == 0)
5630b57cec5SDimitry Andric     return 0;
5640b57cec5SDimitry Andric   return zeroExtend(VReg, V, From, To);
5650b57cec5SDimitry Andric }
5660b57cec5SDimitry Andric 
5670b57cec5SDimitry Andric unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
5680b57cec5SDimitry Andric   MVT::SimpleValueType From = getSimpleType(V->getType());
5690b57cec5SDimitry Andric   MVT::SimpleValueType To = getLegalType(From);
5700b57cec5SDimitry Andric   unsigned VReg = getRegForValue(V);
5710b57cec5SDimitry Andric   if (VReg == 0)
5720b57cec5SDimitry Andric     return 0;
5730b57cec5SDimitry Andric   return signExtend(VReg, V, From, To);
5740b57cec5SDimitry Andric }
5750b57cec5SDimitry Andric 
5760b57cec5SDimitry Andric unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
5770b57cec5SDimitry Andric                                                      bool IsSigned) {
5780b57cec5SDimitry Andric   return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
5790b57cec5SDimitry Andric }
5800b57cec5SDimitry Andric 
5810b57cec5SDimitry Andric unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
5820b57cec5SDimitry Andric   assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric   unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
5850b57cec5SDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
5860b57cec5SDimitry Andric           TII.get(WebAssembly::EQZ_I32), NotReg)
5870b57cec5SDimitry Andric       .addReg(Reg);
5880b57cec5SDimitry Andric   return NotReg;
5890b57cec5SDimitry Andric }
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
5920b57cec5SDimitry Andric   unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
5930b57cec5SDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
5940b57cec5SDimitry Andric           ResultReg)
5950b57cec5SDimitry Andric       .addReg(Reg);
5960b57cec5SDimitry Andric   return ResultReg;
5970b57cec5SDimitry Andric }
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
6000b57cec5SDimitry Andric   DenseMap<const AllocaInst *, int>::iterator SI =
6010b57cec5SDimitry Andric       FuncInfo.StaticAllocaMap.find(AI);
6020b57cec5SDimitry Andric 
6030b57cec5SDimitry Andric   if (SI != FuncInfo.StaticAllocaMap.end()) {
6040b57cec5SDimitry Andric     unsigned ResultReg =
6050b57cec5SDimitry Andric         createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
6060b57cec5SDimitry Andric                                                : &WebAssembly::I32RegClass);
6070b57cec5SDimitry Andric     unsigned Opc =
6080b57cec5SDimitry Andric         Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
6090b57cec5SDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
6100b57cec5SDimitry Andric         .addFrameIndex(SI->second);
6110b57cec5SDimitry Andric     return ResultReg;
6120b57cec5SDimitry Andric   }
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   return 0;
6150b57cec5SDimitry Andric }
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
6180b57cec5SDimitry Andric   if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
6190b57cec5SDimitry Andric     if (TLI.isPositionIndependent())
6200b57cec5SDimitry Andric       return 0;
6210b57cec5SDimitry Andric     if (GV->isThreadLocal())
6220b57cec5SDimitry Andric       return 0;
6230b57cec5SDimitry Andric     unsigned ResultReg =
6240b57cec5SDimitry Andric         createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
6250b57cec5SDimitry Andric                                                : &WebAssembly::I32RegClass);
6260b57cec5SDimitry Andric     unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
6270b57cec5SDimitry Andric                                           : WebAssembly::CONST_I32;
6280b57cec5SDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
6290b57cec5SDimitry Andric         .addGlobalAddress(GV);
6300b57cec5SDimitry Andric     return ResultReg;
6310b57cec5SDimitry Andric   }
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric   // Let target-independent code handle it.
6340b57cec5SDimitry Andric   return 0;
6350b57cec5SDimitry Andric }
6360b57cec5SDimitry Andric 
6370b57cec5SDimitry Andric bool WebAssemblyFastISel::fastLowerArguments() {
6380b57cec5SDimitry Andric   if (!FuncInfo.CanLowerReturn)
6390b57cec5SDimitry Andric     return false;
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric   const Function *F = FuncInfo.Fn;
6420b57cec5SDimitry Andric   if (F->isVarArg())
6430b57cec5SDimitry Andric     return false;
6440b57cec5SDimitry Andric 
6455ffd83dbSDimitry Andric   if (FuncInfo.Fn->getCallingConv() == CallingConv::Swift)
6465ffd83dbSDimitry Andric     return false;
6475ffd83dbSDimitry Andric 
6480b57cec5SDimitry Andric   unsigned I = 0;
6490b57cec5SDimitry Andric   for (auto const &Arg : F->args()) {
6500b57cec5SDimitry Andric     const AttributeList &Attrs = F->getAttributes();
6510b57cec5SDimitry Andric     if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
6520b57cec5SDimitry Andric         Attrs.hasParamAttribute(I, Attribute::SwiftSelf) ||
6530b57cec5SDimitry Andric         Attrs.hasParamAttribute(I, Attribute::SwiftError) ||
6540b57cec5SDimitry Andric         Attrs.hasParamAttribute(I, Attribute::InAlloca) ||
6550b57cec5SDimitry Andric         Attrs.hasParamAttribute(I, Attribute::Nest))
6560b57cec5SDimitry Andric       return false;
6570b57cec5SDimitry Andric 
6580b57cec5SDimitry Andric     Type *ArgTy = Arg.getType();
6590b57cec5SDimitry Andric     if (ArgTy->isStructTy() || ArgTy->isArrayTy())
6600b57cec5SDimitry Andric       return false;
6610b57cec5SDimitry Andric     if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
6620b57cec5SDimitry Andric       return false;
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric     unsigned Opc;
6650b57cec5SDimitry Andric     const TargetRegisterClass *RC;
6660b57cec5SDimitry Andric     switch (getSimpleType(ArgTy)) {
6670b57cec5SDimitry Andric     case MVT::i1:
6680b57cec5SDimitry Andric     case MVT::i8:
6690b57cec5SDimitry Andric     case MVT::i16:
6700b57cec5SDimitry Andric     case MVT::i32:
6710b57cec5SDimitry Andric       Opc = WebAssembly::ARGUMENT_i32;
6720b57cec5SDimitry Andric       RC = &WebAssembly::I32RegClass;
6730b57cec5SDimitry Andric       break;
6740b57cec5SDimitry Andric     case MVT::i64:
6750b57cec5SDimitry Andric       Opc = WebAssembly::ARGUMENT_i64;
6760b57cec5SDimitry Andric       RC = &WebAssembly::I64RegClass;
6770b57cec5SDimitry Andric       break;
6780b57cec5SDimitry Andric     case MVT::f32:
6790b57cec5SDimitry Andric       Opc = WebAssembly::ARGUMENT_f32;
6800b57cec5SDimitry Andric       RC = &WebAssembly::F32RegClass;
6810b57cec5SDimitry Andric       break;
6820b57cec5SDimitry Andric     case MVT::f64:
6830b57cec5SDimitry Andric       Opc = WebAssembly::ARGUMENT_f64;
6840b57cec5SDimitry Andric       RC = &WebAssembly::F64RegClass;
6850b57cec5SDimitry Andric       break;
6860b57cec5SDimitry Andric     case MVT::v16i8:
6870b57cec5SDimitry Andric       Opc = WebAssembly::ARGUMENT_v16i8;
6880b57cec5SDimitry Andric       RC = &WebAssembly::V128RegClass;
6890b57cec5SDimitry Andric       break;
6900b57cec5SDimitry Andric     case MVT::v8i16:
6910b57cec5SDimitry Andric       Opc = WebAssembly::ARGUMENT_v8i16;
6920b57cec5SDimitry Andric       RC = &WebAssembly::V128RegClass;
6930b57cec5SDimitry Andric       break;
6940b57cec5SDimitry Andric     case MVT::v4i32:
6950b57cec5SDimitry Andric       Opc = WebAssembly::ARGUMENT_v4i32;
6960b57cec5SDimitry Andric       RC = &WebAssembly::V128RegClass;
6970b57cec5SDimitry Andric       break;
6980b57cec5SDimitry Andric     case MVT::v2i64:
6990b57cec5SDimitry Andric       Opc = WebAssembly::ARGUMENT_v2i64;
7000b57cec5SDimitry Andric       RC = &WebAssembly::V128RegClass;
7010b57cec5SDimitry Andric       break;
7020b57cec5SDimitry Andric     case MVT::v4f32:
7030b57cec5SDimitry Andric       Opc = WebAssembly::ARGUMENT_v4f32;
7040b57cec5SDimitry Andric       RC = &WebAssembly::V128RegClass;
7050b57cec5SDimitry Andric       break;
7060b57cec5SDimitry Andric     case MVT::v2f64:
7070b57cec5SDimitry Andric       Opc = WebAssembly::ARGUMENT_v2f64;
7080b57cec5SDimitry Andric       RC = &WebAssembly::V128RegClass;
7090b57cec5SDimitry Andric       break;
710e8d8bef9SDimitry Andric     case MVT::funcref:
711e8d8bef9SDimitry Andric       Opc = WebAssembly::ARGUMENT_funcref;
712e8d8bef9SDimitry Andric       RC = &WebAssembly::FUNCREFRegClass;
713e8d8bef9SDimitry Andric       break;
714e8d8bef9SDimitry Andric     case MVT::externref:
715e8d8bef9SDimitry Andric       Opc = WebAssembly::ARGUMENT_externref;
716e8d8bef9SDimitry Andric       RC = &WebAssembly::EXTERNREFRegClass;
7170b57cec5SDimitry Andric       break;
7180b57cec5SDimitry Andric     default:
7190b57cec5SDimitry Andric       return false;
7200b57cec5SDimitry Andric     }
7210b57cec5SDimitry Andric     unsigned ResultReg = createResultReg(RC);
7220b57cec5SDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
7230b57cec5SDimitry Andric         .addImm(I);
7240b57cec5SDimitry Andric     updateValueMap(&Arg, ResultReg);
7250b57cec5SDimitry Andric 
7260b57cec5SDimitry Andric     ++I;
7270b57cec5SDimitry Andric   }
7280b57cec5SDimitry Andric 
7290b57cec5SDimitry Andric   MRI.addLiveIn(WebAssembly::ARGUMENTS);
7300b57cec5SDimitry Andric 
7310b57cec5SDimitry Andric   auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
7320b57cec5SDimitry Andric   for (auto const &Arg : F->args()) {
7330b57cec5SDimitry Andric     MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType()));
7340b57cec5SDimitry Andric     if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
7350b57cec5SDimitry Andric       MFI->clearParamsAndResults();
7360b57cec5SDimitry Andric       return false;
7370b57cec5SDimitry Andric     }
7380b57cec5SDimitry Andric     MFI->addParam(ArgTy);
7390b57cec5SDimitry Andric   }
7400b57cec5SDimitry Andric 
7410b57cec5SDimitry Andric   if (!F->getReturnType()->isVoidTy()) {
7420b57cec5SDimitry Andric     MVT::SimpleValueType RetTy =
7430b57cec5SDimitry Andric         getLegalType(getSimpleType(F->getReturnType()));
7440b57cec5SDimitry Andric     if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
7450b57cec5SDimitry Andric       MFI->clearParamsAndResults();
7460b57cec5SDimitry Andric       return false;
7470b57cec5SDimitry Andric     }
7480b57cec5SDimitry Andric     MFI->addResult(RetTy);
7490b57cec5SDimitry Andric   }
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric   return true;
7520b57cec5SDimitry Andric }
7530b57cec5SDimitry Andric 
7540b57cec5SDimitry Andric bool WebAssemblyFastISel::selectCall(const Instruction *I) {
7550b57cec5SDimitry Andric   const auto *Call = cast<CallInst>(I);
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric   // TODO: Support tail calls in FastISel
7580b57cec5SDimitry Andric   if (Call->isMustTailCall() || Call->isInlineAsm() ||
7590b57cec5SDimitry Andric       Call->getFunctionType()->isVarArg())
7600b57cec5SDimitry Andric     return false;
7610b57cec5SDimitry Andric 
7620b57cec5SDimitry Andric   Function *Func = Call->getCalledFunction();
7630b57cec5SDimitry Andric   if (Func && Func->isIntrinsic())
7640b57cec5SDimitry Andric     return false;
7650b57cec5SDimitry Andric 
7665ffd83dbSDimitry Andric   if (Call->getCallingConv() == CallingConv::Swift)
7675ffd83dbSDimitry Andric     return false;
7685ffd83dbSDimitry Andric 
7690b57cec5SDimitry Andric   bool IsDirect = Func != nullptr;
7705ffd83dbSDimitry Andric   if (!IsDirect && isa<ConstantExpr>(Call->getCalledOperand()))
7710b57cec5SDimitry Andric     return false;
7720b57cec5SDimitry Andric 
7730b57cec5SDimitry Andric   FunctionType *FuncTy = Call->getFunctionType();
7745ffd83dbSDimitry Andric   unsigned Opc = IsDirect ? WebAssembly::CALL : WebAssembly::CALL_INDIRECT;
7750b57cec5SDimitry Andric   bool IsVoid = FuncTy->getReturnType()->isVoidTy();
7760b57cec5SDimitry Andric   unsigned ResultReg;
7775ffd83dbSDimitry Andric   if (!IsVoid) {
7780b57cec5SDimitry Andric     if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
7790b57cec5SDimitry Andric       return false;
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric     MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
7820b57cec5SDimitry Andric     switch (RetTy) {
7830b57cec5SDimitry Andric     case MVT::i1:
7840b57cec5SDimitry Andric     case MVT::i8:
7850b57cec5SDimitry Andric     case MVT::i16:
7860b57cec5SDimitry Andric     case MVT::i32:
7870b57cec5SDimitry Andric       ResultReg = createResultReg(&WebAssembly::I32RegClass);
7880b57cec5SDimitry Andric       break;
7890b57cec5SDimitry Andric     case MVT::i64:
7900b57cec5SDimitry Andric       ResultReg = createResultReg(&WebAssembly::I64RegClass);
7910b57cec5SDimitry Andric       break;
7920b57cec5SDimitry Andric     case MVT::f32:
7930b57cec5SDimitry Andric       ResultReg = createResultReg(&WebAssembly::F32RegClass);
7940b57cec5SDimitry Andric       break;
7950b57cec5SDimitry Andric     case MVT::f64:
7960b57cec5SDimitry Andric       ResultReg = createResultReg(&WebAssembly::F64RegClass);
7970b57cec5SDimitry Andric       break;
7980b57cec5SDimitry Andric     case MVT::v16i8:
7990b57cec5SDimitry Andric       ResultReg = createResultReg(&WebAssembly::V128RegClass);
8000b57cec5SDimitry Andric       break;
8010b57cec5SDimitry Andric     case MVT::v8i16:
8020b57cec5SDimitry Andric       ResultReg = createResultReg(&WebAssembly::V128RegClass);
8030b57cec5SDimitry Andric       break;
8040b57cec5SDimitry Andric     case MVT::v4i32:
8050b57cec5SDimitry Andric       ResultReg = createResultReg(&WebAssembly::V128RegClass);
8060b57cec5SDimitry Andric       break;
8070b57cec5SDimitry Andric     case MVT::v2i64:
8080b57cec5SDimitry Andric       ResultReg = createResultReg(&WebAssembly::V128RegClass);
8090b57cec5SDimitry Andric       break;
8100b57cec5SDimitry Andric     case MVT::v4f32:
8110b57cec5SDimitry Andric       ResultReg = createResultReg(&WebAssembly::V128RegClass);
8120b57cec5SDimitry Andric       break;
8130b57cec5SDimitry Andric     case MVT::v2f64:
8140b57cec5SDimitry Andric       ResultReg = createResultReg(&WebAssembly::V128RegClass);
8150b57cec5SDimitry Andric       break;
816e8d8bef9SDimitry Andric     case MVT::funcref:
817e8d8bef9SDimitry Andric       ResultReg = createResultReg(&WebAssembly::FUNCREFRegClass);
818e8d8bef9SDimitry Andric       break;
819e8d8bef9SDimitry Andric     case MVT::externref:
820e8d8bef9SDimitry Andric       ResultReg = createResultReg(&WebAssembly::EXTERNREFRegClass);
8210b57cec5SDimitry Andric       break;
8220b57cec5SDimitry Andric     default:
8230b57cec5SDimitry Andric       return false;
8240b57cec5SDimitry Andric     }
8250b57cec5SDimitry Andric   }
8260b57cec5SDimitry Andric 
8270b57cec5SDimitry Andric   SmallVector<unsigned, 8> Args;
8280b57cec5SDimitry Andric   for (unsigned I = 0, E = Call->getNumArgOperands(); I < E; ++I) {
8290b57cec5SDimitry Andric     Value *V = Call->getArgOperand(I);
8300b57cec5SDimitry Andric     MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
8310b57cec5SDimitry Andric     if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
8320b57cec5SDimitry Andric       return false;
8330b57cec5SDimitry Andric 
8340b57cec5SDimitry Andric     const AttributeList &Attrs = Call->getAttributes();
8350b57cec5SDimitry Andric     if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
8360b57cec5SDimitry Andric         Attrs.hasParamAttribute(I, Attribute::SwiftSelf) ||
8370b57cec5SDimitry Andric         Attrs.hasParamAttribute(I, Attribute::SwiftError) ||
8380b57cec5SDimitry Andric         Attrs.hasParamAttribute(I, Attribute::InAlloca) ||
8390b57cec5SDimitry Andric         Attrs.hasParamAttribute(I, Attribute::Nest))
8400b57cec5SDimitry Andric       return false;
8410b57cec5SDimitry Andric 
8420b57cec5SDimitry Andric     unsigned Reg;
8430b57cec5SDimitry Andric 
8440b57cec5SDimitry Andric     if (Attrs.hasParamAttribute(I, Attribute::SExt))
8450b57cec5SDimitry Andric       Reg = getRegForSignedValue(V);
8460b57cec5SDimitry Andric     else if (Attrs.hasParamAttribute(I, Attribute::ZExt))
8470b57cec5SDimitry Andric       Reg = getRegForUnsignedValue(V);
8480b57cec5SDimitry Andric     else
8490b57cec5SDimitry Andric       Reg = getRegForValue(V);
8500b57cec5SDimitry Andric 
8510b57cec5SDimitry Andric     if (Reg == 0)
8520b57cec5SDimitry Andric       return false;
8530b57cec5SDimitry Andric 
8540b57cec5SDimitry Andric     Args.push_back(Reg);
8550b57cec5SDimitry Andric   }
8560b57cec5SDimitry Andric 
8570b57cec5SDimitry Andric   unsigned CalleeReg = 0;
8580b57cec5SDimitry Andric   if (!IsDirect) {
8595ffd83dbSDimitry Andric     CalleeReg = getRegForValue(Call->getCalledOperand());
8600b57cec5SDimitry Andric     if (!CalleeReg)
8610b57cec5SDimitry Andric       return false;
8620b57cec5SDimitry Andric   }
8630b57cec5SDimitry Andric 
8640b57cec5SDimitry Andric   auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
8650b57cec5SDimitry Andric 
8660b57cec5SDimitry Andric   if (!IsVoid)
8670b57cec5SDimitry Andric     MIB.addReg(ResultReg, RegState::Define);
8680b57cec5SDimitry Andric 
8695ffd83dbSDimitry Andric   if (IsDirect) {
8700b57cec5SDimitry Andric     MIB.addGlobalAddress(Func);
8715ffd83dbSDimitry Andric   } else {
872*fe6060f1SDimitry Andric     // Placeholder for the type index.
8735ffd83dbSDimitry Andric     MIB.addImm(0);
874*fe6060f1SDimitry Andric     // The table into which this call_indirect indexes.
875*fe6060f1SDimitry Andric     MCSymbolWasm *Table = WebAssembly::getOrCreateFunctionTableSymbol(
876*fe6060f1SDimitry Andric         MF->getMMI().getContext(), Subtarget);
877*fe6060f1SDimitry Andric     if (Subtarget->hasReferenceTypes()) {
878*fe6060f1SDimitry Andric       MIB.addSym(Table);
879*fe6060f1SDimitry Andric     } else {
880*fe6060f1SDimitry Andric       // Otherwise for the MVP there is at most one table whose number is 0, but
881*fe6060f1SDimitry Andric       // we can't write a table symbol or issue relocations.  Instead we just
882*fe6060f1SDimitry Andric       // ensure the table is live.
883*fe6060f1SDimitry Andric       Table->setNoStrip();
8845ffd83dbSDimitry Andric       MIB.addImm(0);
885*fe6060f1SDimitry Andric     }
886*fe6060f1SDimitry Andric     // See if we must truncate the function pointer.
887*fe6060f1SDimitry Andric     // CALL_INDIRECT takes an i32, but in wasm64 we represent function pointers
888*fe6060f1SDimitry Andric     // as 64-bit for uniformity with other pointer types.
889*fe6060f1SDimitry Andric     // See also: WebAssemblyISelLowering.cpp: LowerCallResults
890*fe6060f1SDimitry Andric     if (Subtarget->hasAddr64()) {
891*fe6060f1SDimitry Andric       auto Wrap = BuildMI(*FuncInfo.MBB, std::prev(FuncInfo.InsertPt), DbgLoc,
892*fe6060f1SDimitry Andric                           TII.get(WebAssembly::I32_WRAP_I64));
893*fe6060f1SDimitry Andric       unsigned Reg32 = createResultReg(&WebAssembly::I32RegClass);
894*fe6060f1SDimitry Andric       Wrap.addReg(Reg32, RegState::Define);
895*fe6060f1SDimitry Andric       Wrap.addReg(CalleeReg);
896*fe6060f1SDimitry Andric       CalleeReg = Reg32;
897*fe6060f1SDimitry Andric     }
8985ffd83dbSDimitry Andric   }
8990b57cec5SDimitry Andric 
9000b57cec5SDimitry Andric   for (unsigned ArgReg : Args)
9010b57cec5SDimitry Andric     MIB.addReg(ArgReg);
9020b57cec5SDimitry Andric 
9035ffd83dbSDimitry Andric   if (!IsDirect)
9045ffd83dbSDimitry Andric     MIB.addReg(CalleeReg);
9055ffd83dbSDimitry Andric 
9060b57cec5SDimitry Andric   if (!IsVoid)
9070b57cec5SDimitry Andric     updateValueMap(Call, ResultReg);
9080b57cec5SDimitry Andric   return true;
9090b57cec5SDimitry Andric }
9100b57cec5SDimitry Andric 
9110b57cec5SDimitry Andric bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
9120b57cec5SDimitry Andric   const auto *Select = cast<SelectInst>(I);
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric   bool Not;
9150b57cec5SDimitry Andric   unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
9160b57cec5SDimitry Andric   if (CondReg == 0)
9170b57cec5SDimitry Andric     return false;
9180b57cec5SDimitry Andric 
9190b57cec5SDimitry Andric   unsigned TrueReg = getRegForValue(Select->getTrueValue());
9200b57cec5SDimitry Andric   if (TrueReg == 0)
9210b57cec5SDimitry Andric     return false;
9220b57cec5SDimitry Andric 
9230b57cec5SDimitry Andric   unsigned FalseReg = getRegForValue(Select->getFalseValue());
9240b57cec5SDimitry Andric   if (FalseReg == 0)
9250b57cec5SDimitry Andric     return false;
9260b57cec5SDimitry Andric 
9270b57cec5SDimitry Andric   if (Not)
9280b57cec5SDimitry Andric     std::swap(TrueReg, FalseReg);
9290b57cec5SDimitry Andric 
9300b57cec5SDimitry Andric   unsigned Opc;
9310b57cec5SDimitry Andric   const TargetRegisterClass *RC;
9320b57cec5SDimitry Andric   switch (getSimpleType(Select->getType())) {
9330b57cec5SDimitry Andric   case MVT::i1:
9340b57cec5SDimitry Andric   case MVT::i8:
9350b57cec5SDimitry Andric   case MVT::i16:
9360b57cec5SDimitry Andric   case MVT::i32:
9370b57cec5SDimitry Andric     Opc = WebAssembly::SELECT_I32;
9380b57cec5SDimitry Andric     RC = &WebAssembly::I32RegClass;
9390b57cec5SDimitry Andric     break;
9400b57cec5SDimitry Andric   case MVT::i64:
9410b57cec5SDimitry Andric     Opc = WebAssembly::SELECT_I64;
9420b57cec5SDimitry Andric     RC = &WebAssembly::I64RegClass;
9430b57cec5SDimitry Andric     break;
9440b57cec5SDimitry Andric   case MVT::f32:
9450b57cec5SDimitry Andric     Opc = WebAssembly::SELECT_F32;
9460b57cec5SDimitry Andric     RC = &WebAssembly::F32RegClass;
9470b57cec5SDimitry Andric     break;
9480b57cec5SDimitry Andric   case MVT::f64:
9490b57cec5SDimitry Andric     Opc = WebAssembly::SELECT_F64;
9500b57cec5SDimitry Andric     RC = &WebAssembly::F64RegClass;
9510b57cec5SDimitry Andric     break;
952e8d8bef9SDimitry Andric   case MVT::funcref:
953e8d8bef9SDimitry Andric     Opc = WebAssembly::SELECT_FUNCREF;
954e8d8bef9SDimitry Andric     RC = &WebAssembly::FUNCREFRegClass;
955e8d8bef9SDimitry Andric     break;
956e8d8bef9SDimitry Andric   case MVT::externref:
957e8d8bef9SDimitry Andric     Opc = WebAssembly::SELECT_EXTERNREF;
958e8d8bef9SDimitry Andric     RC = &WebAssembly::EXTERNREFRegClass;
9590b57cec5SDimitry Andric     break;
9600b57cec5SDimitry Andric   default:
9610b57cec5SDimitry Andric     return false;
9620b57cec5SDimitry Andric   }
9630b57cec5SDimitry Andric 
9640b57cec5SDimitry Andric   unsigned ResultReg = createResultReg(RC);
9650b57cec5SDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
9660b57cec5SDimitry Andric       .addReg(TrueReg)
9670b57cec5SDimitry Andric       .addReg(FalseReg)
9680b57cec5SDimitry Andric       .addReg(CondReg);
9690b57cec5SDimitry Andric 
9700b57cec5SDimitry Andric   updateValueMap(Select, ResultReg);
9710b57cec5SDimitry Andric   return true;
9720b57cec5SDimitry Andric }
9730b57cec5SDimitry Andric 
9740b57cec5SDimitry Andric bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
9750b57cec5SDimitry Andric   const auto *Trunc = cast<TruncInst>(I);
9760b57cec5SDimitry Andric 
9770b57cec5SDimitry Andric   unsigned Reg = getRegForValue(Trunc->getOperand(0));
9780b57cec5SDimitry Andric   if (Reg == 0)
9790b57cec5SDimitry Andric     return false;
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric   if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
9820b57cec5SDimitry Andric     unsigned Result = createResultReg(&WebAssembly::I32RegClass);
9830b57cec5SDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
9840b57cec5SDimitry Andric             TII.get(WebAssembly::I32_WRAP_I64), Result)
9850b57cec5SDimitry Andric         .addReg(Reg);
9860b57cec5SDimitry Andric     Reg = Result;
9870b57cec5SDimitry Andric   }
9880b57cec5SDimitry Andric 
9890b57cec5SDimitry Andric   updateValueMap(Trunc, Reg);
9900b57cec5SDimitry Andric   return true;
9910b57cec5SDimitry Andric }
9920b57cec5SDimitry Andric 
9930b57cec5SDimitry Andric bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
9940b57cec5SDimitry Andric   const auto *ZExt = cast<ZExtInst>(I);
9950b57cec5SDimitry Andric 
9960b57cec5SDimitry Andric   const Value *Op = ZExt->getOperand(0);
9970b57cec5SDimitry Andric   MVT::SimpleValueType From = getSimpleType(Op->getType());
9980b57cec5SDimitry Andric   MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
9990b57cec5SDimitry Andric   unsigned In = getRegForValue(Op);
10000b57cec5SDimitry Andric   if (In == 0)
10010b57cec5SDimitry Andric     return false;
10020b57cec5SDimitry Andric   unsigned Reg = zeroExtend(In, Op, From, To);
10030b57cec5SDimitry Andric   if (Reg == 0)
10040b57cec5SDimitry Andric     return false;
10050b57cec5SDimitry Andric 
10060b57cec5SDimitry Andric   updateValueMap(ZExt, Reg);
10070b57cec5SDimitry Andric   return true;
10080b57cec5SDimitry Andric }
10090b57cec5SDimitry Andric 
10100b57cec5SDimitry Andric bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
10110b57cec5SDimitry Andric   const auto *SExt = cast<SExtInst>(I);
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric   const Value *Op = SExt->getOperand(0);
10140b57cec5SDimitry Andric   MVT::SimpleValueType From = getSimpleType(Op->getType());
10150b57cec5SDimitry Andric   MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
10160b57cec5SDimitry Andric   unsigned In = getRegForValue(Op);
10170b57cec5SDimitry Andric   if (In == 0)
10180b57cec5SDimitry Andric     return false;
10190b57cec5SDimitry Andric   unsigned Reg = signExtend(In, Op, From, To);
10200b57cec5SDimitry Andric   if (Reg == 0)
10210b57cec5SDimitry Andric     return false;
10220b57cec5SDimitry Andric 
10230b57cec5SDimitry Andric   updateValueMap(SExt, Reg);
10240b57cec5SDimitry Andric   return true;
10250b57cec5SDimitry Andric }
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
10280b57cec5SDimitry Andric   const auto *ICmp = cast<ICmpInst>(I);
10290b57cec5SDimitry Andric 
10300b57cec5SDimitry Andric   bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
10310b57cec5SDimitry Andric   unsigned Opc;
10320b57cec5SDimitry Andric   bool IsSigned = false;
10330b57cec5SDimitry Andric   switch (ICmp->getPredicate()) {
10340b57cec5SDimitry Andric   case ICmpInst::ICMP_EQ:
10350b57cec5SDimitry Andric     Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
10360b57cec5SDimitry Andric     break;
10370b57cec5SDimitry Andric   case ICmpInst::ICMP_NE:
10380b57cec5SDimitry Andric     Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
10390b57cec5SDimitry Andric     break;
10400b57cec5SDimitry Andric   case ICmpInst::ICMP_UGT:
10410b57cec5SDimitry Andric     Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
10420b57cec5SDimitry Andric     break;
10430b57cec5SDimitry Andric   case ICmpInst::ICMP_UGE:
10440b57cec5SDimitry Andric     Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
10450b57cec5SDimitry Andric     break;
10460b57cec5SDimitry Andric   case ICmpInst::ICMP_ULT:
10470b57cec5SDimitry Andric     Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
10480b57cec5SDimitry Andric     break;
10490b57cec5SDimitry Andric   case ICmpInst::ICMP_ULE:
10500b57cec5SDimitry Andric     Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
10510b57cec5SDimitry Andric     break;
10520b57cec5SDimitry Andric   case ICmpInst::ICMP_SGT:
10530b57cec5SDimitry Andric     Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
10540b57cec5SDimitry Andric     IsSigned = true;
10550b57cec5SDimitry Andric     break;
10560b57cec5SDimitry Andric   case ICmpInst::ICMP_SGE:
10570b57cec5SDimitry Andric     Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
10580b57cec5SDimitry Andric     IsSigned = true;
10590b57cec5SDimitry Andric     break;
10600b57cec5SDimitry Andric   case ICmpInst::ICMP_SLT:
10610b57cec5SDimitry Andric     Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
10620b57cec5SDimitry Andric     IsSigned = true;
10630b57cec5SDimitry Andric     break;
10640b57cec5SDimitry Andric   case ICmpInst::ICMP_SLE:
10650b57cec5SDimitry Andric     Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
10660b57cec5SDimitry Andric     IsSigned = true;
10670b57cec5SDimitry Andric     break;
10680b57cec5SDimitry Andric   default:
10690b57cec5SDimitry Andric     return false;
10700b57cec5SDimitry Andric   }
10710b57cec5SDimitry Andric 
10720b57cec5SDimitry Andric   unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
10730b57cec5SDimitry Andric   if (LHS == 0)
10740b57cec5SDimitry Andric     return false;
10750b57cec5SDimitry Andric 
10760b57cec5SDimitry Andric   unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
10770b57cec5SDimitry Andric   if (RHS == 0)
10780b57cec5SDimitry Andric     return false;
10790b57cec5SDimitry Andric 
10800b57cec5SDimitry Andric   unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
10810b57cec5SDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
10820b57cec5SDimitry Andric       .addReg(LHS)
10830b57cec5SDimitry Andric       .addReg(RHS);
10840b57cec5SDimitry Andric   updateValueMap(ICmp, ResultReg);
10850b57cec5SDimitry Andric   return true;
10860b57cec5SDimitry Andric }
10870b57cec5SDimitry Andric 
10880b57cec5SDimitry Andric bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
10890b57cec5SDimitry Andric   const auto *FCmp = cast<FCmpInst>(I);
10900b57cec5SDimitry Andric 
10910b57cec5SDimitry Andric   unsigned LHS = getRegForValue(FCmp->getOperand(0));
10920b57cec5SDimitry Andric   if (LHS == 0)
10930b57cec5SDimitry Andric     return false;
10940b57cec5SDimitry Andric 
10950b57cec5SDimitry Andric   unsigned RHS = getRegForValue(FCmp->getOperand(1));
10960b57cec5SDimitry Andric   if (RHS == 0)
10970b57cec5SDimitry Andric     return false;
10980b57cec5SDimitry Andric 
10990b57cec5SDimitry Andric   bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
11000b57cec5SDimitry Andric   unsigned Opc;
11010b57cec5SDimitry Andric   bool Not = false;
11020b57cec5SDimitry Andric   switch (FCmp->getPredicate()) {
11030b57cec5SDimitry Andric   case FCmpInst::FCMP_OEQ:
11040b57cec5SDimitry Andric     Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
11050b57cec5SDimitry Andric     break;
11060b57cec5SDimitry Andric   case FCmpInst::FCMP_UNE:
11070b57cec5SDimitry Andric     Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
11080b57cec5SDimitry Andric     break;
11090b57cec5SDimitry Andric   case FCmpInst::FCMP_OGT:
11100b57cec5SDimitry Andric     Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
11110b57cec5SDimitry Andric     break;
11120b57cec5SDimitry Andric   case FCmpInst::FCMP_OGE:
11130b57cec5SDimitry Andric     Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
11140b57cec5SDimitry Andric     break;
11150b57cec5SDimitry Andric   case FCmpInst::FCMP_OLT:
11160b57cec5SDimitry Andric     Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
11170b57cec5SDimitry Andric     break;
11180b57cec5SDimitry Andric   case FCmpInst::FCMP_OLE:
11190b57cec5SDimitry Andric     Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
11200b57cec5SDimitry Andric     break;
11210b57cec5SDimitry Andric   case FCmpInst::FCMP_UGT:
11220b57cec5SDimitry Andric     Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
11230b57cec5SDimitry Andric     Not = true;
11240b57cec5SDimitry Andric     break;
11250b57cec5SDimitry Andric   case FCmpInst::FCMP_UGE:
11260b57cec5SDimitry Andric     Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
11270b57cec5SDimitry Andric     Not = true;
11280b57cec5SDimitry Andric     break;
11290b57cec5SDimitry Andric   case FCmpInst::FCMP_ULT:
11300b57cec5SDimitry Andric     Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
11310b57cec5SDimitry Andric     Not = true;
11320b57cec5SDimitry Andric     break;
11330b57cec5SDimitry Andric   case FCmpInst::FCMP_ULE:
11340b57cec5SDimitry Andric     Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
11350b57cec5SDimitry Andric     Not = true;
11360b57cec5SDimitry Andric     break;
11370b57cec5SDimitry Andric   default:
11380b57cec5SDimitry Andric     return false;
11390b57cec5SDimitry Andric   }
11400b57cec5SDimitry Andric 
11410b57cec5SDimitry Andric   unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
11420b57cec5SDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
11430b57cec5SDimitry Andric       .addReg(LHS)
11440b57cec5SDimitry Andric       .addReg(RHS);
11450b57cec5SDimitry Andric 
11460b57cec5SDimitry Andric   if (Not)
11470b57cec5SDimitry Andric     ResultReg = notValue(ResultReg);
11480b57cec5SDimitry Andric 
11490b57cec5SDimitry Andric   updateValueMap(FCmp, ResultReg);
11500b57cec5SDimitry Andric   return true;
11510b57cec5SDimitry Andric }
11520b57cec5SDimitry Andric 
11530b57cec5SDimitry Andric bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
11540b57cec5SDimitry Andric   // Target-independent code can handle this, except it doesn't set the dead
11550b57cec5SDimitry Andric   // flag on the ARGUMENTS clobber, so we have to do that manually in order
11560b57cec5SDimitry Andric   // to satisfy code that expects this of isBitcast() instructions.
11570b57cec5SDimitry Andric   EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
11580b57cec5SDimitry Andric   EVT RetVT = TLI.getValueType(DL, I->getType());
11590b57cec5SDimitry Andric   if (!VT.isSimple() || !RetVT.isSimple())
11600b57cec5SDimitry Andric     return false;
11610b57cec5SDimitry Andric 
11620b57cec5SDimitry Andric   unsigned In = getRegForValue(I->getOperand(0));
11630b57cec5SDimitry Andric   if (In == 0)
11640b57cec5SDimitry Andric     return false;
11650b57cec5SDimitry Andric 
11660b57cec5SDimitry Andric   if (VT == RetVT) {
11670b57cec5SDimitry Andric     // No-op bitcast.
11680b57cec5SDimitry Andric     updateValueMap(I, In);
11690b57cec5SDimitry Andric     return true;
11700b57cec5SDimitry Andric   }
11710b57cec5SDimitry Andric 
11728bcb0991SDimitry Andric   Register Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
1173*fe6060f1SDimitry Andric                                         In);
11740b57cec5SDimitry Andric   if (!Reg)
11750b57cec5SDimitry Andric     return false;
11760b57cec5SDimitry Andric   MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
11770b57cec5SDimitry Andric   --Iter;
11780b57cec5SDimitry Andric   assert(Iter->isBitcast());
11798bcb0991SDimitry Andric   Iter->setPhysRegsDeadExcept(ArrayRef<Register>(), TRI);
11800b57cec5SDimitry Andric   updateValueMap(I, Reg);
11810b57cec5SDimitry Andric   return true;
11820b57cec5SDimitry Andric }
11830b57cec5SDimitry Andric 
11840b57cec5SDimitry Andric bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
11850b57cec5SDimitry Andric   const auto *Load = cast<LoadInst>(I);
11860b57cec5SDimitry Andric   if (Load->isAtomic())
11870b57cec5SDimitry Andric     return false;
1188*fe6060f1SDimitry Andric   if (!WebAssembly::isDefaultAddressSpace(Load->getPointerAddressSpace()))
1189*fe6060f1SDimitry Andric     return false;
11900b57cec5SDimitry Andric   if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
11910b57cec5SDimitry Andric     return false;
11920b57cec5SDimitry Andric 
11930b57cec5SDimitry Andric   Address Addr;
11940b57cec5SDimitry Andric   if (!computeAddress(Load->getPointerOperand(), Addr))
11950b57cec5SDimitry Andric     return false;
11960b57cec5SDimitry Andric 
11970b57cec5SDimitry Andric   // TODO: Fold a following sign-/zero-extend into the load instruction.
11980b57cec5SDimitry Andric 
11990b57cec5SDimitry Andric   unsigned Opc;
12000b57cec5SDimitry Andric   const TargetRegisterClass *RC;
12015ffd83dbSDimitry Andric   bool A64 = Subtarget->hasAddr64();
12020b57cec5SDimitry Andric   switch (getSimpleType(Load->getType())) {
12030b57cec5SDimitry Andric   case MVT::i1:
12040b57cec5SDimitry Andric   case MVT::i8:
12055ffd83dbSDimitry Andric     Opc = A64 ? WebAssembly::LOAD8_U_I32_A64 : WebAssembly::LOAD8_U_I32_A32;
12060b57cec5SDimitry Andric     RC = &WebAssembly::I32RegClass;
12070b57cec5SDimitry Andric     break;
12080b57cec5SDimitry Andric   case MVT::i16:
12095ffd83dbSDimitry Andric     Opc = A64 ? WebAssembly::LOAD16_U_I32_A64 : WebAssembly::LOAD16_U_I32_A32;
12100b57cec5SDimitry Andric     RC = &WebAssembly::I32RegClass;
12110b57cec5SDimitry Andric     break;
12120b57cec5SDimitry Andric   case MVT::i32:
12135ffd83dbSDimitry Andric     Opc = A64 ? WebAssembly::LOAD_I32_A64 : WebAssembly::LOAD_I32_A32;
12140b57cec5SDimitry Andric     RC = &WebAssembly::I32RegClass;
12150b57cec5SDimitry Andric     break;
12160b57cec5SDimitry Andric   case MVT::i64:
12175ffd83dbSDimitry Andric     Opc = A64 ? WebAssembly::LOAD_I64_A64 : WebAssembly::LOAD_I64_A32;
12180b57cec5SDimitry Andric     RC = &WebAssembly::I64RegClass;
12190b57cec5SDimitry Andric     break;
12200b57cec5SDimitry Andric   case MVT::f32:
12215ffd83dbSDimitry Andric     Opc = A64 ? WebAssembly::LOAD_F32_A64 : WebAssembly::LOAD_F32_A32;
12220b57cec5SDimitry Andric     RC = &WebAssembly::F32RegClass;
12230b57cec5SDimitry Andric     break;
12240b57cec5SDimitry Andric   case MVT::f64:
12255ffd83dbSDimitry Andric     Opc = A64 ? WebAssembly::LOAD_F64_A64 : WebAssembly::LOAD_F64_A32;
12260b57cec5SDimitry Andric     RC = &WebAssembly::F64RegClass;
12270b57cec5SDimitry Andric     break;
12280b57cec5SDimitry Andric   default:
12290b57cec5SDimitry Andric     return false;
12300b57cec5SDimitry Andric   }
12310b57cec5SDimitry Andric 
12320b57cec5SDimitry Andric   materializeLoadStoreOperands(Addr);
12330b57cec5SDimitry Andric 
12340b57cec5SDimitry Andric   unsigned ResultReg = createResultReg(RC);
12350b57cec5SDimitry Andric   auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
12360b57cec5SDimitry Andric                      ResultReg);
12370b57cec5SDimitry Andric 
12380b57cec5SDimitry Andric   addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
12390b57cec5SDimitry Andric 
12400b57cec5SDimitry Andric   updateValueMap(Load, ResultReg);
12410b57cec5SDimitry Andric   return true;
12420b57cec5SDimitry Andric }
12430b57cec5SDimitry Andric 
12440b57cec5SDimitry Andric bool WebAssemblyFastISel::selectStore(const Instruction *I) {
12450b57cec5SDimitry Andric   const auto *Store = cast<StoreInst>(I);
12460b57cec5SDimitry Andric   if (Store->isAtomic())
12470b57cec5SDimitry Andric     return false;
1248*fe6060f1SDimitry Andric   if (!WebAssembly::isDefaultAddressSpace(Store->getPointerAddressSpace()))
1249*fe6060f1SDimitry Andric     return false;
12500b57cec5SDimitry Andric   if (!Subtarget->hasSIMD128() &&
12510b57cec5SDimitry Andric       Store->getValueOperand()->getType()->isVectorTy())
12520b57cec5SDimitry Andric     return false;
12530b57cec5SDimitry Andric 
12540b57cec5SDimitry Andric   Address Addr;
12550b57cec5SDimitry Andric   if (!computeAddress(Store->getPointerOperand(), Addr))
12560b57cec5SDimitry Andric     return false;
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric   unsigned Opc;
12590b57cec5SDimitry Andric   bool VTIsi1 = false;
12605ffd83dbSDimitry Andric   bool A64 = Subtarget->hasAddr64();
12610b57cec5SDimitry Andric   switch (getSimpleType(Store->getValueOperand()->getType())) {
12620b57cec5SDimitry Andric   case MVT::i1:
12630b57cec5SDimitry Andric     VTIsi1 = true;
12640b57cec5SDimitry Andric     LLVM_FALLTHROUGH;
12650b57cec5SDimitry Andric   case MVT::i8:
12665ffd83dbSDimitry Andric     Opc = A64 ? WebAssembly::STORE8_I32_A64 : WebAssembly::STORE8_I32_A32;
12670b57cec5SDimitry Andric     break;
12680b57cec5SDimitry Andric   case MVT::i16:
12695ffd83dbSDimitry Andric     Opc = A64 ? WebAssembly::STORE16_I32_A64 : WebAssembly::STORE16_I32_A32;
12700b57cec5SDimitry Andric     break;
12710b57cec5SDimitry Andric   case MVT::i32:
12725ffd83dbSDimitry Andric     Opc = A64 ? WebAssembly::STORE_I32_A64 : WebAssembly::STORE_I32_A32;
12730b57cec5SDimitry Andric     break;
12740b57cec5SDimitry Andric   case MVT::i64:
12755ffd83dbSDimitry Andric     Opc = A64 ? WebAssembly::STORE_I64_A64 : WebAssembly::STORE_I64_A32;
12760b57cec5SDimitry Andric     break;
12770b57cec5SDimitry Andric   case MVT::f32:
12785ffd83dbSDimitry Andric     Opc = A64 ? WebAssembly::STORE_F32_A64 : WebAssembly::STORE_F32_A32;
12790b57cec5SDimitry Andric     break;
12800b57cec5SDimitry Andric   case MVT::f64:
12815ffd83dbSDimitry Andric     Opc = A64 ? WebAssembly::STORE_F64_A64 : WebAssembly::STORE_F64_A32;
12820b57cec5SDimitry Andric     break;
12830b57cec5SDimitry Andric   default:
12840b57cec5SDimitry Andric     return false;
12850b57cec5SDimitry Andric   }
12860b57cec5SDimitry Andric 
12870b57cec5SDimitry Andric   materializeLoadStoreOperands(Addr);
12880b57cec5SDimitry Andric 
12890b57cec5SDimitry Andric   unsigned ValueReg = getRegForValue(Store->getValueOperand());
12900b57cec5SDimitry Andric   if (ValueReg == 0)
12910b57cec5SDimitry Andric     return false;
12920b57cec5SDimitry Andric   if (VTIsi1)
12930b57cec5SDimitry Andric     ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric   auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
12960b57cec5SDimitry Andric 
12970b57cec5SDimitry Andric   addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric   MIB.addReg(ValueReg);
13000b57cec5SDimitry Andric   return true;
13010b57cec5SDimitry Andric }
13020b57cec5SDimitry Andric 
13030b57cec5SDimitry Andric bool WebAssemblyFastISel::selectBr(const Instruction *I) {
13040b57cec5SDimitry Andric   const auto *Br = cast<BranchInst>(I);
13050b57cec5SDimitry Andric   if (Br->isUnconditional()) {
13060b57cec5SDimitry Andric     MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
13070b57cec5SDimitry Andric     fastEmitBranch(MSucc, Br->getDebugLoc());
13080b57cec5SDimitry Andric     return true;
13090b57cec5SDimitry Andric   }
13100b57cec5SDimitry Andric 
13110b57cec5SDimitry Andric   MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
13120b57cec5SDimitry Andric   MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
13130b57cec5SDimitry Andric 
13140b57cec5SDimitry Andric   bool Not;
13150b57cec5SDimitry Andric   unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
13160b57cec5SDimitry Andric   if (CondReg == 0)
13170b57cec5SDimitry Andric     return false;
13180b57cec5SDimitry Andric 
13190b57cec5SDimitry Andric   unsigned Opc = WebAssembly::BR_IF;
13200b57cec5SDimitry Andric   if (Not)
13210b57cec5SDimitry Andric     Opc = WebAssembly::BR_UNLESS;
13220b57cec5SDimitry Andric 
13230b57cec5SDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
13240b57cec5SDimitry Andric       .addMBB(TBB)
13250b57cec5SDimitry Andric       .addReg(CondReg);
13260b57cec5SDimitry Andric 
13270b57cec5SDimitry Andric   finishCondBranch(Br->getParent(), TBB, FBB);
13280b57cec5SDimitry Andric   return true;
13290b57cec5SDimitry Andric }
13300b57cec5SDimitry Andric 
13310b57cec5SDimitry Andric bool WebAssemblyFastISel::selectRet(const Instruction *I) {
13320b57cec5SDimitry Andric   if (!FuncInfo.CanLowerReturn)
13330b57cec5SDimitry Andric     return false;
13340b57cec5SDimitry Andric 
13350b57cec5SDimitry Andric   const auto *Ret = cast<ReturnInst>(I);
13360b57cec5SDimitry Andric 
13370b57cec5SDimitry Andric   if (Ret->getNumOperands() == 0) {
13380b57cec5SDimitry Andric     BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
13398bcb0991SDimitry Andric             TII.get(WebAssembly::RETURN));
13400b57cec5SDimitry Andric     return true;
13410b57cec5SDimitry Andric   }
13420b57cec5SDimitry Andric 
13438bcb0991SDimitry Andric   // TODO: support multiple return in FastISel
13448bcb0991SDimitry Andric   if (Ret->getNumOperands() > 1)
13458bcb0991SDimitry Andric     return false;
13468bcb0991SDimitry Andric 
13470b57cec5SDimitry Andric   Value *RV = Ret->getOperand(0);
13480b57cec5SDimitry Andric   if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
13490b57cec5SDimitry Andric     return false;
13500b57cec5SDimitry Andric 
13510b57cec5SDimitry Andric   switch (getSimpleType(RV->getType())) {
13520b57cec5SDimitry Andric   case MVT::i1:
13530b57cec5SDimitry Andric   case MVT::i8:
13540b57cec5SDimitry Andric   case MVT::i16:
13550b57cec5SDimitry Andric   case MVT::i32:
13560b57cec5SDimitry Andric   case MVT::i64:
13570b57cec5SDimitry Andric   case MVT::f32:
13580b57cec5SDimitry Andric   case MVT::f64:
13590b57cec5SDimitry Andric   case MVT::v16i8:
13600b57cec5SDimitry Andric   case MVT::v8i16:
13610b57cec5SDimitry Andric   case MVT::v4i32:
13620b57cec5SDimitry Andric   case MVT::v2i64:
13630b57cec5SDimitry Andric   case MVT::v4f32:
13640b57cec5SDimitry Andric   case MVT::v2f64:
1365e8d8bef9SDimitry Andric   case MVT::funcref:
1366e8d8bef9SDimitry Andric   case MVT::externref:
13670b57cec5SDimitry Andric     break;
13680b57cec5SDimitry Andric   default:
13690b57cec5SDimitry Andric     return false;
13700b57cec5SDimitry Andric   }
13710b57cec5SDimitry Andric 
13720b57cec5SDimitry Andric   unsigned Reg;
13730b57cec5SDimitry Andric   if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
13740b57cec5SDimitry Andric     Reg = getRegForSignedValue(RV);
13750b57cec5SDimitry Andric   else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
13760b57cec5SDimitry Andric     Reg = getRegForUnsignedValue(RV);
13770b57cec5SDimitry Andric   else
13780b57cec5SDimitry Andric     Reg = getRegForValue(RV);
13790b57cec5SDimitry Andric 
13800b57cec5SDimitry Andric   if (Reg == 0)
13810b57cec5SDimitry Andric     return false;
13820b57cec5SDimitry Andric 
13838bcb0991SDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
13848bcb0991SDimitry Andric           TII.get(WebAssembly::RETURN))
13858bcb0991SDimitry Andric       .addReg(Reg);
13860b57cec5SDimitry Andric   return true;
13870b57cec5SDimitry Andric }
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
13900b57cec5SDimitry Andric   BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
13910b57cec5SDimitry Andric           TII.get(WebAssembly::UNREACHABLE));
13920b57cec5SDimitry Andric   return true;
13930b57cec5SDimitry Andric }
13940b57cec5SDimitry Andric 
13950b57cec5SDimitry Andric bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
13960b57cec5SDimitry Andric   switch (I->getOpcode()) {
13970b57cec5SDimitry Andric   case Instruction::Call:
13980b57cec5SDimitry Andric     if (selectCall(I))
13990b57cec5SDimitry Andric       return true;
14000b57cec5SDimitry Andric     break;
14010b57cec5SDimitry Andric   case Instruction::Select:
14020b57cec5SDimitry Andric     return selectSelect(I);
14030b57cec5SDimitry Andric   case Instruction::Trunc:
14040b57cec5SDimitry Andric     return selectTrunc(I);
14050b57cec5SDimitry Andric   case Instruction::ZExt:
14060b57cec5SDimitry Andric     return selectZExt(I);
14070b57cec5SDimitry Andric   case Instruction::SExt:
14080b57cec5SDimitry Andric     return selectSExt(I);
14090b57cec5SDimitry Andric   case Instruction::ICmp:
14100b57cec5SDimitry Andric     return selectICmp(I);
14110b57cec5SDimitry Andric   case Instruction::FCmp:
14120b57cec5SDimitry Andric     return selectFCmp(I);
14130b57cec5SDimitry Andric   case Instruction::BitCast:
14140b57cec5SDimitry Andric     return selectBitCast(I);
14150b57cec5SDimitry Andric   case Instruction::Load:
14160b57cec5SDimitry Andric     return selectLoad(I);
14170b57cec5SDimitry Andric   case Instruction::Store:
14180b57cec5SDimitry Andric     return selectStore(I);
14190b57cec5SDimitry Andric   case Instruction::Br:
14200b57cec5SDimitry Andric     return selectBr(I);
14210b57cec5SDimitry Andric   case Instruction::Ret:
14220b57cec5SDimitry Andric     return selectRet(I);
14230b57cec5SDimitry Andric   case Instruction::Unreachable:
14240b57cec5SDimitry Andric     return selectUnreachable(I);
14250b57cec5SDimitry Andric   default:
14260b57cec5SDimitry Andric     break;
14270b57cec5SDimitry Andric   }
14280b57cec5SDimitry Andric 
14290b57cec5SDimitry Andric   // Fall back to target-independent instruction selection.
14300b57cec5SDimitry Andric   return selectOperator(I, I->getOpcode());
14310b57cec5SDimitry Andric }
14320b57cec5SDimitry Andric 
14330b57cec5SDimitry Andric FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,
14340b57cec5SDimitry Andric                                       const TargetLibraryInfo *LibInfo) {
14350b57cec5SDimitry Andric   return new WebAssemblyFastISel(FuncInfo, LibInfo);
14360b57cec5SDimitry Andric }
1437