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