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