blob: 3856700cca9489f5be3ee24ada7dd5d90b7247d6 [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"
Sanjay Patel47a52a02018-10-23 16:05:09 +000040#include "llvm/IR/PatternMatch.h"
41
Dan Gohman7b634842015-08-24 18:44:37 +000042using namespace llvm;
Sanjay Patel47a52a02018-10-23 16:05:09 +000043using namespace PatternMatch;
Dan Gohman7b634842015-08-24 18:44:37 +000044
45#define DEBUG_TYPE "wasm-fastisel"
46
47namespace {
48
49class WebAssemblyFastISel final : public FastISel {
Dan Gohman2e644382016-05-10 17:39:48 +000050 // All possible address modes.
51 class Address {
52 public:
53 typedef enum { RegBase, FrameIndexBase } BaseKind;
54
55 private:
56 BaseKind Kind;
57 union {
58 unsigned Reg;
59 int FI;
60 } Base;
61
62 int64_t Offset;
63
64 const GlobalValue *GV;
65
66 public:
67 // Innocuous defaults for our address.
68 Address() : Kind(RegBase), Offset(0), GV(0) { Base.Reg = 0; }
Jacob Gravellea31ec612017-06-22 21:26:08 +000069 void setKind(BaseKind K) {
70 assert(!isSet() && "Can't change kind with non-zero base");
71 Kind = K;
72 }
Dan Gohman2e644382016-05-10 17:39:48 +000073 BaseKind getKind() const { return Kind; }
74 bool isRegBase() const { return Kind == RegBase; }
75 bool isFIBase() const { return Kind == FrameIndexBase; }
76 void setReg(unsigned Reg) {
77 assert(isRegBase() && "Invalid base register access!");
Jacob Gravellea31ec612017-06-22 21:26:08 +000078 assert(Base.Reg == 0 && "Overwriting non-zero register");
Dan Gohman2e644382016-05-10 17:39:48 +000079 Base.Reg = Reg;
80 }
81 unsigned getReg() const {
82 assert(isRegBase() && "Invalid base register access!");
83 return Base.Reg;
84 }
85 void setFI(unsigned FI) {
86 assert(isFIBase() && "Invalid base frame index access!");
Jacob Gravellea31ec612017-06-22 21:26:08 +000087 assert(Base.FI == 0 && "Overwriting non-zero frame index");
Dan Gohman2e644382016-05-10 17:39:48 +000088 Base.FI = FI;
89 }
90 unsigned getFI() const {
91 assert(isFIBase() && "Invalid base frame index access!");
92 return Base.FI;
93 }
94
Dan Gohman728926a2016-12-22 15:15:10 +000095 void setOffset(int64_t Offset_) {
96 assert(Offset_ >= 0 && "Offsets must be non-negative");
97 Offset = Offset_;
98 }
Dan Gohman2e644382016-05-10 17:39:48 +000099 int64_t getOffset() const { return Offset; }
100 void setGlobalValue(const GlobalValue *G) { GV = G; }
101 const GlobalValue *getGlobalValue() const { return GV; }
Jacob Gravellea31ec612017-06-22 21:26:08 +0000102 bool isSet() const {
103 if (isRegBase()) {
104 return Base.Reg != 0;
105 } else {
106 return Base.FI != 0;
107 }
108 }
Dan Gohman2e644382016-05-10 17:39:48 +0000109 };
110
Dan Gohman7b634842015-08-24 18:44:37 +0000111 /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
112 /// right decision when generating code for different targets.
113 const WebAssemblySubtarget *Subtarget;
114 LLVMContext *Context;
115
Dan Gohman7b634842015-08-24 18:44:37 +0000116private:
Dan Gohman2e644382016-05-10 17:39:48 +0000117 // Utility helper routines
Dan Gohman3a5ce732016-05-11 16:32:42 +0000118 MVT::SimpleValueType getSimpleType(Type *Ty) {
119 EVT VT = TLI.getValueType(DL, Ty, /*HandleUnknown=*/true);
Heejin Ahnf208f632018-09-05 01:27:38 +0000120 return VT.isSimple() ? VT.getSimpleVT().SimpleTy
121 : MVT::INVALID_SIMPLE_VALUE_TYPE;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000122 }
123 MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
124 switch (VT) {
125 case MVT::i1:
126 case MVT::i8:
127 case MVT::i16:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000128 return MVT::i32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000129 case MVT::i32:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000130 case MVT::i64:
Dan Gohman33e694a2016-05-12 04:19:09 +0000131 case MVT::f32:
132 case MVT::f64:
Heejin Ahn0de58722018-03-08 04:05:37 +0000133 case MVT::ExceptRef:
Dan Gohman33e694a2016-05-12 04:19:09 +0000134 return VT;
Dan Gohman6999c4f2017-02-24 21:05:35 +0000135 case MVT::f16:
136 return MVT::f32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000137 case MVT::v16i8:
138 case MVT::v8i16:
139 case MVT::v4i32:
140 case MVT::v4f32:
141 if (Subtarget->hasSIMD128())
142 return VT;
143 break;
Thomas Livelyb6dac892018-12-21 06:58:15 +0000144 case MVT::v2i64:
145 case MVT::v2f64:
Thomas Lively64a39a12019-01-10 22:32:11 +0000146 if (Subtarget->hasUnimplementedSIMD128())
Thomas Livelyb6dac892018-12-21 06:58:15 +0000147 return VT;
148 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000149 default:
150 break;
151 }
152 return MVT::INVALID_SIMPLE_VALUE_TYPE;
153 }
Dan Gohman2e644382016-05-10 17:39:48 +0000154 bool computeAddress(const Value *Obj, Address &Addr);
155 void materializeLoadStoreOperands(Address &Addr);
156 void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
157 MachineMemOperand *MMO);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000158 unsigned maskI1Value(unsigned Reg, const Value *V);
Dan Gohman33e694a2016-05-12 04:19:09 +0000159 unsigned getRegForI1Value(const Value *V, bool &Not);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000160 unsigned zeroExtendToI32(unsigned Reg, const Value *V,
161 MVT::SimpleValueType From);
162 unsigned signExtendToI32(unsigned Reg, const Value *V,
163 MVT::SimpleValueType From);
Heejin Ahnf208f632018-09-05 01:27:38 +0000164 unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
Dan Gohman3a5ce732016-05-11 16:32:42 +0000165 MVT::SimpleValueType To);
Heejin Ahnf208f632018-09-05 01:27:38 +0000166 unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
Dan Gohman3a5ce732016-05-11 16:32:42 +0000167 MVT::SimpleValueType To);
168 unsigned getRegForUnsignedValue(const Value *V);
169 unsigned getRegForSignedValue(const Value *V);
170 unsigned getRegForPromotedValue(const Value *V, bool IsSigned);
171 unsigned notValue(unsigned Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000172 unsigned copyValue(unsigned Reg);
Dan Gohman2e644382016-05-10 17:39:48 +0000173
174 // Backend specific FastISel code.
175 unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
176 unsigned fastMaterializeConstant(const Constant *C) override;
Dan Gohman33e694a2016-05-12 04:19:09 +0000177 bool fastLowerArguments() override;
Dan Gohman2e644382016-05-10 17:39:48 +0000178
179 // Selection routines.
Dan Gohman33e694a2016-05-12 04:19:09 +0000180 bool selectCall(const Instruction *I);
181 bool selectSelect(const Instruction *I);
182 bool selectTrunc(const Instruction *I);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000183 bool selectZExt(const Instruction *I);
184 bool selectSExt(const Instruction *I);
185 bool selectICmp(const Instruction *I);
186 bool selectFCmp(const Instruction *I);
Dan Gohman2e644382016-05-10 17:39:48 +0000187 bool selectBitCast(const Instruction *I);
188 bool selectLoad(const Instruction *I);
189 bool selectStore(const Instruction *I);
190 bool selectBr(const Instruction *I);
191 bool selectRet(const Instruction *I);
192 bool selectUnreachable(const Instruction *I);
193
Dan Gohman7b634842015-08-24 18:44:37 +0000194public:
195 // Backend specific FastISel code.
196 WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo,
197 const TargetLibraryInfo *LibInfo)
198 : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
199 Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>();
200 Context = &FuncInfo.Fn->getContext();
201 }
202
203 bool fastSelectInstruction(const Instruction *I) override;
204
205#include "WebAssemblyGenFastISel.inc"
206};
207
208} // end anonymous namespace
209
Dan Gohman2e644382016-05-10 17:39:48 +0000210bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {
211
212 const User *U = nullptr;
213 unsigned Opcode = Instruction::UserOp1;
214 if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
215 // Don't walk into other basic blocks unless the object is an alloca from
216 // another block, otherwise it may not have a virtual register assigned.
217 if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
218 FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
219 Opcode = I->getOpcode();
220 U = I;
221 }
222 } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
223 Opcode = C->getOpcode();
224 U = C;
225 }
226
227 if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
228 if (Ty->getAddressSpace() > 255)
229 // Fast instruction selection doesn't support the special
230 // address spaces.
231 return false;
232
233 if (const GlobalValue *GV = dyn_cast<GlobalValue>(Obj)) {
234 if (Addr.getGlobalValue())
235 return false;
236 Addr.setGlobalValue(GV);
237 return true;
238 }
239
240 switch (Opcode) {
Dan Gohman7b634842015-08-24 18:44:37 +0000241 default:
242 break;
Dan Gohman2e644382016-05-10 17:39:48 +0000243 case Instruction::BitCast: {
244 // Look through bitcasts.
245 return computeAddress(U->getOperand(0), Addr);
246 }
247 case Instruction::IntToPtr: {
248 // Look past no-op inttoptrs.
249 if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
250 TLI.getPointerTy(DL))
251 return computeAddress(U->getOperand(0), Addr);
252 break;
253 }
254 case Instruction::PtrToInt: {
255 // Look past no-op ptrtoints.
256 if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
257 return computeAddress(U->getOperand(0), Addr);
258 break;
259 }
260 case Instruction::GetElementPtr: {
261 Address SavedAddr = Addr;
262 uint64_t TmpOffset = Addr.getOffset();
Dan Gohman728926a2016-12-22 15:15:10 +0000263 // Non-inbounds geps can wrap; wasm's offsets can't.
264 if (!cast<GEPOperator>(U)->isInBounds())
265 goto unsupported_gep;
Dan Gohman2e644382016-05-10 17:39:48 +0000266 // Iterate through the GEP folding the constants into offsets where
267 // we can.
Dan Gohman33e694a2016-05-12 04:19:09 +0000268 for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
Dan Gohman2e644382016-05-10 17:39:48 +0000269 GTI != E; ++GTI) {
270 const Value *Op = GTI.getOperand();
Peter Collingbourneab85225b2016-12-02 02:24:42 +0000271 if (StructType *STy = GTI.getStructTypeOrNull()) {
Dan Gohman2e644382016-05-10 17:39:48 +0000272 const StructLayout *SL = DL.getStructLayout(STy);
273 unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
274 TmpOffset += SL->getElementOffset(Idx);
275 } else {
276 uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
277 for (;;) {
278 if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
279 // Constant-offset addressing.
280 TmpOffset += CI->getSExtValue() * S;
281 break;
282 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000283 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
284 // An unscaled add of a register. Set it as the new base.
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000285 unsigned Reg = getRegForValue(Op);
286 if (Reg == 0)
287 return false;
288 Addr.setReg(Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000289 break;
290 }
Dan Gohman2e644382016-05-10 17:39:48 +0000291 if (canFoldAddIntoGEP(U, Op)) {
292 // A compatible add with a constant operand. Fold the constant.
293 ConstantInt *CI =
294 cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
295 TmpOffset += CI->getSExtValue() * S;
296 // Iterate on the other operand.
297 Op = cast<AddOperator>(Op)->getOperand(0);
298 continue;
299 }
300 // Unsupported
301 goto unsupported_gep;
302 }
303 }
304 }
Dan Gohman728926a2016-12-22 15:15:10 +0000305 // Don't fold in negative offsets.
306 if (int64_t(TmpOffset) >= 0) {
307 // Try to grab the base operand now.
308 Addr.setOffset(TmpOffset);
309 if (computeAddress(U->getOperand(0), Addr))
310 return true;
311 }
Dan Gohman2e644382016-05-10 17:39:48 +0000312 // We failed, restore everything and try the other options.
313 Addr = SavedAddr;
314 unsupported_gep:
315 break;
316 }
317 case Instruction::Alloca: {
318 const AllocaInst *AI = cast<AllocaInst>(Obj);
319 DenseMap<const AllocaInst *, int>::iterator SI =
320 FuncInfo.StaticAllocaMap.find(AI);
321 if (SI != FuncInfo.StaticAllocaMap.end()) {
Jacob Gravellea31ec612017-06-22 21:26:08 +0000322 if (Addr.isSet()) {
323 return false;
324 }
Dan Gohman2e644382016-05-10 17:39:48 +0000325 Addr.setKind(Address::FrameIndexBase);
326 Addr.setFI(SI->second);
327 return true;
328 }
329 break;
330 }
331 case Instruction::Add: {
332 // Adds of constants are common and easy enough.
333 const Value *LHS = U->getOperand(0);
334 const Value *RHS = U->getOperand(1);
335
336 if (isa<ConstantInt>(LHS))
337 std::swap(LHS, RHS);
338
339 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
Dan Gohman728926a2016-12-22 15:15:10 +0000340 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
341 if (int64_t(TmpOffset) >= 0) {
342 Addr.setOffset(TmpOffset);
343 return computeAddress(LHS, Addr);
344 }
Dan Gohman2e644382016-05-10 17:39:48 +0000345 }
346
347 Address Backup = Addr;
348 if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
349 return true;
350 Addr = Backup;
351
352 break;
353 }
354 case Instruction::Sub: {
355 // Subs of constants are common and easy enough.
356 const Value *LHS = U->getOperand(0);
357 const Value *RHS = U->getOperand(1);
358
359 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
Dan Gohman728926a2016-12-22 15:15:10 +0000360 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
361 if (TmpOffset >= 0) {
362 Addr.setOffset(TmpOffset);
363 return computeAddress(LHS, Addr);
364 }
Dan Gohman2e644382016-05-10 17:39:48 +0000365 }
366 break;
367 }
368 }
Jacob Gravellea31ec612017-06-22 21:26:08 +0000369 if (Addr.isSet()) {
370 return false;
371 }
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000372 unsigned Reg = getRegForValue(Obj);
373 if (Reg == 0)
374 return false;
375 Addr.setReg(Reg);
Dan Gohman2e644382016-05-10 17:39:48 +0000376 return Addr.getReg() != 0;
377}
378
379void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
380 if (Addr.isRegBase()) {
381 unsigned Reg = Addr.getReg();
382 if (Reg == 0) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000383 Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
384 : &WebAssembly::I32RegClass);
385 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
386 : WebAssembly::CONST_I32;
Dan Gohman2e644382016-05-10 17:39:48 +0000387 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000388 .addImm(0);
Dan Gohman2e644382016-05-10 17:39:48 +0000389 Addr.setReg(Reg);
390 }
391 }
392}
393
394void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
395 const MachineInstrBuilder &MIB,
396 MachineMemOperand *MMO) {
Dan Gohman48abaa92016-10-25 00:17:11 +0000397 // Set the alignment operand (this is rewritten in SetP2AlignOperands).
398 // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
399 MIB.addImm(0);
400
Dan Gohman2e644382016-05-10 17:39:48 +0000401 if (const GlobalValue *GV = Addr.getGlobalValue())
402 MIB.addGlobalAddress(GV, Addr.getOffset());
403 else
404 MIB.addImm(Addr.getOffset());
405
406 if (Addr.isRegBase())
407 MIB.addReg(Addr.getReg());
408 else
409 MIB.addFrameIndex(Addr.getFI());
410
Dan Gohman2e644382016-05-10 17:39:48 +0000411 MIB.addMemOperand(MMO);
412}
413
Dan Gohman3a5ce732016-05-11 16:32:42 +0000414unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
415 return zeroExtendToI32(Reg, V, MVT::i1);
Dan Gohman2e644382016-05-10 17:39:48 +0000416}
417
Dan Gohman33e694a2016-05-12 04:19:09 +0000418unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
419 if (const ICmpInst *ICmp = dyn_cast<ICmpInst>(V))
420 if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
421 if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
422 Not = ICmp->isTrueWhenEqual();
423 return getRegForValue(ICmp->getOperand(0));
424 }
425
Sanjay Patel47a52a02018-10-23 16:05:09 +0000426 Value *NotV;
427 if (match(V, m_Not(m_Value(NotV))) && V->getType()->isIntegerTy(32)) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000428 Not = true;
Sanjay Patel47a52a02018-10-23 16:05:09 +0000429 return getRegForValue(NotV);
Dan Gohman33e694a2016-05-12 04:19:09 +0000430 }
431
432 Not = false;
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000433 unsigned Reg = getRegForValue(V);
434 if (Reg == 0)
435 return 0;
436 return maskI1Value(Reg, V);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000437}
438
439unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
440 MVT::SimpleValueType From) {
Derek Schuff732636d2016-08-04 18:01:52 +0000441 if (Reg == 0)
442 return 0;
443
Dan Gohman3a5ce732016-05-11 16:32:42 +0000444 switch (From) {
445 case MVT::i1:
Thomas Lively2a47e032019-01-14 22:03:43 +0000446 // If the value is naturally an i1, we don't need to mask it. We only know
447 // if a value is naturally an i1 if it is definitely lowered by FastISel,
448 // not a DAG ISel fallback.
449 if (V != nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr())
450 return copyValue(Reg);
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000451 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000452 case MVT::i8:
453 case MVT::i16:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000454 break;
455 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000456 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000457 default:
458 return 0;
459 }
460
461 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
462 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
463 TII.get(WebAssembly::CONST_I32), Imm)
Heejin Ahnf208f632018-09-05 01:27:38 +0000464 .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
Dan Gohman3a5ce732016-05-11 16:32:42 +0000465
466 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
467 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
468 TII.get(WebAssembly::AND_I32), Result)
Heejin Ahnf208f632018-09-05 01:27:38 +0000469 .addReg(Reg)
470 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000471
472 return Result;
473}
474
475unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
476 MVT::SimpleValueType From) {
Derek Schuff732636d2016-08-04 18:01:52 +0000477 if (Reg == 0)
478 return 0;
479
Dan Gohman3a5ce732016-05-11 16:32:42 +0000480 switch (From) {
481 case MVT::i1:
482 case MVT::i8:
483 case MVT::i16:
484 break;
485 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000486 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000487 default:
Dan Gohman33e694a2016-05-12 04:19:09 +0000488 return 0;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000489 }
490
491 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
492 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
493 TII.get(WebAssembly::CONST_I32), Imm)
Heejin Ahnf208f632018-09-05 01:27:38 +0000494 .addImm(32 - MVT(From).getSizeInBits());
Dan Gohman3a5ce732016-05-11 16:32:42 +0000495
496 unsigned Left = createResultReg(&WebAssembly::I32RegClass);
497 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
498 TII.get(WebAssembly::SHL_I32), Left)
Heejin Ahnf208f632018-09-05 01:27:38 +0000499 .addReg(Reg)
500 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000501
502 unsigned Right = createResultReg(&WebAssembly::I32RegClass);
503 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
504 TII.get(WebAssembly::SHR_S_I32), Right)
Heejin Ahnf208f632018-09-05 01:27:38 +0000505 .addReg(Left)
506 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000507
508 return Right;
509}
510
511unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
512 MVT::SimpleValueType From,
513 MVT::SimpleValueType To) {
514 if (To == MVT::i64) {
515 if (From == MVT::i64)
Dan Gohman33e694a2016-05-12 04:19:09 +0000516 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000517
518 Reg = zeroExtendToI32(Reg, V, From);
519
520 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
521 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
522 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
523 .addReg(Reg);
524 return Result;
525 }
526
Dan Gohman3a5ce732016-05-11 16:32:42 +0000527 return zeroExtendToI32(Reg, V, From);
528}
529
530unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
531 MVT::SimpleValueType From,
532 MVT::SimpleValueType To) {
533 if (To == MVT::i64) {
534 if (From == MVT::i64)
Dan Gohman33e694a2016-05-12 04:19:09 +0000535 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000536
537 Reg = signExtendToI32(Reg, V, From);
538
539 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
540 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
541 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
542 .addReg(Reg);
543 return Result;
544 }
545
Dan Gohman3a5ce732016-05-11 16:32:42 +0000546 return signExtendToI32(Reg, V, From);
547}
548
549unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
550 MVT::SimpleValueType From = getSimpleType(V->getType());
551 MVT::SimpleValueType To = getLegalType(From);
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000552 unsigned VReg = getRegForValue(V);
553 if (VReg == 0)
554 return 0;
555 return zeroExtend(VReg, V, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000556}
557
558unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
559 MVT::SimpleValueType From = getSimpleType(V->getType());
560 MVT::SimpleValueType To = getLegalType(From);
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000561 unsigned VReg = getRegForValue(V);
562 if (VReg == 0)
563 return 0;
564 return signExtend(VReg, V, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000565}
566
567unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
568 bool IsSigned) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000569 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000570}
571
572unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000573 assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
574
Dan Gohman3a5ce732016-05-11 16:32:42 +0000575 unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
576 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
577 TII.get(WebAssembly::EQZ_I32), NotReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000578 .addReg(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000579 return NotReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000580}
581
Dan Gohman33e694a2016-05-12 04:19:09 +0000582unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
583 unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
Heejin Ahnf208f632018-09-05 01:27:38 +0000584 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
585 ResultReg)
586 .addReg(Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000587 return ResultReg;
588}
589
Dan Gohman2e644382016-05-10 17:39:48 +0000590unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
591 DenseMap<const AllocaInst *, int>::iterator SI =
592 FuncInfo.StaticAllocaMap.find(AI);
593
594 if (SI != FuncInfo.StaticAllocaMap.end()) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000595 unsigned ResultReg =
596 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
597 : &WebAssembly::I32RegClass);
598 unsigned Opc =
599 Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
Dan Gohman2e644382016-05-10 17:39:48 +0000600 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
601 .addFrameIndex(SI->second);
602 return ResultReg;
603 }
604
605 return 0;
606}
607
608unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
609 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000610 unsigned ResultReg =
611 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
612 : &WebAssembly::I32RegClass);
613 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
614 : WebAssembly::CONST_I32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000615 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000616 .addGlobalAddress(GV);
Dan Gohman33e694a2016-05-12 04:19:09 +0000617 return ResultReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000618 }
619
620 // Let target-independent code handle it.
621 return 0;
622}
623
Dan Gohman33e694a2016-05-12 04:19:09 +0000624bool WebAssemblyFastISel::fastLowerArguments() {
625 if (!FuncInfo.CanLowerReturn)
626 return false;
627
628 const Function *F = FuncInfo.Fn;
629 if (F->isVarArg())
630 return false;
631
632 unsigned i = 0;
633 for (auto const &Arg : F->args()) {
Reid Klecknerb5180542017-03-21 16:57:19 +0000634 const AttributeList &Attrs = F->getAttributes();
Reid Klecknerf021fab2017-04-13 23:12:13 +0000635 if (Attrs.hasParamAttribute(i, Attribute::ByVal) ||
636 Attrs.hasParamAttribute(i, Attribute::SwiftSelf) ||
637 Attrs.hasParamAttribute(i, Attribute::SwiftError) ||
638 Attrs.hasParamAttribute(i, Attribute::InAlloca) ||
639 Attrs.hasParamAttribute(i, Attribute::Nest))
Dan Gohman33e694a2016-05-12 04:19:09 +0000640 return false;
641
642 Type *ArgTy = Arg.getType();
Derek Schuff39bf39f2016-08-02 23:16:09 +0000643 if (ArgTy->isStructTy() || ArgTy->isArrayTy())
644 return false;
645 if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
Dan Gohman33e694a2016-05-12 04:19:09 +0000646 return false;
647
648 unsigned Opc;
649 const TargetRegisterClass *RC;
650 switch (getSimpleType(ArgTy)) {
651 case MVT::i1:
652 case MVT::i8:
653 case MVT::i16:
654 case MVT::i32:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000655 Opc = WebAssembly::ARGUMENT_i32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000656 RC = &WebAssembly::I32RegClass;
657 break;
658 case MVT::i64:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000659 Opc = WebAssembly::ARGUMENT_i64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000660 RC = &WebAssembly::I64RegClass;
661 break;
662 case MVT::f32:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000663 Opc = WebAssembly::ARGUMENT_f32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000664 RC = &WebAssembly::F32RegClass;
665 break;
666 case MVT::f64:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000667 Opc = WebAssembly::ARGUMENT_f64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000668 RC = &WebAssembly::F64RegClass;
669 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000670 case MVT::v16i8:
671 Opc = WebAssembly::ARGUMENT_v16i8;
672 RC = &WebAssembly::V128RegClass;
673 break;
674 case MVT::v8i16:
675 Opc = WebAssembly::ARGUMENT_v8i16;
676 RC = &WebAssembly::V128RegClass;
677 break;
678 case MVT::v4i32:
679 Opc = WebAssembly::ARGUMENT_v4i32;
680 RC = &WebAssembly::V128RegClass;
681 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000682 case MVT::v2i64:
683 Opc = WebAssembly::ARGUMENT_v2i64;
684 RC = &WebAssembly::V128RegClass;
685 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000686 case MVT::v4f32:
687 Opc = WebAssembly::ARGUMENT_v4f32;
688 RC = &WebAssembly::V128RegClass;
689 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000690 case MVT::v2f64:
691 Opc = WebAssembly::ARGUMENT_v2f64;
692 RC = &WebAssembly::V128RegClass;
693 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000694 case MVT::ExceptRef:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000695 Opc = WebAssembly::ARGUMENT_ExceptRef;
Heejin Ahn0de58722018-03-08 04:05:37 +0000696 RC = &WebAssembly::EXCEPT_REFRegClass;
697 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000698 default:
699 return false;
700 }
701 unsigned ResultReg = createResultReg(RC);
702 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000703 .addImm(i);
Dan Gohman33e694a2016-05-12 04:19:09 +0000704 updateValueMap(&Arg, ResultReg);
705
706 ++i;
707 }
708
709 MRI.addLiveIn(WebAssembly::ARGUMENTS);
710
711 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
Dan Gohmanb8184822018-05-22 04:58:36 +0000712 for (auto const &Arg : F->args()) {
713 MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType()));
714 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
715 MFI->clearParamsAndResults();
716 return false;
717 }
718 MFI->addParam(ArgTy);
719 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000720
Dan Gohman4576dc02018-04-17 20:46:42 +0000721 if (!F->getReturnType()->isVoidTy()) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000722 MVT::SimpleValueType RetTy =
723 getLegalType(getSimpleType(F->getReturnType()));
Dan Gohmanb8184822018-05-22 04:58:36 +0000724 if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
725 MFI->clearParamsAndResults();
Dan Gohman4576dc02018-04-17 20:46:42 +0000726 return false;
Dan Gohmanb8184822018-05-22 04:58:36 +0000727 }
728 MFI->addResult(RetTy);
Dan Gohman4576dc02018-04-17 20:46:42 +0000729 }
Dan Gohman6055fba2017-01-09 23:09:38 +0000730
Dan Gohman33e694a2016-05-12 04:19:09 +0000731 return true;
732}
733
734bool WebAssemblyFastISel::selectCall(const Instruction *I) {
735 const CallInst *Call = cast<CallInst>(I);
736
737 if (Call->isMustTailCall() || Call->isInlineAsm() ||
738 Call->getFunctionType()->isVarArg())
739 return false;
740
741 Function *Func = Call->getCalledFunction();
742 if (Func && Func->isIntrinsic())
743 return false;
744
Jacob Gravelle690b76e2017-08-24 19:53:44 +0000745 bool IsDirect = Func != nullptr;
746 if (!IsDirect && isa<ConstantExpr>(Call->getCalledValue()))
747 return false;
748
Dan Gohman33e694a2016-05-12 04:19:09 +0000749 FunctionType *FuncTy = Call->getFunctionType();
750 unsigned Opc;
Dan Gohman33e694a2016-05-12 04:19:09 +0000751 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
752 unsigned ResultReg;
753 if (IsVoid) {
Derek Schuff6f697832016-10-21 16:38:07 +0000754 Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
Dan Gohman33e694a2016-05-12 04:19:09 +0000755 } else {
Derek Schuff39bf39f2016-08-02 23:16:09 +0000756 if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
757 return false;
758
Dan Gohman33e694a2016-05-12 04:19:09 +0000759 MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
760 switch (RetTy) {
761 case MVT::i1:
762 case MVT::i8:
763 case MVT::i16:
764 case MVT::i32:
Derek Schuff6f697832016-10-21 16:38:07 +0000765 Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::PCALL_INDIRECT_I32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000766 ResultReg = createResultReg(&WebAssembly::I32RegClass);
767 break;
768 case MVT::i64:
Derek Schuff6f697832016-10-21 16:38:07 +0000769 Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::PCALL_INDIRECT_I64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000770 ResultReg = createResultReg(&WebAssembly::I64RegClass);
771 break;
772 case MVT::f32:
Derek Schuff6f697832016-10-21 16:38:07 +0000773 Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::PCALL_INDIRECT_F32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000774 ResultReg = createResultReg(&WebAssembly::F32RegClass);
775 break;
776 case MVT::f64:
Derek Schuff6f697832016-10-21 16:38:07 +0000777 Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::PCALL_INDIRECT_F64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000778 ResultReg = createResultReg(&WebAssembly::F64RegClass);
779 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000780 case MVT::v16i8:
Heejin Ahnf208f632018-09-05 01:27:38 +0000781 Opc = IsDirect ? WebAssembly::CALL_v16i8
782 : WebAssembly::PCALL_INDIRECT_v16i8;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000783 ResultReg = createResultReg(&WebAssembly::V128RegClass);
784 break;
785 case MVT::v8i16:
Heejin Ahnf208f632018-09-05 01:27:38 +0000786 Opc = IsDirect ? WebAssembly::CALL_v8i16
787 : WebAssembly::PCALL_INDIRECT_v8i16;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000788 ResultReg = createResultReg(&WebAssembly::V128RegClass);
789 break;
790 case MVT::v4i32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000791 Opc = IsDirect ? WebAssembly::CALL_v4i32
792 : WebAssembly::PCALL_INDIRECT_v4i32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000793 ResultReg = createResultReg(&WebAssembly::V128RegClass);
794 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000795 case MVT::v2i64:
Heejin Ahnf208f632018-09-05 01:27:38 +0000796 Opc = IsDirect ? WebAssembly::CALL_v2i64
797 : WebAssembly::PCALL_INDIRECT_v2i64;
Derek Schuff51ed1312018-08-07 21:24:01 +0000798 ResultReg = createResultReg(&WebAssembly::V128RegClass);
799 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000800 case MVT::v4f32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000801 Opc = IsDirect ? WebAssembly::CALL_v4f32
802 : WebAssembly::PCALL_INDIRECT_v4f32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000803 ResultReg = createResultReg(&WebAssembly::V128RegClass);
804 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000805 case MVT::v2f64:
Heejin Ahnf208f632018-09-05 01:27:38 +0000806 Opc = IsDirect ? WebAssembly::CALL_v2f64
807 : WebAssembly::PCALL_INDIRECT_v2f64;
Derek Schuff51ed1312018-08-07 21:24:01 +0000808 ResultReg = createResultReg(&WebAssembly::V128RegClass);
809 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000810 case MVT::ExceptRef:
811 Opc = IsDirect ? WebAssembly::CALL_EXCEPT_REF
812 : WebAssembly::PCALL_INDIRECT_EXCEPT_REF;
813 ResultReg = createResultReg(&WebAssembly::EXCEPT_REFRegClass);
814 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000815 default:
816 return false;
817 }
818 }
819
820 SmallVector<unsigned, 8> Args;
821 for (unsigned i = 0, e = Call->getNumArgOperands(); i < e; ++i) {
822 Value *V = Call->getArgOperand(i);
823 MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
824 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
825 return false;
826
Reid Klecknerb5180542017-03-21 16:57:19 +0000827 const AttributeList &Attrs = Call->getAttributes();
Reid Klecknerf021fab2017-04-13 23:12:13 +0000828 if (Attrs.hasParamAttribute(i, Attribute::ByVal) ||
829 Attrs.hasParamAttribute(i, Attribute::SwiftSelf) ||
830 Attrs.hasParamAttribute(i, Attribute::SwiftError) ||
831 Attrs.hasParamAttribute(i, Attribute::InAlloca) ||
832 Attrs.hasParamAttribute(i, Attribute::Nest))
Dan Gohman33e694a2016-05-12 04:19:09 +0000833 return false;
834
835 unsigned Reg;
836
Reid Klecknerf021fab2017-04-13 23:12:13 +0000837 if (Attrs.hasParamAttribute(i, Attribute::SExt))
Dan Gohman33e694a2016-05-12 04:19:09 +0000838 Reg = getRegForSignedValue(V);
Reid Klecknerf021fab2017-04-13 23:12:13 +0000839 else if (Attrs.hasParamAttribute(i, Attribute::ZExt))
Dan Gohman33e694a2016-05-12 04:19:09 +0000840 Reg = getRegForUnsignedValue(V);
841 else
842 Reg = getRegForValue(V);
843
844 if (Reg == 0)
845 return false;
846
847 Args.push_back(Reg);
848 }
849
850 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
851
852 if (!IsVoid)
853 MIB.addReg(ResultReg, RegState::Define);
854
855 if (IsDirect)
856 MIB.addGlobalAddress(Func);
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000857 else {
858 unsigned Reg = getRegForValue(Call->getCalledValue());
859 if (Reg == 0)
860 return false;
861 MIB.addReg(Reg);
862 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000863
864 for (unsigned ArgReg : Args)
865 MIB.addReg(ArgReg);
866
867 if (!IsVoid)
868 updateValueMap(Call, ResultReg);
869 return true;
870}
871
872bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
873 const SelectInst *Select = cast<SelectInst>(I);
874
875 bool Not;
Heejin Ahnf208f632018-09-05 01:27:38 +0000876 unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
Dan Gohman33e694a2016-05-12 04:19:09 +0000877 if (CondReg == 0)
878 return false;
879
Heejin Ahnf208f632018-09-05 01:27:38 +0000880 unsigned TrueReg = getRegForValue(Select->getTrueValue());
Dan Gohman33e694a2016-05-12 04:19:09 +0000881 if (TrueReg == 0)
882 return false;
883
884 unsigned FalseReg = getRegForValue(Select->getFalseValue());
885 if (FalseReg == 0)
886 return false;
887
888 if (Not)
889 std::swap(TrueReg, FalseReg);
890
891 unsigned Opc;
892 const TargetRegisterClass *RC;
893 switch (getSimpleType(Select->getType())) {
894 case MVT::i1:
895 case MVT::i8:
896 case MVT::i16:
897 case MVT::i32:
898 Opc = WebAssembly::SELECT_I32;
899 RC = &WebAssembly::I32RegClass;
900 break;
901 case MVT::i64:
902 Opc = WebAssembly::SELECT_I64;
903 RC = &WebAssembly::I64RegClass;
904 break;
905 case MVT::f32:
906 Opc = WebAssembly::SELECT_F32;
907 RC = &WebAssembly::F32RegClass;
908 break;
909 case MVT::f64:
910 Opc = WebAssembly::SELECT_F64;
911 RC = &WebAssembly::F64RegClass;
912 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000913 case MVT::ExceptRef:
914 Opc = WebAssembly::SELECT_EXCEPT_REF;
915 RC = &WebAssembly::EXCEPT_REFRegClass;
916 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000917 default:
918 return false;
919 }
920
921 unsigned ResultReg = createResultReg(RC);
922 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000923 .addReg(TrueReg)
924 .addReg(FalseReg)
925 .addReg(CondReg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000926
927 updateValueMap(Select, ResultReg);
928 return true;
929}
930
931bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
932 const TruncInst *Trunc = cast<TruncInst>(I);
933
934 unsigned Reg = getRegForValue(Trunc->getOperand(0));
935 if (Reg == 0)
936 return false;
937
938 if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
939 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
940 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
941 TII.get(WebAssembly::I32_WRAP_I64), Result)
942 .addReg(Reg);
943 Reg = Result;
944 }
945
946 updateValueMap(Trunc, Reg);
947 return true;
948}
949
Dan Gohman3a5ce732016-05-11 16:32:42 +0000950bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
951 const ZExtInst *ZExt = cast<ZExtInst>(I);
952
Dan Gohman33e694a2016-05-12 04:19:09 +0000953 const Value *Op = ZExt->getOperand(0);
954 MVT::SimpleValueType From = getSimpleType(Op->getType());
955 MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000956 unsigned In = getRegForValue(Op);
957 if (In == 0)
958 return false;
959 unsigned Reg = zeroExtend(In, Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000960 if (Reg == 0)
961 return false;
962
963 updateValueMap(ZExt, Reg);
964 return true;
965}
966
967bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
968 const SExtInst *SExt = cast<SExtInst>(I);
969
Dan Gohman33e694a2016-05-12 04:19:09 +0000970 const Value *Op = SExt->getOperand(0);
971 MVT::SimpleValueType From = getSimpleType(Op->getType());
972 MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000973 unsigned In = getRegForValue(Op);
974 if (In == 0)
975 return false;
976 unsigned Reg = signExtend(In, Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000977 if (Reg == 0)
978 return false;
979
980 updateValueMap(SExt, Reg);
981 return true;
982}
983
984bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
985 const ICmpInst *ICmp = cast<ICmpInst>(I);
986
987 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
988 unsigned Opc;
989 bool isSigned = false;
990 switch (ICmp->getPredicate()) {
991 case ICmpInst::ICMP_EQ:
992 Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
993 break;
994 case ICmpInst::ICMP_NE:
995 Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
996 break;
997 case ICmpInst::ICMP_UGT:
998 Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
999 break;
1000 case ICmpInst::ICMP_UGE:
1001 Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1002 break;
1003 case ICmpInst::ICMP_ULT:
1004 Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1005 break;
1006 case ICmpInst::ICMP_ULE:
1007 Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1008 break;
1009 case ICmpInst::ICMP_SGT:
1010 Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1011 isSigned = true;
1012 break;
1013 case ICmpInst::ICMP_SGE:
1014 Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1015 isSigned = true;
1016 break;
1017 case ICmpInst::ICMP_SLT:
1018 Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1019 isSigned = true;
1020 break;
1021 case ICmpInst::ICMP_SLE:
1022 Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1023 isSigned = true;
1024 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001025 default:
1026 return false;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001027 }
1028
1029 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), isSigned);
1030 if (LHS == 0)
1031 return false;
1032
1033 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), isSigned);
1034 if (RHS == 0)
1035 return false;
1036
1037 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1038 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1039 .addReg(LHS)
1040 .addReg(RHS);
1041 updateValueMap(ICmp, ResultReg);
1042 return true;
1043}
1044
1045bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
1046 const FCmpInst *FCmp = cast<FCmpInst>(I);
1047
1048 unsigned LHS = getRegForValue(FCmp->getOperand(0));
1049 if (LHS == 0)
1050 return false;
1051
1052 unsigned RHS = getRegForValue(FCmp->getOperand(1));
1053 if (RHS == 0)
1054 return false;
1055
1056 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1057 unsigned Opc;
1058 bool Not = false;
1059 switch (FCmp->getPredicate()) {
1060 case FCmpInst::FCMP_OEQ:
1061 Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1062 break;
1063 case FCmpInst::FCMP_UNE:
1064 Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1065 break;
1066 case FCmpInst::FCMP_OGT:
1067 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1068 break;
1069 case FCmpInst::FCMP_OGE:
1070 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1071 break;
1072 case FCmpInst::FCMP_OLT:
1073 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1074 break;
1075 case FCmpInst::FCMP_OLE:
1076 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1077 break;
1078 case FCmpInst::FCMP_UGT:
1079 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1080 Not = true;
1081 break;
1082 case FCmpInst::FCMP_UGE:
1083 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1084 Not = true;
1085 break;
1086 case FCmpInst::FCMP_ULT:
1087 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1088 Not = true;
1089 break;
1090 case FCmpInst::FCMP_ULE:
1091 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1092 Not = true;
1093 break;
1094 default:
1095 return false;
1096 }
1097
1098 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1099 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1100 .addReg(LHS)
1101 .addReg(RHS);
1102
1103 if (Not)
1104 ResultReg = notValue(ResultReg);
1105
1106 updateValueMap(FCmp, ResultReg);
1107 return true;
1108}
1109
Dan Gohman2e644382016-05-10 17:39:48 +00001110bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
1111 // Target-independent code can handle this, except it doesn't set the dead
1112 // flag on the ARGUMENTS clobber, so we have to do that manually in order
1113 // to satisfy code that expects this of isBitcast() instructions.
1114 EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
1115 EVT RetVT = TLI.getValueType(DL, I->getType());
1116 if (!VT.isSimple() || !RetVT.isSimple())
1117 return false;
Dan Gohman33e694a2016-05-12 04:19:09 +00001118
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001119 unsigned In = getRegForValue(I->getOperand(0));
1120 if (In == 0)
1121 return false;
1122
Dan Gohman33e694a2016-05-12 04:19:09 +00001123 if (VT == RetVT) {
1124 // No-op bitcast.
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001125 updateValueMap(I, In);
Dan Gohman33e694a2016-05-12 04:19:09 +00001126 return true;
1127 }
1128
Dan Gohman2e644382016-05-10 17:39:48 +00001129 unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001130 In, I->getOperand(0)->hasOneUse());
Dan Gohman2e644382016-05-10 17:39:48 +00001131 if (!Reg)
1132 return false;
1133 MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
1134 --Iter;
1135 assert(Iter->isBitcast());
1136 Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI);
1137 updateValueMap(I, Reg);
1138 return true;
1139}
1140
1141bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
1142 const LoadInst *Load = cast<LoadInst>(I);
1143 if (Load->isAtomic())
1144 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001145 if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
1146 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001147
1148 Address Addr;
1149 if (!computeAddress(Load->getPointerOperand(), Addr))
1150 return false;
1151
1152 // TODO: Fold a following sign-/zero-extend into the load instruction.
1153
1154 unsigned Opc;
1155 const TargetRegisterClass *RC;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001156 switch (getSimpleType(Load->getType())) {
1157 case MVT::i1:
1158 case MVT::i8:
1159 Opc = WebAssembly::LOAD8_U_I32;
1160 RC = &WebAssembly::I32RegClass;
Dan Gohman2e644382016-05-10 17:39:48 +00001161 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001162 case MVT::i16:
1163 Opc = WebAssembly::LOAD16_U_I32;
1164 RC = &WebAssembly::I32RegClass;
1165 break;
1166 case MVT::i32:
1167 Opc = WebAssembly::LOAD_I32;
1168 RC = &WebAssembly::I32RegClass;
1169 break;
1170 case MVT::i64:
1171 Opc = WebAssembly::LOAD_I64;
1172 RC = &WebAssembly::I64RegClass;
1173 break;
1174 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001175 Opc = WebAssembly::LOAD_F32;
1176 RC = &WebAssembly::F32RegClass;
1177 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001178 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001179 Opc = WebAssembly::LOAD_F64;
1180 RC = &WebAssembly::F64RegClass;
1181 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001182 default:
1183 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001184 }
1185
1186 materializeLoadStoreOperands(Addr);
1187
1188 unsigned ResultReg = createResultReg(RC);
1189 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
1190 ResultReg);
1191
1192 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1193
1194 updateValueMap(Load, ResultReg);
1195 return true;
1196}
1197
1198bool WebAssemblyFastISel::selectStore(const Instruction *I) {
1199 const StoreInst *Store = cast<StoreInst>(I);
1200 if (Store->isAtomic())
1201 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001202 if (!Subtarget->hasSIMD128() &&
1203 Store->getValueOperand()->getType()->isVectorTy())
1204 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001205
1206 Address Addr;
1207 if (!computeAddress(Store->getPointerOperand(), Addr))
1208 return false;
1209
1210 unsigned Opc;
Dan Gohman2e644382016-05-10 17:39:48 +00001211 bool VTIsi1 = false;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001212 switch (getSimpleType(Store->getValueOperand()->getType())) {
1213 case MVT::i1:
1214 VTIsi1 = true;
Dan Gohman861bec22018-02-09 22:59:01 +00001215 LLVM_FALLTHROUGH;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001216 case MVT::i8:
1217 Opc = WebAssembly::STORE8_I32;
Dan Gohman2e644382016-05-10 17:39:48 +00001218 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001219 case MVT::i16:
1220 Opc = WebAssembly::STORE16_I32;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001221 break;
1222 case MVT::i32:
1223 Opc = WebAssembly::STORE_I32;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001224 break;
1225 case MVT::i64:
1226 Opc = WebAssembly::STORE_I64;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001227 break;
1228 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001229 Opc = WebAssembly::STORE_F32;
Dan Gohman2e644382016-05-10 17:39:48 +00001230 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001231 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001232 Opc = WebAssembly::STORE_F64;
Dan Gohman2e644382016-05-10 17:39:48 +00001233 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001234 default:
1235 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001236 }
1237
1238 materializeLoadStoreOperands(Addr);
1239
1240 unsigned ValueReg = getRegForValue(Store->getValueOperand());
Derek Schuff732636d2016-08-04 18:01:52 +00001241 if (ValueReg == 0)
1242 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001243 if (VTIsi1)
Dan Gohman3a5ce732016-05-11 16:32:42 +00001244 ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
Dan Gohman2e644382016-05-10 17:39:48 +00001245
Dan Gohman7f1bdb22016-10-06 22:08:28 +00001246 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
Dan Gohman2e644382016-05-10 17:39:48 +00001247
1248 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1249
1250 MIB.addReg(ValueReg);
1251 return true;
1252}
1253
1254bool WebAssemblyFastISel::selectBr(const Instruction *I) {
1255 const BranchInst *Br = cast<BranchInst>(I);
1256 if (Br->isUnconditional()) {
1257 MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
1258 fastEmitBranch(MSucc, Br->getDebugLoc());
1259 return true;
1260 }
1261
1262 MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
1263 MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
1264
Dan Gohman33e694a2016-05-12 04:19:09 +00001265 bool Not;
1266 unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
Derek Schuff732636d2016-08-04 18:01:52 +00001267 if (CondReg == 0)
1268 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001269
Dan Gohman33e694a2016-05-12 04:19:09 +00001270 unsigned Opc = WebAssembly::BR_IF;
1271 if (Not)
1272 Opc = WebAssembly::BR_UNLESS;
1273
Dan Gohman2e644382016-05-10 17:39:48 +00001274 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1275 .addMBB(TBB)
1276 .addReg(CondReg);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001277
Dan Gohman2e644382016-05-10 17:39:48 +00001278 finishCondBranch(Br->getParent(), TBB, FBB);
1279 return true;
1280}
1281
1282bool WebAssemblyFastISel::selectRet(const Instruction *I) {
1283 if (!FuncInfo.CanLowerReturn)
1284 return false;
1285
1286 const ReturnInst *Ret = cast<ReturnInst>(I);
1287
1288 if (Ret->getNumOperands() == 0) {
1289 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1290 TII.get(WebAssembly::RETURN_VOID));
1291 return true;
1292 }
1293
1294 Value *RV = Ret->getOperand(0);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001295 if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
1296 return false;
1297
Dan Gohman2e644382016-05-10 17:39:48 +00001298 unsigned Opc;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001299 switch (getSimpleType(RV->getType())) {
Heejin Ahnf208f632018-09-05 01:27:38 +00001300 case MVT::i1:
1301 case MVT::i8:
1302 case MVT::i16:
1303 case MVT::i32:
Dan Gohman3a5ce732016-05-11 16:32:42 +00001304 Opc = WebAssembly::RETURN_I32;
Dan Gohman2e644382016-05-10 17:39:48 +00001305 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001306 case MVT::i64:
1307 Opc = WebAssembly::RETURN_I64;
1308 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001309 case MVT::f32:
1310 Opc = WebAssembly::RETURN_F32;
1311 break;
1312 case MVT::f64:
1313 Opc = WebAssembly::RETURN_F64;
1314 break;
1315 case MVT::v16i8:
1316 Opc = WebAssembly::RETURN_v16i8;
1317 break;
1318 case MVT::v8i16:
1319 Opc = WebAssembly::RETURN_v8i16;
1320 break;
1321 case MVT::v4i32:
1322 Opc = WebAssembly::RETURN_v4i32;
1323 break;
Derek Schuff51ed1312018-08-07 21:24:01 +00001324 case MVT::v2i64:
1325 Opc = WebAssembly::RETURN_v2i64;
1326 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001327 case MVT::v4f32:
1328 Opc = WebAssembly::RETURN_v4f32;
1329 break;
Derek Schuff51ed1312018-08-07 21:24:01 +00001330 case MVT::v2f64:
1331 Opc = WebAssembly::RETURN_v2f64;
1332 break;
Heejin Ahn0de58722018-03-08 04:05:37 +00001333 case MVT::ExceptRef:
1334 Opc = WebAssembly::RETURN_EXCEPT_REF;
1335 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001336 default:
1337 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001338 }
1339
Dan Gohman33e694a2016-05-12 04:19:09 +00001340 unsigned Reg;
1341 if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
1342 Reg = getRegForSignedValue(RV);
1343 else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
1344 Reg = getRegForUnsignedValue(RV);
1345 else
1346 Reg = getRegForValue(RV);
1347
Derek Schuff732636d2016-08-04 18:01:52 +00001348 if (Reg == 0)
1349 return false;
1350
Dan Gohman2e644382016-05-10 17:39:48 +00001351 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg);
1352 return true;
1353}
1354
1355bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
1356 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1357 TII.get(WebAssembly::UNREACHABLE));
1358 return true;
1359}
1360
1361bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
1362 switch (I->getOpcode()) {
Dan Gohman33e694a2016-05-12 04:19:09 +00001363 case Instruction::Call:
1364 if (selectCall(I))
1365 return true;
1366 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001367 case Instruction::Select:
1368 return selectSelect(I);
1369 case Instruction::Trunc:
1370 return selectTrunc(I);
1371 case Instruction::ZExt:
1372 return selectZExt(I);
1373 case Instruction::SExt:
1374 return selectSExt(I);
1375 case Instruction::ICmp:
1376 return selectICmp(I);
1377 case Instruction::FCmp:
1378 return selectFCmp(I);
1379 case Instruction::BitCast:
1380 return selectBitCast(I);
1381 case Instruction::Load:
1382 return selectLoad(I);
1383 case Instruction::Store:
1384 return selectStore(I);
1385 case Instruction::Br:
1386 return selectBr(I);
1387 case Instruction::Ret:
1388 return selectRet(I);
1389 case Instruction::Unreachable:
1390 return selectUnreachable(I);
1391 default:
1392 break;
Dan Gohman7b634842015-08-24 18:44:37 +00001393 }
1394
1395 // Fall back to target-independent instruction selection.
1396 return selectOperator(I, I->getOpcode());
1397}
1398
1399FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,
1400 const TargetLibraryInfo *LibInfo) {
1401 return new WebAssemblyFastISel(FuncInfo, LibInfo);
1402}