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