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