17d523365SDimitry Andric //===-- WebAssemblyFastISel.cpp - WebAssembly FastISel implementation -----===//
27d523365SDimitry Andric //
37d523365SDimitry Andric // The LLVM Compiler Infrastructure
47d523365SDimitry Andric //
57d523365SDimitry Andric // This file is distributed under the University of Illinois Open Source
67d523365SDimitry Andric // License. See LICENSE.TXT for details.
77d523365SDimitry Andric //
87d523365SDimitry Andric //===----------------------------------------------------------------------===//
97d523365SDimitry Andric ///
107d523365SDimitry Andric /// \file
114ba319b5SDimitry Andric /// This file defines the WebAssembly-specific support for the FastISel
127d523365SDimitry Andric /// class. Some of the target-specific code is generated by tablegen in the file
137d523365SDimitry Andric /// WebAssemblyGenFastISel.inc, which is #included here.
147d523365SDimitry Andric ///
153ca95b02SDimitry Andric /// TODO: kill flags
163ca95b02SDimitry Andric ///
177d523365SDimitry Andric //===----------------------------------------------------------------------===//
187d523365SDimitry Andric
197d523365SDimitry Andric #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
20db17bf38SDimitry Andric #include "WebAssembly.h"
213ca95b02SDimitry Andric #include "WebAssemblyMachineFunctionInfo.h"
227d523365SDimitry Andric #include "WebAssemblySubtarget.h"
237d523365SDimitry Andric #include "WebAssemblyTargetMachine.h"
247d523365SDimitry Andric #include "llvm/Analysis/BranchProbabilityInfo.h"
257d523365SDimitry Andric #include "llvm/CodeGen/FastISel.h"
267d523365SDimitry Andric #include "llvm/CodeGen/FunctionLoweringInfo.h"
277d523365SDimitry Andric #include "llvm/CodeGen/MachineConstantPool.h"
287d523365SDimitry Andric #include "llvm/CodeGen/MachineFrameInfo.h"
297d523365SDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
307d523365SDimitry Andric #include "llvm/CodeGen/MachineRegisterInfo.h"
317d523365SDimitry Andric #include "llvm/IR/DataLayout.h"
327d523365SDimitry Andric #include "llvm/IR/DerivedTypes.h"
337d523365SDimitry Andric #include "llvm/IR/Function.h"
347d523365SDimitry Andric #include "llvm/IR/GetElementPtrTypeIterator.h"
357d523365SDimitry Andric #include "llvm/IR/GlobalAlias.h"
367d523365SDimitry Andric #include "llvm/IR/GlobalVariable.h"
377d523365SDimitry Andric #include "llvm/IR/Instructions.h"
387d523365SDimitry Andric #include "llvm/IR/IntrinsicInst.h"
397d523365SDimitry Andric #include "llvm/IR/Operator.h"
40*b5893f02SDimitry Andric #include "llvm/IR/PatternMatch.h"
41*b5893f02SDimitry Andric
427d523365SDimitry Andric using namespace llvm;
43*b5893f02SDimitry Andric using namespace PatternMatch;
447d523365SDimitry Andric
457d523365SDimitry Andric #define DEBUG_TYPE "wasm-fastisel"
467d523365SDimitry Andric
477d523365SDimitry Andric namespace {
487d523365SDimitry Andric
497d523365SDimitry Andric class WebAssemblyFastISel final : public FastISel {
503ca95b02SDimitry Andric // All possible address modes.
513ca95b02SDimitry Andric class Address {
523ca95b02SDimitry Andric public:
533ca95b02SDimitry Andric typedef enum { RegBase, FrameIndexBase } BaseKind;
543ca95b02SDimitry Andric
553ca95b02SDimitry Andric private:
563ca95b02SDimitry Andric BaseKind Kind;
573ca95b02SDimitry Andric union {
583ca95b02SDimitry Andric unsigned Reg;
593ca95b02SDimitry Andric int FI;
603ca95b02SDimitry Andric } Base;
613ca95b02SDimitry Andric
623ca95b02SDimitry Andric int64_t Offset;
633ca95b02SDimitry Andric
643ca95b02SDimitry Andric const GlobalValue *GV;
653ca95b02SDimitry Andric
663ca95b02SDimitry Andric public:
673ca95b02SDimitry Andric // Innocuous defaults for our address.
Address()683ca95b02SDimitry Andric Address() : Kind(RegBase), Offset(0), GV(0) { Base.Reg = 0; }
setKind(BaseKind K)69edd7eaddSDimitry Andric void setKind(BaseKind K) {
70edd7eaddSDimitry Andric assert(!isSet() && "Can't change kind with non-zero base");
71edd7eaddSDimitry Andric Kind = K;
72edd7eaddSDimitry Andric }
getKind() const733ca95b02SDimitry Andric BaseKind getKind() const { return Kind; }
isRegBase() const743ca95b02SDimitry Andric bool isRegBase() const { return Kind == RegBase; }
isFIBase() const753ca95b02SDimitry Andric bool isFIBase() const { return Kind == FrameIndexBase; }
setReg(unsigned Reg)763ca95b02SDimitry Andric void setReg(unsigned Reg) {
773ca95b02SDimitry Andric assert(isRegBase() && "Invalid base register access!");
78edd7eaddSDimitry Andric assert(Base.Reg == 0 && "Overwriting non-zero register");
793ca95b02SDimitry Andric Base.Reg = Reg;
803ca95b02SDimitry Andric }
getReg() const813ca95b02SDimitry Andric unsigned getReg() const {
823ca95b02SDimitry Andric assert(isRegBase() && "Invalid base register access!");
833ca95b02SDimitry Andric return Base.Reg;
843ca95b02SDimitry Andric }
setFI(unsigned FI)853ca95b02SDimitry Andric void setFI(unsigned FI) {
863ca95b02SDimitry Andric assert(isFIBase() && "Invalid base frame index access!");
87edd7eaddSDimitry Andric assert(Base.FI == 0 && "Overwriting non-zero frame index");
883ca95b02SDimitry Andric Base.FI = FI;
893ca95b02SDimitry Andric }
getFI() const903ca95b02SDimitry Andric unsigned getFI() const {
913ca95b02SDimitry Andric assert(isFIBase() && "Invalid base frame index access!");
923ca95b02SDimitry Andric return Base.FI;
933ca95b02SDimitry Andric }
943ca95b02SDimitry Andric
setOffset(int64_t Offset_)95d88c1a5aSDimitry Andric void setOffset(int64_t Offset_) {
96d88c1a5aSDimitry Andric assert(Offset_ >= 0 && "Offsets must be non-negative");
97d88c1a5aSDimitry Andric Offset = Offset_;
98d88c1a5aSDimitry Andric }
getOffset() const993ca95b02SDimitry Andric int64_t getOffset() const { return Offset; }
setGlobalValue(const GlobalValue * G)1003ca95b02SDimitry Andric void setGlobalValue(const GlobalValue *G) { GV = G; }
getGlobalValue() const1013ca95b02SDimitry Andric const GlobalValue *getGlobalValue() const { return GV; }
isSet() const102edd7eaddSDimitry Andric bool isSet() const {
103edd7eaddSDimitry Andric if (isRegBase()) {
104edd7eaddSDimitry Andric return Base.Reg != 0;
105edd7eaddSDimitry Andric } else {
106edd7eaddSDimitry Andric return Base.FI != 0;
107edd7eaddSDimitry Andric }
108edd7eaddSDimitry Andric }
1093ca95b02SDimitry Andric };
1103ca95b02SDimitry Andric
1117d523365SDimitry Andric /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
1127d523365SDimitry Andric /// right decision when generating code for different targets.
1137d523365SDimitry Andric const WebAssemblySubtarget *Subtarget;
1147d523365SDimitry Andric LLVMContext *Context;
1157d523365SDimitry Andric
1167d523365SDimitry Andric private:
1173ca95b02SDimitry Andric // Utility helper routines
getSimpleType(Type * Ty)1183ca95b02SDimitry Andric MVT::SimpleValueType getSimpleType(Type *Ty) {
1193ca95b02SDimitry Andric EVT VT = TLI.getValueType(DL, Ty, /*HandleUnknown=*/true);
120*b5893f02SDimitry Andric return VT.isSimple() ? VT.getSimpleVT().SimpleTy
121*b5893f02SDimitry Andric : MVT::INVALID_SIMPLE_VALUE_TYPE;
1223ca95b02SDimitry Andric }
getLegalType(MVT::SimpleValueType VT)1233ca95b02SDimitry Andric MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
1243ca95b02SDimitry Andric switch (VT) {
1253ca95b02SDimitry Andric case MVT::i1:
1263ca95b02SDimitry Andric case MVT::i8:
1273ca95b02SDimitry Andric case MVT::i16:
1283ca95b02SDimitry Andric return MVT::i32;
1293ca95b02SDimitry Andric case MVT::i32:
1303ca95b02SDimitry Andric case MVT::i64:
1313ca95b02SDimitry Andric case MVT::f32:
1323ca95b02SDimitry Andric case MVT::f64:
1334ba319b5SDimitry Andric case MVT::ExceptRef:
1343ca95b02SDimitry Andric return VT;
1357a7e6055SDimitry Andric case MVT::f16:
1367a7e6055SDimitry Andric return MVT::f32;
137d88c1a5aSDimitry Andric case MVT::v16i8:
138d88c1a5aSDimitry Andric case MVT::v8i16:
139d88c1a5aSDimitry Andric case MVT::v4i32:
140d88c1a5aSDimitry Andric case MVT::v4f32:
141d88c1a5aSDimitry Andric if (Subtarget->hasSIMD128())
142d88c1a5aSDimitry Andric return VT;
143d88c1a5aSDimitry Andric break;
144*b5893f02SDimitry Andric case MVT::v2i64:
145*b5893f02SDimitry Andric case MVT::v2f64:
146*b5893f02SDimitry Andric if (Subtarget->hasUnimplementedSIMD128())
147*b5893f02SDimitry Andric return VT;
148*b5893f02SDimitry Andric break;
1493ca95b02SDimitry Andric default:
1503ca95b02SDimitry Andric break;
1513ca95b02SDimitry Andric }
1523ca95b02SDimitry Andric return MVT::INVALID_SIMPLE_VALUE_TYPE;
1533ca95b02SDimitry Andric }
1543ca95b02SDimitry Andric bool computeAddress(const Value *Obj, Address &Addr);
1553ca95b02SDimitry Andric void materializeLoadStoreOperands(Address &Addr);
1563ca95b02SDimitry Andric void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
1573ca95b02SDimitry Andric MachineMemOperand *MMO);
1583ca95b02SDimitry Andric unsigned maskI1Value(unsigned Reg, const Value *V);
1593ca95b02SDimitry Andric unsigned getRegForI1Value(const Value *V, bool &Not);
1603ca95b02SDimitry Andric unsigned zeroExtendToI32(unsigned Reg, const Value *V,
1613ca95b02SDimitry Andric MVT::SimpleValueType From);
1623ca95b02SDimitry Andric unsigned signExtendToI32(unsigned Reg, const Value *V,
1633ca95b02SDimitry Andric MVT::SimpleValueType From);
164*b5893f02SDimitry Andric unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
1653ca95b02SDimitry Andric MVT::SimpleValueType To);
166*b5893f02SDimitry Andric unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
1673ca95b02SDimitry Andric MVT::SimpleValueType To);
1683ca95b02SDimitry Andric unsigned getRegForUnsignedValue(const Value *V);
1693ca95b02SDimitry Andric unsigned getRegForSignedValue(const Value *V);
1703ca95b02SDimitry Andric unsigned getRegForPromotedValue(const Value *V, bool IsSigned);
1713ca95b02SDimitry Andric unsigned notValue(unsigned Reg);
1723ca95b02SDimitry Andric unsigned copyValue(unsigned Reg);
1733ca95b02SDimitry Andric
1743ca95b02SDimitry Andric // Backend specific FastISel code.
1753ca95b02SDimitry Andric unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
1763ca95b02SDimitry Andric unsigned fastMaterializeConstant(const Constant *C) override;
1773ca95b02SDimitry Andric bool fastLowerArguments() override;
1783ca95b02SDimitry Andric
1793ca95b02SDimitry Andric // Selection routines.
1803ca95b02SDimitry Andric bool selectCall(const Instruction *I);
1813ca95b02SDimitry Andric bool selectSelect(const Instruction *I);
1823ca95b02SDimitry Andric bool selectTrunc(const Instruction *I);
1833ca95b02SDimitry Andric bool selectZExt(const Instruction *I);
1843ca95b02SDimitry Andric bool selectSExt(const Instruction *I);
1853ca95b02SDimitry Andric bool selectICmp(const Instruction *I);
1863ca95b02SDimitry Andric bool selectFCmp(const Instruction *I);
1873ca95b02SDimitry Andric bool selectBitCast(const Instruction *I);
1883ca95b02SDimitry Andric bool selectLoad(const Instruction *I);
1893ca95b02SDimitry Andric bool selectStore(const Instruction *I);
1903ca95b02SDimitry Andric bool selectBr(const Instruction *I);
1913ca95b02SDimitry Andric bool selectRet(const Instruction *I);
1923ca95b02SDimitry Andric bool selectUnreachable(const Instruction *I);
1933ca95b02SDimitry Andric
1947d523365SDimitry Andric public:
1957d523365SDimitry Andric // Backend specific FastISel code.
WebAssemblyFastISel(FunctionLoweringInfo & FuncInfo,const TargetLibraryInfo * LibInfo)1967d523365SDimitry Andric WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo,
1977d523365SDimitry Andric const TargetLibraryInfo *LibInfo)
1987d523365SDimitry Andric : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
1997d523365SDimitry Andric Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>();
2007d523365SDimitry Andric Context = &FuncInfo.Fn->getContext();
2017d523365SDimitry Andric }
2027d523365SDimitry Andric
2037d523365SDimitry Andric bool fastSelectInstruction(const Instruction *I) override;
2047d523365SDimitry Andric
2057d523365SDimitry Andric #include "WebAssemblyGenFastISel.inc"
2067d523365SDimitry Andric };
2077d523365SDimitry Andric
2087d523365SDimitry Andric } // end anonymous namespace
2097d523365SDimitry Andric
computeAddress(const Value * Obj,Address & Addr)2103ca95b02SDimitry Andric bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {
2113ca95b02SDimitry Andric
2123ca95b02SDimitry Andric const User *U = nullptr;
2133ca95b02SDimitry Andric unsigned Opcode = Instruction::UserOp1;
2143ca95b02SDimitry Andric if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
2153ca95b02SDimitry Andric // Don't walk into other basic blocks unless the object is an alloca from
2163ca95b02SDimitry Andric // another block, otherwise it may not have a virtual register assigned.
2173ca95b02SDimitry Andric if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
2183ca95b02SDimitry Andric FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
2193ca95b02SDimitry Andric Opcode = I->getOpcode();
2203ca95b02SDimitry Andric U = I;
2213ca95b02SDimitry Andric }
2223ca95b02SDimitry Andric } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
2233ca95b02SDimitry Andric Opcode = C->getOpcode();
2243ca95b02SDimitry Andric U = C;
2253ca95b02SDimitry Andric }
2263ca95b02SDimitry Andric
2273ca95b02SDimitry Andric if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
2283ca95b02SDimitry Andric if (Ty->getAddressSpace() > 255)
2293ca95b02SDimitry Andric // Fast instruction selection doesn't support the special
2303ca95b02SDimitry Andric // address spaces.
2313ca95b02SDimitry Andric return false;
2323ca95b02SDimitry Andric
2333ca95b02SDimitry Andric if (const GlobalValue *GV = dyn_cast<GlobalValue>(Obj)) {
2343ca95b02SDimitry Andric if (Addr.getGlobalValue())
2353ca95b02SDimitry Andric return false;
2363ca95b02SDimitry Andric Addr.setGlobalValue(GV);
2373ca95b02SDimitry Andric return true;
2383ca95b02SDimitry Andric }
2393ca95b02SDimitry Andric
2403ca95b02SDimitry Andric switch (Opcode) {
2417d523365SDimitry Andric default:
2427d523365SDimitry Andric break;
2433ca95b02SDimitry Andric case Instruction::BitCast: {
2443ca95b02SDimitry Andric // Look through bitcasts.
2453ca95b02SDimitry Andric return computeAddress(U->getOperand(0), Addr);
2463ca95b02SDimitry Andric }
2473ca95b02SDimitry Andric case Instruction::IntToPtr: {
2483ca95b02SDimitry Andric // Look past no-op inttoptrs.
2493ca95b02SDimitry Andric if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
2503ca95b02SDimitry Andric TLI.getPointerTy(DL))
2513ca95b02SDimitry Andric return computeAddress(U->getOperand(0), Addr);
2523ca95b02SDimitry Andric break;
2533ca95b02SDimitry Andric }
2543ca95b02SDimitry Andric case Instruction::PtrToInt: {
2553ca95b02SDimitry Andric // Look past no-op ptrtoints.
2563ca95b02SDimitry Andric if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
2573ca95b02SDimitry Andric return computeAddress(U->getOperand(0), Addr);
2583ca95b02SDimitry Andric break;
2593ca95b02SDimitry Andric }
2603ca95b02SDimitry Andric case Instruction::GetElementPtr: {
2613ca95b02SDimitry Andric Address SavedAddr = Addr;
2623ca95b02SDimitry Andric uint64_t TmpOffset = Addr.getOffset();
263d88c1a5aSDimitry Andric // Non-inbounds geps can wrap; wasm's offsets can't.
264d88c1a5aSDimitry Andric if (!cast<GEPOperator>(U)->isInBounds())
265d88c1a5aSDimitry Andric goto unsupported_gep;
2663ca95b02SDimitry Andric // Iterate through the GEP folding the constants into offsets where
2673ca95b02SDimitry Andric // we can.
2683ca95b02SDimitry Andric for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
2693ca95b02SDimitry Andric GTI != E; ++GTI) {
2703ca95b02SDimitry Andric const Value *Op = GTI.getOperand();
271d88c1a5aSDimitry Andric if (StructType *STy = GTI.getStructTypeOrNull()) {
2723ca95b02SDimitry Andric const StructLayout *SL = DL.getStructLayout(STy);
2733ca95b02SDimitry Andric unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
2743ca95b02SDimitry Andric TmpOffset += SL->getElementOffset(Idx);
2753ca95b02SDimitry Andric } else {
2763ca95b02SDimitry Andric uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
2773ca95b02SDimitry Andric for (;;) {
2783ca95b02SDimitry Andric if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
2793ca95b02SDimitry Andric // Constant-offset addressing.
2803ca95b02SDimitry Andric TmpOffset += CI->getSExtValue() * S;
2813ca95b02SDimitry Andric break;
2823ca95b02SDimitry Andric }
2833ca95b02SDimitry Andric if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
2843ca95b02SDimitry Andric // An unscaled add of a register. Set it as the new base.
2852cab237bSDimitry Andric unsigned Reg = getRegForValue(Op);
2862cab237bSDimitry Andric if (Reg == 0)
2872cab237bSDimitry Andric return false;
2882cab237bSDimitry Andric Addr.setReg(Reg);
2893ca95b02SDimitry Andric break;
2903ca95b02SDimitry Andric }
2913ca95b02SDimitry Andric if (canFoldAddIntoGEP(U, Op)) {
2923ca95b02SDimitry Andric // A compatible add with a constant operand. Fold the constant.
2933ca95b02SDimitry Andric ConstantInt *CI =
2943ca95b02SDimitry Andric cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
2953ca95b02SDimitry Andric TmpOffset += CI->getSExtValue() * S;
2963ca95b02SDimitry Andric // Iterate on the other operand.
2973ca95b02SDimitry Andric Op = cast<AddOperator>(Op)->getOperand(0);
2983ca95b02SDimitry Andric continue;
2993ca95b02SDimitry Andric }
3003ca95b02SDimitry Andric // Unsupported
3013ca95b02SDimitry Andric goto unsupported_gep;
3023ca95b02SDimitry Andric }
3033ca95b02SDimitry Andric }
3043ca95b02SDimitry Andric }
305d88c1a5aSDimitry Andric // Don't fold in negative offsets.
306d88c1a5aSDimitry Andric if (int64_t(TmpOffset) >= 0) {
3073ca95b02SDimitry Andric // Try to grab the base operand now.
3083ca95b02SDimitry Andric Addr.setOffset(TmpOffset);
3093ca95b02SDimitry Andric if (computeAddress(U->getOperand(0), Addr))
3103ca95b02SDimitry Andric return true;
311d88c1a5aSDimitry Andric }
3123ca95b02SDimitry Andric // We failed, restore everything and try the other options.
3133ca95b02SDimitry Andric Addr = SavedAddr;
3143ca95b02SDimitry Andric unsupported_gep:
3153ca95b02SDimitry Andric break;
3163ca95b02SDimitry Andric }
3173ca95b02SDimitry Andric case Instruction::Alloca: {
3183ca95b02SDimitry Andric const AllocaInst *AI = cast<AllocaInst>(Obj);
3193ca95b02SDimitry Andric DenseMap<const AllocaInst *, int>::iterator SI =
3203ca95b02SDimitry Andric FuncInfo.StaticAllocaMap.find(AI);
3213ca95b02SDimitry Andric if (SI != FuncInfo.StaticAllocaMap.end()) {
322edd7eaddSDimitry Andric if (Addr.isSet()) {
323edd7eaddSDimitry Andric return false;
324edd7eaddSDimitry Andric }
3253ca95b02SDimitry Andric Addr.setKind(Address::FrameIndexBase);
3263ca95b02SDimitry Andric Addr.setFI(SI->second);
3273ca95b02SDimitry Andric return true;
3283ca95b02SDimitry Andric }
3293ca95b02SDimitry Andric break;
3303ca95b02SDimitry Andric }
3313ca95b02SDimitry Andric case Instruction::Add: {
3323ca95b02SDimitry Andric // Adds of constants are common and easy enough.
3333ca95b02SDimitry Andric const Value *LHS = U->getOperand(0);
3343ca95b02SDimitry Andric const Value *RHS = U->getOperand(1);
3353ca95b02SDimitry Andric
3363ca95b02SDimitry Andric if (isa<ConstantInt>(LHS))
3373ca95b02SDimitry Andric std::swap(LHS, RHS);
3383ca95b02SDimitry Andric
3393ca95b02SDimitry Andric if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
340d88c1a5aSDimitry Andric uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
341d88c1a5aSDimitry Andric if (int64_t(TmpOffset) >= 0) {
342d88c1a5aSDimitry Andric Addr.setOffset(TmpOffset);
3433ca95b02SDimitry Andric return computeAddress(LHS, Addr);
3443ca95b02SDimitry Andric }
345d88c1a5aSDimitry Andric }
3463ca95b02SDimitry Andric
3473ca95b02SDimitry Andric Address Backup = Addr;
3483ca95b02SDimitry Andric if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
3493ca95b02SDimitry Andric return true;
3503ca95b02SDimitry Andric Addr = Backup;
3513ca95b02SDimitry Andric
3523ca95b02SDimitry Andric break;
3533ca95b02SDimitry Andric }
3543ca95b02SDimitry Andric case Instruction::Sub: {
3553ca95b02SDimitry Andric // Subs of constants are common and easy enough.
3563ca95b02SDimitry Andric const Value *LHS = U->getOperand(0);
3573ca95b02SDimitry Andric const Value *RHS = U->getOperand(1);
3583ca95b02SDimitry Andric
3593ca95b02SDimitry Andric if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
360d88c1a5aSDimitry Andric int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
361d88c1a5aSDimitry Andric if (TmpOffset >= 0) {
362d88c1a5aSDimitry Andric Addr.setOffset(TmpOffset);
3633ca95b02SDimitry Andric return computeAddress(LHS, Addr);
3643ca95b02SDimitry Andric }
365d88c1a5aSDimitry Andric }
3663ca95b02SDimitry Andric break;
3673ca95b02SDimitry Andric }
3683ca95b02SDimitry Andric }
369edd7eaddSDimitry Andric if (Addr.isSet()) {
370edd7eaddSDimitry Andric return false;
371edd7eaddSDimitry Andric }
3722cab237bSDimitry Andric unsigned Reg = getRegForValue(Obj);
3732cab237bSDimitry Andric if (Reg == 0)
3742cab237bSDimitry Andric return false;
3752cab237bSDimitry Andric Addr.setReg(Reg);
3763ca95b02SDimitry Andric return Addr.getReg() != 0;
3773ca95b02SDimitry Andric }
3783ca95b02SDimitry Andric
materializeLoadStoreOperands(Address & Addr)3793ca95b02SDimitry Andric void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
3803ca95b02SDimitry Andric if (Addr.isRegBase()) {
3813ca95b02SDimitry Andric unsigned Reg = Addr.getReg();
3823ca95b02SDimitry Andric if (Reg == 0) {
383*b5893f02SDimitry Andric Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
384*b5893f02SDimitry Andric : &WebAssembly::I32RegClass);
385*b5893f02SDimitry Andric unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
386*b5893f02SDimitry Andric : WebAssembly::CONST_I32;
3873ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
3883ca95b02SDimitry Andric .addImm(0);
3893ca95b02SDimitry Andric Addr.setReg(Reg);
3903ca95b02SDimitry Andric }
3913ca95b02SDimitry Andric }
3923ca95b02SDimitry Andric }
3933ca95b02SDimitry Andric
addLoadStoreOperands(const Address & Addr,const MachineInstrBuilder & MIB,MachineMemOperand * MMO)3943ca95b02SDimitry Andric void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
3953ca95b02SDimitry Andric const MachineInstrBuilder &MIB,
3963ca95b02SDimitry Andric MachineMemOperand *MMO) {
397d88c1a5aSDimitry Andric // Set the alignment operand (this is rewritten in SetP2AlignOperands).
398d88c1a5aSDimitry Andric // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
399d88c1a5aSDimitry Andric MIB.addImm(0);
400d88c1a5aSDimitry Andric
4013ca95b02SDimitry Andric if (const GlobalValue *GV = Addr.getGlobalValue())
4023ca95b02SDimitry Andric MIB.addGlobalAddress(GV, Addr.getOffset());
4033ca95b02SDimitry Andric else
4043ca95b02SDimitry Andric MIB.addImm(Addr.getOffset());
4053ca95b02SDimitry Andric
4063ca95b02SDimitry Andric if (Addr.isRegBase())
4073ca95b02SDimitry Andric MIB.addReg(Addr.getReg());
4083ca95b02SDimitry Andric else
4093ca95b02SDimitry Andric MIB.addFrameIndex(Addr.getFI());
4103ca95b02SDimitry Andric
4113ca95b02SDimitry Andric MIB.addMemOperand(MMO);
4123ca95b02SDimitry Andric }
4133ca95b02SDimitry Andric
maskI1Value(unsigned Reg,const Value * V)4143ca95b02SDimitry Andric unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
4153ca95b02SDimitry Andric return zeroExtendToI32(Reg, V, MVT::i1);
4163ca95b02SDimitry Andric }
4173ca95b02SDimitry Andric
getRegForI1Value(const Value * V,bool & Not)4183ca95b02SDimitry Andric unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
4193ca95b02SDimitry Andric if (const ICmpInst *ICmp = dyn_cast<ICmpInst>(V))
4203ca95b02SDimitry Andric if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
4213ca95b02SDimitry Andric if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
4223ca95b02SDimitry Andric Not = ICmp->isTrueWhenEqual();
4233ca95b02SDimitry Andric return getRegForValue(ICmp->getOperand(0));
4243ca95b02SDimitry Andric }
4253ca95b02SDimitry Andric
426*b5893f02SDimitry Andric Value *NotV;
427*b5893f02SDimitry Andric if (match(V, m_Not(m_Value(NotV))) && V->getType()->isIntegerTy(32)) {
4283ca95b02SDimitry Andric Not = true;
429*b5893f02SDimitry Andric return getRegForValue(NotV);
4303ca95b02SDimitry Andric }
4313ca95b02SDimitry Andric
4323ca95b02SDimitry Andric Not = false;
4332cab237bSDimitry Andric unsigned Reg = getRegForValue(V);
4342cab237bSDimitry Andric if (Reg == 0)
4352cab237bSDimitry Andric return 0;
4362cab237bSDimitry Andric return maskI1Value(Reg, V);
4373ca95b02SDimitry Andric }
4383ca95b02SDimitry Andric
zeroExtendToI32(unsigned Reg,const Value * V,MVT::SimpleValueType From)4393ca95b02SDimitry Andric unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
4403ca95b02SDimitry Andric MVT::SimpleValueType From) {
441d88c1a5aSDimitry Andric if (Reg == 0)
442d88c1a5aSDimitry Andric return 0;
443d88c1a5aSDimitry Andric
4443ca95b02SDimitry Andric switch (From) {
4453ca95b02SDimitry Andric case MVT::i1:
446*b5893f02SDimitry Andric // If the value is naturally an i1, we don't need to mask it. We only know
447*b5893f02SDimitry Andric // if a value is naturally an i1 if it is definitely lowered by FastISel,
448*b5893f02SDimitry Andric // not a DAG ISel fallback.
449*b5893f02SDimitry Andric if (V != nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr())
4503ca95b02SDimitry Andric return copyValue(Reg);
451*b5893f02SDimitry Andric break;
4523ca95b02SDimitry Andric case MVT::i8:
4533ca95b02SDimitry Andric case MVT::i16:
4543ca95b02SDimitry Andric break;
4553ca95b02SDimitry Andric case MVT::i32:
4563ca95b02SDimitry Andric return copyValue(Reg);
4573ca95b02SDimitry Andric default:
4583ca95b02SDimitry Andric return 0;
4593ca95b02SDimitry Andric }
4603ca95b02SDimitry Andric
4613ca95b02SDimitry Andric unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
4623ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4633ca95b02SDimitry Andric TII.get(WebAssembly::CONST_I32), Imm)
4643ca95b02SDimitry Andric .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
4653ca95b02SDimitry Andric
4663ca95b02SDimitry Andric unsigned Result = createResultReg(&WebAssembly::I32RegClass);
4673ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4683ca95b02SDimitry Andric TII.get(WebAssembly::AND_I32), Result)
4693ca95b02SDimitry Andric .addReg(Reg)
4703ca95b02SDimitry Andric .addReg(Imm);
4713ca95b02SDimitry Andric
4723ca95b02SDimitry Andric return Result;
4733ca95b02SDimitry Andric }
4743ca95b02SDimitry Andric
signExtendToI32(unsigned Reg,const Value * V,MVT::SimpleValueType From)4753ca95b02SDimitry Andric unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
4763ca95b02SDimitry Andric MVT::SimpleValueType From) {
477d88c1a5aSDimitry Andric if (Reg == 0)
478d88c1a5aSDimitry Andric return 0;
479d88c1a5aSDimitry Andric
4803ca95b02SDimitry Andric switch (From) {
4813ca95b02SDimitry Andric case MVT::i1:
4823ca95b02SDimitry Andric case MVT::i8:
4833ca95b02SDimitry Andric case MVT::i16:
4843ca95b02SDimitry Andric break;
4853ca95b02SDimitry Andric case MVT::i32:
4863ca95b02SDimitry Andric return copyValue(Reg);
4873ca95b02SDimitry Andric default:
4883ca95b02SDimitry Andric return 0;
4893ca95b02SDimitry Andric }
4903ca95b02SDimitry Andric
4913ca95b02SDimitry Andric unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
4923ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4933ca95b02SDimitry Andric TII.get(WebAssembly::CONST_I32), Imm)
4943ca95b02SDimitry Andric .addImm(32 - MVT(From).getSizeInBits());
4953ca95b02SDimitry Andric
4963ca95b02SDimitry Andric unsigned Left = createResultReg(&WebAssembly::I32RegClass);
4973ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
4983ca95b02SDimitry Andric TII.get(WebAssembly::SHL_I32), Left)
4993ca95b02SDimitry Andric .addReg(Reg)
5003ca95b02SDimitry Andric .addReg(Imm);
5013ca95b02SDimitry Andric
5023ca95b02SDimitry Andric unsigned Right = createResultReg(&WebAssembly::I32RegClass);
5033ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
5043ca95b02SDimitry Andric TII.get(WebAssembly::SHR_S_I32), Right)
5053ca95b02SDimitry Andric .addReg(Left)
5063ca95b02SDimitry Andric .addReg(Imm);
5073ca95b02SDimitry Andric
5083ca95b02SDimitry Andric return Right;
5093ca95b02SDimitry Andric }
5103ca95b02SDimitry Andric
zeroExtend(unsigned Reg,const Value * V,MVT::SimpleValueType From,MVT::SimpleValueType To)5113ca95b02SDimitry Andric unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
5123ca95b02SDimitry Andric MVT::SimpleValueType From,
5133ca95b02SDimitry Andric MVT::SimpleValueType To) {
5143ca95b02SDimitry Andric if (To == MVT::i64) {
5153ca95b02SDimitry Andric if (From == MVT::i64)
5163ca95b02SDimitry Andric return copyValue(Reg);
5173ca95b02SDimitry Andric
5183ca95b02SDimitry Andric Reg = zeroExtendToI32(Reg, V, From);
5193ca95b02SDimitry Andric
5203ca95b02SDimitry Andric unsigned Result = createResultReg(&WebAssembly::I64RegClass);
5213ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
5223ca95b02SDimitry Andric TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
5233ca95b02SDimitry Andric .addReg(Reg);
5243ca95b02SDimitry Andric return Result;
5253ca95b02SDimitry Andric }
5263ca95b02SDimitry Andric
5273ca95b02SDimitry Andric return zeroExtendToI32(Reg, V, From);
5283ca95b02SDimitry Andric }
5293ca95b02SDimitry Andric
signExtend(unsigned Reg,const Value * V,MVT::SimpleValueType From,MVT::SimpleValueType To)5303ca95b02SDimitry Andric unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
5313ca95b02SDimitry Andric MVT::SimpleValueType From,
5323ca95b02SDimitry Andric MVT::SimpleValueType To) {
5333ca95b02SDimitry Andric if (To == MVT::i64) {
5343ca95b02SDimitry Andric if (From == MVT::i64)
5353ca95b02SDimitry Andric return copyValue(Reg);
5363ca95b02SDimitry Andric
5373ca95b02SDimitry Andric Reg = signExtendToI32(Reg, V, From);
5383ca95b02SDimitry Andric
5393ca95b02SDimitry Andric unsigned Result = createResultReg(&WebAssembly::I64RegClass);
5403ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
5413ca95b02SDimitry Andric TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
5423ca95b02SDimitry Andric .addReg(Reg);
5433ca95b02SDimitry Andric return Result;
5443ca95b02SDimitry Andric }
5453ca95b02SDimitry Andric
5463ca95b02SDimitry Andric return signExtendToI32(Reg, V, From);
5473ca95b02SDimitry Andric }
5483ca95b02SDimitry Andric
getRegForUnsignedValue(const Value * V)5493ca95b02SDimitry Andric unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
5503ca95b02SDimitry Andric MVT::SimpleValueType From = getSimpleType(V->getType());
5513ca95b02SDimitry Andric MVT::SimpleValueType To = getLegalType(From);
5522cab237bSDimitry Andric unsigned VReg = getRegForValue(V);
5532cab237bSDimitry Andric if (VReg == 0)
5542cab237bSDimitry Andric return 0;
5552cab237bSDimitry Andric return zeroExtend(VReg, V, From, To);
5563ca95b02SDimitry Andric }
5573ca95b02SDimitry Andric
getRegForSignedValue(const Value * V)5583ca95b02SDimitry Andric unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
5593ca95b02SDimitry Andric MVT::SimpleValueType From = getSimpleType(V->getType());
5603ca95b02SDimitry Andric MVT::SimpleValueType To = getLegalType(From);
5612cab237bSDimitry Andric unsigned VReg = getRegForValue(V);
5622cab237bSDimitry Andric if (VReg == 0)
5632cab237bSDimitry Andric return 0;
5642cab237bSDimitry Andric return signExtend(VReg, V, From, To);
5653ca95b02SDimitry Andric }
5663ca95b02SDimitry Andric
getRegForPromotedValue(const Value * V,bool IsSigned)5673ca95b02SDimitry Andric unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
5683ca95b02SDimitry Andric bool IsSigned) {
569*b5893f02SDimitry Andric return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
5703ca95b02SDimitry Andric }
5713ca95b02SDimitry Andric
notValue(unsigned Reg)5723ca95b02SDimitry Andric unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
5733ca95b02SDimitry Andric assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
5743ca95b02SDimitry Andric
5753ca95b02SDimitry Andric unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
5763ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
5773ca95b02SDimitry Andric TII.get(WebAssembly::EQZ_I32), NotReg)
5783ca95b02SDimitry Andric .addReg(Reg);
5793ca95b02SDimitry Andric return NotReg;
5803ca95b02SDimitry Andric }
5813ca95b02SDimitry Andric
copyValue(unsigned Reg)5823ca95b02SDimitry Andric unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
5833ca95b02SDimitry Andric unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
584*b5893f02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
585*b5893f02SDimitry Andric ResultReg)
5863ca95b02SDimitry Andric .addReg(Reg);
5873ca95b02SDimitry Andric return ResultReg;
5883ca95b02SDimitry Andric }
5893ca95b02SDimitry Andric
fastMaterializeAlloca(const AllocaInst * AI)5903ca95b02SDimitry Andric unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
5913ca95b02SDimitry Andric DenseMap<const AllocaInst *, int>::iterator SI =
5923ca95b02SDimitry Andric FuncInfo.StaticAllocaMap.find(AI);
5933ca95b02SDimitry Andric
5943ca95b02SDimitry Andric if (SI != FuncInfo.StaticAllocaMap.end()) {
595*b5893f02SDimitry Andric unsigned ResultReg =
596*b5893f02SDimitry Andric createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
597*b5893f02SDimitry Andric : &WebAssembly::I32RegClass);
598*b5893f02SDimitry Andric unsigned Opc =
599*b5893f02SDimitry Andric Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
6003ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
6013ca95b02SDimitry Andric .addFrameIndex(SI->second);
6023ca95b02SDimitry Andric return ResultReg;
6033ca95b02SDimitry Andric }
6043ca95b02SDimitry Andric
6053ca95b02SDimitry Andric return 0;
6063ca95b02SDimitry Andric }
6073ca95b02SDimitry Andric
fastMaterializeConstant(const Constant * C)6083ca95b02SDimitry Andric unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
6093ca95b02SDimitry Andric if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
610*b5893f02SDimitry Andric unsigned ResultReg =
611*b5893f02SDimitry Andric createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
612*b5893f02SDimitry Andric : &WebAssembly::I32RegClass);
613*b5893f02SDimitry Andric unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
614*b5893f02SDimitry Andric : WebAssembly::CONST_I32;
6153ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
6163ca95b02SDimitry Andric .addGlobalAddress(GV);
6173ca95b02SDimitry Andric return ResultReg;
6183ca95b02SDimitry Andric }
6193ca95b02SDimitry Andric
6203ca95b02SDimitry Andric // Let target-independent code handle it.
6213ca95b02SDimitry Andric return 0;
6223ca95b02SDimitry Andric }
6233ca95b02SDimitry Andric
fastLowerArguments()6243ca95b02SDimitry Andric bool WebAssemblyFastISel::fastLowerArguments() {
6253ca95b02SDimitry Andric if (!FuncInfo.CanLowerReturn)
6263ca95b02SDimitry Andric return false;
6273ca95b02SDimitry Andric
6283ca95b02SDimitry Andric const Function *F = FuncInfo.Fn;
6293ca95b02SDimitry Andric if (F->isVarArg())
6303ca95b02SDimitry Andric return false;
6313ca95b02SDimitry Andric
6323ca95b02SDimitry Andric unsigned i = 0;
6333ca95b02SDimitry Andric for (auto const &Arg : F->args()) {
6347a7e6055SDimitry Andric const AttributeList &Attrs = F->getAttributes();
6357a7e6055SDimitry Andric if (Attrs.hasParamAttribute(i, Attribute::ByVal) ||
6367a7e6055SDimitry Andric Attrs.hasParamAttribute(i, Attribute::SwiftSelf) ||
6377a7e6055SDimitry Andric Attrs.hasParamAttribute(i, Attribute::SwiftError) ||
6387a7e6055SDimitry Andric Attrs.hasParamAttribute(i, Attribute::InAlloca) ||
6397a7e6055SDimitry Andric Attrs.hasParamAttribute(i, Attribute::Nest))
6403ca95b02SDimitry Andric return false;
6413ca95b02SDimitry Andric
6423ca95b02SDimitry Andric Type *ArgTy = Arg.getType();
643d88c1a5aSDimitry Andric if (ArgTy->isStructTy() || ArgTy->isArrayTy())
644d88c1a5aSDimitry Andric return false;
645d88c1a5aSDimitry Andric if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
6463ca95b02SDimitry Andric return false;
6473ca95b02SDimitry Andric
6483ca95b02SDimitry Andric unsigned Opc;
6493ca95b02SDimitry Andric const TargetRegisterClass *RC;
6503ca95b02SDimitry Andric switch (getSimpleType(ArgTy)) {
6513ca95b02SDimitry Andric case MVT::i1:
6523ca95b02SDimitry Andric case MVT::i8:
6533ca95b02SDimitry Andric case MVT::i16:
6543ca95b02SDimitry Andric case MVT::i32:
655*b5893f02SDimitry Andric Opc = WebAssembly::ARGUMENT_i32;
6563ca95b02SDimitry Andric RC = &WebAssembly::I32RegClass;
6573ca95b02SDimitry Andric break;
6583ca95b02SDimitry Andric case MVT::i64:
659*b5893f02SDimitry Andric Opc = WebAssembly::ARGUMENT_i64;
6603ca95b02SDimitry Andric RC = &WebAssembly::I64RegClass;
6613ca95b02SDimitry Andric break;
6623ca95b02SDimitry Andric case MVT::f32:
663*b5893f02SDimitry Andric Opc = WebAssembly::ARGUMENT_f32;
6643ca95b02SDimitry Andric RC = &WebAssembly::F32RegClass;
6653ca95b02SDimitry Andric break;
6663ca95b02SDimitry Andric case MVT::f64:
667*b5893f02SDimitry Andric Opc = WebAssembly::ARGUMENT_f64;
6683ca95b02SDimitry Andric RC = &WebAssembly::F64RegClass;
6693ca95b02SDimitry Andric break;
670d88c1a5aSDimitry Andric case MVT::v16i8:
671d88c1a5aSDimitry Andric Opc = WebAssembly::ARGUMENT_v16i8;
672d88c1a5aSDimitry Andric RC = &WebAssembly::V128RegClass;
673d88c1a5aSDimitry Andric break;
674d88c1a5aSDimitry Andric case MVT::v8i16:
675d88c1a5aSDimitry Andric Opc = WebAssembly::ARGUMENT_v8i16;
676d88c1a5aSDimitry Andric RC = &WebAssembly::V128RegClass;
677d88c1a5aSDimitry Andric break;
678d88c1a5aSDimitry Andric case MVT::v4i32:
679d88c1a5aSDimitry Andric Opc = WebAssembly::ARGUMENT_v4i32;
680d88c1a5aSDimitry Andric RC = &WebAssembly::V128RegClass;
681d88c1a5aSDimitry Andric break;
682*b5893f02SDimitry Andric case MVT::v2i64:
683*b5893f02SDimitry Andric Opc = WebAssembly::ARGUMENT_v2i64;
684*b5893f02SDimitry Andric RC = &WebAssembly::V128RegClass;
685*b5893f02SDimitry Andric break;
686d88c1a5aSDimitry Andric case MVT::v4f32:
687d88c1a5aSDimitry Andric Opc = WebAssembly::ARGUMENT_v4f32;
688d88c1a5aSDimitry Andric RC = &WebAssembly::V128RegClass;
689d88c1a5aSDimitry Andric break;
690*b5893f02SDimitry Andric case MVT::v2f64:
691*b5893f02SDimitry Andric Opc = WebAssembly::ARGUMENT_v2f64;
692*b5893f02SDimitry Andric RC = &WebAssembly::V128RegClass;
693*b5893f02SDimitry Andric break;
6944ba319b5SDimitry Andric case MVT::ExceptRef:
695*b5893f02SDimitry Andric Opc = WebAssembly::ARGUMENT_ExceptRef;
6964ba319b5SDimitry Andric RC = &WebAssembly::EXCEPT_REFRegClass;
6974ba319b5SDimitry Andric break;
6983ca95b02SDimitry Andric default:
6993ca95b02SDimitry Andric return false;
7003ca95b02SDimitry Andric }
7013ca95b02SDimitry Andric unsigned ResultReg = createResultReg(RC);
7023ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
7033ca95b02SDimitry Andric .addImm(i);
7043ca95b02SDimitry Andric updateValueMap(&Arg, ResultReg);
7053ca95b02SDimitry Andric
7063ca95b02SDimitry Andric ++i;
7073ca95b02SDimitry Andric }
7083ca95b02SDimitry Andric
7093ca95b02SDimitry Andric MRI.addLiveIn(WebAssembly::ARGUMENTS);
7103ca95b02SDimitry Andric
7113ca95b02SDimitry Andric auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
7124ba319b5SDimitry Andric for (auto const &Arg : F->args()) {
7134ba319b5SDimitry Andric MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType()));
7144ba319b5SDimitry Andric if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
7154ba319b5SDimitry Andric MFI->clearParamsAndResults();
7164ba319b5SDimitry Andric return false;
7174ba319b5SDimitry Andric }
7184ba319b5SDimitry Andric MFI->addParam(ArgTy);
7194ba319b5SDimitry Andric }
7203ca95b02SDimitry Andric
7214ba319b5SDimitry Andric if (!F->getReturnType()->isVoidTy()) {
722*b5893f02SDimitry Andric MVT::SimpleValueType RetTy =
723*b5893f02SDimitry Andric getLegalType(getSimpleType(F->getReturnType()));
7244ba319b5SDimitry Andric if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
7254ba319b5SDimitry Andric MFI->clearParamsAndResults();
7264ba319b5SDimitry Andric return false;
7274ba319b5SDimitry Andric }
7284ba319b5SDimitry Andric MFI->addResult(RetTy);
7294ba319b5SDimitry Andric }
730f1a29dd3SDimitry Andric
7313ca95b02SDimitry Andric return true;
7323ca95b02SDimitry Andric }
7333ca95b02SDimitry Andric
selectCall(const Instruction * I)7343ca95b02SDimitry Andric bool WebAssemblyFastISel::selectCall(const Instruction *I) {
7353ca95b02SDimitry Andric const CallInst *Call = cast<CallInst>(I);
7363ca95b02SDimitry Andric
7373ca95b02SDimitry Andric if (Call->isMustTailCall() || Call->isInlineAsm() ||
7383ca95b02SDimitry Andric Call->getFunctionType()->isVarArg())
7393ca95b02SDimitry Andric return false;
7403ca95b02SDimitry Andric
7413ca95b02SDimitry Andric Function *Func = Call->getCalledFunction();
7423ca95b02SDimitry Andric if (Func && Func->isIntrinsic())
7433ca95b02SDimitry Andric return false;
7443ca95b02SDimitry Andric
7452cab237bSDimitry Andric bool IsDirect = Func != nullptr;
7462cab237bSDimitry Andric if (!IsDirect && isa<ConstantExpr>(Call->getCalledValue()))
7472cab237bSDimitry Andric return false;
7482cab237bSDimitry Andric
7493ca95b02SDimitry Andric FunctionType *FuncTy = Call->getFunctionType();
7503ca95b02SDimitry Andric unsigned Opc;
7513ca95b02SDimitry Andric bool IsVoid = FuncTy->getReturnType()->isVoidTy();
7523ca95b02SDimitry Andric unsigned ResultReg;
7533ca95b02SDimitry Andric if (IsVoid) {
754d88c1a5aSDimitry Andric Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
7553ca95b02SDimitry Andric } else {
756d88c1a5aSDimitry Andric if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
757d88c1a5aSDimitry Andric return false;
758d88c1a5aSDimitry Andric
7593ca95b02SDimitry Andric MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
7603ca95b02SDimitry Andric switch (RetTy) {
7613ca95b02SDimitry Andric case MVT::i1:
7623ca95b02SDimitry Andric case MVT::i8:
7633ca95b02SDimitry Andric case MVT::i16:
7643ca95b02SDimitry Andric case MVT::i32:
765d88c1a5aSDimitry Andric Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::PCALL_INDIRECT_I32;
7663ca95b02SDimitry Andric ResultReg = createResultReg(&WebAssembly::I32RegClass);
7673ca95b02SDimitry Andric break;
7683ca95b02SDimitry Andric case MVT::i64:
769d88c1a5aSDimitry Andric Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::PCALL_INDIRECT_I64;
7703ca95b02SDimitry Andric ResultReg = createResultReg(&WebAssembly::I64RegClass);
7713ca95b02SDimitry Andric break;
7723ca95b02SDimitry Andric case MVT::f32:
773d88c1a5aSDimitry Andric Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::PCALL_INDIRECT_F32;
7743ca95b02SDimitry Andric ResultReg = createResultReg(&WebAssembly::F32RegClass);
7753ca95b02SDimitry Andric break;
7763ca95b02SDimitry Andric case MVT::f64:
777d88c1a5aSDimitry Andric Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::PCALL_INDIRECT_F64;
7783ca95b02SDimitry Andric ResultReg = createResultReg(&WebAssembly::F64RegClass);
7793ca95b02SDimitry Andric break;
780d88c1a5aSDimitry Andric case MVT::v16i8:
781*b5893f02SDimitry Andric Opc = IsDirect ? WebAssembly::CALL_v16i8
782*b5893f02SDimitry Andric : WebAssembly::PCALL_INDIRECT_v16i8;
783d88c1a5aSDimitry Andric ResultReg = createResultReg(&WebAssembly::V128RegClass);
784d88c1a5aSDimitry Andric break;
785d88c1a5aSDimitry Andric case MVT::v8i16:
786*b5893f02SDimitry Andric Opc = IsDirect ? WebAssembly::CALL_v8i16
787*b5893f02SDimitry Andric : WebAssembly::PCALL_INDIRECT_v8i16;
788d88c1a5aSDimitry Andric ResultReg = createResultReg(&WebAssembly::V128RegClass);
789d88c1a5aSDimitry Andric break;
790d88c1a5aSDimitry Andric case MVT::v4i32:
791*b5893f02SDimitry Andric Opc = IsDirect ? WebAssembly::CALL_v4i32
792*b5893f02SDimitry Andric : WebAssembly::PCALL_INDIRECT_v4i32;
793*b5893f02SDimitry Andric ResultReg = createResultReg(&WebAssembly::V128RegClass);
794*b5893f02SDimitry Andric break;
795*b5893f02SDimitry Andric case MVT::v2i64:
796*b5893f02SDimitry Andric Opc = IsDirect ? WebAssembly::CALL_v2i64
797*b5893f02SDimitry Andric : WebAssembly::PCALL_INDIRECT_v2i64;
798d88c1a5aSDimitry Andric ResultReg = createResultReg(&WebAssembly::V128RegClass);
799d88c1a5aSDimitry Andric break;
800d88c1a5aSDimitry Andric case MVT::v4f32:
801*b5893f02SDimitry Andric Opc = IsDirect ? WebAssembly::CALL_v4f32
802*b5893f02SDimitry Andric : WebAssembly::PCALL_INDIRECT_v4f32;
803*b5893f02SDimitry Andric ResultReg = createResultReg(&WebAssembly::V128RegClass);
804*b5893f02SDimitry Andric break;
805*b5893f02SDimitry Andric case MVT::v2f64:
806*b5893f02SDimitry Andric Opc = IsDirect ? WebAssembly::CALL_v2f64
807*b5893f02SDimitry Andric : WebAssembly::PCALL_INDIRECT_v2f64;
808d88c1a5aSDimitry Andric ResultReg = createResultReg(&WebAssembly::V128RegClass);
809d88c1a5aSDimitry Andric break;
8104ba319b5SDimitry Andric case MVT::ExceptRef:
8114ba319b5SDimitry Andric Opc = IsDirect ? WebAssembly::CALL_EXCEPT_REF
8124ba319b5SDimitry Andric : WebAssembly::PCALL_INDIRECT_EXCEPT_REF;
8134ba319b5SDimitry Andric ResultReg = createResultReg(&WebAssembly::EXCEPT_REFRegClass);
8144ba319b5SDimitry Andric break;
8153ca95b02SDimitry Andric default:
8163ca95b02SDimitry Andric return false;
8173ca95b02SDimitry Andric }
8183ca95b02SDimitry Andric }
8193ca95b02SDimitry Andric
8203ca95b02SDimitry Andric SmallVector<unsigned, 8> Args;
8213ca95b02SDimitry Andric for (unsigned i = 0, e = Call->getNumArgOperands(); i < e; ++i) {
8223ca95b02SDimitry Andric Value *V = Call->getArgOperand(i);
8233ca95b02SDimitry Andric MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
8243ca95b02SDimitry Andric if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
8253ca95b02SDimitry Andric return false;
8263ca95b02SDimitry Andric
8277a7e6055SDimitry Andric const AttributeList &Attrs = Call->getAttributes();
8287a7e6055SDimitry Andric if (Attrs.hasParamAttribute(i, Attribute::ByVal) ||
8297a7e6055SDimitry Andric Attrs.hasParamAttribute(i, Attribute::SwiftSelf) ||
8307a7e6055SDimitry Andric Attrs.hasParamAttribute(i, Attribute::SwiftError) ||
8317a7e6055SDimitry Andric Attrs.hasParamAttribute(i, Attribute::InAlloca) ||
8327a7e6055SDimitry Andric Attrs.hasParamAttribute(i, Attribute::Nest))
8333ca95b02SDimitry Andric return false;
8343ca95b02SDimitry Andric
8353ca95b02SDimitry Andric unsigned Reg;
8363ca95b02SDimitry Andric
8377a7e6055SDimitry Andric if (Attrs.hasParamAttribute(i, Attribute::SExt))
8383ca95b02SDimitry Andric Reg = getRegForSignedValue(V);
8397a7e6055SDimitry Andric else if (Attrs.hasParamAttribute(i, Attribute::ZExt))
8403ca95b02SDimitry Andric Reg = getRegForUnsignedValue(V);
8413ca95b02SDimitry Andric else
8423ca95b02SDimitry Andric Reg = getRegForValue(V);
8433ca95b02SDimitry Andric
8443ca95b02SDimitry Andric if (Reg == 0)
8453ca95b02SDimitry Andric return false;
8463ca95b02SDimitry Andric
8473ca95b02SDimitry Andric Args.push_back(Reg);
8483ca95b02SDimitry Andric }
8493ca95b02SDimitry Andric
8503ca95b02SDimitry Andric auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
8513ca95b02SDimitry Andric
8523ca95b02SDimitry Andric if (!IsVoid)
8533ca95b02SDimitry Andric MIB.addReg(ResultReg, RegState::Define);
8543ca95b02SDimitry Andric
8553ca95b02SDimitry Andric if (IsDirect)
8563ca95b02SDimitry Andric MIB.addGlobalAddress(Func);
8572cab237bSDimitry Andric else {
8582cab237bSDimitry Andric unsigned Reg = getRegForValue(Call->getCalledValue());
8592cab237bSDimitry Andric if (Reg == 0)
8602cab237bSDimitry Andric return false;
8612cab237bSDimitry Andric MIB.addReg(Reg);
8622cab237bSDimitry Andric }
8633ca95b02SDimitry Andric
8643ca95b02SDimitry Andric for (unsigned ArgReg : Args)
8653ca95b02SDimitry Andric MIB.addReg(ArgReg);
8663ca95b02SDimitry Andric
8673ca95b02SDimitry Andric if (!IsVoid)
8683ca95b02SDimitry Andric updateValueMap(Call, ResultReg);
8693ca95b02SDimitry Andric return true;
8703ca95b02SDimitry Andric }
8713ca95b02SDimitry Andric
selectSelect(const Instruction * I)8723ca95b02SDimitry Andric bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
8733ca95b02SDimitry Andric const SelectInst *Select = cast<SelectInst>(I);
8743ca95b02SDimitry Andric
8753ca95b02SDimitry Andric bool Not;
8763ca95b02SDimitry Andric unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
8773ca95b02SDimitry Andric if (CondReg == 0)
8783ca95b02SDimitry Andric return false;
8793ca95b02SDimitry Andric
8803ca95b02SDimitry Andric unsigned TrueReg = getRegForValue(Select->getTrueValue());
8813ca95b02SDimitry Andric if (TrueReg == 0)
8823ca95b02SDimitry Andric return false;
8833ca95b02SDimitry Andric
8843ca95b02SDimitry Andric unsigned FalseReg = getRegForValue(Select->getFalseValue());
8853ca95b02SDimitry Andric if (FalseReg == 0)
8863ca95b02SDimitry Andric return false;
8873ca95b02SDimitry Andric
8883ca95b02SDimitry Andric if (Not)
8893ca95b02SDimitry Andric std::swap(TrueReg, FalseReg);
8903ca95b02SDimitry Andric
8913ca95b02SDimitry Andric unsigned Opc;
8923ca95b02SDimitry Andric const TargetRegisterClass *RC;
8933ca95b02SDimitry Andric switch (getSimpleType(Select->getType())) {
8943ca95b02SDimitry Andric case MVT::i1:
8953ca95b02SDimitry Andric case MVT::i8:
8963ca95b02SDimitry Andric case MVT::i16:
8973ca95b02SDimitry Andric case MVT::i32:
8983ca95b02SDimitry Andric Opc = WebAssembly::SELECT_I32;
8993ca95b02SDimitry Andric RC = &WebAssembly::I32RegClass;
9003ca95b02SDimitry Andric break;
9013ca95b02SDimitry Andric case MVT::i64:
9023ca95b02SDimitry Andric Opc = WebAssembly::SELECT_I64;
9033ca95b02SDimitry Andric RC = &WebAssembly::I64RegClass;
9043ca95b02SDimitry Andric break;
9053ca95b02SDimitry Andric case MVT::f32:
9063ca95b02SDimitry Andric Opc = WebAssembly::SELECT_F32;
9073ca95b02SDimitry Andric RC = &WebAssembly::F32RegClass;
9083ca95b02SDimitry Andric break;
9093ca95b02SDimitry Andric case MVT::f64:
9103ca95b02SDimitry Andric Opc = WebAssembly::SELECT_F64;
9113ca95b02SDimitry Andric RC = &WebAssembly::F64RegClass;
9123ca95b02SDimitry Andric break;
9134ba319b5SDimitry Andric case MVT::ExceptRef:
9144ba319b5SDimitry Andric Opc = WebAssembly::SELECT_EXCEPT_REF;
9154ba319b5SDimitry Andric RC = &WebAssembly::EXCEPT_REFRegClass;
9164ba319b5SDimitry Andric break;
9173ca95b02SDimitry Andric default:
9183ca95b02SDimitry Andric return false;
9193ca95b02SDimitry Andric }
9203ca95b02SDimitry Andric
9213ca95b02SDimitry Andric unsigned ResultReg = createResultReg(RC);
9223ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
9233ca95b02SDimitry Andric .addReg(TrueReg)
9243ca95b02SDimitry Andric .addReg(FalseReg)
9253ca95b02SDimitry Andric .addReg(CondReg);
9263ca95b02SDimitry Andric
9273ca95b02SDimitry Andric updateValueMap(Select, ResultReg);
9283ca95b02SDimitry Andric return true;
9293ca95b02SDimitry Andric }
9303ca95b02SDimitry Andric
selectTrunc(const Instruction * I)9313ca95b02SDimitry Andric bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
9323ca95b02SDimitry Andric const TruncInst *Trunc = cast<TruncInst>(I);
9333ca95b02SDimitry Andric
9343ca95b02SDimitry Andric unsigned Reg = getRegForValue(Trunc->getOperand(0));
9353ca95b02SDimitry Andric if (Reg == 0)
9363ca95b02SDimitry Andric return false;
9373ca95b02SDimitry Andric
9383ca95b02SDimitry Andric if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
9393ca95b02SDimitry Andric unsigned Result = createResultReg(&WebAssembly::I32RegClass);
9403ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
9413ca95b02SDimitry Andric TII.get(WebAssembly::I32_WRAP_I64), Result)
9423ca95b02SDimitry Andric .addReg(Reg);
9433ca95b02SDimitry Andric Reg = Result;
9443ca95b02SDimitry Andric }
9453ca95b02SDimitry Andric
9463ca95b02SDimitry Andric updateValueMap(Trunc, Reg);
9473ca95b02SDimitry Andric return true;
9483ca95b02SDimitry Andric }
9493ca95b02SDimitry Andric
selectZExt(const Instruction * I)9503ca95b02SDimitry Andric bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
9513ca95b02SDimitry Andric const ZExtInst *ZExt = cast<ZExtInst>(I);
9523ca95b02SDimitry Andric
9533ca95b02SDimitry Andric const Value *Op = ZExt->getOperand(0);
9543ca95b02SDimitry Andric MVT::SimpleValueType From = getSimpleType(Op->getType());
9553ca95b02SDimitry Andric MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
9562cab237bSDimitry Andric unsigned In = getRegForValue(Op);
9572cab237bSDimitry Andric if (In == 0)
9582cab237bSDimitry Andric return false;
9592cab237bSDimitry Andric unsigned Reg = zeroExtend(In, Op, From, To);
9603ca95b02SDimitry Andric if (Reg == 0)
9613ca95b02SDimitry Andric return false;
9623ca95b02SDimitry Andric
9633ca95b02SDimitry Andric updateValueMap(ZExt, Reg);
9643ca95b02SDimitry Andric return true;
9653ca95b02SDimitry Andric }
9663ca95b02SDimitry Andric
selectSExt(const Instruction * I)9673ca95b02SDimitry Andric bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
9683ca95b02SDimitry Andric const SExtInst *SExt = cast<SExtInst>(I);
9693ca95b02SDimitry Andric
9703ca95b02SDimitry Andric const Value *Op = SExt->getOperand(0);
9713ca95b02SDimitry Andric MVT::SimpleValueType From = getSimpleType(Op->getType());
9723ca95b02SDimitry Andric MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
9732cab237bSDimitry Andric unsigned In = getRegForValue(Op);
9742cab237bSDimitry Andric if (In == 0)
9752cab237bSDimitry Andric return false;
9762cab237bSDimitry Andric unsigned Reg = signExtend(In, Op, From, To);
9773ca95b02SDimitry Andric if (Reg == 0)
9783ca95b02SDimitry Andric return false;
9793ca95b02SDimitry Andric
9803ca95b02SDimitry Andric updateValueMap(SExt, Reg);
9813ca95b02SDimitry Andric return true;
9823ca95b02SDimitry Andric }
9833ca95b02SDimitry Andric
selectICmp(const Instruction * I)9843ca95b02SDimitry Andric bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
9853ca95b02SDimitry Andric const ICmpInst *ICmp = cast<ICmpInst>(I);
9863ca95b02SDimitry Andric
9873ca95b02SDimitry Andric bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
9883ca95b02SDimitry Andric unsigned Opc;
9893ca95b02SDimitry Andric bool isSigned = false;
9903ca95b02SDimitry Andric switch (ICmp->getPredicate()) {
9913ca95b02SDimitry Andric case ICmpInst::ICMP_EQ:
9923ca95b02SDimitry Andric Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
9933ca95b02SDimitry Andric break;
9943ca95b02SDimitry Andric case ICmpInst::ICMP_NE:
9953ca95b02SDimitry Andric Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
9963ca95b02SDimitry Andric break;
9973ca95b02SDimitry Andric case ICmpInst::ICMP_UGT:
9983ca95b02SDimitry Andric Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
9993ca95b02SDimitry Andric break;
10003ca95b02SDimitry Andric case ICmpInst::ICMP_UGE:
10013ca95b02SDimitry Andric Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
10023ca95b02SDimitry Andric break;
10033ca95b02SDimitry Andric case ICmpInst::ICMP_ULT:
10043ca95b02SDimitry Andric Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
10053ca95b02SDimitry Andric break;
10063ca95b02SDimitry Andric case ICmpInst::ICMP_ULE:
10073ca95b02SDimitry Andric Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
10083ca95b02SDimitry Andric break;
10093ca95b02SDimitry Andric case ICmpInst::ICMP_SGT:
10103ca95b02SDimitry Andric Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
10113ca95b02SDimitry Andric isSigned = true;
10123ca95b02SDimitry Andric break;
10133ca95b02SDimitry Andric case ICmpInst::ICMP_SGE:
10143ca95b02SDimitry Andric Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
10153ca95b02SDimitry Andric isSigned = true;
10163ca95b02SDimitry Andric break;
10173ca95b02SDimitry Andric case ICmpInst::ICMP_SLT:
10183ca95b02SDimitry Andric Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
10193ca95b02SDimitry Andric isSigned = true;
10203ca95b02SDimitry Andric break;
10213ca95b02SDimitry Andric case ICmpInst::ICMP_SLE:
10223ca95b02SDimitry Andric Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
10233ca95b02SDimitry Andric isSigned = true;
10243ca95b02SDimitry Andric break;
1025*b5893f02SDimitry Andric default:
1026*b5893f02SDimitry Andric return false;
10273ca95b02SDimitry Andric }
10283ca95b02SDimitry Andric
10293ca95b02SDimitry Andric unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), isSigned);
10303ca95b02SDimitry Andric if (LHS == 0)
10313ca95b02SDimitry Andric return false;
10323ca95b02SDimitry Andric
10333ca95b02SDimitry Andric unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), isSigned);
10343ca95b02SDimitry Andric if (RHS == 0)
10353ca95b02SDimitry Andric return false;
10363ca95b02SDimitry Andric
10373ca95b02SDimitry Andric unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
10383ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
10393ca95b02SDimitry Andric .addReg(LHS)
10403ca95b02SDimitry Andric .addReg(RHS);
10413ca95b02SDimitry Andric updateValueMap(ICmp, ResultReg);
10423ca95b02SDimitry Andric return true;
10433ca95b02SDimitry Andric }
10443ca95b02SDimitry Andric
selectFCmp(const Instruction * I)10453ca95b02SDimitry Andric bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
10463ca95b02SDimitry Andric const FCmpInst *FCmp = cast<FCmpInst>(I);
10473ca95b02SDimitry Andric
10483ca95b02SDimitry Andric unsigned LHS = getRegForValue(FCmp->getOperand(0));
10493ca95b02SDimitry Andric if (LHS == 0)
10503ca95b02SDimitry Andric return false;
10513ca95b02SDimitry Andric
10523ca95b02SDimitry Andric unsigned RHS = getRegForValue(FCmp->getOperand(1));
10533ca95b02SDimitry Andric if (RHS == 0)
10543ca95b02SDimitry Andric return false;
10553ca95b02SDimitry Andric
10563ca95b02SDimitry Andric bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
10573ca95b02SDimitry Andric unsigned Opc;
10583ca95b02SDimitry Andric bool Not = false;
10593ca95b02SDimitry Andric switch (FCmp->getPredicate()) {
10603ca95b02SDimitry Andric case FCmpInst::FCMP_OEQ:
10613ca95b02SDimitry Andric Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
10623ca95b02SDimitry Andric break;
10633ca95b02SDimitry Andric case FCmpInst::FCMP_UNE:
10643ca95b02SDimitry Andric Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
10653ca95b02SDimitry Andric break;
10663ca95b02SDimitry Andric case FCmpInst::FCMP_OGT:
10673ca95b02SDimitry Andric Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
10683ca95b02SDimitry Andric break;
10693ca95b02SDimitry Andric case FCmpInst::FCMP_OGE:
10703ca95b02SDimitry Andric Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
10713ca95b02SDimitry Andric break;
10723ca95b02SDimitry Andric case FCmpInst::FCMP_OLT:
10733ca95b02SDimitry Andric Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
10743ca95b02SDimitry Andric break;
10753ca95b02SDimitry Andric case FCmpInst::FCMP_OLE:
10763ca95b02SDimitry Andric Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
10773ca95b02SDimitry Andric break;
10783ca95b02SDimitry Andric case FCmpInst::FCMP_UGT:
10793ca95b02SDimitry Andric Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
10803ca95b02SDimitry Andric Not = true;
10813ca95b02SDimitry Andric break;
10823ca95b02SDimitry Andric case FCmpInst::FCMP_UGE:
10833ca95b02SDimitry Andric Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
10843ca95b02SDimitry Andric Not = true;
10853ca95b02SDimitry Andric break;
10863ca95b02SDimitry Andric case FCmpInst::FCMP_ULT:
10873ca95b02SDimitry Andric Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
10883ca95b02SDimitry Andric Not = true;
10893ca95b02SDimitry Andric break;
10903ca95b02SDimitry Andric case FCmpInst::FCMP_ULE:
10913ca95b02SDimitry Andric Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
10923ca95b02SDimitry Andric Not = true;
10933ca95b02SDimitry Andric break;
10943ca95b02SDimitry Andric default:
10953ca95b02SDimitry Andric return false;
10963ca95b02SDimitry Andric }
10973ca95b02SDimitry Andric
10983ca95b02SDimitry Andric unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
10993ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
11003ca95b02SDimitry Andric .addReg(LHS)
11013ca95b02SDimitry Andric .addReg(RHS);
11023ca95b02SDimitry Andric
11033ca95b02SDimitry Andric if (Not)
11043ca95b02SDimitry Andric ResultReg = notValue(ResultReg);
11053ca95b02SDimitry Andric
11063ca95b02SDimitry Andric updateValueMap(FCmp, ResultReg);
11073ca95b02SDimitry Andric return true;
11083ca95b02SDimitry Andric }
11093ca95b02SDimitry Andric
selectBitCast(const Instruction * I)11103ca95b02SDimitry Andric bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
11113ca95b02SDimitry Andric // Target-independent code can handle this, except it doesn't set the dead
11123ca95b02SDimitry Andric // flag on the ARGUMENTS clobber, so we have to do that manually in order
11133ca95b02SDimitry Andric // to satisfy code that expects this of isBitcast() instructions.
11143ca95b02SDimitry Andric EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
11153ca95b02SDimitry Andric EVT RetVT = TLI.getValueType(DL, I->getType());
11163ca95b02SDimitry Andric if (!VT.isSimple() || !RetVT.isSimple())
11173ca95b02SDimitry Andric return false;
11183ca95b02SDimitry Andric
11192cab237bSDimitry Andric unsigned In = getRegForValue(I->getOperand(0));
11202cab237bSDimitry Andric if (In == 0)
11212cab237bSDimitry Andric return false;
11222cab237bSDimitry Andric
11233ca95b02SDimitry Andric if (VT == RetVT) {
11243ca95b02SDimitry Andric // No-op bitcast.
11252cab237bSDimitry Andric updateValueMap(I, In);
11263ca95b02SDimitry Andric return true;
11273ca95b02SDimitry Andric }
11283ca95b02SDimitry Andric
11293ca95b02SDimitry Andric unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
11302cab237bSDimitry Andric In, I->getOperand(0)->hasOneUse());
11313ca95b02SDimitry Andric if (!Reg)
11323ca95b02SDimitry Andric return false;
11333ca95b02SDimitry Andric MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
11343ca95b02SDimitry Andric --Iter;
11353ca95b02SDimitry Andric assert(Iter->isBitcast());
11363ca95b02SDimitry Andric Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI);
11373ca95b02SDimitry Andric updateValueMap(I, Reg);
11383ca95b02SDimitry Andric return true;
11393ca95b02SDimitry Andric }
11403ca95b02SDimitry Andric
selectLoad(const Instruction * I)11413ca95b02SDimitry Andric bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
11423ca95b02SDimitry Andric const LoadInst *Load = cast<LoadInst>(I);
11433ca95b02SDimitry Andric if (Load->isAtomic())
11443ca95b02SDimitry Andric return false;
1145d88c1a5aSDimitry Andric if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
1146d88c1a5aSDimitry Andric return false;
11473ca95b02SDimitry Andric
11483ca95b02SDimitry Andric Address Addr;
11493ca95b02SDimitry Andric if (!computeAddress(Load->getPointerOperand(), Addr))
11503ca95b02SDimitry Andric return false;
11513ca95b02SDimitry Andric
11523ca95b02SDimitry Andric // TODO: Fold a following sign-/zero-extend into the load instruction.
11533ca95b02SDimitry Andric
11543ca95b02SDimitry Andric unsigned Opc;
11553ca95b02SDimitry Andric const TargetRegisterClass *RC;
11563ca95b02SDimitry Andric switch (getSimpleType(Load->getType())) {
11573ca95b02SDimitry Andric case MVT::i1:
11583ca95b02SDimitry Andric case MVT::i8:
11593ca95b02SDimitry Andric Opc = WebAssembly::LOAD8_U_I32;
11603ca95b02SDimitry Andric RC = &WebAssembly::I32RegClass;
11613ca95b02SDimitry Andric break;
11623ca95b02SDimitry Andric case MVT::i16:
11633ca95b02SDimitry Andric Opc = WebAssembly::LOAD16_U_I32;
11643ca95b02SDimitry Andric RC = &WebAssembly::I32RegClass;
11653ca95b02SDimitry Andric break;
11663ca95b02SDimitry Andric case MVT::i32:
11673ca95b02SDimitry Andric Opc = WebAssembly::LOAD_I32;
11683ca95b02SDimitry Andric RC = &WebAssembly::I32RegClass;
11693ca95b02SDimitry Andric break;
11703ca95b02SDimitry Andric case MVT::i64:
11713ca95b02SDimitry Andric Opc = WebAssembly::LOAD_I64;
11723ca95b02SDimitry Andric RC = &WebAssembly::I64RegClass;
11733ca95b02SDimitry Andric break;
11743ca95b02SDimitry Andric case MVT::f32:
11753ca95b02SDimitry Andric Opc = WebAssembly::LOAD_F32;
11763ca95b02SDimitry Andric RC = &WebAssembly::F32RegClass;
11773ca95b02SDimitry Andric break;
11783ca95b02SDimitry Andric case MVT::f64:
11793ca95b02SDimitry Andric Opc = WebAssembly::LOAD_F64;
11803ca95b02SDimitry Andric RC = &WebAssembly::F64RegClass;
11813ca95b02SDimitry Andric break;
11823ca95b02SDimitry Andric default:
11833ca95b02SDimitry Andric return false;
11843ca95b02SDimitry Andric }
11853ca95b02SDimitry Andric
11863ca95b02SDimitry Andric materializeLoadStoreOperands(Addr);
11873ca95b02SDimitry Andric
11883ca95b02SDimitry Andric unsigned ResultReg = createResultReg(RC);
11893ca95b02SDimitry Andric auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
11903ca95b02SDimitry Andric ResultReg);
11913ca95b02SDimitry Andric
11923ca95b02SDimitry Andric addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
11933ca95b02SDimitry Andric
11943ca95b02SDimitry Andric updateValueMap(Load, ResultReg);
11953ca95b02SDimitry Andric return true;
11963ca95b02SDimitry Andric }
11973ca95b02SDimitry Andric
selectStore(const Instruction * I)11983ca95b02SDimitry Andric bool WebAssemblyFastISel::selectStore(const Instruction *I) {
11993ca95b02SDimitry Andric const StoreInst *Store = cast<StoreInst>(I);
12003ca95b02SDimitry Andric if (Store->isAtomic())
12013ca95b02SDimitry Andric return false;
1202d88c1a5aSDimitry Andric if (!Subtarget->hasSIMD128() &&
1203d88c1a5aSDimitry Andric Store->getValueOperand()->getType()->isVectorTy())
1204d88c1a5aSDimitry Andric return false;
12053ca95b02SDimitry Andric
12063ca95b02SDimitry Andric Address Addr;
12073ca95b02SDimitry Andric if (!computeAddress(Store->getPointerOperand(), Addr))
12083ca95b02SDimitry Andric return false;
12093ca95b02SDimitry Andric
12103ca95b02SDimitry Andric unsigned Opc;
12113ca95b02SDimitry Andric bool VTIsi1 = false;
12123ca95b02SDimitry Andric switch (getSimpleType(Store->getValueOperand()->getType())) {
12133ca95b02SDimitry Andric case MVT::i1:
12143ca95b02SDimitry Andric VTIsi1 = true;
12154ba319b5SDimitry Andric LLVM_FALLTHROUGH;
12163ca95b02SDimitry Andric case MVT::i8:
12173ca95b02SDimitry Andric Opc = WebAssembly::STORE8_I32;
12183ca95b02SDimitry Andric break;
12193ca95b02SDimitry Andric case MVT::i16:
12203ca95b02SDimitry Andric Opc = WebAssembly::STORE16_I32;
12213ca95b02SDimitry Andric break;
12223ca95b02SDimitry Andric case MVT::i32:
12233ca95b02SDimitry Andric Opc = WebAssembly::STORE_I32;
12243ca95b02SDimitry Andric break;
12253ca95b02SDimitry Andric case MVT::i64:
12263ca95b02SDimitry Andric Opc = WebAssembly::STORE_I64;
12273ca95b02SDimitry Andric break;
12283ca95b02SDimitry Andric case MVT::f32:
12293ca95b02SDimitry Andric Opc = WebAssembly::STORE_F32;
12303ca95b02SDimitry Andric break;
12313ca95b02SDimitry Andric case MVT::f64:
12323ca95b02SDimitry Andric Opc = WebAssembly::STORE_F64;
12333ca95b02SDimitry Andric break;
1234*b5893f02SDimitry Andric default:
1235*b5893f02SDimitry Andric return false;
12363ca95b02SDimitry Andric }
12373ca95b02SDimitry Andric
12383ca95b02SDimitry Andric materializeLoadStoreOperands(Addr);
12393ca95b02SDimitry Andric
12403ca95b02SDimitry Andric unsigned ValueReg = getRegForValue(Store->getValueOperand());
1241d88c1a5aSDimitry Andric if (ValueReg == 0)
1242d88c1a5aSDimitry Andric return false;
12433ca95b02SDimitry Andric if (VTIsi1)
12443ca95b02SDimitry Andric ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
12453ca95b02SDimitry Andric
1246d88c1a5aSDimitry Andric auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
12473ca95b02SDimitry Andric
12483ca95b02SDimitry Andric addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
12493ca95b02SDimitry Andric
12503ca95b02SDimitry Andric MIB.addReg(ValueReg);
12513ca95b02SDimitry Andric return true;
12523ca95b02SDimitry Andric }
12533ca95b02SDimitry Andric
selectBr(const Instruction * I)12543ca95b02SDimitry Andric bool WebAssemblyFastISel::selectBr(const Instruction *I) {
12553ca95b02SDimitry Andric const BranchInst *Br = cast<BranchInst>(I);
12563ca95b02SDimitry Andric if (Br->isUnconditional()) {
12573ca95b02SDimitry Andric MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
12583ca95b02SDimitry Andric fastEmitBranch(MSucc, Br->getDebugLoc());
12593ca95b02SDimitry Andric return true;
12603ca95b02SDimitry Andric }
12613ca95b02SDimitry Andric
12623ca95b02SDimitry Andric MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
12633ca95b02SDimitry Andric MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
12643ca95b02SDimitry Andric
12653ca95b02SDimitry Andric bool Not;
12663ca95b02SDimitry Andric unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
1267d88c1a5aSDimitry Andric if (CondReg == 0)
1268d88c1a5aSDimitry Andric return false;
12693ca95b02SDimitry Andric
12703ca95b02SDimitry Andric unsigned Opc = WebAssembly::BR_IF;
12713ca95b02SDimitry Andric if (Not)
12723ca95b02SDimitry Andric Opc = WebAssembly::BR_UNLESS;
12733ca95b02SDimitry Andric
12743ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
12753ca95b02SDimitry Andric .addMBB(TBB)
12763ca95b02SDimitry Andric .addReg(CondReg);
12773ca95b02SDimitry Andric
12783ca95b02SDimitry Andric finishCondBranch(Br->getParent(), TBB, FBB);
12793ca95b02SDimitry Andric return true;
12803ca95b02SDimitry Andric }
12813ca95b02SDimitry Andric
selectRet(const Instruction * I)12823ca95b02SDimitry Andric bool WebAssemblyFastISel::selectRet(const Instruction *I) {
12833ca95b02SDimitry Andric if (!FuncInfo.CanLowerReturn)
12843ca95b02SDimitry Andric return false;
12853ca95b02SDimitry Andric
12863ca95b02SDimitry Andric const ReturnInst *Ret = cast<ReturnInst>(I);
12873ca95b02SDimitry Andric
12883ca95b02SDimitry Andric if (Ret->getNumOperands() == 0) {
12893ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
12903ca95b02SDimitry Andric TII.get(WebAssembly::RETURN_VOID));
12913ca95b02SDimitry Andric return true;
12923ca95b02SDimitry Andric }
12933ca95b02SDimitry Andric
12943ca95b02SDimitry Andric Value *RV = Ret->getOperand(0);
1295d88c1a5aSDimitry Andric if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
1296d88c1a5aSDimitry Andric return false;
1297d88c1a5aSDimitry Andric
12983ca95b02SDimitry Andric unsigned Opc;
12993ca95b02SDimitry Andric switch (getSimpleType(RV->getType())) {
1300*b5893f02SDimitry Andric case MVT::i1:
1301*b5893f02SDimitry Andric case MVT::i8:
1302*b5893f02SDimitry Andric case MVT::i16:
1303*b5893f02SDimitry Andric case MVT::i32:
13043ca95b02SDimitry Andric Opc = WebAssembly::RETURN_I32;
13053ca95b02SDimitry Andric break;
13063ca95b02SDimitry Andric case MVT::i64:
13073ca95b02SDimitry Andric Opc = WebAssembly::RETURN_I64;
13083ca95b02SDimitry Andric break;
1309d88c1a5aSDimitry Andric case MVT::f32:
1310d88c1a5aSDimitry Andric Opc = WebAssembly::RETURN_F32;
1311d88c1a5aSDimitry Andric break;
1312d88c1a5aSDimitry Andric case MVT::f64:
1313d88c1a5aSDimitry Andric Opc = WebAssembly::RETURN_F64;
1314d88c1a5aSDimitry Andric break;
1315d88c1a5aSDimitry Andric case MVT::v16i8:
1316d88c1a5aSDimitry Andric Opc = WebAssembly::RETURN_v16i8;
1317d88c1a5aSDimitry Andric break;
1318d88c1a5aSDimitry Andric case MVT::v8i16:
1319d88c1a5aSDimitry Andric Opc = WebAssembly::RETURN_v8i16;
1320d88c1a5aSDimitry Andric break;
1321d88c1a5aSDimitry Andric case MVT::v4i32:
1322d88c1a5aSDimitry Andric Opc = WebAssembly::RETURN_v4i32;
1323d88c1a5aSDimitry Andric break;
1324*b5893f02SDimitry Andric case MVT::v2i64:
1325*b5893f02SDimitry Andric Opc = WebAssembly::RETURN_v2i64;
1326*b5893f02SDimitry Andric break;
1327d88c1a5aSDimitry Andric case MVT::v4f32:
1328d88c1a5aSDimitry Andric Opc = WebAssembly::RETURN_v4f32;
1329d88c1a5aSDimitry Andric break;
1330*b5893f02SDimitry Andric case MVT::v2f64:
1331*b5893f02SDimitry Andric Opc = WebAssembly::RETURN_v2f64;
1332*b5893f02SDimitry Andric break;
13334ba319b5SDimitry Andric case MVT::ExceptRef:
13344ba319b5SDimitry Andric Opc = WebAssembly::RETURN_EXCEPT_REF;
13354ba319b5SDimitry Andric break;
1336*b5893f02SDimitry Andric default:
1337*b5893f02SDimitry Andric return false;
13383ca95b02SDimitry Andric }
13393ca95b02SDimitry Andric
13403ca95b02SDimitry Andric unsigned Reg;
13413ca95b02SDimitry Andric if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
13423ca95b02SDimitry Andric Reg = getRegForSignedValue(RV);
13433ca95b02SDimitry Andric else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
13443ca95b02SDimitry Andric Reg = getRegForUnsignedValue(RV);
13453ca95b02SDimitry Andric else
13463ca95b02SDimitry Andric Reg = getRegForValue(RV);
13473ca95b02SDimitry Andric
1348d88c1a5aSDimitry Andric if (Reg == 0)
1349d88c1a5aSDimitry Andric return false;
1350d88c1a5aSDimitry Andric
13513ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg);
13523ca95b02SDimitry Andric return true;
13533ca95b02SDimitry Andric }
13543ca95b02SDimitry Andric
selectUnreachable(const Instruction * I)13553ca95b02SDimitry Andric bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
13563ca95b02SDimitry Andric BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
13573ca95b02SDimitry Andric TII.get(WebAssembly::UNREACHABLE));
13583ca95b02SDimitry Andric return true;
13593ca95b02SDimitry Andric }
13603ca95b02SDimitry Andric
fastSelectInstruction(const Instruction * I)13613ca95b02SDimitry Andric bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
13623ca95b02SDimitry Andric switch (I->getOpcode()) {
13633ca95b02SDimitry Andric case Instruction::Call:
13643ca95b02SDimitry Andric if (selectCall(I))
13653ca95b02SDimitry Andric return true;
13663ca95b02SDimitry Andric break;
1367*b5893f02SDimitry Andric case Instruction::Select:
1368*b5893f02SDimitry Andric return selectSelect(I);
1369*b5893f02SDimitry Andric case Instruction::Trunc:
1370*b5893f02SDimitry Andric return selectTrunc(I);
1371*b5893f02SDimitry Andric case Instruction::ZExt:
1372*b5893f02SDimitry Andric return selectZExt(I);
1373*b5893f02SDimitry Andric case Instruction::SExt:
1374*b5893f02SDimitry Andric return selectSExt(I);
1375*b5893f02SDimitry Andric case Instruction::ICmp:
1376*b5893f02SDimitry Andric return selectICmp(I);
1377*b5893f02SDimitry Andric case Instruction::FCmp:
1378*b5893f02SDimitry Andric return selectFCmp(I);
1379*b5893f02SDimitry Andric case Instruction::BitCast:
1380*b5893f02SDimitry Andric return selectBitCast(I);
1381*b5893f02SDimitry Andric case Instruction::Load:
1382*b5893f02SDimitry Andric return selectLoad(I);
1383*b5893f02SDimitry Andric case Instruction::Store:
1384*b5893f02SDimitry Andric return selectStore(I);
1385*b5893f02SDimitry Andric case Instruction::Br:
1386*b5893f02SDimitry Andric return selectBr(I);
1387*b5893f02SDimitry Andric case Instruction::Ret:
1388*b5893f02SDimitry Andric return selectRet(I);
1389*b5893f02SDimitry Andric case Instruction::Unreachable:
1390*b5893f02SDimitry Andric return selectUnreachable(I);
1391*b5893f02SDimitry Andric default:
1392*b5893f02SDimitry Andric break;
13937d523365SDimitry Andric }
13947d523365SDimitry Andric
13957d523365SDimitry Andric // Fall back to target-independent instruction selection.
13967d523365SDimitry Andric return selectOperator(I, I->getOpcode());
13977d523365SDimitry Andric }
13987d523365SDimitry Andric
createFastISel(FunctionLoweringInfo & FuncInfo,const TargetLibraryInfo * LibInfo)13997d523365SDimitry Andric FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,
14007d523365SDimitry Andric const TargetLibraryInfo *LibInfo) {
14017d523365SDimitry Andric return new WebAssemblyFastISel(FuncInfo, LibInfo);
14027d523365SDimitry Andric }
1403