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