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