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