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