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