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