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