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