blob: a452a005df7016ff56f6e52d07b9dd2f88bb7e72 [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
Thomas Livelyfdd49992019-01-10 04:09:25 +000047extern cl::opt<bool> EnableUnimplementedWasmSIMDInstrs;
48
Dan Gohman7b634842015-08-24 18:44:37 +000049namespace {
50
51class WebAssemblyFastISel final : public FastISel {
Dan Gohman2e644382016-05-10 17:39:48 +000052 // All possible address modes.
53 class Address {
54 public:
55 typedef enum { RegBase, FrameIndexBase } BaseKind;
56
57 private:
58 BaseKind Kind;
59 union {
60 unsigned Reg;
61 int FI;
62 } Base;
63
64 int64_t Offset;
65
66 const GlobalValue *GV;
67
68 public:
69 // Innocuous defaults for our address.
70 Address() : Kind(RegBase), Offset(0), GV(0) { Base.Reg = 0; }
Jacob Gravellea31ec612017-06-22 21:26:08 +000071 void setKind(BaseKind K) {
72 assert(!isSet() && "Can't change kind with non-zero base");
73 Kind = K;
74 }
Dan Gohman2e644382016-05-10 17:39:48 +000075 BaseKind getKind() const { return Kind; }
76 bool isRegBase() const { return Kind == RegBase; }
77 bool isFIBase() const { return Kind == FrameIndexBase; }
78 void setReg(unsigned Reg) {
79 assert(isRegBase() && "Invalid base register access!");
Jacob Gravellea31ec612017-06-22 21:26:08 +000080 assert(Base.Reg == 0 && "Overwriting non-zero register");
Dan Gohman2e644382016-05-10 17:39:48 +000081 Base.Reg = Reg;
82 }
83 unsigned getReg() const {
84 assert(isRegBase() && "Invalid base register access!");
85 return Base.Reg;
86 }
87 void setFI(unsigned FI) {
88 assert(isFIBase() && "Invalid base frame index access!");
Jacob Gravellea31ec612017-06-22 21:26:08 +000089 assert(Base.FI == 0 && "Overwriting non-zero frame index");
Dan Gohman2e644382016-05-10 17:39:48 +000090 Base.FI = FI;
91 }
92 unsigned getFI() const {
93 assert(isFIBase() && "Invalid base frame index access!");
94 return Base.FI;
95 }
96
Dan Gohman728926a2016-12-22 15:15:10 +000097 void setOffset(int64_t Offset_) {
98 assert(Offset_ >= 0 && "Offsets must be non-negative");
99 Offset = Offset_;
100 }
Dan Gohman2e644382016-05-10 17:39:48 +0000101 int64_t getOffset() const { return Offset; }
102 void setGlobalValue(const GlobalValue *G) { GV = G; }
103 const GlobalValue *getGlobalValue() const { return GV; }
Jacob Gravellea31ec612017-06-22 21:26:08 +0000104 bool isSet() const {
105 if (isRegBase()) {
106 return Base.Reg != 0;
107 } else {
108 return Base.FI != 0;
109 }
110 }
Dan Gohman2e644382016-05-10 17:39:48 +0000111 };
112
Dan Gohman7b634842015-08-24 18:44:37 +0000113 /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
114 /// right decision when generating code for different targets.
115 const WebAssemblySubtarget *Subtarget;
116 LLVMContext *Context;
117
Dan Gohman7b634842015-08-24 18:44:37 +0000118private:
Dan Gohman2e644382016-05-10 17:39:48 +0000119 // Utility helper routines
Dan Gohman3a5ce732016-05-11 16:32:42 +0000120 MVT::SimpleValueType getSimpleType(Type *Ty) {
121 EVT VT = TLI.getValueType(DL, Ty, /*HandleUnknown=*/true);
Heejin Ahnf208f632018-09-05 01:27:38 +0000122 return VT.isSimple() ? VT.getSimpleVT().SimpleTy
123 : MVT::INVALID_SIMPLE_VALUE_TYPE;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000124 }
125 MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
126 switch (VT) {
127 case MVT::i1:
128 case MVT::i8:
129 case MVT::i16:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000130 return MVT::i32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000131 case MVT::i32:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000132 case MVT::i64:
Dan Gohman33e694a2016-05-12 04:19:09 +0000133 case MVT::f32:
134 case MVT::f64:
Heejin Ahn0de58722018-03-08 04:05:37 +0000135 case MVT::ExceptRef:
Dan Gohman33e694a2016-05-12 04:19:09 +0000136 return VT;
Dan Gohman6999c4f2017-02-24 21:05:35 +0000137 case MVT::f16:
138 return MVT::f32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000139 case MVT::v16i8:
140 case MVT::v8i16:
141 case MVT::v4i32:
142 case MVT::v4f32:
143 if (Subtarget->hasSIMD128())
144 return VT;
145 break;
Thomas Livelyb6dac892018-12-21 06:58:15 +0000146 case MVT::v2i64:
147 case MVT::v2f64:
Thomas Livelyfdd49992019-01-10 04:09:25 +0000148 if (Subtarget->hasSIMD128() && EnableUnimplementedWasmSIMDInstrs)
Thomas Livelyb6dac892018-12-21 06:58:15 +0000149 return VT;
150 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000151 default:
152 break;
153 }
154 return MVT::INVALID_SIMPLE_VALUE_TYPE;
155 }
Dan Gohman2e644382016-05-10 17:39:48 +0000156 bool computeAddress(const Value *Obj, Address &Addr);
157 void materializeLoadStoreOperands(Address &Addr);
158 void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
159 MachineMemOperand *MMO);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000160 unsigned maskI1Value(unsigned Reg, const Value *V);
Dan Gohman33e694a2016-05-12 04:19:09 +0000161 unsigned getRegForI1Value(const Value *V, bool &Not);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000162 unsigned zeroExtendToI32(unsigned Reg, const Value *V,
163 MVT::SimpleValueType From);
164 unsigned signExtendToI32(unsigned Reg, const Value *V,
165 MVT::SimpleValueType From);
Heejin Ahnf208f632018-09-05 01:27:38 +0000166 unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
Dan Gohman3a5ce732016-05-11 16:32:42 +0000167 MVT::SimpleValueType To);
Heejin Ahnf208f632018-09-05 01:27:38 +0000168 unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
Dan Gohman3a5ce732016-05-11 16:32:42 +0000169 MVT::SimpleValueType To);
170 unsigned getRegForUnsignedValue(const Value *V);
171 unsigned getRegForSignedValue(const Value *V);
172 unsigned getRegForPromotedValue(const Value *V, bool IsSigned);
173 unsigned notValue(unsigned Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000174 unsigned copyValue(unsigned Reg);
Dan Gohman2e644382016-05-10 17:39:48 +0000175
176 // Backend specific FastISel code.
177 unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
178 unsigned fastMaterializeConstant(const Constant *C) override;
Dan Gohman33e694a2016-05-12 04:19:09 +0000179 bool fastLowerArguments() override;
Dan Gohman2e644382016-05-10 17:39:48 +0000180
181 // Selection routines.
Dan Gohman33e694a2016-05-12 04:19:09 +0000182 bool selectCall(const Instruction *I);
183 bool selectSelect(const Instruction *I);
184 bool selectTrunc(const Instruction *I);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000185 bool selectZExt(const Instruction *I);
186 bool selectSExt(const Instruction *I);
187 bool selectICmp(const Instruction *I);
188 bool selectFCmp(const Instruction *I);
Dan Gohman2e644382016-05-10 17:39:48 +0000189 bool selectBitCast(const Instruction *I);
190 bool selectLoad(const Instruction *I);
191 bool selectStore(const Instruction *I);
192 bool selectBr(const Instruction *I);
193 bool selectRet(const Instruction *I);
194 bool selectUnreachable(const Instruction *I);
195
Dan Gohman7b634842015-08-24 18:44:37 +0000196public:
197 // Backend specific FastISel code.
198 WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo,
199 const TargetLibraryInfo *LibInfo)
200 : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
201 Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>();
202 Context = &FuncInfo.Fn->getContext();
203 }
204
205 bool fastSelectInstruction(const Instruction *I) override;
206
207#include "WebAssemblyGenFastISel.inc"
208};
209
210} // end anonymous namespace
211
Dan Gohman2e644382016-05-10 17:39:48 +0000212bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {
213
214 const User *U = nullptr;
215 unsigned Opcode = Instruction::UserOp1;
216 if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
217 // Don't walk into other basic blocks unless the object is an alloca from
218 // another block, otherwise it may not have a virtual register assigned.
219 if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
220 FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
221 Opcode = I->getOpcode();
222 U = I;
223 }
224 } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
225 Opcode = C->getOpcode();
226 U = C;
227 }
228
229 if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
230 if (Ty->getAddressSpace() > 255)
231 // Fast instruction selection doesn't support the special
232 // address spaces.
233 return false;
234
235 if (const GlobalValue *GV = dyn_cast<GlobalValue>(Obj)) {
236 if (Addr.getGlobalValue())
237 return false;
238 Addr.setGlobalValue(GV);
239 return true;
240 }
241
242 switch (Opcode) {
Dan Gohman7b634842015-08-24 18:44:37 +0000243 default:
244 break;
Dan Gohman2e644382016-05-10 17:39:48 +0000245 case Instruction::BitCast: {
246 // Look through bitcasts.
247 return computeAddress(U->getOperand(0), Addr);
248 }
249 case Instruction::IntToPtr: {
250 // Look past no-op inttoptrs.
251 if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
252 TLI.getPointerTy(DL))
253 return computeAddress(U->getOperand(0), Addr);
254 break;
255 }
256 case Instruction::PtrToInt: {
257 // Look past no-op ptrtoints.
258 if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
259 return computeAddress(U->getOperand(0), Addr);
260 break;
261 }
262 case Instruction::GetElementPtr: {
263 Address SavedAddr = Addr;
264 uint64_t TmpOffset = Addr.getOffset();
Dan Gohman728926a2016-12-22 15:15:10 +0000265 // Non-inbounds geps can wrap; wasm's offsets can't.
266 if (!cast<GEPOperator>(U)->isInBounds())
267 goto unsupported_gep;
Dan Gohman2e644382016-05-10 17:39:48 +0000268 // Iterate through the GEP folding the constants into offsets where
269 // we can.
Dan Gohman33e694a2016-05-12 04:19:09 +0000270 for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
Dan Gohman2e644382016-05-10 17:39:48 +0000271 GTI != E; ++GTI) {
272 const Value *Op = GTI.getOperand();
Peter Collingbourneab85225b2016-12-02 02:24:42 +0000273 if (StructType *STy = GTI.getStructTypeOrNull()) {
Dan Gohman2e644382016-05-10 17:39:48 +0000274 const StructLayout *SL = DL.getStructLayout(STy);
275 unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
276 TmpOffset += SL->getElementOffset(Idx);
277 } else {
278 uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
279 for (;;) {
280 if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
281 // Constant-offset addressing.
282 TmpOffset += CI->getSExtValue() * S;
283 break;
284 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000285 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
286 // An unscaled add of a register. Set it as the new base.
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000287 unsigned Reg = getRegForValue(Op);
288 if (Reg == 0)
289 return false;
290 Addr.setReg(Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000291 break;
292 }
Dan Gohman2e644382016-05-10 17:39:48 +0000293 if (canFoldAddIntoGEP(U, Op)) {
294 // A compatible add with a constant operand. Fold the constant.
295 ConstantInt *CI =
296 cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
297 TmpOffset += CI->getSExtValue() * S;
298 // Iterate on the other operand.
299 Op = cast<AddOperator>(Op)->getOperand(0);
300 continue;
301 }
302 // Unsupported
303 goto unsupported_gep;
304 }
305 }
306 }
Dan Gohman728926a2016-12-22 15:15:10 +0000307 // Don't fold in negative offsets.
308 if (int64_t(TmpOffset) >= 0) {
309 // Try to grab the base operand now.
310 Addr.setOffset(TmpOffset);
311 if (computeAddress(U->getOperand(0), Addr))
312 return true;
313 }
Dan Gohman2e644382016-05-10 17:39:48 +0000314 // We failed, restore everything and try the other options.
315 Addr = SavedAddr;
316 unsupported_gep:
317 break;
318 }
319 case Instruction::Alloca: {
320 const AllocaInst *AI = cast<AllocaInst>(Obj);
321 DenseMap<const AllocaInst *, int>::iterator SI =
322 FuncInfo.StaticAllocaMap.find(AI);
323 if (SI != FuncInfo.StaticAllocaMap.end()) {
Jacob Gravellea31ec612017-06-22 21:26:08 +0000324 if (Addr.isSet()) {
325 return false;
326 }
Dan Gohman2e644382016-05-10 17:39:48 +0000327 Addr.setKind(Address::FrameIndexBase);
328 Addr.setFI(SI->second);
329 return true;
330 }
331 break;
332 }
333 case Instruction::Add: {
334 // Adds of constants are common and easy enough.
335 const Value *LHS = U->getOperand(0);
336 const Value *RHS = U->getOperand(1);
337
338 if (isa<ConstantInt>(LHS))
339 std::swap(LHS, RHS);
340
341 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
Dan Gohman728926a2016-12-22 15:15:10 +0000342 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
343 if (int64_t(TmpOffset) >= 0) {
344 Addr.setOffset(TmpOffset);
345 return computeAddress(LHS, Addr);
346 }
Dan Gohman2e644382016-05-10 17:39:48 +0000347 }
348
349 Address Backup = Addr;
350 if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
351 return true;
352 Addr = Backup;
353
354 break;
355 }
356 case Instruction::Sub: {
357 // Subs of constants are common and easy enough.
358 const Value *LHS = U->getOperand(0);
359 const Value *RHS = U->getOperand(1);
360
361 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
Dan Gohman728926a2016-12-22 15:15:10 +0000362 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
363 if (TmpOffset >= 0) {
364 Addr.setOffset(TmpOffset);
365 return computeAddress(LHS, Addr);
366 }
Dan Gohman2e644382016-05-10 17:39:48 +0000367 }
368 break;
369 }
370 }
Jacob Gravellea31ec612017-06-22 21:26:08 +0000371 if (Addr.isSet()) {
372 return false;
373 }
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000374 unsigned Reg = getRegForValue(Obj);
375 if (Reg == 0)
376 return false;
377 Addr.setReg(Reg);
Dan Gohman2e644382016-05-10 17:39:48 +0000378 return Addr.getReg() != 0;
379}
380
381void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
382 if (Addr.isRegBase()) {
383 unsigned Reg = Addr.getReg();
384 if (Reg == 0) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000385 Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
386 : &WebAssembly::I32RegClass);
387 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
388 : WebAssembly::CONST_I32;
Dan Gohman2e644382016-05-10 17:39:48 +0000389 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000390 .addImm(0);
Dan Gohman2e644382016-05-10 17:39:48 +0000391 Addr.setReg(Reg);
392 }
393 }
394}
395
396void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
397 const MachineInstrBuilder &MIB,
398 MachineMemOperand *MMO) {
Dan Gohman48abaa92016-10-25 00:17:11 +0000399 // Set the alignment operand (this is rewritten in SetP2AlignOperands).
400 // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
401 MIB.addImm(0);
402
Dan Gohman2e644382016-05-10 17:39:48 +0000403 if (const GlobalValue *GV = Addr.getGlobalValue())
404 MIB.addGlobalAddress(GV, Addr.getOffset());
405 else
406 MIB.addImm(Addr.getOffset());
407
408 if (Addr.isRegBase())
409 MIB.addReg(Addr.getReg());
410 else
411 MIB.addFrameIndex(Addr.getFI());
412
Dan Gohman2e644382016-05-10 17:39:48 +0000413 MIB.addMemOperand(MMO);
414}
415
Dan Gohman3a5ce732016-05-11 16:32:42 +0000416unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
417 return zeroExtendToI32(Reg, V, MVT::i1);
Dan Gohman2e644382016-05-10 17:39:48 +0000418}
419
Dan Gohman33e694a2016-05-12 04:19:09 +0000420unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
421 if (const ICmpInst *ICmp = dyn_cast<ICmpInst>(V))
422 if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
423 if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
424 Not = ICmp->isTrueWhenEqual();
425 return getRegForValue(ICmp->getOperand(0));
426 }
427
Sanjay Patel47a52a02018-10-23 16:05:09 +0000428 Value *NotV;
429 if (match(V, m_Not(m_Value(NotV))) && V->getType()->isIntegerTy(32)) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000430 Not = true;
Sanjay Patel47a52a02018-10-23 16:05:09 +0000431 return getRegForValue(NotV);
Dan Gohman33e694a2016-05-12 04:19:09 +0000432 }
433
434 Not = false;
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000435 unsigned Reg = getRegForValue(V);
436 if (Reg == 0)
437 return 0;
438 return maskI1Value(Reg, V);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000439}
440
441unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
442 MVT::SimpleValueType From) {
Derek Schuff732636d2016-08-04 18:01:52 +0000443 if (Reg == 0)
444 return 0;
445
Dan Gohman3a5ce732016-05-11 16:32:42 +0000446 switch (From) {
447 case MVT::i1:
448 // If the value is naturally an i1, we don't need to mask it.
449 // TODO: Recursively examine selects, phis, and, or, xor, constants.
Dan Gohman33e694a2016-05-12 04:19:09 +0000450 if (From == MVT::i1 && V != nullptr) {
451 if (isa<CmpInst>(V) ||
452 (isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr()))
453 return copyValue(Reg);
454 }
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000455 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000456 case MVT::i8:
457 case MVT::i16:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000458 break;
459 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000460 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000461 default:
462 return 0;
463 }
464
465 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
466 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
467 TII.get(WebAssembly::CONST_I32), Imm)
Heejin Ahnf208f632018-09-05 01:27:38 +0000468 .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
Dan Gohman3a5ce732016-05-11 16:32:42 +0000469
470 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
471 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
472 TII.get(WebAssembly::AND_I32), Result)
Heejin Ahnf208f632018-09-05 01:27:38 +0000473 .addReg(Reg)
474 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000475
476 return Result;
477}
478
479unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
480 MVT::SimpleValueType From) {
Derek Schuff732636d2016-08-04 18:01:52 +0000481 if (Reg == 0)
482 return 0;
483
Dan Gohman3a5ce732016-05-11 16:32:42 +0000484 switch (From) {
485 case MVT::i1:
486 case MVT::i8:
487 case MVT::i16:
488 break;
489 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000490 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000491 default:
Dan Gohman33e694a2016-05-12 04:19:09 +0000492 return 0;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000493 }
494
495 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
496 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
497 TII.get(WebAssembly::CONST_I32), Imm)
Heejin Ahnf208f632018-09-05 01:27:38 +0000498 .addImm(32 - MVT(From).getSizeInBits());
Dan Gohman3a5ce732016-05-11 16:32:42 +0000499
500 unsigned Left = createResultReg(&WebAssembly::I32RegClass);
501 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
502 TII.get(WebAssembly::SHL_I32), Left)
Heejin Ahnf208f632018-09-05 01:27:38 +0000503 .addReg(Reg)
504 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000505
506 unsigned Right = createResultReg(&WebAssembly::I32RegClass);
507 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
508 TII.get(WebAssembly::SHR_S_I32), Right)
Heejin Ahnf208f632018-09-05 01:27:38 +0000509 .addReg(Left)
510 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000511
512 return Right;
513}
514
515unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
516 MVT::SimpleValueType From,
517 MVT::SimpleValueType To) {
518 if (To == MVT::i64) {
519 if (From == MVT::i64)
Dan Gohman33e694a2016-05-12 04:19:09 +0000520 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000521
522 Reg = zeroExtendToI32(Reg, V, From);
523
524 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
525 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
526 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
527 .addReg(Reg);
528 return Result;
529 }
530
Dan Gohman3a5ce732016-05-11 16:32:42 +0000531 return zeroExtendToI32(Reg, V, From);
532}
533
534unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
535 MVT::SimpleValueType From,
536 MVT::SimpleValueType To) {
537 if (To == MVT::i64) {
538 if (From == MVT::i64)
Dan Gohman33e694a2016-05-12 04:19:09 +0000539 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000540
541 Reg = signExtendToI32(Reg, V, From);
542
543 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
544 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
545 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
546 .addReg(Reg);
547 return Result;
548 }
549
Dan Gohman3a5ce732016-05-11 16:32:42 +0000550 return signExtendToI32(Reg, V, From);
551}
552
553unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
554 MVT::SimpleValueType From = getSimpleType(V->getType());
555 MVT::SimpleValueType To = getLegalType(From);
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000556 unsigned VReg = getRegForValue(V);
557 if (VReg == 0)
558 return 0;
559 return zeroExtend(VReg, V, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000560}
561
562unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
563 MVT::SimpleValueType From = getSimpleType(V->getType());
564 MVT::SimpleValueType To = getLegalType(From);
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000565 unsigned VReg = getRegForValue(V);
566 if (VReg == 0)
567 return 0;
568 return signExtend(VReg, V, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000569}
570
571unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
572 bool IsSigned) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000573 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000574}
575
576unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000577 assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
578
Dan Gohman3a5ce732016-05-11 16:32:42 +0000579 unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
580 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
581 TII.get(WebAssembly::EQZ_I32), NotReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000582 .addReg(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000583 return NotReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000584}
585
Dan Gohman33e694a2016-05-12 04:19:09 +0000586unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
587 unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
Heejin Ahnf208f632018-09-05 01:27:38 +0000588 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
589 ResultReg)
590 .addReg(Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000591 return ResultReg;
592}
593
Dan Gohman2e644382016-05-10 17:39:48 +0000594unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
595 DenseMap<const AllocaInst *, int>::iterator SI =
596 FuncInfo.StaticAllocaMap.find(AI);
597
598 if (SI != FuncInfo.StaticAllocaMap.end()) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000599 unsigned ResultReg =
600 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
601 : &WebAssembly::I32RegClass);
602 unsigned Opc =
603 Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
Dan Gohman2e644382016-05-10 17:39:48 +0000604 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
605 .addFrameIndex(SI->second);
606 return ResultReg;
607 }
608
609 return 0;
610}
611
612unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
613 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000614 unsigned ResultReg =
615 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
616 : &WebAssembly::I32RegClass);
617 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
618 : WebAssembly::CONST_I32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000619 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000620 .addGlobalAddress(GV);
Dan Gohman33e694a2016-05-12 04:19:09 +0000621 return ResultReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000622 }
623
624 // Let target-independent code handle it.
625 return 0;
626}
627
Dan Gohman33e694a2016-05-12 04:19:09 +0000628bool WebAssemblyFastISel::fastLowerArguments() {
629 if (!FuncInfo.CanLowerReturn)
630 return false;
631
632 const Function *F = FuncInfo.Fn;
633 if (F->isVarArg())
634 return false;
635
636 unsigned i = 0;
637 for (auto const &Arg : F->args()) {
Reid Klecknerb5180542017-03-21 16:57:19 +0000638 const AttributeList &Attrs = F->getAttributes();
Reid Klecknerf021fab2017-04-13 23:12:13 +0000639 if (Attrs.hasParamAttribute(i, Attribute::ByVal) ||
640 Attrs.hasParamAttribute(i, Attribute::SwiftSelf) ||
641 Attrs.hasParamAttribute(i, Attribute::SwiftError) ||
642 Attrs.hasParamAttribute(i, Attribute::InAlloca) ||
643 Attrs.hasParamAttribute(i, Attribute::Nest))
Dan Gohman33e694a2016-05-12 04:19:09 +0000644 return false;
645
646 Type *ArgTy = Arg.getType();
Derek Schuff39bf39f2016-08-02 23:16:09 +0000647 if (ArgTy->isStructTy() || ArgTy->isArrayTy())
648 return false;
649 if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
Dan Gohman33e694a2016-05-12 04:19:09 +0000650 return false;
651
652 unsigned Opc;
653 const TargetRegisterClass *RC;
654 switch (getSimpleType(ArgTy)) {
655 case MVT::i1:
656 case MVT::i8:
657 case MVT::i16:
658 case MVT::i32:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000659 Opc = WebAssembly::ARGUMENT_i32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000660 RC = &WebAssembly::I32RegClass;
661 break;
662 case MVT::i64:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000663 Opc = WebAssembly::ARGUMENT_i64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000664 RC = &WebAssembly::I64RegClass;
665 break;
666 case MVT::f32:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000667 Opc = WebAssembly::ARGUMENT_f32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000668 RC = &WebAssembly::F32RegClass;
669 break;
670 case MVT::f64:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000671 Opc = WebAssembly::ARGUMENT_f64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000672 RC = &WebAssembly::F64RegClass;
673 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000674 case MVT::v16i8:
675 Opc = WebAssembly::ARGUMENT_v16i8;
676 RC = &WebAssembly::V128RegClass;
677 break;
678 case MVT::v8i16:
679 Opc = WebAssembly::ARGUMENT_v8i16;
680 RC = &WebAssembly::V128RegClass;
681 break;
682 case MVT::v4i32:
683 Opc = WebAssembly::ARGUMENT_v4i32;
684 RC = &WebAssembly::V128RegClass;
685 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000686 case MVT::v2i64:
687 Opc = WebAssembly::ARGUMENT_v2i64;
688 RC = &WebAssembly::V128RegClass;
689 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000690 case MVT::v4f32:
691 Opc = WebAssembly::ARGUMENT_v4f32;
692 RC = &WebAssembly::V128RegClass;
693 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000694 case MVT::v2f64:
695 Opc = WebAssembly::ARGUMENT_v2f64;
696 RC = &WebAssembly::V128RegClass;
697 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000698 case MVT::ExceptRef:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000699 Opc = WebAssembly::ARGUMENT_ExceptRef;
Heejin Ahn0de58722018-03-08 04:05:37 +0000700 RC = &WebAssembly::EXCEPT_REFRegClass;
701 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000702 default:
703 return false;
704 }
705 unsigned ResultReg = createResultReg(RC);
706 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000707 .addImm(i);
Dan Gohman33e694a2016-05-12 04:19:09 +0000708 updateValueMap(&Arg, ResultReg);
709
710 ++i;
711 }
712
713 MRI.addLiveIn(WebAssembly::ARGUMENTS);
714
715 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
Dan Gohmanb8184822018-05-22 04:58:36 +0000716 for (auto const &Arg : F->args()) {
717 MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType()));
718 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
719 MFI->clearParamsAndResults();
720 return false;
721 }
722 MFI->addParam(ArgTy);
723 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000724
Dan Gohman4576dc02018-04-17 20:46:42 +0000725 if (!F->getReturnType()->isVoidTy()) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000726 MVT::SimpleValueType RetTy =
727 getLegalType(getSimpleType(F->getReturnType()));
Dan Gohmanb8184822018-05-22 04:58:36 +0000728 if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
729 MFI->clearParamsAndResults();
Dan Gohman4576dc02018-04-17 20:46:42 +0000730 return false;
Dan Gohmanb8184822018-05-22 04:58:36 +0000731 }
732 MFI->addResult(RetTy);
Dan Gohman4576dc02018-04-17 20:46:42 +0000733 }
Dan Gohman6055fba2017-01-09 23:09:38 +0000734
Dan Gohman33e694a2016-05-12 04:19:09 +0000735 return true;
736}
737
738bool WebAssemblyFastISel::selectCall(const Instruction *I) {
739 const CallInst *Call = cast<CallInst>(I);
740
741 if (Call->isMustTailCall() || Call->isInlineAsm() ||
742 Call->getFunctionType()->isVarArg())
743 return false;
744
745 Function *Func = Call->getCalledFunction();
746 if (Func && Func->isIntrinsic())
747 return false;
748
Jacob Gravelle690b76e2017-08-24 19:53:44 +0000749 bool IsDirect = Func != nullptr;
750 if (!IsDirect && isa<ConstantExpr>(Call->getCalledValue()))
751 return false;
752
Dan Gohman33e694a2016-05-12 04:19:09 +0000753 FunctionType *FuncTy = Call->getFunctionType();
754 unsigned Opc;
Dan Gohman33e694a2016-05-12 04:19:09 +0000755 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
756 unsigned ResultReg;
757 if (IsVoid) {
Derek Schuff6f697832016-10-21 16:38:07 +0000758 Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
Dan Gohman33e694a2016-05-12 04:19:09 +0000759 } else {
Derek Schuff39bf39f2016-08-02 23:16:09 +0000760 if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
761 return false;
762
Dan Gohman33e694a2016-05-12 04:19:09 +0000763 MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
764 switch (RetTy) {
765 case MVT::i1:
766 case MVT::i8:
767 case MVT::i16:
768 case MVT::i32:
Derek Schuff6f697832016-10-21 16:38:07 +0000769 Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::PCALL_INDIRECT_I32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000770 ResultReg = createResultReg(&WebAssembly::I32RegClass);
771 break;
772 case MVT::i64:
Derek Schuff6f697832016-10-21 16:38:07 +0000773 Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::PCALL_INDIRECT_I64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000774 ResultReg = createResultReg(&WebAssembly::I64RegClass);
775 break;
776 case MVT::f32:
Derek Schuff6f697832016-10-21 16:38:07 +0000777 Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::PCALL_INDIRECT_F32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000778 ResultReg = createResultReg(&WebAssembly::F32RegClass);
779 break;
780 case MVT::f64:
Derek Schuff6f697832016-10-21 16:38:07 +0000781 Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::PCALL_INDIRECT_F64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000782 ResultReg = createResultReg(&WebAssembly::F64RegClass);
783 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000784 case MVT::v16i8:
Heejin Ahnf208f632018-09-05 01:27:38 +0000785 Opc = IsDirect ? WebAssembly::CALL_v16i8
786 : WebAssembly::PCALL_INDIRECT_v16i8;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000787 ResultReg = createResultReg(&WebAssembly::V128RegClass);
788 break;
789 case MVT::v8i16:
Heejin Ahnf208f632018-09-05 01:27:38 +0000790 Opc = IsDirect ? WebAssembly::CALL_v8i16
791 : WebAssembly::PCALL_INDIRECT_v8i16;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000792 ResultReg = createResultReg(&WebAssembly::V128RegClass);
793 break;
794 case MVT::v4i32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000795 Opc = IsDirect ? WebAssembly::CALL_v4i32
796 : WebAssembly::PCALL_INDIRECT_v4i32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000797 ResultReg = createResultReg(&WebAssembly::V128RegClass);
798 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000799 case MVT::v2i64:
Heejin Ahnf208f632018-09-05 01:27:38 +0000800 Opc = IsDirect ? WebAssembly::CALL_v2i64
801 : WebAssembly::PCALL_INDIRECT_v2i64;
Derek Schuff51ed1312018-08-07 21:24:01 +0000802 ResultReg = createResultReg(&WebAssembly::V128RegClass);
803 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000804 case MVT::v4f32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000805 Opc = IsDirect ? WebAssembly::CALL_v4f32
806 : WebAssembly::PCALL_INDIRECT_v4f32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000807 ResultReg = createResultReg(&WebAssembly::V128RegClass);
808 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000809 case MVT::v2f64:
Heejin Ahnf208f632018-09-05 01:27:38 +0000810 Opc = IsDirect ? WebAssembly::CALL_v2f64
811 : WebAssembly::PCALL_INDIRECT_v2f64;
Derek Schuff51ed1312018-08-07 21:24:01 +0000812 ResultReg = createResultReg(&WebAssembly::V128RegClass);
813 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000814 case MVT::ExceptRef:
815 Opc = IsDirect ? WebAssembly::CALL_EXCEPT_REF
816 : WebAssembly::PCALL_INDIRECT_EXCEPT_REF;
817 ResultReg = createResultReg(&WebAssembly::EXCEPT_REFRegClass);
818 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000819 default:
820 return false;
821 }
822 }
823
824 SmallVector<unsigned, 8> Args;
825 for (unsigned i = 0, e = Call->getNumArgOperands(); i < e; ++i) {
826 Value *V = Call->getArgOperand(i);
827 MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
828 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
829 return false;
830
Reid Klecknerb5180542017-03-21 16:57:19 +0000831 const AttributeList &Attrs = Call->getAttributes();
Reid Klecknerf021fab2017-04-13 23:12:13 +0000832 if (Attrs.hasParamAttribute(i, Attribute::ByVal) ||
833 Attrs.hasParamAttribute(i, Attribute::SwiftSelf) ||
834 Attrs.hasParamAttribute(i, Attribute::SwiftError) ||
835 Attrs.hasParamAttribute(i, Attribute::InAlloca) ||
836 Attrs.hasParamAttribute(i, Attribute::Nest))
Dan Gohman33e694a2016-05-12 04:19:09 +0000837 return false;
838
839 unsigned Reg;
840
Reid Klecknerf021fab2017-04-13 23:12:13 +0000841 if (Attrs.hasParamAttribute(i, Attribute::SExt))
Dan Gohman33e694a2016-05-12 04:19:09 +0000842 Reg = getRegForSignedValue(V);
Reid Klecknerf021fab2017-04-13 23:12:13 +0000843 else if (Attrs.hasParamAttribute(i, Attribute::ZExt))
Dan Gohman33e694a2016-05-12 04:19:09 +0000844 Reg = getRegForUnsignedValue(V);
845 else
846 Reg = getRegForValue(V);
847
848 if (Reg == 0)
849 return false;
850
851 Args.push_back(Reg);
852 }
853
854 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
855
856 if (!IsVoid)
857 MIB.addReg(ResultReg, RegState::Define);
858
859 if (IsDirect)
860 MIB.addGlobalAddress(Func);
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000861 else {
862 unsigned Reg = getRegForValue(Call->getCalledValue());
863 if (Reg == 0)
864 return false;
865 MIB.addReg(Reg);
866 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000867
868 for (unsigned ArgReg : Args)
869 MIB.addReg(ArgReg);
870
871 if (!IsVoid)
872 updateValueMap(Call, ResultReg);
873 return true;
874}
875
876bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
877 const SelectInst *Select = cast<SelectInst>(I);
878
879 bool Not;
Heejin Ahnf208f632018-09-05 01:27:38 +0000880 unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
Dan Gohman33e694a2016-05-12 04:19:09 +0000881 if (CondReg == 0)
882 return false;
883
Heejin Ahnf208f632018-09-05 01:27:38 +0000884 unsigned TrueReg = getRegForValue(Select->getTrueValue());
Dan Gohman33e694a2016-05-12 04:19:09 +0000885 if (TrueReg == 0)
886 return false;
887
888 unsigned FalseReg = getRegForValue(Select->getFalseValue());
889 if (FalseReg == 0)
890 return false;
891
892 if (Not)
893 std::swap(TrueReg, FalseReg);
894
895 unsigned Opc;
896 const TargetRegisterClass *RC;
897 switch (getSimpleType(Select->getType())) {
898 case MVT::i1:
899 case MVT::i8:
900 case MVT::i16:
901 case MVT::i32:
902 Opc = WebAssembly::SELECT_I32;
903 RC = &WebAssembly::I32RegClass;
904 break;
905 case MVT::i64:
906 Opc = WebAssembly::SELECT_I64;
907 RC = &WebAssembly::I64RegClass;
908 break;
909 case MVT::f32:
910 Opc = WebAssembly::SELECT_F32;
911 RC = &WebAssembly::F32RegClass;
912 break;
913 case MVT::f64:
914 Opc = WebAssembly::SELECT_F64;
915 RC = &WebAssembly::F64RegClass;
916 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000917 case MVT::ExceptRef:
918 Opc = WebAssembly::SELECT_EXCEPT_REF;
919 RC = &WebAssembly::EXCEPT_REFRegClass;
920 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000921 default:
922 return false;
923 }
924
925 unsigned ResultReg = createResultReg(RC);
926 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000927 .addReg(TrueReg)
928 .addReg(FalseReg)
929 .addReg(CondReg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000930
931 updateValueMap(Select, ResultReg);
932 return true;
933}
934
935bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
936 const TruncInst *Trunc = cast<TruncInst>(I);
937
938 unsigned Reg = getRegForValue(Trunc->getOperand(0));
939 if (Reg == 0)
940 return false;
941
942 if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
943 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
944 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
945 TII.get(WebAssembly::I32_WRAP_I64), Result)
946 .addReg(Reg);
947 Reg = Result;
948 }
949
950 updateValueMap(Trunc, Reg);
951 return true;
952}
953
Dan Gohman3a5ce732016-05-11 16:32:42 +0000954bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
955 const ZExtInst *ZExt = cast<ZExtInst>(I);
956
Dan Gohman33e694a2016-05-12 04:19:09 +0000957 const Value *Op = ZExt->getOperand(0);
958 MVT::SimpleValueType From = getSimpleType(Op->getType());
959 MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000960 unsigned In = getRegForValue(Op);
961 if (In == 0)
962 return false;
963 unsigned Reg = zeroExtend(In, Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000964 if (Reg == 0)
965 return false;
966
967 updateValueMap(ZExt, Reg);
968 return true;
969}
970
971bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
972 const SExtInst *SExt = cast<SExtInst>(I);
973
Dan Gohman33e694a2016-05-12 04:19:09 +0000974 const Value *Op = SExt->getOperand(0);
975 MVT::SimpleValueType From = getSimpleType(Op->getType());
976 MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000977 unsigned In = getRegForValue(Op);
978 if (In == 0)
979 return false;
980 unsigned Reg = signExtend(In, Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000981 if (Reg == 0)
982 return false;
983
984 updateValueMap(SExt, Reg);
985 return true;
986}
987
988bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
989 const ICmpInst *ICmp = cast<ICmpInst>(I);
990
991 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
992 unsigned Opc;
993 bool isSigned = false;
994 switch (ICmp->getPredicate()) {
995 case ICmpInst::ICMP_EQ:
996 Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
997 break;
998 case ICmpInst::ICMP_NE:
999 Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1000 break;
1001 case ICmpInst::ICMP_UGT:
1002 Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1003 break;
1004 case ICmpInst::ICMP_UGE:
1005 Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1006 break;
1007 case ICmpInst::ICMP_ULT:
1008 Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1009 break;
1010 case ICmpInst::ICMP_ULE:
1011 Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1012 break;
1013 case ICmpInst::ICMP_SGT:
1014 Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1015 isSigned = true;
1016 break;
1017 case ICmpInst::ICMP_SGE:
1018 Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1019 isSigned = true;
1020 break;
1021 case ICmpInst::ICMP_SLT:
1022 Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1023 isSigned = true;
1024 break;
1025 case ICmpInst::ICMP_SLE:
1026 Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1027 isSigned = true;
1028 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001029 default:
1030 return false;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001031 }
1032
1033 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), isSigned);
1034 if (LHS == 0)
1035 return false;
1036
1037 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), isSigned);
1038 if (RHS == 0)
1039 return false;
1040
1041 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1042 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1043 .addReg(LHS)
1044 .addReg(RHS);
1045 updateValueMap(ICmp, ResultReg);
1046 return true;
1047}
1048
1049bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
1050 const FCmpInst *FCmp = cast<FCmpInst>(I);
1051
1052 unsigned LHS = getRegForValue(FCmp->getOperand(0));
1053 if (LHS == 0)
1054 return false;
1055
1056 unsigned RHS = getRegForValue(FCmp->getOperand(1));
1057 if (RHS == 0)
1058 return false;
1059
1060 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1061 unsigned Opc;
1062 bool Not = false;
1063 switch (FCmp->getPredicate()) {
1064 case FCmpInst::FCMP_OEQ:
1065 Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1066 break;
1067 case FCmpInst::FCMP_UNE:
1068 Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1069 break;
1070 case FCmpInst::FCMP_OGT:
1071 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1072 break;
1073 case FCmpInst::FCMP_OGE:
1074 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1075 break;
1076 case FCmpInst::FCMP_OLT:
1077 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1078 break;
1079 case FCmpInst::FCMP_OLE:
1080 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1081 break;
1082 case FCmpInst::FCMP_UGT:
1083 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1084 Not = true;
1085 break;
1086 case FCmpInst::FCMP_UGE:
1087 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1088 Not = true;
1089 break;
1090 case FCmpInst::FCMP_ULT:
1091 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1092 Not = true;
1093 break;
1094 case FCmpInst::FCMP_ULE:
1095 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1096 Not = true;
1097 break;
1098 default:
1099 return false;
1100 }
1101
1102 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1103 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1104 .addReg(LHS)
1105 .addReg(RHS);
1106
1107 if (Not)
1108 ResultReg = notValue(ResultReg);
1109
1110 updateValueMap(FCmp, ResultReg);
1111 return true;
1112}
1113
Dan Gohman2e644382016-05-10 17:39:48 +00001114bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
1115 // Target-independent code can handle this, except it doesn't set the dead
1116 // flag on the ARGUMENTS clobber, so we have to do that manually in order
1117 // to satisfy code that expects this of isBitcast() instructions.
1118 EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
1119 EVT RetVT = TLI.getValueType(DL, I->getType());
1120 if (!VT.isSimple() || !RetVT.isSimple())
1121 return false;
Dan Gohman33e694a2016-05-12 04:19:09 +00001122
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001123 unsigned In = getRegForValue(I->getOperand(0));
1124 if (In == 0)
1125 return false;
1126
Dan Gohman33e694a2016-05-12 04:19:09 +00001127 if (VT == RetVT) {
1128 // No-op bitcast.
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001129 updateValueMap(I, In);
Dan Gohman33e694a2016-05-12 04:19:09 +00001130 return true;
1131 }
1132
Dan Gohman2e644382016-05-10 17:39:48 +00001133 unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001134 In, I->getOperand(0)->hasOneUse());
Dan Gohman2e644382016-05-10 17:39:48 +00001135 if (!Reg)
1136 return false;
1137 MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
1138 --Iter;
1139 assert(Iter->isBitcast());
1140 Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI);
1141 updateValueMap(I, Reg);
1142 return true;
1143}
1144
1145bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
1146 const LoadInst *Load = cast<LoadInst>(I);
1147 if (Load->isAtomic())
1148 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001149 if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
1150 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001151
1152 Address Addr;
1153 if (!computeAddress(Load->getPointerOperand(), Addr))
1154 return false;
1155
1156 // TODO: Fold a following sign-/zero-extend into the load instruction.
1157
1158 unsigned Opc;
1159 const TargetRegisterClass *RC;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001160 switch (getSimpleType(Load->getType())) {
1161 case MVT::i1:
1162 case MVT::i8:
1163 Opc = WebAssembly::LOAD8_U_I32;
1164 RC = &WebAssembly::I32RegClass;
Dan Gohman2e644382016-05-10 17:39:48 +00001165 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001166 case MVT::i16:
1167 Opc = WebAssembly::LOAD16_U_I32;
1168 RC = &WebAssembly::I32RegClass;
1169 break;
1170 case MVT::i32:
1171 Opc = WebAssembly::LOAD_I32;
1172 RC = &WebAssembly::I32RegClass;
1173 break;
1174 case MVT::i64:
1175 Opc = WebAssembly::LOAD_I64;
1176 RC = &WebAssembly::I64RegClass;
1177 break;
1178 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001179 Opc = WebAssembly::LOAD_F32;
1180 RC = &WebAssembly::F32RegClass;
1181 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001182 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001183 Opc = WebAssembly::LOAD_F64;
1184 RC = &WebAssembly::F64RegClass;
1185 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001186 default:
1187 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001188 }
1189
1190 materializeLoadStoreOperands(Addr);
1191
1192 unsigned ResultReg = createResultReg(RC);
1193 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
1194 ResultReg);
1195
1196 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1197
1198 updateValueMap(Load, ResultReg);
1199 return true;
1200}
1201
1202bool WebAssemblyFastISel::selectStore(const Instruction *I) {
1203 const StoreInst *Store = cast<StoreInst>(I);
1204 if (Store->isAtomic())
1205 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001206 if (!Subtarget->hasSIMD128() &&
1207 Store->getValueOperand()->getType()->isVectorTy())
1208 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001209
1210 Address Addr;
1211 if (!computeAddress(Store->getPointerOperand(), Addr))
1212 return false;
1213
1214 unsigned Opc;
Dan Gohman2e644382016-05-10 17:39:48 +00001215 bool VTIsi1 = false;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001216 switch (getSimpleType(Store->getValueOperand()->getType())) {
1217 case MVT::i1:
1218 VTIsi1 = true;
Dan Gohman861bec22018-02-09 22:59:01 +00001219 LLVM_FALLTHROUGH;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001220 case MVT::i8:
1221 Opc = WebAssembly::STORE8_I32;
Dan Gohman2e644382016-05-10 17:39:48 +00001222 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001223 case MVT::i16:
1224 Opc = WebAssembly::STORE16_I32;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001225 break;
1226 case MVT::i32:
1227 Opc = WebAssembly::STORE_I32;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001228 break;
1229 case MVT::i64:
1230 Opc = WebAssembly::STORE_I64;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001231 break;
1232 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001233 Opc = WebAssembly::STORE_F32;
Dan Gohman2e644382016-05-10 17:39:48 +00001234 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001235 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001236 Opc = WebAssembly::STORE_F64;
Dan Gohman2e644382016-05-10 17:39:48 +00001237 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001238 default:
1239 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001240 }
1241
1242 materializeLoadStoreOperands(Addr);
1243
1244 unsigned ValueReg = getRegForValue(Store->getValueOperand());
Derek Schuff732636d2016-08-04 18:01:52 +00001245 if (ValueReg == 0)
1246 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001247 if (VTIsi1)
Dan Gohman3a5ce732016-05-11 16:32:42 +00001248 ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
Dan Gohman2e644382016-05-10 17:39:48 +00001249
Dan Gohman7f1bdb22016-10-06 22:08:28 +00001250 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
Dan Gohman2e644382016-05-10 17:39:48 +00001251
1252 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1253
1254 MIB.addReg(ValueReg);
1255 return true;
1256}
1257
1258bool WebAssemblyFastISel::selectBr(const Instruction *I) {
1259 const BranchInst *Br = cast<BranchInst>(I);
1260 if (Br->isUnconditional()) {
1261 MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
1262 fastEmitBranch(MSucc, Br->getDebugLoc());
1263 return true;
1264 }
1265
1266 MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
1267 MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
1268
Dan Gohman33e694a2016-05-12 04:19:09 +00001269 bool Not;
1270 unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
Derek Schuff732636d2016-08-04 18:01:52 +00001271 if (CondReg == 0)
1272 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001273
Dan Gohman33e694a2016-05-12 04:19:09 +00001274 unsigned Opc = WebAssembly::BR_IF;
1275 if (Not)
1276 Opc = WebAssembly::BR_UNLESS;
1277
Dan Gohman2e644382016-05-10 17:39:48 +00001278 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1279 .addMBB(TBB)
1280 .addReg(CondReg);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001281
Dan Gohman2e644382016-05-10 17:39:48 +00001282 finishCondBranch(Br->getParent(), TBB, FBB);
1283 return true;
1284}
1285
1286bool WebAssemblyFastISel::selectRet(const Instruction *I) {
1287 if (!FuncInfo.CanLowerReturn)
1288 return false;
1289
1290 const ReturnInst *Ret = cast<ReturnInst>(I);
1291
1292 if (Ret->getNumOperands() == 0) {
1293 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1294 TII.get(WebAssembly::RETURN_VOID));
1295 return true;
1296 }
1297
1298 Value *RV = Ret->getOperand(0);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001299 if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
1300 return false;
1301
Dan Gohman2e644382016-05-10 17:39:48 +00001302 unsigned Opc;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001303 switch (getSimpleType(RV->getType())) {
Heejin Ahnf208f632018-09-05 01:27:38 +00001304 case MVT::i1:
1305 case MVT::i8:
1306 case MVT::i16:
1307 case MVT::i32:
Dan Gohman3a5ce732016-05-11 16:32:42 +00001308 Opc = WebAssembly::RETURN_I32;
Dan Gohman2e644382016-05-10 17:39:48 +00001309 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001310 case MVT::i64:
1311 Opc = WebAssembly::RETURN_I64;
1312 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001313 case MVT::f32:
1314 Opc = WebAssembly::RETURN_F32;
1315 break;
1316 case MVT::f64:
1317 Opc = WebAssembly::RETURN_F64;
1318 break;
1319 case MVT::v16i8:
1320 Opc = WebAssembly::RETURN_v16i8;
1321 break;
1322 case MVT::v8i16:
1323 Opc = WebAssembly::RETURN_v8i16;
1324 break;
1325 case MVT::v4i32:
1326 Opc = WebAssembly::RETURN_v4i32;
1327 break;
Derek Schuff51ed1312018-08-07 21:24:01 +00001328 case MVT::v2i64:
1329 Opc = WebAssembly::RETURN_v2i64;
1330 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001331 case MVT::v4f32:
1332 Opc = WebAssembly::RETURN_v4f32;
1333 break;
Derek Schuff51ed1312018-08-07 21:24:01 +00001334 case MVT::v2f64:
1335 Opc = WebAssembly::RETURN_v2f64;
1336 break;
Heejin Ahn0de58722018-03-08 04:05:37 +00001337 case MVT::ExceptRef:
1338 Opc = WebAssembly::RETURN_EXCEPT_REF;
1339 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001340 default:
1341 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001342 }
1343
Dan Gohman33e694a2016-05-12 04:19:09 +00001344 unsigned Reg;
1345 if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
1346 Reg = getRegForSignedValue(RV);
1347 else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
1348 Reg = getRegForUnsignedValue(RV);
1349 else
1350 Reg = getRegForValue(RV);
1351
Derek Schuff732636d2016-08-04 18:01:52 +00001352 if (Reg == 0)
1353 return false;
1354
Dan Gohman2e644382016-05-10 17:39:48 +00001355 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg);
1356 return true;
1357}
1358
1359bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
1360 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1361 TII.get(WebAssembly::UNREACHABLE));
1362 return true;
1363}
1364
1365bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
1366 switch (I->getOpcode()) {
Dan Gohman33e694a2016-05-12 04:19:09 +00001367 case Instruction::Call:
1368 if (selectCall(I))
1369 return true;
1370 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001371 case Instruction::Select:
1372 return selectSelect(I);
1373 case Instruction::Trunc:
1374 return selectTrunc(I);
1375 case Instruction::ZExt:
1376 return selectZExt(I);
1377 case Instruction::SExt:
1378 return selectSExt(I);
1379 case Instruction::ICmp:
1380 return selectICmp(I);
1381 case Instruction::FCmp:
1382 return selectFCmp(I);
1383 case Instruction::BitCast:
1384 return selectBitCast(I);
1385 case Instruction::Load:
1386 return selectLoad(I);
1387 case Instruction::Store:
1388 return selectStore(I);
1389 case Instruction::Br:
1390 return selectBr(I);
1391 case Instruction::Ret:
1392 return selectRet(I);
1393 case Instruction::Unreachable:
1394 return selectUnreachable(I);
1395 default:
1396 break;
Dan Gohman7b634842015-08-24 18:44:37 +00001397 }
1398
1399 // Fall back to target-independent instruction selection.
1400 return selectOperator(I, I->getOpcode());
1401}
1402
1403FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,
1404 const TargetLibraryInfo *LibInfo) {
1405 return new WebAssemblyFastISel(FuncInfo, LibInfo);
1406}