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