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
41using namespace llvm;
42using namespace PatternMatch;
43
44#define DEBUG_TYPE "wasm-fastisel"
45
46namespace {
47
48class 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
115private:
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
193public:
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
209bool 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
380void 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
395void 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
415unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
416  return zeroExtendToI32(Reg, V, MVT::i1);
417}
418
419unsigned 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
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  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
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  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
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    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
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    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
556unsigned 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
565unsigned 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
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  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
589unsigned 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
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    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
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    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
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  unsigned I = 0;
644  for (auto const &Arg : F->args()) {
645    const AttributeList &Attrs = F->getAttributes();
646    if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
647        Attrs.hasParamAttribute(I, Attribute::SwiftSelf) ||
648        Attrs.hasParamAttribute(I, Attribute::SwiftError) ||
649        Attrs.hasParamAttribute(I, Attribute::InAlloca) ||
650        Attrs.hasParamAttribute(I, Attribute::Nest))
651      return false;
652
653    Type *ArgTy = Arg.getType();
654    if (ArgTy->isStructTy() || ArgTy->isArrayTy())
655      return false;
656    if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
657      return false;
658
659    unsigned Opc;
660    const TargetRegisterClass *RC;
661    switch (getSimpleType(ArgTy)) {
662    case MVT::i1:
663    case MVT::i8:
664    case MVT::i16:
665    case MVT::i32:
666      Opc = WebAssembly::ARGUMENT_i32;
667      RC = &WebAssembly::I32RegClass;
668      break;
669    case MVT::i64:
670      Opc = WebAssembly::ARGUMENT_i64;
671      RC = &WebAssembly::I64RegClass;
672      break;
673    case MVT::f32:
674      Opc = WebAssembly::ARGUMENT_f32;
675      RC = &WebAssembly::F32RegClass;
676      break;
677    case MVT::f64:
678      Opc = WebAssembly::ARGUMENT_f64;
679      RC = &WebAssembly::F64RegClass;
680      break;
681    case MVT::v16i8:
682      Opc = WebAssembly::ARGUMENT_v16i8;
683      RC = &WebAssembly::V128RegClass;
684      break;
685    case MVT::v8i16:
686      Opc = WebAssembly::ARGUMENT_v8i16;
687      RC = &WebAssembly::V128RegClass;
688      break;
689    case MVT::v4i32:
690      Opc = WebAssembly::ARGUMENT_v4i32;
691      RC = &WebAssembly::V128RegClass;
692      break;
693    case MVT::v2i64:
694      Opc = WebAssembly::ARGUMENT_v2i64;
695      RC = &WebAssembly::V128RegClass;
696      break;
697    case MVT::v4f32:
698      Opc = WebAssembly::ARGUMENT_v4f32;
699      RC = &WebAssembly::V128RegClass;
700      break;
701    case MVT::v2f64:
702      Opc = WebAssembly::ARGUMENT_v2f64;
703      RC = &WebAssembly::V128RegClass;
704      break;
705    case MVT::exnref:
706      Opc = WebAssembly::ARGUMENT_exnref;
707      RC = &WebAssembly::EXNREFRegClass;
708      break;
709    default:
710      return false;
711    }
712    unsigned ResultReg = createResultReg(RC);
713    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
714        .addImm(I);
715    updateValueMap(&Arg, ResultReg);
716
717    ++I;
718  }
719
720  MRI.addLiveIn(WebAssembly::ARGUMENTS);
721
722  auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
723  for (auto const &Arg : F->args()) {
724    MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType()));
725    if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
726      MFI->clearParamsAndResults();
727      return false;
728    }
729    MFI->addParam(ArgTy);
730  }
731
732  if (!F->getReturnType()->isVoidTy()) {
733    MVT::SimpleValueType RetTy =
734        getLegalType(getSimpleType(F->getReturnType()));
735    if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
736      MFI->clearParamsAndResults();
737      return false;
738    }
739    MFI->addResult(RetTy);
740  }
741
742  return true;
743}
744
745bool WebAssemblyFastISel::selectCall(const Instruction *I) {
746  const auto *Call = cast<CallInst>(I);
747
748  // TODO: Support tail calls in FastISel
749  if (Call->isMustTailCall() || Call->isInlineAsm() ||
750      Call->getFunctionType()->isVarArg())
751    return false;
752
753  Function *Func = Call->getCalledFunction();
754  if (Func && Func->isIntrinsic())
755    return false;
756
757  bool IsDirect = Func != nullptr;
758  if (!IsDirect && isa<ConstantExpr>(Call->getCalledValue()))
759    return false;
760
761  FunctionType *FuncTy = Call->getFunctionType();
762  unsigned Opc;
763  bool IsVoid = FuncTy->getReturnType()->isVoidTy();
764  unsigned ResultReg;
765  if (IsVoid) {
766    Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
767  } else {
768    if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
769      return false;
770
771    MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
772    switch (RetTy) {
773    case MVT::i1:
774    case MVT::i8:
775    case MVT::i16:
776    case MVT::i32:
777      Opc = IsDirect ? WebAssembly::CALL_i32 : WebAssembly::PCALL_INDIRECT_i32;
778      ResultReg = createResultReg(&WebAssembly::I32RegClass);
779      break;
780    case MVT::i64:
781      Opc = IsDirect ? WebAssembly::CALL_i64 : WebAssembly::PCALL_INDIRECT_i64;
782      ResultReg = createResultReg(&WebAssembly::I64RegClass);
783      break;
784    case MVT::f32:
785      Opc = IsDirect ? WebAssembly::CALL_f32 : WebAssembly::PCALL_INDIRECT_f32;
786      ResultReg = createResultReg(&WebAssembly::F32RegClass);
787      break;
788    case MVT::f64:
789      Opc = IsDirect ? WebAssembly::CALL_f64 : WebAssembly::PCALL_INDIRECT_f64;
790      ResultReg = createResultReg(&WebAssembly::F64RegClass);
791      break;
792    case MVT::v16i8:
793      Opc = IsDirect ? WebAssembly::CALL_v16i8
794                     : WebAssembly::PCALL_INDIRECT_v16i8;
795      ResultReg = createResultReg(&WebAssembly::V128RegClass);
796      break;
797    case MVT::v8i16:
798      Opc = IsDirect ? WebAssembly::CALL_v8i16
799                     : WebAssembly::PCALL_INDIRECT_v8i16;
800      ResultReg = createResultReg(&WebAssembly::V128RegClass);
801      break;
802    case MVT::v4i32:
803      Opc = IsDirect ? WebAssembly::CALL_v4i32
804                     : WebAssembly::PCALL_INDIRECT_v4i32;
805      ResultReg = createResultReg(&WebAssembly::V128RegClass);
806      break;
807    case MVT::v2i64:
808      Opc = IsDirect ? WebAssembly::CALL_v2i64
809                     : WebAssembly::PCALL_INDIRECT_v2i64;
810      ResultReg = createResultReg(&WebAssembly::V128RegClass);
811      break;
812    case MVT::v4f32:
813      Opc = IsDirect ? WebAssembly::CALL_v4f32
814                     : WebAssembly::PCALL_INDIRECT_v4f32;
815      ResultReg = createResultReg(&WebAssembly::V128RegClass);
816      break;
817    case MVT::v2f64:
818      Opc = IsDirect ? WebAssembly::CALL_v2f64
819                     : WebAssembly::PCALL_INDIRECT_v2f64;
820      ResultReg = createResultReg(&WebAssembly::V128RegClass);
821      break;
822    case MVT::exnref:
823      Opc = IsDirect ? WebAssembly::CALL_exnref
824                     : WebAssembly::PCALL_INDIRECT_exnref;
825      ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);
826      break;
827    default:
828      return false;
829    }
830  }
831
832  SmallVector<unsigned, 8> Args;
833  for (unsigned I = 0, E = Call->getNumArgOperands(); I < E; ++I) {
834    Value *V = Call->getArgOperand(I);
835    MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
836    if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
837      return false;
838
839    const AttributeList &Attrs = Call->getAttributes();
840    if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
841        Attrs.hasParamAttribute(I, Attribute::SwiftSelf) ||
842        Attrs.hasParamAttribute(I, Attribute::SwiftError) ||
843        Attrs.hasParamAttribute(I, Attribute::InAlloca) ||
844        Attrs.hasParamAttribute(I, Attribute::Nest))
845      return false;
846
847    unsigned Reg;
848
849    if (Attrs.hasParamAttribute(I, Attribute::SExt))
850      Reg = getRegForSignedValue(V);
851    else if (Attrs.hasParamAttribute(I, Attribute::ZExt))
852      Reg = getRegForUnsignedValue(V);
853    else
854      Reg = getRegForValue(V);
855
856    if (Reg == 0)
857      return false;
858
859    Args.push_back(Reg);
860  }
861
862  unsigned CalleeReg = 0;
863  if (!IsDirect) {
864    CalleeReg = getRegForValue(Call->getCalledValue());
865    if (!CalleeReg)
866      return false;
867  }
868
869  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
870
871  if (!IsVoid)
872    MIB.addReg(ResultReg, RegState::Define);
873
874  if (IsDirect)
875    MIB.addGlobalAddress(Func);
876  else
877    MIB.addReg(CalleeReg);
878
879  for (unsigned ArgReg : Args)
880    MIB.addReg(ArgReg);
881
882  if (!IsVoid)
883    updateValueMap(Call, ResultReg);
884  return true;
885}
886
887bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
888  const auto *Select = cast<SelectInst>(I);
889
890  bool Not;
891  unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
892  if (CondReg == 0)
893    return false;
894
895  unsigned TrueReg = getRegForValue(Select->getTrueValue());
896  if (TrueReg == 0)
897    return false;
898
899  unsigned FalseReg = getRegForValue(Select->getFalseValue());
900  if (FalseReg == 0)
901    return false;
902
903  if (Not)
904    std::swap(TrueReg, FalseReg);
905
906  unsigned Opc;
907  const TargetRegisterClass *RC;
908  switch (getSimpleType(Select->getType())) {
909  case MVT::i1:
910  case MVT::i8:
911  case MVT::i16:
912  case MVT::i32:
913    Opc = WebAssembly::SELECT_I32;
914    RC = &WebAssembly::I32RegClass;
915    break;
916  case MVT::i64:
917    Opc = WebAssembly::SELECT_I64;
918    RC = &WebAssembly::I64RegClass;
919    break;
920  case MVT::f32:
921    Opc = WebAssembly::SELECT_F32;
922    RC = &WebAssembly::F32RegClass;
923    break;
924  case MVT::f64:
925    Opc = WebAssembly::SELECT_F64;
926    RC = &WebAssembly::F64RegClass;
927    break;
928  case MVT::exnref:
929    Opc = WebAssembly::SELECT_EXNREF;
930    RC = &WebAssembly::EXNREFRegClass;
931    break;
932  default:
933    return false;
934  }
935
936  unsigned ResultReg = createResultReg(RC);
937  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
938      .addReg(TrueReg)
939      .addReg(FalseReg)
940      .addReg(CondReg);
941
942  updateValueMap(Select, ResultReg);
943  return true;
944}
945
946bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
947  const auto *Trunc = cast<TruncInst>(I);
948
949  unsigned Reg = getRegForValue(Trunc->getOperand(0));
950  if (Reg == 0)
951    return false;
952
953  if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
954    unsigned Result = createResultReg(&WebAssembly::I32RegClass);
955    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
956            TII.get(WebAssembly::I32_WRAP_I64), Result)
957        .addReg(Reg);
958    Reg = Result;
959  }
960
961  updateValueMap(Trunc, Reg);
962  return true;
963}
964
965bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
966  const auto *ZExt = cast<ZExtInst>(I);
967
968  const Value *Op = ZExt->getOperand(0);
969  MVT::SimpleValueType From = getSimpleType(Op->getType());
970  MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
971  unsigned In = getRegForValue(Op);
972  if (In == 0)
973    return false;
974  unsigned Reg = zeroExtend(In, Op, From, To);
975  if (Reg == 0)
976    return false;
977
978  updateValueMap(ZExt, Reg);
979  return true;
980}
981
982bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
983  const auto *SExt = cast<SExtInst>(I);
984
985  const Value *Op = SExt->getOperand(0);
986  MVT::SimpleValueType From = getSimpleType(Op->getType());
987  MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
988  unsigned In = getRegForValue(Op);
989  if (In == 0)
990    return false;
991  unsigned Reg = signExtend(In, Op, From, To);
992  if (Reg == 0)
993    return false;
994
995  updateValueMap(SExt, Reg);
996  return true;
997}
998
999bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
1000  const auto *ICmp = cast<ICmpInst>(I);
1001
1002  bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
1003  unsigned Opc;
1004  bool IsSigned = false;
1005  switch (ICmp->getPredicate()) {
1006  case ICmpInst::ICMP_EQ:
1007    Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
1008    break;
1009  case ICmpInst::ICMP_NE:
1010    Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1011    break;
1012  case ICmpInst::ICMP_UGT:
1013    Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1014    break;
1015  case ICmpInst::ICMP_UGE:
1016    Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1017    break;
1018  case ICmpInst::ICMP_ULT:
1019    Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1020    break;
1021  case ICmpInst::ICMP_ULE:
1022    Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1023    break;
1024  case ICmpInst::ICMP_SGT:
1025    Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1026    IsSigned = true;
1027    break;
1028  case ICmpInst::ICMP_SGE:
1029    Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1030    IsSigned = true;
1031    break;
1032  case ICmpInst::ICMP_SLT:
1033    Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1034    IsSigned = true;
1035    break;
1036  case ICmpInst::ICMP_SLE:
1037    Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1038    IsSigned = true;
1039    break;
1040  default:
1041    return false;
1042  }
1043
1044  unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
1045  if (LHS == 0)
1046    return false;
1047
1048  unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
1049  if (RHS == 0)
1050    return false;
1051
1052  unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1053  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1054      .addReg(LHS)
1055      .addReg(RHS);
1056  updateValueMap(ICmp, ResultReg);
1057  return true;
1058}
1059
1060bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
1061  const auto *FCmp = cast<FCmpInst>(I);
1062
1063  unsigned LHS = getRegForValue(FCmp->getOperand(0));
1064  if (LHS == 0)
1065    return false;
1066
1067  unsigned RHS = getRegForValue(FCmp->getOperand(1));
1068  if (RHS == 0)
1069    return false;
1070
1071  bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1072  unsigned Opc;
1073  bool Not = false;
1074  switch (FCmp->getPredicate()) {
1075  case FCmpInst::FCMP_OEQ:
1076    Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1077    break;
1078  case FCmpInst::FCMP_UNE:
1079    Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1080    break;
1081  case FCmpInst::FCMP_OGT:
1082    Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1083    break;
1084  case FCmpInst::FCMP_OGE:
1085    Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1086    break;
1087  case FCmpInst::FCMP_OLT:
1088    Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1089    break;
1090  case FCmpInst::FCMP_OLE:
1091    Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1092    break;
1093  case FCmpInst::FCMP_UGT:
1094    Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1095    Not = true;
1096    break;
1097  case FCmpInst::FCMP_UGE:
1098    Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1099    Not = true;
1100    break;
1101  case FCmpInst::FCMP_ULT:
1102    Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1103    Not = true;
1104    break;
1105  case FCmpInst::FCMP_ULE:
1106    Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1107    Not = true;
1108    break;
1109  default:
1110    return false;
1111  }
1112
1113  unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1114  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1115      .addReg(LHS)
1116      .addReg(RHS);
1117
1118  if (Not)
1119    ResultReg = notValue(ResultReg);
1120
1121  updateValueMap(FCmp, ResultReg);
1122  return true;
1123}
1124
1125bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
1126  // Target-independent code can handle this, except it doesn't set the dead
1127  // flag on the ARGUMENTS clobber, so we have to do that manually in order
1128  // to satisfy code that expects this of isBitcast() instructions.
1129  EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
1130  EVT RetVT = TLI.getValueType(DL, I->getType());
1131  if (!VT.isSimple() || !RetVT.isSimple())
1132    return false;
1133
1134  unsigned In = getRegForValue(I->getOperand(0));
1135  if (In == 0)
1136    return false;
1137
1138  if (VT == RetVT) {
1139    // No-op bitcast.
1140    updateValueMap(I, In);
1141    return true;
1142  }
1143
1144  Register Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
1145                                        In, I->getOperand(0)->hasOneUse());
1146  if (!Reg)
1147    return false;
1148  MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
1149  --Iter;
1150  assert(Iter->isBitcast());
1151  Iter->setPhysRegsDeadExcept(ArrayRef<Register>(), TRI);
1152  updateValueMap(I, Reg);
1153  return true;
1154}
1155
1156bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
1157  const auto *Load = cast<LoadInst>(I);
1158  if (Load->isAtomic())
1159    return false;
1160  if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
1161    return false;
1162
1163  Address Addr;
1164  if (!computeAddress(Load->getPointerOperand(), Addr))
1165    return false;
1166
1167  // TODO: Fold a following sign-/zero-extend into the load instruction.
1168
1169  unsigned Opc;
1170  const TargetRegisterClass *RC;
1171  switch (getSimpleType(Load->getType())) {
1172  case MVT::i1:
1173  case MVT::i8:
1174    Opc = WebAssembly::LOAD8_U_I32;
1175    RC = &WebAssembly::I32RegClass;
1176    break;
1177  case MVT::i16:
1178    Opc = WebAssembly::LOAD16_U_I32;
1179    RC = &WebAssembly::I32RegClass;
1180    break;
1181  case MVT::i32:
1182    Opc = WebAssembly::LOAD_I32;
1183    RC = &WebAssembly::I32RegClass;
1184    break;
1185  case MVT::i64:
1186    Opc = WebAssembly::LOAD_I64;
1187    RC = &WebAssembly::I64RegClass;
1188    break;
1189  case MVT::f32:
1190    Opc = WebAssembly::LOAD_F32;
1191    RC = &WebAssembly::F32RegClass;
1192    break;
1193  case MVT::f64:
1194    Opc = WebAssembly::LOAD_F64;
1195    RC = &WebAssembly::F64RegClass;
1196    break;
1197  default:
1198    return false;
1199  }
1200
1201  materializeLoadStoreOperands(Addr);
1202
1203  unsigned ResultReg = createResultReg(RC);
1204  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
1205                     ResultReg);
1206
1207  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1208
1209  updateValueMap(Load, ResultReg);
1210  return true;
1211}
1212
1213bool WebAssemblyFastISel::selectStore(const Instruction *I) {
1214  const auto *Store = cast<StoreInst>(I);
1215  if (Store->isAtomic())
1216    return false;
1217  if (!Subtarget->hasSIMD128() &&
1218      Store->getValueOperand()->getType()->isVectorTy())
1219    return false;
1220
1221  Address Addr;
1222  if (!computeAddress(Store->getPointerOperand(), Addr))
1223    return false;
1224
1225  unsigned Opc;
1226  bool VTIsi1 = false;
1227  switch (getSimpleType(Store->getValueOperand()->getType())) {
1228  case MVT::i1:
1229    VTIsi1 = true;
1230    LLVM_FALLTHROUGH;
1231  case MVT::i8:
1232    Opc = WebAssembly::STORE8_I32;
1233    break;
1234  case MVT::i16:
1235    Opc = WebAssembly::STORE16_I32;
1236    break;
1237  case MVT::i32:
1238    Opc = WebAssembly::STORE_I32;
1239    break;
1240  case MVT::i64:
1241    Opc = WebAssembly::STORE_I64;
1242    break;
1243  case MVT::f32:
1244    Opc = WebAssembly::STORE_F32;
1245    break;
1246  case MVT::f64:
1247    Opc = WebAssembly::STORE_F64;
1248    break;
1249  default:
1250    return false;
1251  }
1252
1253  materializeLoadStoreOperands(Addr);
1254
1255  unsigned ValueReg = getRegForValue(Store->getValueOperand());
1256  if (ValueReg == 0)
1257    return false;
1258  if (VTIsi1)
1259    ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
1260
1261  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
1262
1263  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1264
1265  MIB.addReg(ValueReg);
1266  return true;
1267}
1268
1269bool WebAssemblyFastISel::selectBr(const Instruction *I) {
1270  const auto *Br = cast<BranchInst>(I);
1271  if (Br->isUnconditional()) {
1272    MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
1273    fastEmitBranch(MSucc, Br->getDebugLoc());
1274    return true;
1275  }
1276
1277  MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
1278  MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
1279
1280  bool Not;
1281  unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
1282  if (CondReg == 0)
1283    return false;
1284
1285  unsigned Opc = WebAssembly::BR_IF;
1286  if (Not)
1287    Opc = WebAssembly::BR_UNLESS;
1288
1289  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1290      .addMBB(TBB)
1291      .addReg(CondReg);
1292
1293  finishCondBranch(Br->getParent(), TBB, FBB);
1294  return true;
1295}
1296
1297bool WebAssemblyFastISel::selectRet(const Instruction *I) {
1298  if (!FuncInfo.CanLowerReturn)
1299    return false;
1300
1301  const auto *Ret = cast<ReturnInst>(I);
1302
1303  if (Ret->getNumOperands() == 0) {
1304    BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1305            TII.get(WebAssembly::RETURN));
1306    return true;
1307  }
1308
1309  // TODO: support multiple return in FastISel
1310  if (Ret->getNumOperands() > 1)
1311    return false;
1312
1313  Value *RV = Ret->getOperand(0);
1314  if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
1315    return false;
1316
1317  switch (getSimpleType(RV->getType())) {
1318  case MVT::i1:
1319  case MVT::i8:
1320  case MVT::i16:
1321  case MVT::i32:
1322  case MVT::i64:
1323  case MVT::f32:
1324  case MVT::f64:
1325  case MVT::v16i8:
1326  case MVT::v8i16:
1327  case MVT::v4i32:
1328  case MVT::v2i64:
1329  case MVT::v4f32:
1330  case MVT::v2f64:
1331  case MVT::exnref:
1332    break;
1333  default:
1334    return false;
1335  }
1336
1337  unsigned Reg;
1338  if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
1339    Reg = getRegForSignedValue(RV);
1340  else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
1341    Reg = getRegForUnsignedValue(RV);
1342  else
1343    Reg = getRegForValue(RV);
1344
1345  if (Reg == 0)
1346    return false;
1347
1348  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1349          TII.get(WebAssembly::RETURN))
1350      .addReg(Reg);
1351  return true;
1352}
1353
1354bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
1355  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1356          TII.get(WebAssembly::UNREACHABLE));
1357  return true;
1358}
1359
1360bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
1361  switch (I->getOpcode()) {
1362  case Instruction::Call:
1363    if (selectCall(I))
1364      return true;
1365    break;
1366  case Instruction::Select:
1367    return selectSelect(I);
1368  case Instruction::Trunc:
1369    return selectTrunc(I);
1370  case Instruction::ZExt:
1371    return selectZExt(I);
1372  case Instruction::SExt:
1373    return selectSExt(I);
1374  case Instruction::ICmp:
1375    return selectICmp(I);
1376  case Instruction::FCmp:
1377    return selectFCmp(I);
1378  case Instruction::BitCast:
1379    return selectBitCast(I);
1380  case Instruction::Load:
1381    return selectLoad(I);
1382  case Instruction::Store:
1383    return selectStore(I);
1384  case Instruction::Br:
1385    return selectBr(I);
1386  case Instruction::Ret:
1387    return selectRet(I);
1388  case Instruction::Unreachable:
1389    return selectUnreachable(I);
1390  default:
1391    break;
1392  }
1393
1394  // Fall back to target-independent instruction selection.
1395  return selectOperator(I, I->getOpcode());
1396}
1397
1398FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,
1399                                      const TargetLibraryInfo *LibInfo) {
1400  return new WebAssemblyFastISel(FuncInfo, LibInfo);
1401}
1402