blob: 8dc535445d6f7839db0eae11efda182e11b26bb8 [file] [log] [blame]
Dan Gohman7b634842015-08-24 18:44:37 +00001//===-- WebAssemblyFastISel.cpp - WebAssembly FastISel implementation -----===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000011/// This file defines the WebAssembly-specific support for the FastISel
Dan Gohman7b634842015-08-24 18:44:37 +000012/// class. Some of the target-specific code is generated by tablegen in the file
13/// WebAssemblyGenFastISel.inc, which is #included here.
14///
Dan Gohman33e694a2016-05-12 04:19:09 +000015/// TODO: kill flags
16///
Dan Gohman7b634842015-08-24 18:44:37 +000017//===----------------------------------------------------------------------===//
18
Dan Gohman7b634842015-08-24 18:44:37 +000019#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "WebAssembly.h"
Dan Gohman33e694a2016-05-12 04:19:09 +000021#include "WebAssemblyMachineFunctionInfo.h"
Dan Gohman7b634842015-08-24 18:44:37 +000022#include "WebAssemblySubtarget.h"
23#include "WebAssemblyTargetMachine.h"
24#include "llvm/Analysis/BranchProbabilityInfo.h"
25#include "llvm/CodeGen/FastISel.h"
26#include "llvm/CodeGen/FunctionLoweringInfo.h"
27#include "llvm/CodeGen/MachineConstantPool.h"
28#include "llvm/CodeGen/MachineFrameInfo.h"
29#include "llvm/CodeGen/MachineInstrBuilder.h"
30#include "llvm/CodeGen/MachineRegisterInfo.h"
31#include "llvm/IR/DataLayout.h"
32#include "llvm/IR/DerivedTypes.h"
33#include "llvm/IR/Function.h"
34#include "llvm/IR/GetElementPtrTypeIterator.h"
35#include "llvm/IR/GlobalAlias.h"
36#include "llvm/IR/GlobalVariable.h"
37#include "llvm/IR/Instructions.h"
38#include "llvm/IR/IntrinsicInst.h"
39#include "llvm/IR/Operator.h"
40using namespace llvm;
41
42#define DEBUG_TYPE "wasm-fastisel"
43
44namespace {
45
46class WebAssemblyFastISel final : public FastISel {
Dan Gohman2e644382016-05-10 17:39:48 +000047 // All possible address modes.
48 class Address {
49 public:
50 typedef enum { RegBase, FrameIndexBase } BaseKind;
51
52 private:
53 BaseKind Kind;
54 union {
55 unsigned Reg;
56 int FI;
57 } Base;
58
59 int64_t Offset;
60
61 const GlobalValue *GV;
62
63 public:
64 // Innocuous defaults for our address.
65 Address() : Kind(RegBase), Offset(0), GV(0) { Base.Reg = 0; }
Jacob Gravellea31ec612017-06-22 21:26:08 +000066 void setKind(BaseKind K) {
67 assert(!isSet() && "Can't change kind with non-zero base");
68 Kind = K;
69 }
Dan Gohman2e644382016-05-10 17:39:48 +000070 BaseKind getKind() const { return Kind; }
71 bool isRegBase() const { return Kind == RegBase; }
72 bool isFIBase() const { return Kind == FrameIndexBase; }
73 void setReg(unsigned Reg) {
74 assert(isRegBase() && "Invalid base register access!");
Jacob Gravellea31ec612017-06-22 21:26:08 +000075 assert(Base.Reg == 0 && "Overwriting non-zero register");
Dan Gohman2e644382016-05-10 17:39:48 +000076 Base.Reg = Reg;
77 }
78 unsigned getReg() const {
79 assert(isRegBase() && "Invalid base register access!");
80 return Base.Reg;
81 }
82 void setFI(unsigned FI) {
83 assert(isFIBase() && "Invalid base frame index access!");
Jacob Gravellea31ec612017-06-22 21:26:08 +000084 assert(Base.FI == 0 && "Overwriting non-zero frame index");
Dan Gohman2e644382016-05-10 17:39:48 +000085 Base.FI = FI;
86 }
87 unsigned getFI() const {
88 assert(isFIBase() && "Invalid base frame index access!");
89 return Base.FI;
90 }
91
Dan Gohman728926a2016-12-22 15:15:10 +000092 void setOffset(int64_t Offset_) {
93 assert(Offset_ >= 0 && "Offsets must be non-negative");
94 Offset = Offset_;
95 }
Dan Gohman2e644382016-05-10 17:39:48 +000096 int64_t getOffset() const { return Offset; }
97 void setGlobalValue(const GlobalValue *G) { GV = G; }
98 const GlobalValue *getGlobalValue() const { return GV; }
Jacob Gravellea31ec612017-06-22 21:26:08 +000099 bool isSet() const {
100 if (isRegBase()) {
101 return Base.Reg != 0;
102 } else {
103 return Base.FI != 0;
104 }
105 }
Dan Gohman2e644382016-05-10 17:39:48 +0000106 };
107
Dan Gohman7b634842015-08-24 18:44:37 +0000108 /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
109 /// right decision when generating code for different targets.
110 const WebAssemblySubtarget *Subtarget;
111 LLVMContext *Context;
112
Dan Gohman7b634842015-08-24 18:44:37 +0000113private:
Dan Gohman2e644382016-05-10 17:39:48 +0000114 // Utility helper routines
Dan Gohman3a5ce732016-05-11 16:32:42 +0000115 MVT::SimpleValueType getSimpleType(Type *Ty) {
116 EVT VT = TLI.getValueType(DL, Ty, /*HandleUnknown=*/true);
Heejin Ahnf208f632018-09-05 01:27:38 +0000117 return VT.isSimple() ? VT.getSimpleVT().SimpleTy
118 : MVT::INVALID_SIMPLE_VALUE_TYPE;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000119 }
120 MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
121 switch (VT) {
122 case MVT::i1:
123 case MVT::i8:
124 case MVT::i16:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000125 return MVT::i32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000126 case MVT::i32:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000127 case MVT::i64:
Dan Gohman33e694a2016-05-12 04:19:09 +0000128 case MVT::f32:
129 case MVT::f64:
Heejin Ahn0de58722018-03-08 04:05:37 +0000130 case MVT::ExceptRef:
Dan Gohman33e694a2016-05-12 04:19:09 +0000131 return VT;
Dan Gohman6999c4f2017-02-24 21:05:35 +0000132 case MVT::f16:
133 return MVT::f32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000134 case MVT::v16i8:
135 case MVT::v8i16:
136 case MVT::v4i32:
Derek Schuff51ed1312018-08-07 21:24:01 +0000137 case MVT::v2i64:
Derek Schuff39bf39f2016-08-02 23:16:09 +0000138 case MVT::v4f32:
Derek Schuff51ed1312018-08-07 21:24:01 +0000139 case MVT::v2f64:
Derek Schuff39bf39f2016-08-02 23:16:09 +0000140 if (Subtarget->hasSIMD128())
141 return VT;
142 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000143 default:
144 break;
145 }
146 return MVT::INVALID_SIMPLE_VALUE_TYPE;
147 }
Dan Gohman2e644382016-05-10 17:39:48 +0000148 bool computeAddress(const Value *Obj, Address &Addr);
149 void materializeLoadStoreOperands(Address &Addr);
150 void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
151 MachineMemOperand *MMO);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000152 unsigned maskI1Value(unsigned Reg, const Value *V);
Dan Gohman33e694a2016-05-12 04:19:09 +0000153 unsigned getRegForI1Value(const Value *V, bool &Not);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000154 unsigned zeroExtendToI32(unsigned Reg, const Value *V,
155 MVT::SimpleValueType From);
156 unsigned signExtendToI32(unsigned Reg, const Value *V,
157 MVT::SimpleValueType From);
Heejin Ahnf208f632018-09-05 01:27:38 +0000158 unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
Dan Gohman3a5ce732016-05-11 16:32:42 +0000159 MVT::SimpleValueType To);
Heejin Ahnf208f632018-09-05 01:27:38 +0000160 unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
Dan Gohman3a5ce732016-05-11 16:32:42 +0000161 MVT::SimpleValueType To);
162 unsigned getRegForUnsignedValue(const Value *V);
163 unsigned getRegForSignedValue(const Value *V);
164 unsigned getRegForPromotedValue(const Value *V, bool IsSigned);
165 unsigned notValue(unsigned Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000166 unsigned copyValue(unsigned Reg);
Dan Gohman2e644382016-05-10 17:39:48 +0000167
168 // Backend specific FastISel code.
169 unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
170 unsigned fastMaterializeConstant(const Constant *C) override;
Dan Gohman33e694a2016-05-12 04:19:09 +0000171 bool fastLowerArguments() override;
Dan Gohman2e644382016-05-10 17:39:48 +0000172
173 // Selection routines.
Dan Gohman33e694a2016-05-12 04:19:09 +0000174 bool selectCall(const Instruction *I);
175 bool selectSelect(const Instruction *I);
176 bool selectTrunc(const Instruction *I);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000177 bool selectZExt(const Instruction *I);
178 bool selectSExt(const Instruction *I);
179 bool selectICmp(const Instruction *I);
180 bool selectFCmp(const Instruction *I);
Dan Gohman2e644382016-05-10 17:39:48 +0000181 bool selectBitCast(const Instruction *I);
182 bool selectLoad(const Instruction *I);
183 bool selectStore(const Instruction *I);
184 bool selectBr(const Instruction *I);
185 bool selectRet(const Instruction *I);
186 bool selectUnreachable(const Instruction *I);
187
Dan Gohman7b634842015-08-24 18:44:37 +0000188public:
189 // Backend specific FastISel code.
190 WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo,
191 const TargetLibraryInfo *LibInfo)
192 : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
193 Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>();
194 Context = &FuncInfo.Fn->getContext();
195 }
196
197 bool fastSelectInstruction(const Instruction *I) override;
198
199#include "WebAssemblyGenFastISel.inc"
200};
201
202} // end anonymous namespace
203
Dan Gohman2e644382016-05-10 17:39:48 +0000204bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {
205
206 const User *U = nullptr;
207 unsigned Opcode = Instruction::UserOp1;
208 if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
209 // Don't walk into other basic blocks unless the object is an alloca from
210 // another block, otherwise it may not have a virtual register assigned.
211 if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
212 FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
213 Opcode = I->getOpcode();
214 U = I;
215 }
216 } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
217 Opcode = C->getOpcode();
218 U = C;
219 }
220
221 if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
222 if (Ty->getAddressSpace() > 255)
223 // Fast instruction selection doesn't support the special
224 // address spaces.
225 return false;
226
227 if (const GlobalValue *GV = dyn_cast<GlobalValue>(Obj)) {
228 if (Addr.getGlobalValue())
229 return false;
230 Addr.setGlobalValue(GV);
231 return true;
232 }
233
234 switch (Opcode) {
Dan Gohman7b634842015-08-24 18:44:37 +0000235 default:
236 break;
Dan Gohman2e644382016-05-10 17:39:48 +0000237 case Instruction::BitCast: {
238 // Look through bitcasts.
239 return computeAddress(U->getOperand(0), Addr);
240 }
241 case Instruction::IntToPtr: {
242 // Look past no-op inttoptrs.
243 if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
244 TLI.getPointerTy(DL))
245 return computeAddress(U->getOperand(0), Addr);
246 break;
247 }
248 case Instruction::PtrToInt: {
249 // Look past no-op ptrtoints.
250 if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
251 return computeAddress(U->getOperand(0), Addr);
252 break;
253 }
254 case Instruction::GetElementPtr: {
255 Address SavedAddr = Addr;
256 uint64_t TmpOffset = Addr.getOffset();
Dan Gohman728926a2016-12-22 15:15:10 +0000257 // Non-inbounds geps can wrap; wasm's offsets can't.
258 if (!cast<GEPOperator>(U)->isInBounds())
259 goto unsupported_gep;
Dan Gohman2e644382016-05-10 17:39:48 +0000260 // Iterate through the GEP folding the constants into offsets where
261 // we can.
Dan Gohman33e694a2016-05-12 04:19:09 +0000262 for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
Dan Gohman2e644382016-05-10 17:39:48 +0000263 GTI != E; ++GTI) {
264 const Value *Op = GTI.getOperand();
Peter Collingbourneab85225b2016-12-02 02:24:42 +0000265 if (StructType *STy = GTI.getStructTypeOrNull()) {
Dan Gohman2e644382016-05-10 17:39:48 +0000266 const StructLayout *SL = DL.getStructLayout(STy);
267 unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
268 TmpOffset += SL->getElementOffset(Idx);
269 } else {
270 uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
271 for (;;) {
272 if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
273 // Constant-offset addressing.
274 TmpOffset += CI->getSExtValue() * S;
275 break;
276 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000277 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
278 // An unscaled add of a register. Set it as the new base.
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000279 unsigned Reg = getRegForValue(Op);
280 if (Reg == 0)
281 return false;
282 Addr.setReg(Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000283 break;
284 }
Dan Gohman2e644382016-05-10 17:39:48 +0000285 if (canFoldAddIntoGEP(U, Op)) {
286 // A compatible add with a constant operand. Fold the constant.
287 ConstantInt *CI =
288 cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
289 TmpOffset += CI->getSExtValue() * S;
290 // Iterate on the other operand.
291 Op = cast<AddOperator>(Op)->getOperand(0);
292 continue;
293 }
294 // Unsupported
295 goto unsupported_gep;
296 }
297 }
298 }
Dan Gohman728926a2016-12-22 15:15:10 +0000299 // Don't fold in negative offsets.
300 if (int64_t(TmpOffset) >= 0) {
301 // Try to grab the base operand now.
302 Addr.setOffset(TmpOffset);
303 if (computeAddress(U->getOperand(0), Addr))
304 return true;
305 }
Dan Gohman2e644382016-05-10 17:39:48 +0000306 // We failed, restore everything and try the other options.
307 Addr = SavedAddr;
308 unsupported_gep:
309 break;
310 }
311 case Instruction::Alloca: {
312 const AllocaInst *AI = cast<AllocaInst>(Obj);
313 DenseMap<const AllocaInst *, int>::iterator SI =
314 FuncInfo.StaticAllocaMap.find(AI);
315 if (SI != FuncInfo.StaticAllocaMap.end()) {
Jacob Gravellea31ec612017-06-22 21:26:08 +0000316 if (Addr.isSet()) {
317 return false;
318 }
Dan Gohman2e644382016-05-10 17:39:48 +0000319 Addr.setKind(Address::FrameIndexBase);
320 Addr.setFI(SI->second);
321 return true;
322 }
323 break;
324 }
325 case Instruction::Add: {
326 // Adds of constants are common and easy enough.
327 const Value *LHS = U->getOperand(0);
328 const Value *RHS = U->getOperand(1);
329
330 if (isa<ConstantInt>(LHS))
331 std::swap(LHS, RHS);
332
333 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
Dan Gohman728926a2016-12-22 15:15:10 +0000334 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
335 if (int64_t(TmpOffset) >= 0) {
336 Addr.setOffset(TmpOffset);
337 return computeAddress(LHS, Addr);
338 }
Dan Gohman2e644382016-05-10 17:39:48 +0000339 }
340
341 Address Backup = Addr;
342 if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
343 return true;
344 Addr = Backup;
345
346 break;
347 }
348 case Instruction::Sub: {
349 // Subs of constants are common and easy enough.
350 const Value *LHS = U->getOperand(0);
351 const Value *RHS = U->getOperand(1);
352
353 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
Dan Gohman728926a2016-12-22 15:15:10 +0000354 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
355 if (TmpOffset >= 0) {
356 Addr.setOffset(TmpOffset);
357 return computeAddress(LHS, Addr);
358 }
Dan Gohman2e644382016-05-10 17:39:48 +0000359 }
360 break;
361 }
362 }
Jacob Gravellea31ec612017-06-22 21:26:08 +0000363 if (Addr.isSet()) {
364 return false;
365 }
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000366 unsigned Reg = getRegForValue(Obj);
367 if (Reg == 0)
368 return false;
369 Addr.setReg(Reg);
Dan Gohman2e644382016-05-10 17:39:48 +0000370 return Addr.getReg() != 0;
371}
372
373void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
374 if (Addr.isRegBase()) {
375 unsigned Reg = Addr.getReg();
376 if (Reg == 0) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000377 Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
378 : &WebAssembly::I32RegClass);
379 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
380 : WebAssembly::CONST_I32;
Dan Gohman2e644382016-05-10 17:39:48 +0000381 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000382 .addImm(0);
Dan Gohman2e644382016-05-10 17:39:48 +0000383 Addr.setReg(Reg);
384 }
385 }
386}
387
388void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
389 const MachineInstrBuilder &MIB,
390 MachineMemOperand *MMO) {
Dan Gohman48abaa92016-10-25 00:17:11 +0000391 // Set the alignment operand (this is rewritten in SetP2AlignOperands).
392 // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
393 MIB.addImm(0);
394
Dan Gohman2e644382016-05-10 17:39:48 +0000395 if (const GlobalValue *GV = Addr.getGlobalValue())
396 MIB.addGlobalAddress(GV, Addr.getOffset());
397 else
398 MIB.addImm(Addr.getOffset());
399
400 if (Addr.isRegBase())
401 MIB.addReg(Addr.getReg());
402 else
403 MIB.addFrameIndex(Addr.getFI());
404
Dan Gohman2e644382016-05-10 17:39:48 +0000405 MIB.addMemOperand(MMO);
406}
407
Dan Gohman3a5ce732016-05-11 16:32:42 +0000408unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
409 return zeroExtendToI32(Reg, V, MVT::i1);
Dan Gohman2e644382016-05-10 17:39:48 +0000410}
411
Dan Gohman33e694a2016-05-12 04:19:09 +0000412unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
413 if (const ICmpInst *ICmp = dyn_cast<ICmpInst>(V))
414 if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
415 if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
416 Not = ICmp->isTrueWhenEqual();
417 return getRegForValue(ICmp->getOperand(0));
418 }
419
Dan Gohmanb01d8762018-07-02 19:45:57 +0000420 if (BinaryOperator::isNot(V) && V->getType()->isIntegerTy(32)) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000421 Not = true;
422 return getRegForValue(BinaryOperator::getNotArgument(V));
423 }
424
425 Not = false;
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000426 unsigned Reg = getRegForValue(V);
427 if (Reg == 0)
428 return 0;
429 return maskI1Value(Reg, V);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000430}
431
432unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
433 MVT::SimpleValueType From) {
Derek Schuff732636d2016-08-04 18:01:52 +0000434 if (Reg == 0)
435 return 0;
436
Dan Gohman3a5ce732016-05-11 16:32:42 +0000437 switch (From) {
438 case MVT::i1:
439 // If the value is naturally an i1, we don't need to mask it.
440 // TODO: Recursively examine selects, phis, and, or, xor, constants.
Dan Gohman33e694a2016-05-12 04:19:09 +0000441 if (From == MVT::i1 && V != nullptr) {
442 if (isa<CmpInst>(V) ||
443 (isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr()))
444 return copyValue(Reg);
445 }
446 case MVT::i8:
447 case MVT::i16:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000448 break;
449 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000450 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000451 default:
452 return 0;
453 }
454
455 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
456 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
457 TII.get(WebAssembly::CONST_I32), Imm)
Heejin Ahnf208f632018-09-05 01:27:38 +0000458 .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
Dan Gohman3a5ce732016-05-11 16:32:42 +0000459
460 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
461 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
462 TII.get(WebAssembly::AND_I32), Result)
Heejin Ahnf208f632018-09-05 01:27:38 +0000463 .addReg(Reg)
464 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000465
466 return Result;
467}
468
469unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
470 MVT::SimpleValueType From) {
Derek Schuff732636d2016-08-04 18:01:52 +0000471 if (Reg == 0)
472 return 0;
473
Dan Gohman3a5ce732016-05-11 16:32:42 +0000474 switch (From) {
475 case MVT::i1:
476 case MVT::i8:
477 case MVT::i16:
478 break;
479 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000480 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000481 default:
Dan Gohman33e694a2016-05-12 04:19:09 +0000482 return 0;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000483 }
484
485 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
486 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
487 TII.get(WebAssembly::CONST_I32), Imm)
Heejin Ahnf208f632018-09-05 01:27:38 +0000488 .addImm(32 - MVT(From).getSizeInBits());
Dan Gohman3a5ce732016-05-11 16:32:42 +0000489
490 unsigned Left = createResultReg(&WebAssembly::I32RegClass);
491 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
492 TII.get(WebAssembly::SHL_I32), Left)
Heejin Ahnf208f632018-09-05 01:27:38 +0000493 .addReg(Reg)
494 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000495
496 unsigned Right = createResultReg(&WebAssembly::I32RegClass);
497 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
498 TII.get(WebAssembly::SHR_S_I32), Right)
Heejin Ahnf208f632018-09-05 01:27:38 +0000499 .addReg(Left)
500 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000501
502 return Right;
503}
504
505unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
506 MVT::SimpleValueType From,
507 MVT::SimpleValueType To) {
508 if (To == MVT::i64) {
509 if (From == MVT::i64)
Dan Gohman33e694a2016-05-12 04:19:09 +0000510 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000511
512 Reg = zeroExtendToI32(Reg, V, From);
513
514 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
515 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
516 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
517 .addReg(Reg);
518 return Result;
519 }
520
Dan Gohman3a5ce732016-05-11 16:32:42 +0000521 return zeroExtendToI32(Reg, V, From);
522}
523
524unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
525 MVT::SimpleValueType From,
526 MVT::SimpleValueType To) {
527 if (To == MVT::i64) {
528 if (From == MVT::i64)
Dan Gohman33e694a2016-05-12 04:19:09 +0000529 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000530
531 Reg = signExtendToI32(Reg, V, From);
532
533 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
534 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
535 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
536 .addReg(Reg);
537 return Result;
538 }
539
Dan Gohman3a5ce732016-05-11 16:32:42 +0000540 return signExtendToI32(Reg, V, From);
541}
542
543unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
544 MVT::SimpleValueType From = getSimpleType(V->getType());
545 MVT::SimpleValueType To = getLegalType(From);
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000546 unsigned VReg = getRegForValue(V);
547 if (VReg == 0)
548 return 0;
549 return zeroExtend(VReg, V, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000550}
551
552unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
553 MVT::SimpleValueType From = getSimpleType(V->getType());
554 MVT::SimpleValueType To = getLegalType(From);
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000555 unsigned VReg = getRegForValue(V);
556 if (VReg == 0)
557 return 0;
558 return signExtend(VReg, V, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000559}
560
561unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
562 bool IsSigned) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000563 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000564}
565
566unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000567 assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
568
Dan Gohman3a5ce732016-05-11 16:32:42 +0000569 unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
570 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
571 TII.get(WebAssembly::EQZ_I32), NotReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000572 .addReg(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000573 return NotReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000574}
575
Dan Gohman33e694a2016-05-12 04:19:09 +0000576unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
577 unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
Heejin Ahnf208f632018-09-05 01:27:38 +0000578 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
579 ResultReg)
580 .addReg(Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000581 return ResultReg;
582}
583
Dan Gohman2e644382016-05-10 17:39:48 +0000584unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
585 DenseMap<const AllocaInst *, int>::iterator SI =
586 FuncInfo.StaticAllocaMap.find(AI);
587
588 if (SI != FuncInfo.StaticAllocaMap.end()) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000589 unsigned ResultReg =
590 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
591 : &WebAssembly::I32RegClass);
592 unsigned Opc =
593 Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
Dan Gohman2e644382016-05-10 17:39:48 +0000594 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
595 .addFrameIndex(SI->second);
596 return ResultReg;
597 }
598
599 return 0;
600}
601
602unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
603 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000604 unsigned ResultReg =
605 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
606 : &WebAssembly::I32RegClass);
607 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
608 : WebAssembly::CONST_I32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000609 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000610 .addGlobalAddress(GV);
Dan Gohman33e694a2016-05-12 04:19:09 +0000611 return ResultReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000612 }
613
614 // Let target-independent code handle it.
615 return 0;
616}
617
Dan Gohman33e694a2016-05-12 04:19:09 +0000618bool WebAssemblyFastISel::fastLowerArguments() {
619 if (!FuncInfo.CanLowerReturn)
620 return false;
621
622 const Function *F = FuncInfo.Fn;
623 if (F->isVarArg())
624 return false;
625
626 unsigned i = 0;
627 for (auto const &Arg : F->args()) {
Reid Klecknerb5180542017-03-21 16:57:19 +0000628 const AttributeList &Attrs = F->getAttributes();
Reid Klecknerf021fab2017-04-13 23:12:13 +0000629 if (Attrs.hasParamAttribute(i, Attribute::ByVal) ||
630 Attrs.hasParamAttribute(i, Attribute::SwiftSelf) ||
631 Attrs.hasParamAttribute(i, Attribute::SwiftError) ||
632 Attrs.hasParamAttribute(i, Attribute::InAlloca) ||
633 Attrs.hasParamAttribute(i, Attribute::Nest))
Dan Gohman33e694a2016-05-12 04:19:09 +0000634 return false;
635
636 Type *ArgTy = Arg.getType();
Derek Schuff39bf39f2016-08-02 23:16:09 +0000637 if (ArgTy->isStructTy() || ArgTy->isArrayTy())
638 return false;
639 if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
Dan Gohman33e694a2016-05-12 04:19:09 +0000640 return false;
641
642 unsigned Opc;
643 const TargetRegisterClass *RC;
644 switch (getSimpleType(ArgTy)) {
645 case MVT::i1:
646 case MVT::i8:
647 case MVT::i16:
648 case MVT::i32:
649 Opc = WebAssembly::ARGUMENT_I32;
650 RC = &WebAssembly::I32RegClass;
651 break;
652 case MVT::i64:
653 Opc = WebAssembly::ARGUMENT_I64;
654 RC = &WebAssembly::I64RegClass;
655 break;
656 case MVT::f32:
657 Opc = WebAssembly::ARGUMENT_F32;
658 RC = &WebAssembly::F32RegClass;
659 break;
660 case MVT::f64:
661 Opc = WebAssembly::ARGUMENT_F64;
662 RC = &WebAssembly::F64RegClass;
663 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000664 case MVT::v16i8:
665 Opc = WebAssembly::ARGUMENT_v16i8;
666 RC = &WebAssembly::V128RegClass;
667 break;
668 case MVT::v8i16:
669 Opc = WebAssembly::ARGUMENT_v8i16;
670 RC = &WebAssembly::V128RegClass;
671 break;
672 case MVT::v4i32:
673 Opc = WebAssembly::ARGUMENT_v4i32;
674 RC = &WebAssembly::V128RegClass;
675 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000676 case MVT::v2i64:
677 Opc = WebAssembly::ARGUMENT_v2i64;
678 RC = &WebAssembly::V128RegClass;
679 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000680 case MVT::v4f32:
681 Opc = WebAssembly::ARGUMENT_v4f32;
682 RC = &WebAssembly::V128RegClass;
683 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000684 case MVT::v2f64:
685 Opc = WebAssembly::ARGUMENT_v2f64;
686 RC = &WebAssembly::V128RegClass;
687 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000688 case MVT::ExceptRef:
689 Opc = WebAssembly::ARGUMENT_EXCEPT_REF;
690 RC = &WebAssembly::EXCEPT_REFRegClass;
691 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000692 default:
693 return false;
694 }
695 unsigned ResultReg = createResultReg(RC);
696 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000697 .addImm(i);
Dan Gohman33e694a2016-05-12 04:19:09 +0000698 updateValueMap(&Arg, ResultReg);
699
700 ++i;
701 }
702
703 MRI.addLiveIn(WebAssembly::ARGUMENTS);
704
705 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
Dan Gohmanb8184822018-05-22 04:58:36 +0000706 for (auto const &Arg : F->args()) {
707 MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType()));
708 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
709 MFI->clearParamsAndResults();
710 return false;
711 }
712 MFI->addParam(ArgTy);
713 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000714
Dan Gohman4576dc02018-04-17 20:46:42 +0000715 if (!F->getReturnType()->isVoidTy()) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000716 MVT::SimpleValueType RetTy =
717 getLegalType(getSimpleType(F->getReturnType()));
Dan Gohmanb8184822018-05-22 04:58:36 +0000718 if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
719 MFI->clearParamsAndResults();
Dan Gohman4576dc02018-04-17 20:46:42 +0000720 return false;
Dan Gohmanb8184822018-05-22 04:58:36 +0000721 }
722 MFI->addResult(RetTy);
Dan Gohman4576dc02018-04-17 20:46:42 +0000723 }
Dan Gohman6055fba2017-01-09 23:09:38 +0000724
Dan Gohman33e694a2016-05-12 04:19:09 +0000725 return true;
726}
727
728bool WebAssemblyFastISel::selectCall(const Instruction *I) {
729 const CallInst *Call = cast<CallInst>(I);
730
731 if (Call->isMustTailCall() || Call->isInlineAsm() ||
732 Call->getFunctionType()->isVarArg())
733 return false;
734
735 Function *Func = Call->getCalledFunction();
736 if (Func && Func->isIntrinsic())
737 return false;
738
Jacob Gravelle690b76e2017-08-24 19:53:44 +0000739 bool IsDirect = Func != nullptr;
740 if (!IsDirect && isa<ConstantExpr>(Call->getCalledValue()))
741 return false;
742
Dan Gohman33e694a2016-05-12 04:19:09 +0000743 FunctionType *FuncTy = Call->getFunctionType();
744 unsigned Opc;
Dan Gohman33e694a2016-05-12 04:19:09 +0000745 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
746 unsigned ResultReg;
747 if (IsVoid) {
Derek Schuff6f697832016-10-21 16:38:07 +0000748 Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
Dan Gohman33e694a2016-05-12 04:19:09 +0000749 } else {
Derek Schuff39bf39f2016-08-02 23:16:09 +0000750 if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
751 return false;
752
Dan Gohman33e694a2016-05-12 04:19:09 +0000753 MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
754 switch (RetTy) {
755 case MVT::i1:
756 case MVT::i8:
757 case MVT::i16:
758 case MVT::i32:
Derek Schuff6f697832016-10-21 16:38:07 +0000759 Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::PCALL_INDIRECT_I32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000760 ResultReg = createResultReg(&WebAssembly::I32RegClass);
761 break;
762 case MVT::i64:
Derek Schuff6f697832016-10-21 16:38:07 +0000763 Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::PCALL_INDIRECT_I64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000764 ResultReg = createResultReg(&WebAssembly::I64RegClass);
765 break;
766 case MVT::f32:
Derek Schuff6f697832016-10-21 16:38:07 +0000767 Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::PCALL_INDIRECT_F32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000768 ResultReg = createResultReg(&WebAssembly::F32RegClass);
769 break;
770 case MVT::f64:
Derek Schuff6f697832016-10-21 16:38:07 +0000771 Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::PCALL_INDIRECT_F64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000772 ResultReg = createResultReg(&WebAssembly::F64RegClass);
773 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000774 case MVT::v16i8:
Heejin Ahnf208f632018-09-05 01:27:38 +0000775 Opc = IsDirect ? WebAssembly::CALL_v16i8
776 : WebAssembly::PCALL_INDIRECT_v16i8;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000777 ResultReg = createResultReg(&WebAssembly::V128RegClass);
778 break;
779 case MVT::v8i16:
Heejin Ahnf208f632018-09-05 01:27:38 +0000780 Opc = IsDirect ? WebAssembly::CALL_v8i16
781 : WebAssembly::PCALL_INDIRECT_v8i16;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000782 ResultReg = createResultReg(&WebAssembly::V128RegClass);
783 break;
784 case MVT::v4i32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000785 Opc = IsDirect ? WebAssembly::CALL_v4i32
786 : WebAssembly::PCALL_INDIRECT_v4i32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000787 ResultReg = createResultReg(&WebAssembly::V128RegClass);
788 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000789 case MVT::v2i64:
Heejin Ahnf208f632018-09-05 01:27:38 +0000790 Opc = IsDirect ? WebAssembly::CALL_v2i64
791 : WebAssembly::PCALL_INDIRECT_v2i64;
Derek Schuff51ed1312018-08-07 21:24:01 +0000792 ResultReg = createResultReg(&WebAssembly::V128RegClass);
793 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000794 case MVT::v4f32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000795 Opc = IsDirect ? WebAssembly::CALL_v4f32
796 : WebAssembly::PCALL_INDIRECT_v4f32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000797 ResultReg = createResultReg(&WebAssembly::V128RegClass);
798 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000799 case MVT::v2f64:
Heejin Ahnf208f632018-09-05 01:27:38 +0000800 Opc = IsDirect ? WebAssembly::CALL_v2f64
801 : WebAssembly::PCALL_INDIRECT_v2f64;
Derek Schuff51ed1312018-08-07 21:24:01 +0000802 ResultReg = createResultReg(&WebAssembly::V128RegClass);
803 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000804 case MVT::ExceptRef:
805 Opc = IsDirect ? WebAssembly::CALL_EXCEPT_REF
806 : WebAssembly::PCALL_INDIRECT_EXCEPT_REF;
807 ResultReg = createResultReg(&WebAssembly::EXCEPT_REFRegClass);
808 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000809 default:
810 return false;
811 }
812 }
813
814 SmallVector<unsigned, 8> Args;
815 for (unsigned i = 0, e = Call->getNumArgOperands(); i < e; ++i) {
816 Value *V = Call->getArgOperand(i);
817 MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
818 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
819 return false;
820
Reid Klecknerb5180542017-03-21 16:57:19 +0000821 const AttributeList &Attrs = Call->getAttributes();
Reid Klecknerf021fab2017-04-13 23:12:13 +0000822 if (Attrs.hasParamAttribute(i, Attribute::ByVal) ||
823 Attrs.hasParamAttribute(i, Attribute::SwiftSelf) ||
824 Attrs.hasParamAttribute(i, Attribute::SwiftError) ||
825 Attrs.hasParamAttribute(i, Attribute::InAlloca) ||
826 Attrs.hasParamAttribute(i, Attribute::Nest))
Dan Gohman33e694a2016-05-12 04:19:09 +0000827 return false;
828
829 unsigned Reg;
830
Reid Klecknerf021fab2017-04-13 23:12:13 +0000831 if (Attrs.hasParamAttribute(i, Attribute::SExt))
Dan Gohman33e694a2016-05-12 04:19:09 +0000832 Reg = getRegForSignedValue(V);
Reid Klecknerf021fab2017-04-13 23:12:13 +0000833 else if (Attrs.hasParamAttribute(i, Attribute::ZExt))
Dan Gohman33e694a2016-05-12 04:19:09 +0000834 Reg = getRegForUnsignedValue(V);
835 else
836 Reg = getRegForValue(V);
837
838 if (Reg == 0)
839 return false;
840
841 Args.push_back(Reg);
842 }
843
844 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
845
846 if (!IsVoid)
847 MIB.addReg(ResultReg, RegState::Define);
848
849 if (IsDirect)
850 MIB.addGlobalAddress(Func);
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000851 else {
852 unsigned Reg = getRegForValue(Call->getCalledValue());
853 if (Reg == 0)
854 return false;
855 MIB.addReg(Reg);
856 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000857
858 for (unsigned ArgReg : Args)
859 MIB.addReg(ArgReg);
860
861 if (!IsVoid)
862 updateValueMap(Call, ResultReg);
863 return true;
864}
865
866bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
867 const SelectInst *Select = cast<SelectInst>(I);
868
869 bool Not;
Heejin Ahnf208f632018-09-05 01:27:38 +0000870 unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
Dan Gohman33e694a2016-05-12 04:19:09 +0000871 if (CondReg == 0)
872 return false;
873
Heejin Ahnf208f632018-09-05 01:27:38 +0000874 unsigned TrueReg = getRegForValue(Select->getTrueValue());
Dan Gohman33e694a2016-05-12 04:19:09 +0000875 if (TrueReg == 0)
876 return false;
877
878 unsigned FalseReg = getRegForValue(Select->getFalseValue());
879 if (FalseReg == 0)
880 return false;
881
882 if (Not)
883 std::swap(TrueReg, FalseReg);
884
885 unsigned Opc;
886 const TargetRegisterClass *RC;
887 switch (getSimpleType(Select->getType())) {
888 case MVT::i1:
889 case MVT::i8:
890 case MVT::i16:
891 case MVT::i32:
892 Opc = WebAssembly::SELECT_I32;
893 RC = &WebAssembly::I32RegClass;
894 break;
895 case MVT::i64:
896 Opc = WebAssembly::SELECT_I64;
897 RC = &WebAssembly::I64RegClass;
898 break;
899 case MVT::f32:
900 Opc = WebAssembly::SELECT_F32;
901 RC = &WebAssembly::F32RegClass;
902 break;
903 case MVT::f64:
904 Opc = WebAssembly::SELECT_F64;
905 RC = &WebAssembly::F64RegClass;
906 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000907 case MVT::ExceptRef:
908 Opc = WebAssembly::SELECT_EXCEPT_REF;
909 RC = &WebAssembly::EXCEPT_REFRegClass;
910 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000911 default:
912 return false;
913 }
914
915 unsigned ResultReg = createResultReg(RC);
916 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000917 .addReg(TrueReg)
918 .addReg(FalseReg)
919 .addReg(CondReg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000920
921 updateValueMap(Select, ResultReg);
922 return true;
923}
924
925bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
926 const TruncInst *Trunc = cast<TruncInst>(I);
927
928 unsigned Reg = getRegForValue(Trunc->getOperand(0));
929 if (Reg == 0)
930 return false;
931
932 if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
933 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
934 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
935 TII.get(WebAssembly::I32_WRAP_I64), Result)
936 .addReg(Reg);
937 Reg = Result;
938 }
939
940 updateValueMap(Trunc, Reg);
941 return true;
942}
943
Dan Gohman3a5ce732016-05-11 16:32:42 +0000944bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
945 const ZExtInst *ZExt = cast<ZExtInst>(I);
946
Dan Gohman33e694a2016-05-12 04:19:09 +0000947 const Value *Op = ZExt->getOperand(0);
948 MVT::SimpleValueType From = getSimpleType(Op->getType());
949 MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000950 unsigned In = getRegForValue(Op);
951 if (In == 0)
952 return false;
953 unsigned Reg = zeroExtend(In, Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000954 if (Reg == 0)
955 return false;
956
957 updateValueMap(ZExt, Reg);
958 return true;
959}
960
961bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
962 const SExtInst *SExt = cast<SExtInst>(I);
963
Dan Gohman33e694a2016-05-12 04:19:09 +0000964 const Value *Op = SExt->getOperand(0);
965 MVT::SimpleValueType From = getSimpleType(Op->getType());
966 MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000967 unsigned In = getRegForValue(Op);
968 if (In == 0)
969 return false;
970 unsigned Reg = signExtend(In, Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000971 if (Reg == 0)
972 return false;
973
974 updateValueMap(SExt, Reg);
975 return true;
976}
977
978bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
979 const ICmpInst *ICmp = cast<ICmpInst>(I);
980
981 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
982 unsigned Opc;
983 bool isSigned = false;
984 switch (ICmp->getPredicate()) {
985 case ICmpInst::ICMP_EQ:
986 Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
987 break;
988 case ICmpInst::ICMP_NE:
989 Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
990 break;
991 case ICmpInst::ICMP_UGT:
992 Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
993 break;
994 case ICmpInst::ICMP_UGE:
995 Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
996 break;
997 case ICmpInst::ICMP_ULT:
998 Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
999 break;
1000 case ICmpInst::ICMP_ULE:
1001 Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1002 break;
1003 case ICmpInst::ICMP_SGT:
1004 Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1005 isSigned = true;
1006 break;
1007 case ICmpInst::ICMP_SGE:
1008 Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1009 isSigned = true;
1010 break;
1011 case ICmpInst::ICMP_SLT:
1012 Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1013 isSigned = true;
1014 break;
1015 case ICmpInst::ICMP_SLE:
1016 Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1017 isSigned = true;
1018 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001019 default:
1020 return false;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001021 }
1022
1023 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), isSigned);
1024 if (LHS == 0)
1025 return false;
1026
1027 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), isSigned);
1028 if (RHS == 0)
1029 return false;
1030
1031 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1032 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1033 .addReg(LHS)
1034 .addReg(RHS);
1035 updateValueMap(ICmp, ResultReg);
1036 return true;
1037}
1038
1039bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
1040 const FCmpInst *FCmp = cast<FCmpInst>(I);
1041
1042 unsigned LHS = getRegForValue(FCmp->getOperand(0));
1043 if (LHS == 0)
1044 return false;
1045
1046 unsigned RHS = getRegForValue(FCmp->getOperand(1));
1047 if (RHS == 0)
1048 return false;
1049
1050 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1051 unsigned Opc;
1052 bool Not = false;
1053 switch (FCmp->getPredicate()) {
1054 case FCmpInst::FCMP_OEQ:
1055 Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1056 break;
1057 case FCmpInst::FCMP_UNE:
1058 Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1059 break;
1060 case FCmpInst::FCMP_OGT:
1061 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1062 break;
1063 case FCmpInst::FCMP_OGE:
1064 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1065 break;
1066 case FCmpInst::FCMP_OLT:
1067 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1068 break;
1069 case FCmpInst::FCMP_OLE:
1070 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1071 break;
1072 case FCmpInst::FCMP_UGT:
1073 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1074 Not = true;
1075 break;
1076 case FCmpInst::FCMP_UGE:
1077 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1078 Not = true;
1079 break;
1080 case FCmpInst::FCMP_ULT:
1081 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1082 Not = true;
1083 break;
1084 case FCmpInst::FCMP_ULE:
1085 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1086 Not = true;
1087 break;
1088 default:
1089 return false;
1090 }
1091
1092 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1093 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1094 .addReg(LHS)
1095 .addReg(RHS);
1096
1097 if (Not)
1098 ResultReg = notValue(ResultReg);
1099
1100 updateValueMap(FCmp, ResultReg);
1101 return true;
1102}
1103
Dan Gohman2e644382016-05-10 17:39:48 +00001104bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
1105 // Target-independent code can handle this, except it doesn't set the dead
1106 // flag on the ARGUMENTS clobber, so we have to do that manually in order
1107 // to satisfy code that expects this of isBitcast() instructions.
1108 EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
1109 EVT RetVT = TLI.getValueType(DL, I->getType());
1110 if (!VT.isSimple() || !RetVT.isSimple())
1111 return false;
Dan Gohman33e694a2016-05-12 04:19:09 +00001112
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001113 unsigned In = getRegForValue(I->getOperand(0));
1114 if (In == 0)
1115 return false;
1116
Dan Gohman33e694a2016-05-12 04:19:09 +00001117 if (VT == RetVT) {
1118 // No-op bitcast.
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001119 updateValueMap(I, In);
Dan Gohman33e694a2016-05-12 04:19:09 +00001120 return true;
1121 }
1122
Dan Gohman2e644382016-05-10 17:39:48 +00001123 unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001124 In, I->getOperand(0)->hasOneUse());
Dan Gohman2e644382016-05-10 17:39:48 +00001125 if (!Reg)
1126 return false;
1127 MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
1128 --Iter;
1129 assert(Iter->isBitcast());
1130 Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI);
1131 updateValueMap(I, Reg);
1132 return true;
1133}
1134
1135bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
1136 const LoadInst *Load = cast<LoadInst>(I);
1137 if (Load->isAtomic())
1138 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001139 if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
1140 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001141
1142 Address Addr;
1143 if (!computeAddress(Load->getPointerOperand(), Addr))
1144 return false;
1145
1146 // TODO: Fold a following sign-/zero-extend into the load instruction.
1147
1148 unsigned Opc;
1149 const TargetRegisterClass *RC;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001150 switch (getSimpleType(Load->getType())) {
1151 case MVT::i1:
1152 case MVT::i8:
1153 Opc = WebAssembly::LOAD8_U_I32;
1154 RC = &WebAssembly::I32RegClass;
Dan Gohman2e644382016-05-10 17:39:48 +00001155 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001156 case MVT::i16:
1157 Opc = WebAssembly::LOAD16_U_I32;
1158 RC = &WebAssembly::I32RegClass;
1159 break;
1160 case MVT::i32:
1161 Opc = WebAssembly::LOAD_I32;
1162 RC = &WebAssembly::I32RegClass;
1163 break;
1164 case MVT::i64:
1165 Opc = WebAssembly::LOAD_I64;
1166 RC = &WebAssembly::I64RegClass;
1167 break;
1168 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001169 Opc = WebAssembly::LOAD_F32;
1170 RC = &WebAssembly::F32RegClass;
1171 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001172 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001173 Opc = WebAssembly::LOAD_F64;
1174 RC = &WebAssembly::F64RegClass;
1175 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001176 default:
1177 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001178 }
1179
1180 materializeLoadStoreOperands(Addr);
1181
1182 unsigned ResultReg = createResultReg(RC);
1183 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
1184 ResultReg);
1185
1186 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1187
1188 updateValueMap(Load, ResultReg);
1189 return true;
1190}
1191
1192bool WebAssemblyFastISel::selectStore(const Instruction *I) {
1193 const StoreInst *Store = cast<StoreInst>(I);
1194 if (Store->isAtomic())
1195 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001196 if (!Subtarget->hasSIMD128() &&
1197 Store->getValueOperand()->getType()->isVectorTy())
1198 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001199
1200 Address Addr;
1201 if (!computeAddress(Store->getPointerOperand(), Addr))
1202 return false;
1203
1204 unsigned Opc;
Dan Gohman2e644382016-05-10 17:39:48 +00001205 bool VTIsi1 = false;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001206 switch (getSimpleType(Store->getValueOperand()->getType())) {
1207 case MVT::i1:
1208 VTIsi1 = true;
Dan Gohman861bec22018-02-09 22:59:01 +00001209 LLVM_FALLTHROUGH;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001210 case MVT::i8:
1211 Opc = WebAssembly::STORE8_I32;
Dan Gohman2e644382016-05-10 17:39:48 +00001212 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001213 case MVT::i16:
1214 Opc = WebAssembly::STORE16_I32;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001215 break;
1216 case MVT::i32:
1217 Opc = WebAssembly::STORE_I32;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001218 break;
1219 case MVT::i64:
1220 Opc = WebAssembly::STORE_I64;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001221 break;
1222 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001223 Opc = WebAssembly::STORE_F32;
Dan Gohman2e644382016-05-10 17:39:48 +00001224 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001225 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001226 Opc = WebAssembly::STORE_F64;
Dan Gohman2e644382016-05-10 17:39:48 +00001227 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001228 default:
1229 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001230 }
1231
1232 materializeLoadStoreOperands(Addr);
1233
1234 unsigned ValueReg = getRegForValue(Store->getValueOperand());
Derek Schuff732636d2016-08-04 18:01:52 +00001235 if (ValueReg == 0)
1236 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001237 if (VTIsi1)
Dan Gohman3a5ce732016-05-11 16:32:42 +00001238 ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
Dan Gohman2e644382016-05-10 17:39:48 +00001239
Dan Gohman7f1bdb22016-10-06 22:08:28 +00001240 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
Dan Gohman2e644382016-05-10 17:39:48 +00001241
1242 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1243
1244 MIB.addReg(ValueReg);
1245 return true;
1246}
1247
1248bool WebAssemblyFastISel::selectBr(const Instruction *I) {
1249 const BranchInst *Br = cast<BranchInst>(I);
1250 if (Br->isUnconditional()) {
1251 MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
1252 fastEmitBranch(MSucc, Br->getDebugLoc());
1253 return true;
1254 }
1255
1256 MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
1257 MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
1258
Dan Gohman33e694a2016-05-12 04:19:09 +00001259 bool Not;
1260 unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
Derek Schuff732636d2016-08-04 18:01:52 +00001261 if (CondReg == 0)
1262 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001263
Dan Gohman33e694a2016-05-12 04:19:09 +00001264 unsigned Opc = WebAssembly::BR_IF;
1265 if (Not)
1266 Opc = WebAssembly::BR_UNLESS;
1267
Dan Gohman2e644382016-05-10 17:39:48 +00001268 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1269 .addMBB(TBB)
1270 .addReg(CondReg);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001271
Dan Gohman2e644382016-05-10 17:39:48 +00001272 finishCondBranch(Br->getParent(), TBB, FBB);
1273 return true;
1274}
1275
1276bool WebAssemblyFastISel::selectRet(const Instruction *I) {
1277 if (!FuncInfo.CanLowerReturn)
1278 return false;
1279
1280 const ReturnInst *Ret = cast<ReturnInst>(I);
1281
1282 if (Ret->getNumOperands() == 0) {
1283 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1284 TII.get(WebAssembly::RETURN_VOID));
1285 return true;
1286 }
1287
1288 Value *RV = Ret->getOperand(0);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001289 if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
1290 return false;
1291
Dan Gohman2e644382016-05-10 17:39:48 +00001292 unsigned Opc;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001293 switch (getSimpleType(RV->getType())) {
Heejin Ahnf208f632018-09-05 01:27:38 +00001294 case MVT::i1:
1295 case MVT::i8:
1296 case MVT::i16:
1297 case MVT::i32:
Dan Gohman3a5ce732016-05-11 16:32:42 +00001298 Opc = WebAssembly::RETURN_I32;
Dan Gohman2e644382016-05-10 17:39:48 +00001299 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001300 case MVT::i64:
1301 Opc = WebAssembly::RETURN_I64;
1302 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001303 case MVT::f32:
1304 Opc = WebAssembly::RETURN_F32;
1305 break;
1306 case MVT::f64:
1307 Opc = WebAssembly::RETURN_F64;
1308 break;
1309 case MVT::v16i8:
1310 Opc = WebAssembly::RETURN_v16i8;
1311 break;
1312 case MVT::v8i16:
1313 Opc = WebAssembly::RETURN_v8i16;
1314 break;
1315 case MVT::v4i32:
1316 Opc = WebAssembly::RETURN_v4i32;
1317 break;
Derek Schuff51ed1312018-08-07 21:24:01 +00001318 case MVT::v2i64:
1319 Opc = WebAssembly::RETURN_v2i64;
1320 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001321 case MVT::v4f32:
1322 Opc = WebAssembly::RETURN_v4f32;
1323 break;
Derek Schuff51ed1312018-08-07 21:24:01 +00001324 case MVT::v2f64:
1325 Opc = WebAssembly::RETURN_v2f64;
1326 break;
Heejin Ahn0de58722018-03-08 04:05:37 +00001327 case MVT::ExceptRef:
1328 Opc = WebAssembly::RETURN_EXCEPT_REF;
1329 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001330 default:
1331 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001332 }
1333
Dan Gohman33e694a2016-05-12 04:19:09 +00001334 unsigned Reg;
1335 if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
1336 Reg = getRegForSignedValue(RV);
1337 else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
1338 Reg = getRegForUnsignedValue(RV);
1339 else
1340 Reg = getRegForValue(RV);
1341
Derek Schuff732636d2016-08-04 18:01:52 +00001342 if (Reg == 0)
1343 return false;
1344
Dan Gohman2e644382016-05-10 17:39:48 +00001345 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg);
1346 return true;
1347}
1348
1349bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
1350 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1351 TII.get(WebAssembly::UNREACHABLE));
1352 return true;
1353}
1354
1355bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
1356 switch (I->getOpcode()) {
Dan Gohman33e694a2016-05-12 04:19:09 +00001357 case Instruction::Call:
1358 if (selectCall(I))
1359 return true;
1360 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001361 case Instruction::Select:
1362 return selectSelect(I);
1363 case Instruction::Trunc:
1364 return selectTrunc(I);
1365 case Instruction::ZExt:
1366 return selectZExt(I);
1367 case Instruction::SExt:
1368 return selectSExt(I);
1369 case Instruction::ICmp:
1370 return selectICmp(I);
1371 case Instruction::FCmp:
1372 return selectFCmp(I);
1373 case Instruction::BitCast:
1374 return selectBitCast(I);
1375 case Instruction::Load:
1376 return selectLoad(I);
1377 case Instruction::Store:
1378 return selectStore(I);
1379 case Instruction::Br:
1380 return selectBr(I);
1381 case Instruction::Ret:
1382 return selectRet(I);
1383 case Instruction::Unreachable:
1384 return selectUnreachable(I);
1385 default:
1386 break;
Dan Gohman7b634842015-08-24 18:44:37 +00001387 }
1388
1389 // Fall back to target-independent instruction selection.
1390 return selectOperator(I, I->getOpcode());
1391}
1392
1393FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,
1394 const TargetLibraryInfo *LibInfo) {
1395 return new WebAssemblyFastISel(FuncInfo, LibInfo);
1396}