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