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