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