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