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