blob: f48b7f3af83fc111fee4aa096abdee86ccbffdac [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
11/// \brief This file defines the WebAssembly-specific support for the FastISel
12/// 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
19#include "WebAssembly.h"
20#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
Dan Gohman33e694a2016-05-12 04:19:09 +000021#include "WebAssemblyMachineFunctionInfo.h"
Dan Gohman7b634842015-08-24 18:44:37 +000022#include "WebAssemblySubtarget.h"
23#include "WebAssemblyTargetMachine.h"
24#include "llvm/Analysis/BranchProbabilityInfo.h"
25#include "llvm/CodeGen/FastISel.h"
26#include "llvm/CodeGen/FunctionLoweringInfo.h"
27#include "llvm/CodeGen/MachineConstantPool.h"
28#include "llvm/CodeGen/MachineFrameInfo.h"
29#include "llvm/CodeGen/MachineInstrBuilder.h"
30#include "llvm/CodeGen/MachineRegisterInfo.h"
31#include "llvm/IR/DataLayout.h"
32#include "llvm/IR/DerivedTypes.h"
33#include "llvm/IR/Function.h"
34#include "llvm/IR/GetElementPtrTypeIterator.h"
35#include "llvm/IR/GlobalAlias.h"
36#include "llvm/IR/GlobalVariable.h"
37#include "llvm/IR/Instructions.h"
38#include "llvm/IR/IntrinsicInst.h"
39#include "llvm/IR/Operator.h"
40using namespace llvm;
41
42#define DEBUG_TYPE "wasm-fastisel"
43
44namespace {
45
46class WebAssemblyFastISel final : public FastISel {
Dan Gohman2e644382016-05-10 17:39:48 +000047 // All possible address modes.
48 class Address {
49 public:
50 typedef enum { RegBase, FrameIndexBase } BaseKind;
51
52 private:
53 BaseKind Kind;
54 union {
55 unsigned Reg;
56 int FI;
57 } Base;
58
59 int64_t Offset;
60
61 const GlobalValue *GV;
62
63 public:
64 // Innocuous defaults for our address.
65 Address() : Kind(RegBase), Offset(0), GV(0) { Base.Reg = 0; }
66 void setKind(BaseKind K) { Kind = K; }
67 BaseKind getKind() const { return Kind; }
68 bool isRegBase() const { return Kind == RegBase; }
69 bool isFIBase() const { return Kind == FrameIndexBase; }
70 void setReg(unsigned Reg) {
71 assert(isRegBase() && "Invalid base register access!");
72 Base.Reg = Reg;
73 }
74 unsigned getReg() const {
75 assert(isRegBase() && "Invalid base register access!");
76 return Base.Reg;
77 }
78 void setFI(unsigned FI) {
79 assert(isFIBase() && "Invalid base frame index access!");
80 Base.FI = FI;
81 }
82 unsigned getFI() const {
83 assert(isFIBase() && "Invalid base frame index access!");
84 return Base.FI;
85 }
86
Dan Gohman728926a2016-12-22 15:15:10 +000087 void setOffset(int64_t Offset_) {
88 assert(Offset_ >= 0 && "Offsets must be non-negative");
89 Offset = Offset_;
90 }
Dan Gohman2e644382016-05-10 17:39:48 +000091 int64_t getOffset() const { return Offset; }
92 void setGlobalValue(const GlobalValue *G) { GV = G; }
93 const GlobalValue *getGlobalValue() const { return GV; }
94 };
95
Dan Gohman7b634842015-08-24 18:44:37 +000096 /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
97 /// right decision when generating code for different targets.
98 const WebAssemblySubtarget *Subtarget;
99 LLVMContext *Context;
100
Dan Gohman7b634842015-08-24 18:44:37 +0000101private:
Dan Gohman2e644382016-05-10 17:39:48 +0000102 // Utility helper routines
Dan Gohman3a5ce732016-05-11 16:32:42 +0000103 MVT::SimpleValueType getSimpleType(Type *Ty) {
104 EVT VT = TLI.getValueType(DL, Ty, /*HandleUnknown=*/true);
105 return VT.isSimple() ? VT.getSimpleVT().SimpleTy :
106 MVT::INVALID_SIMPLE_VALUE_TYPE;
107 }
108 MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
109 switch (VT) {
110 case MVT::i1:
111 case MVT::i8:
112 case MVT::i16:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000113 return MVT::i32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000114 case MVT::i32:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000115 case MVT::i64:
Dan Gohman33e694a2016-05-12 04:19:09 +0000116 case MVT::f32:
117 case MVT::f64:
118 return VT;
Dan Gohman6999c4f2017-02-24 21:05:35 +0000119 case MVT::f16:
120 return MVT::f32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000121 case MVT::v16i8:
122 case MVT::v8i16:
123 case MVT::v4i32:
124 case MVT::v4f32:
125 if (Subtarget->hasSIMD128())
126 return VT;
127 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000128 default:
129 break;
130 }
131 return MVT::INVALID_SIMPLE_VALUE_TYPE;
132 }
Dan Gohman2e644382016-05-10 17:39:48 +0000133 bool computeAddress(const Value *Obj, Address &Addr);
134 void materializeLoadStoreOperands(Address &Addr);
135 void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
136 MachineMemOperand *MMO);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000137 unsigned maskI1Value(unsigned Reg, const Value *V);
Dan Gohman33e694a2016-05-12 04:19:09 +0000138 unsigned getRegForI1Value(const Value *V, bool &Not);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000139 unsigned zeroExtendToI32(unsigned Reg, const Value *V,
140 MVT::SimpleValueType From);
141 unsigned signExtendToI32(unsigned Reg, const Value *V,
142 MVT::SimpleValueType From);
143 unsigned zeroExtend(unsigned Reg, const Value *V,
144 MVT::SimpleValueType From,
145 MVT::SimpleValueType To);
146 unsigned signExtend(unsigned Reg, const Value *V,
147 MVT::SimpleValueType From,
148 MVT::SimpleValueType To);
149 unsigned getRegForUnsignedValue(const Value *V);
150 unsigned getRegForSignedValue(const Value *V);
151 unsigned getRegForPromotedValue(const Value *V, bool IsSigned);
152 unsigned notValue(unsigned Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000153 unsigned copyValue(unsigned Reg);
Dan Gohman2e644382016-05-10 17:39:48 +0000154
155 // Backend specific FastISel code.
156 unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
157 unsigned fastMaterializeConstant(const Constant *C) override;
Dan Gohman33e694a2016-05-12 04:19:09 +0000158 bool fastLowerArguments() override;
Dan Gohman2e644382016-05-10 17:39:48 +0000159
160 // Selection routines.
Dan Gohman33e694a2016-05-12 04:19:09 +0000161 bool selectCall(const Instruction *I);
162 bool selectSelect(const Instruction *I);
163 bool selectTrunc(const Instruction *I);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000164 bool selectZExt(const Instruction *I);
165 bool selectSExt(const Instruction *I);
166 bool selectICmp(const Instruction *I);
167 bool selectFCmp(const Instruction *I);
Dan Gohman2e644382016-05-10 17:39:48 +0000168 bool selectBitCast(const Instruction *I);
169 bool selectLoad(const Instruction *I);
170 bool selectStore(const Instruction *I);
171 bool selectBr(const Instruction *I);
172 bool selectRet(const Instruction *I);
173 bool selectUnreachable(const Instruction *I);
174
Dan Gohman7b634842015-08-24 18:44:37 +0000175public:
176 // Backend specific FastISel code.
177 WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo,
178 const TargetLibraryInfo *LibInfo)
179 : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
180 Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>();
181 Context = &FuncInfo.Fn->getContext();
182 }
183
184 bool fastSelectInstruction(const Instruction *I) override;
185
186#include "WebAssemblyGenFastISel.inc"
187};
188
189} // end anonymous namespace
190
Dan Gohman2e644382016-05-10 17:39:48 +0000191bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {
192
193 const User *U = nullptr;
194 unsigned Opcode = Instruction::UserOp1;
195 if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
196 // Don't walk into other basic blocks unless the object is an alloca from
197 // another block, otherwise it may not have a virtual register assigned.
198 if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
199 FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
200 Opcode = I->getOpcode();
201 U = I;
202 }
203 } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
204 Opcode = C->getOpcode();
205 U = C;
206 }
207
208 if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
209 if (Ty->getAddressSpace() > 255)
210 // Fast instruction selection doesn't support the special
211 // address spaces.
212 return false;
213
214 if (const GlobalValue *GV = dyn_cast<GlobalValue>(Obj)) {
215 if (Addr.getGlobalValue())
216 return false;
217 Addr.setGlobalValue(GV);
218 return true;
219 }
220
221 switch (Opcode) {
Dan Gohman7b634842015-08-24 18:44:37 +0000222 default:
223 break;
Dan Gohman2e644382016-05-10 17:39:48 +0000224 case Instruction::BitCast: {
225 // Look through bitcasts.
226 return computeAddress(U->getOperand(0), Addr);
227 }
228 case Instruction::IntToPtr: {
229 // Look past no-op inttoptrs.
230 if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
231 TLI.getPointerTy(DL))
232 return computeAddress(U->getOperand(0), Addr);
233 break;
234 }
235 case Instruction::PtrToInt: {
236 // Look past no-op ptrtoints.
237 if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
238 return computeAddress(U->getOperand(0), Addr);
239 break;
240 }
241 case Instruction::GetElementPtr: {
242 Address SavedAddr = Addr;
243 uint64_t TmpOffset = Addr.getOffset();
Dan Gohman728926a2016-12-22 15:15:10 +0000244 // Non-inbounds geps can wrap; wasm's offsets can't.
245 if (!cast<GEPOperator>(U)->isInBounds())
246 goto unsupported_gep;
Dan Gohman2e644382016-05-10 17:39:48 +0000247 // Iterate through the GEP folding the constants into offsets where
248 // we can.
Dan Gohman33e694a2016-05-12 04:19:09 +0000249 for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
Dan Gohman2e644382016-05-10 17:39:48 +0000250 GTI != E; ++GTI) {
251 const Value *Op = GTI.getOperand();
Peter Collingbourneab85225b2016-12-02 02:24:42 +0000252 if (StructType *STy = GTI.getStructTypeOrNull()) {
Dan Gohman2e644382016-05-10 17:39:48 +0000253 const StructLayout *SL = DL.getStructLayout(STy);
254 unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
255 TmpOffset += SL->getElementOffset(Idx);
256 } else {
257 uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
258 for (;;) {
259 if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
260 // Constant-offset addressing.
261 TmpOffset += CI->getSExtValue() * S;
262 break;
263 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000264 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
265 // An unscaled add of a register. Set it as the new base.
266 Addr.setReg(getRegForValue(Op));
267 break;
268 }
Dan Gohman2e644382016-05-10 17:39:48 +0000269 if (canFoldAddIntoGEP(U, Op)) {
270 // A compatible add with a constant operand. Fold the constant.
271 ConstantInt *CI =
272 cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
273 TmpOffset += CI->getSExtValue() * S;
274 // Iterate on the other operand.
275 Op = cast<AddOperator>(Op)->getOperand(0);
276 continue;
277 }
278 // Unsupported
279 goto unsupported_gep;
280 }
281 }
282 }
Dan Gohman728926a2016-12-22 15:15:10 +0000283 // Don't fold in negative offsets.
284 if (int64_t(TmpOffset) >= 0) {
285 // Try to grab the base operand now.
286 Addr.setOffset(TmpOffset);
287 if (computeAddress(U->getOperand(0), Addr))
288 return true;
289 }
Dan Gohman2e644382016-05-10 17:39:48 +0000290 // We failed, restore everything and try the other options.
291 Addr = SavedAddr;
292 unsupported_gep:
293 break;
294 }
295 case Instruction::Alloca: {
296 const AllocaInst *AI = cast<AllocaInst>(Obj);
297 DenseMap<const AllocaInst *, int>::iterator SI =
298 FuncInfo.StaticAllocaMap.find(AI);
299 if (SI != FuncInfo.StaticAllocaMap.end()) {
300 Addr.setKind(Address::FrameIndexBase);
301 Addr.setFI(SI->second);
302 return true;
303 }
304 break;
305 }
306 case Instruction::Add: {
307 // Adds of constants are common and easy enough.
308 const Value *LHS = U->getOperand(0);
309 const Value *RHS = U->getOperand(1);
310
311 if (isa<ConstantInt>(LHS))
312 std::swap(LHS, RHS);
313
314 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
Dan Gohman728926a2016-12-22 15:15:10 +0000315 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
316 if (int64_t(TmpOffset) >= 0) {
317 Addr.setOffset(TmpOffset);
318 return computeAddress(LHS, Addr);
319 }
Dan Gohman2e644382016-05-10 17:39:48 +0000320 }
321
322 Address Backup = Addr;
323 if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
324 return true;
325 Addr = Backup;
326
327 break;
328 }
329 case Instruction::Sub: {
330 // Subs of constants are common and easy enough.
331 const Value *LHS = U->getOperand(0);
332 const Value *RHS = U->getOperand(1);
333
334 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
Dan Gohman728926a2016-12-22 15:15:10 +0000335 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
336 if (TmpOffset >= 0) {
337 Addr.setOffset(TmpOffset);
338 return computeAddress(LHS, Addr);
339 }
Dan Gohman2e644382016-05-10 17:39:48 +0000340 }
341 break;
342 }
343 }
344 Addr.setReg(getRegForValue(Obj));
345 return Addr.getReg() != 0;
346}
347
348void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
349 if (Addr.isRegBase()) {
350 unsigned Reg = Addr.getReg();
351 if (Reg == 0) {
352 Reg = createResultReg(Subtarget->hasAddr64() ?
353 &WebAssembly::I64RegClass :
354 &WebAssembly::I32RegClass);
355 unsigned Opc = Subtarget->hasAddr64() ?
356 WebAssembly::CONST_I64 :
357 WebAssembly::CONST_I32;
358 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
359 .addImm(0);
360 Addr.setReg(Reg);
361 }
362 }
363}
364
365void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
366 const MachineInstrBuilder &MIB,
367 MachineMemOperand *MMO) {
Dan Gohman48abaa92016-10-25 00:17:11 +0000368 // Set the alignment operand (this is rewritten in SetP2AlignOperands).
369 // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
370 MIB.addImm(0);
371
Dan Gohman2e644382016-05-10 17:39:48 +0000372 if (const GlobalValue *GV = Addr.getGlobalValue())
373 MIB.addGlobalAddress(GV, Addr.getOffset());
374 else
375 MIB.addImm(Addr.getOffset());
376
377 if (Addr.isRegBase())
378 MIB.addReg(Addr.getReg());
379 else
380 MIB.addFrameIndex(Addr.getFI());
381
Dan Gohman2e644382016-05-10 17:39:48 +0000382 MIB.addMemOperand(MMO);
383}
384
Dan Gohman3a5ce732016-05-11 16:32:42 +0000385unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
386 return zeroExtendToI32(Reg, V, MVT::i1);
Dan Gohman2e644382016-05-10 17:39:48 +0000387}
388
Dan Gohman33e694a2016-05-12 04:19:09 +0000389unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
390 if (const ICmpInst *ICmp = dyn_cast<ICmpInst>(V))
391 if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
392 if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
393 Not = ICmp->isTrueWhenEqual();
394 return getRegForValue(ICmp->getOperand(0));
395 }
396
397 if (BinaryOperator::isNot(V)) {
398 Not = true;
399 return getRegForValue(BinaryOperator::getNotArgument(V));
400 }
401
402 Not = false;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000403 return maskI1Value(getRegForValue(V), V);
404}
405
406unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
407 MVT::SimpleValueType From) {
Derek Schuff732636d2016-08-04 18:01:52 +0000408 if (Reg == 0)
409 return 0;
410
Dan Gohman3a5ce732016-05-11 16:32:42 +0000411 switch (From) {
412 case MVT::i1:
413 // If the value is naturally an i1, we don't need to mask it.
414 // TODO: Recursively examine selects, phis, and, or, xor, constants.
Dan Gohman33e694a2016-05-12 04:19:09 +0000415 if (From == MVT::i1 && V != nullptr) {
416 if (isa<CmpInst>(V) ||
417 (isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr()))
418 return copyValue(Reg);
419 }
420 case MVT::i8:
421 case MVT::i16:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000422 break;
423 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000424 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000425 default:
426 return 0;
427 }
428
429 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
430 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
431 TII.get(WebAssembly::CONST_I32), Imm)
432 .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
433
434 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
435 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
436 TII.get(WebAssembly::AND_I32), Result)
437 .addReg(Reg)
438 .addReg(Imm);
439
440 return Result;
441}
442
443unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
444 MVT::SimpleValueType From) {
Derek Schuff732636d2016-08-04 18:01:52 +0000445 if (Reg == 0)
446 return 0;
447
Dan Gohman3a5ce732016-05-11 16:32:42 +0000448 switch (From) {
449 case MVT::i1:
450 case MVT::i8:
451 case MVT::i16:
452 break;
453 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000454 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000455 default:
Dan Gohman33e694a2016-05-12 04:19:09 +0000456 return 0;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000457 }
458
459 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
460 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
461 TII.get(WebAssembly::CONST_I32), Imm)
462 .addImm(32 - MVT(From).getSizeInBits());
463
464 unsigned Left = createResultReg(&WebAssembly::I32RegClass);
465 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
466 TII.get(WebAssembly::SHL_I32), Left)
467 .addReg(Reg)
468 .addReg(Imm);
469
470 unsigned Right = createResultReg(&WebAssembly::I32RegClass);
471 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
472 TII.get(WebAssembly::SHR_S_I32), Right)
473 .addReg(Left)
474 .addReg(Imm);
475
476 return Right;
477}
478
479unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
480 MVT::SimpleValueType From,
481 MVT::SimpleValueType To) {
482 if (To == MVT::i64) {
483 if (From == MVT::i64)
Dan Gohman33e694a2016-05-12 04:19:09 +0000484 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000485
486 Reg = zeroExtendToI32(Reg, V, From);
487
488 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
489 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
490 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
491 .addReg(Reg);
492 return Result;
493 }
494
Dan Gohman3a5ce732016-05-11 16:32:42 +0000495 return zeroExtendToI32(Reg, V, From);
496}
497
498unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
499 MVT::SimpleValueType From,
500 MVT::SimpleValueType To) {
501 if (To == MVT::i64) {
502 if (From == MVT::i64)
Dan Gohman33e694a2016-05-12 04:19:09 +0000503 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000504
505 Reg = signExtendToI32(Reg, V, From);
506
507 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
508 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
509 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
510 .addReg(Reg);
511 return Result;
512 }
513
Dan Gohman3a5ce732016-05-11 16:32:42 +0000514 return signExtendToI32(Reg, V, From);
515}
516
517unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
518 MVT::SimpleValueType From = getSimpleType(V->getType());
519 MVT::SimpleValueType To = getLegalType(From);
520 return zeroExtend(getRegForValue(V), V, From, To);
521}
522
523unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
524 MVT::SimpleValueType From = getSimpleType(V->getType());
525 MVT::SimpleValueType To = getLegalType(From);
526 return zeroExtend(getRegForValue(V), V, From, To);
527}
528
529unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
530 bool IsSigned) {
531 return IsSigned ? getRegForSignedValue(V) :
532 getRegForUnsignedValue(V);
533}
534
535unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000536 assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
537
Dan Gohman3a5ce732016-05-11 16:32:42 +0000538 unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
539 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
540 TII.get(WebAssembly::EQZ_I32), NotReg)
541 .addReg(Reg);
542 return NotReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000543}
544
Dan Gohman33e694a2016-05-12 04:19:09 +0000545unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
546 unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
547 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
548 TII.get(WebAssembly::COPY), ResultReg)
549 .addReg(Reg);
550 return ResultReg;
551}
552
Dan Gohman2e644382016-05-10 17:39:48 +0000553unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
554 DenseMap<const AllocaInst *, int>::iterator SI =
555 FuncInfo.StaticAllocaMap.find(AI);
556
557 if (SI != FuncInfo.StaticAllocaMap.end()) {
558 unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ?
559 &WebAssembly::I64RegClass :
560 &WebAssembly::I32RegClass);
561 unsigned Opc = Subtarget->hasAddr64() ?
Dan Gohman4fc4e422016-10-24 19:49:43 +0000562 WebAssembly::COPY_I64 :
563 WebAssembly::COPY_I32;
Dan Gohman2e644382016-05-10 17:39:48 +0000564 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
565 .addFrameIndex(SI->second);
566 return ResultReg;
567 }
568
569 return 0;
570}
571
572unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
573 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000574 unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ?
575 &WebAssembly::I64RegClass :
576 &WebAssembly::I32RegClass);
Dan Gohman2e644382016-05-10 17:39:48 +0000577 unsigned Opc = Subtarget->hasAddr64() ?
578 WebAssembly::CONST_I64 :
579 WebAssembly::CONST_I32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000580 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Dan Gohman2e644382016-05-10 17:39:48 +0000581 .addGlobalAddress(GV);
Dan Gohman33e694a2016-05-12 04:19:09 +0000582 return ResultReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000583 }
584
585 // Let target-independent code handle it.
586 return 0;
587}
588
Dan Gohman33e694a2016-05-12 04:19:09 +0000589bool WebAssemblyFastISel::fastLowerArguments() {
590 if (!FuncInfo.CanLowerReturn)
591 return false;
592
593 const Function *F = FuncInfo.Fn;
594 if (F->isVarArg())
595 return false;
596
597 unsigned i = 0;
598 for (auto const &Arg : F->args()) {
599 const AttributeSet &Attrs = F->getAttributes();
600 if (Attrs.hasAttribute(i+1, Attribute::ByVal) ||
601 Attrs.hasAttribute(i+1, Attribute::SwiftSelf) ||
602 Attrs.hasAttribute(i+1, Attribute::SwiftError) ||
603 Attrs.hasAttribute(i+1, Attribute::InAlloca) ||
604 Attrs.hasAttribute(i+1, Attribute::Nest))
605 return false;
606
607 Type *ArgTy = Arg.getType();
Derek Schuff39bf39f2016-08-02 23:16:09 +0000608 if (ArgTy->isStructTy() || ArgTy->isArrayTy())
609 return false;
610 if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
Dan Gohman33e694a2016-05-12 04:19:09 +0000611 return false;
612
613 unsigned Opc;
614 const TargetRegisterClass *RC;
615 switch (getSimpleType(ArgTy)) {
616 case MVT::i1:
617 case MVT::i8:
618 case MVT::i16:
619 case MVT::i32:
620 Opc = WebAssembly::ARGUMENT_I32;
621 RC = &WebAssembly::I32RegClass;
622 break;
623 case MVT::i64:
624 Opc = WebAssembly::ARGUMENT_I64;
625 RC = &WebAssembly::I64RegClass;
626 break;
627 case MVT::f32:
628 Opc = WebAssembly::ARGUMENT_F32;
629 RC = &WebAssembly::F32RegClass;
630 break;
631 case MVT::f64:
632 Opc = WebAssembly::ARGUMENT_F64;
633 RC = &WebAssembly::F64RegClass;
634 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000635 case MVT::v16i8:
636 Opc = WebAssembly::ARGUMENT_v16i8;
637 RC = &WebAssembly::V128RegClass;
638 break;
639 case MVT::v8i16:
640 Opc = WebAssembly::ARGUMENT_v8i16;
641 RC = &WebAssembly::V128RegClass;
642 break;
643 case MVT::v4i32:
644 Opc = WebAssembly::ARGUMENT_v4i32;
645 RC = &WebAssembly::V128RegClass;
646 break;
647 case MVT::v4f32:
648 Opc = WebAssembly::ARGUMENT_v4f32;
649 RC = &WebAssembly::V128RegClass;
650 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000651 default:
652 return false;
653 }
654 unsigned ResultReg = createResultReg(RC);
655 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
656 .addImm(i);
657 updateValueMap(&Arg, ResultReg);
658
659 ++i;
660 }
661
662 MRI.addLiveIn(WebAssembly::ARGUMENTS);
663
664 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
665 for (auto const &Arg : F->args())
666 MFI->addParam(getLegalType(getSimpleType(Arg.getType())));
667
Dan Gohman6055fba2017-01-09 23:09:38 +0000668 if (!F->getReturnType()->isVoidTy())
669 MFI->addResult(getLegalType(getSimpleType(F->getReturnType())));
670
Dan Gohman33e694a2016-05-12 04:19:09 +0000671 return true;
672}
673
674bool WebAssemblyFastISel::selectCall(const Instruction *I) {
675 const CallInst *Call = cast<CallInst>(I);
676
677 if (Call->isMustTailCall() || Call->isInlineAsm() ||
678 Call->getFunctionType()->isVarArg())
679 return false;
680
681 Function *Func = Call->getCalledFunction();
682 if (Func && Func->isIntrinsic())
683 return false;
684
685 FunctionType *FuncTy = Call->getFunctionType();
686 unsigned Opc;
687 bool IsDirect = Func != nullptr;
688 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
689 unsigned ResultReg;
690 if (IsVoid) {
Derek Schuff6f697832016-10-21 16:38:07 +0000691 Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
Dan Gohman33e694a2016-05-12 04:19:09 +0000692 } else {
Derek Schuff39bf39f2016-08-02 23:16:09 +0000693 if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
694 return false;
695
Dan Gohman33e694a2016-05-12 04:19:09 +0000696 MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
697 switch (RetTy) {
698 case MVT::i1:
699 case MVT::i8:
700 case MVT::i16:
701 case MVT::i32:
Derek Schuff6f697832016-10-21 16:38:07 +0000702 Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::PCALL_INDIRECT_I32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000703 ResultReg = createResultReg(&WebAssembly::I32RegClass);
704 break;
705 case MVT::i64:
Derek Schuff6f697832016-10-21 16:38:07 +0000706 Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::PCALL_INDIRECT_I64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000707 ResultReg = createResultReg(&WebAssembly::I64RegClass);
708 break;
709 case MVT::f32:
Derek Schuff6f697832016-10-21 16:38:07 +0000710 Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::PCALL_INDIRECT_F32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000711 ResultReg = createResultReg(&WebAssembly::F32RegClass);
712 break;
713 case MVT::f64:
Derek Schuff6f697832016-10-21 16:38:07 +0000714 Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::PCALL_INDIRECT_F64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000715 ResultReg = createResultReg(&WebAssembly::F64RegClass);
716 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000717 case MVT::v16i8:
718 Opc =
Derek Schuff6f697832016-10-21 16:38:07 +0000719 IsDirect ? WebAssembly::CALL_v16i8 : WebAssembly::PCALL_INDIRECT_v16i8;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000720 ResultReg = createResultReg(&WebAssembly::V128RegClass);
721 break;
722 case MVT::v8i16:
723 Opc =
Derek Schuff6f697832016-10-21 16:38:07 +0000724 IsDirect ? WebAssembly::CALL_v8i16 : WebAssembly::PCALL_INDIRECT_v8i16;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000725 ResultReg = createResultReg(&WebAssembly::V128RegClass);
726 break;
727 case MVT::v4i32:
728 Opc =
Derek Schuff6f697832016-10-21 16:38:07 +0000729 IsDirect ? WebAssembly::CALL_v4i32 : WebAssembly::PCALL_INDIRECT_v4i32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000730 ResultReg = createResultReg(&WebAssembly::V128RegClass);
731 break;
732 case MVT::v4f32:
733 Opc =
Derek Schuff6f697832016-10-21 16:38:07 +0000734 IsDirect ? WebAssembly::CALL_v4f32 : WebAssembly::PCALL_INDIRECT_v4f32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000735 ResultReg = createResultReg(&WebAssembly::V128RegClass);
736 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000737 default:
738 return false;
739 }
740 }
741
742 SmallVector<unsigned, 8> Args;
743 for (unsigned i = 0, e = Call->getNumArgOperands(); i < e; ++i) {
744 Value *V = Call->getArgOperand(i);
745 MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
746 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
747 return false;
748
749 const AttributeSet &Attrs = Call->getAttributes();
750 if (Attrs.hasAttribute(i+1, Attribute::ByVal) ||
751 Attrs.hasAttribute(i+1, Attribute::SwiftSelf) ||
752 Attrs.hasAttribute(i+1, Attribute::SwiftError) ||
753 Attrs.hasAttribute(i+1, Attribute::InAlloca) ||
754 Attrs.hasAttribute(i+1, Attribute::Nest))
755 return false;
756
757 unsigned Reg;
758
759 if (Attrs.hasAttribute(i+1, Attribute::SExt))
760 Reg = getRegForSignedValue(V);
761 else if (Attrs.hasAttribute(i+1, Attribute::ZExt))
762 Reg = getRegForUnsignedValue(V);
763 else
764 Reg = getRegForValue(V);
765
766 if (Reg == 0)
767 return false;
768
769 Args.push_back(Reg);
770 }
771
772 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
773
774 if (!IsVoid)
775 MIB.addReg(ResultReg, RegState::Define);
776
777 if (IsDirect)
778 MIB.addGlobalAddress(Func);
779 else
780 MIB.addReg(getRegForValue(Call->getCalledValue()));
781
782 for (unsigned ArgReg : Args)
783 MIB.addReg(ArgReg);
784
785 if (!IsVoid)
786 updateValueMap(Call, ResultReg);
787 return true;
788}
789
790bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
791 const SelectInst *Select = cast<SelectInst>(I);
792
793 bool Not;
794 unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
795 if (CondReg == 0)
796 return false;
797
798 unsigned TrueReg = getRegForValue(Select->getTrueValue());
799 if (TrueReg == 0)
800 return false;
801
802 unsigned FalseReg = getRegForValue(Select->getFalseValue());
803 if (FalseReg == 0)
804 return false;
805
806 if (Not)
807 std::swap(TrueReg, FalseReg);
808
809 unsigned Opc;
810 const TargetRegisterClass *RC;
811 switch (getSimpleType(Select->getType())) {
812 case MVT::i1:
813 case MVT::i8:
814 case MVT::i16:
815 case MVT::i32:
816 Opc = WebAssembly::SELECT_I32;
817 RC = &WebAssembly::I32RegClass;
818 break;
819 case MVT::i64:
820 Opc = WebAssembly::SELECT_I64;
821 RC = &WebAssembly::I64RegClass;
822 break;
823 case MVT::f32:
824 Opc = WebAssembly::SELECT_F32;
825 RC = &WebAssembly::F32RegClass;
826 break;
827 case MVT::f64:
828 Opc = WebAssembly::SELECT_F64;
829 RC = &WebAssembly::F64RegClass;
830 break;
831 default:
832 return false;
833 }
834
835 unsigned ResultReg = createResultReg(RC);
836 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
837 .addReg(TrueReg)
838 .addReg(FalseReg)
839 .addReg(CondReg);
840
841 updateValueMap(Select, ResultReg);
842 return true;
843}
844
845bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
846 const TruncInst *Trunc = cast<TruncInst>(I);
847
848 unsigned Reg = getRegForValue(Trunc->getOperand(0));
849 if (Reg == 0)
850 return false;
851
852 if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
853 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
854 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
855 TII.get(WebAssembly::I32_WRAP_I64), Result)
856 .addReg(Reg);
857 Reg = Result;
858 }
859
860 updateValueMap(Trunc, Reg);
861 return true;
862}
863
Dan Gohman3a5ce732016-05-11 16:32:42 +0000864bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
865 const ZExtInst *ZExt = cast<ZExtInst>(I);
866
Dan Gohman33e694a2016-05-12 04:19:09 +0000867 const Value *Op = ZExt->getOperand(0);
868 MVT::SimpleValueType From = getSimpleType(Op->getType());
869 MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
870 unsigned Reg = zeroExtend(getRegForValue(Op), Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000871 if (Reg == 0)
872 return false;
873
874 updateValueMap(ZExt, Reg);
875 return true;
876}
877
878bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
879 const SExtInst *SExt = cast<SExtInst>(I);
880
Dan Gohman33e694a2016-05-12 04:19:09 +0000881 const Value *Op = SExt->getOperand(0);
882 MVT::SimpleValueType From = getSimpleType(Op->getType());
883 MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
884 unsigned Reg = signExtend(getRegForValue(Op), Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000885 if (Reg == 0)
886 return false;
887
888 updateValueMap(SExt, Reg);
889 return true;
890}
891
892bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
893 const ICmpInst *ICmp = cast<ICmpInst>(I);
894
895 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
896 unsigned Opc;
897 bool isSigned = false;
898 switch (ICmp->getPredicate()) {
899 case ICmpInst::ICMP_EQ:
900 Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
901 break;
902 case ICmpInst::ICMP_NE:
903 Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
904 break;
905 case ICmpInst::ICMP_UGT:
906 Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
907 break;
908 case ICmpInst::ICMP_UGE:
909 Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
910 break;
911 case ICmpInst::ICMP_ULT:
912 Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
913 break;
914 case ICmpInst::ICMP_ULE:
915 Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
916 break;
917 case ICmpInst::ICMP_SGT:
918 Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
919 isSigned = true;
920 break;
921 case ICmpInst::ICMP_SGE:
922 Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
923 isSigned = true;
924 break;
925 case ICmpInst::ICMP_SLT:
926 Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
927 isSigned = true;
928 break;
929 case ICmpInst::ICMP_SLE:
930 Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
931 isSigned = true;
932 break;
933 default: return false;
934 }
935
936 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), isSigned);
937 if (LHS == 0)
938 return false;
939
940 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), isSigned);
941 if (RHS == 0)
942 return false;
943
944 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
945 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
946 .addReg(LHS)
947 .addReg(RHS);
948 updateValueMap(ICmp, ResultReg);
949 return true;
950}
951
952bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
953 const FCmpInst *FCmp = cast<FCmpInst>(I);
954
955 unsigned LHS = getRegForValue(FCmp->getOperand(0));
956 if (LHS == 0)
957 return false;
958
959 unsigned RHS = getRegForValue(FCmp->getOperand(1));
960 if (RHS == 0)
961 return false;
962
963 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
964 unsigned Opc;
965 bool Not = false;
966 switch (FCmp->getPredicate()) {
967 case FCmpInst::FCMP_OEQ:
968 Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
969 break;
970 case FCmpInst::FCMP_UNE:
971 Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
972 break;
973 case FCmpInst::FCMP_OGT:
974 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
975 break;
976 case FCmpInst::FCMP_OGE:
977 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
978 break;
979 case FCmpInst::FCMP_OLT:
980 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
981 break;
982 case FCmpInst::FCMP_OLE:
983 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
984 break;
985 case FCmpInst::FCMP_UGT:
986 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
987 Not = true;
988 break;
989 case FCmpInst::FCMP_UGE:
990 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
991 Not = true;
992 break;
993 case FCmpInst::FCMP_ULT:
994 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
995 Not = true;
996 break;
997 case FCmpInst::FCMP_ULE:
998 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
999 Not = true;
1000 break;
1001 default:
1002 return false;
1003 }
1004
1005 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1006 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1007 .addReg(LHS)
1008 .addReg(RHS);
1009
1010 if (Not)
1011 ResultReg = notValue(ResultReg);
1012
1013 updateValueMap(FCmp, ResultReg);
1014 return true;
1015}
1016
Dan Gohman2e644382016-05-10 17:39:48 +00001017bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
1018 // Target-independent code can handle this, except it doesn't set the dead
1019 // flag on the ARGUMENTS clobber, so we have to do that manually in order
1020 // to satisfy code that expects this of isBitcast() instructions.
1021 EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
1022 EVT RetVT = TLI.getValueType(DL, I->getType());
1023 if (!VT.isSimple() || !RetVT.isSimple())
1024 return false;
Dan Gohman33e694a2016-05-12 04:19:09 +00001025
1026 if (VT == RetVT) {
1027 // No-op bitcast.
1028 updateValueMap(I, getRegForValue(I->getOperand(0)));
1029 return true;
1030 }
1031
Dan Gohman2e644382016-05-10 17:39:48 +00001032 unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
1033 getRegForValue(I->getOperand(0)),
1034 I->getOperand(0)->hasOneUse());
1035 if (!Reg)
1036 return false;
1037 MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
1038 --Iter;
1039 assert(Iter->isBitcast());
1040 Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI);
1041 updateValueMap(I, Reg);
1042 return true;
1043}
1044
1045bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
1046 const LoadInst *Load = cast<LoadInst>(I);
1047 if (Load->isAtomic())
1048 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001049 if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
1050 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001051
1052 Address Addr;
1053 if (!computeAddress(Load->getPointerOperand(), Addr))
1054 return false;
1055
1056 // TODO: Fold a following sign-/zero-extend into the load instruction.
1057
1058 unsigned Opc;
1059 const TargetRegisterClass *RC;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001060 switch (getSimpleType(Load->getType())) {
1061 case MVT::i1:
1062 case MVT::i8:
1063 Opc = WebAssembly::LOAD8_U_I32;
1064 RC = &WebAssembly::I32RegClass;
Dan Gohman2e644382016-05-10 17:39:48 +00001065 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001066 case MVT::i16:
1067 Opc = WebAssembly::LOAD16_U_I32;
1068 RC = &WebAssembly::I32RegClass;
1069 break;
1070 case MVT::i32:
1071 Opc = WebAssembly::LOAD_I32;
1072 RC = &WebAssembly::I32RegClass;
1073 break;
1074 case MVT::i64:
1075 Opc = WebAssembly::LOAD_I64;
1076 RC = &WebAssembly::I64RegClass;
1077 break;
1078 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001079 Opc = WebAssembly::LOAD_F32;
1080 RC = &WebAssembly::F32RegClass;
1081 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001082 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001083 Opc = WebAssembly::LOAD_F64;
1084 RC = &WebAssembly::F64RegClass;
1085 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001086 default:
1087 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001088 }
1089
1090 materializeLoadStoreOperands(Addr);
1091
1092 unsigned ResultReg = createResultReg(RC);
1093 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
1094 ResultReg);
1095
1096 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1097
1098 updateValueMap(Load, ResultReg);
1099 return true;
1100}
1101
1102bool WebAssemblyFastISel::selectStore(const Instruction *I) {
1103 const StoreInst *Store = cast<StoreInst>(I);
1104 if (Store->isAtomic())
1105 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001106 if (!Subtarget->hasSIMD128() &&
1107 Store->getValueOperand()->getType()->isVectorTy())
1108 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001109
1110 Address Addr;
1111 if (!computeAddress(Store->getPointerOperand(), Addr))
1112 return false;
1113
1114 unsigned Opc;
Dan Gohman2e644382016-05-10 17:39:48 +00001115 bool VTIsi1 = false;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001116 switch (getSimpleType(Store->getValueOperand()->getType())) {
1117 case MVT::i1:
1118 VTIsi1 = true;
1119 case MVT::i8:
1120 Opc = WebAssembly::STORE8_I32;
Dan Gohman2e644382016-05-10 17:39:48 +00001121 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001122 case MVT::i16:
1123 Opc = WebAssembly::STORE16_I32;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001124 break;
1125 case MVT::i32:
1126 Opc = WebAssembly::STORE_I32;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001127 break;
1128 case MVT::i64:
1129 Opc = WebAssembly::STORE_I64;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001130 break;
1131 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001132 Opc = WebAssembly::STORE_F32;
Dan Gohman2e644382016-05-10 17:39:48 +00001133 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001134 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001135 Opc = WebAssembly::STORE_F64;
Dan Gohman2e644382016-05-10 17:39:48 +00001136 break;
1137 default: return false;
1138 }
1139
1140 materializeLoadStoreOperands(Addr);
1141
1142 unsigned ValueReg = getRegForValue(Store->getValueOperand());
Derek Schuff732636d2016-08-04 18:01:52 +00001143 if (ValueReg == 0)
1144 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001145 if (VTIsi1)
Dan Gohman3a5ce732016-05-11 16:32:42 +00001146 ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
Dan Gohman2e644382016-05-10 17:39:48 +00001147
Dan Gohman7f1bdb22016-10-06 22:08:28 +00001148 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
Dan Gohman2e644382016-05-10 17:39:48 +00001149
1150 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1151
1152 MIB.addReg(ValueReg);
1153 return true;
1154}
1155
1156bool WebAssemblyFastISel::selectBr(const Instruction *I) {
1157 const BranchInst *Br = cast<BranchInst>(I);
1158 if (Br->isUnconditional()) {
1159 MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
1160 fastEmitBranch(MSucc, Br->getDebugLoc());
1161 return true;
1162 }
1163
1164 MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
1165 MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
1166
Dan Gohman33e694a2016-05-12 04:19:09 +00001167 bool Not;
1168 unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
Derek Schuff732636d2016-08-04 18:01:52 +00001169 if (CondReg == 0)
1170 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001171
Dan Gohman33e694a2016-05-12 04:19:09 +00001172 unsigned Opc = WebAssembly::BR_IF;
1173 if (Not)
1174 Opc = WebAssembly::BR_UNLESS;
1175
Dan Gohman2e644382016-05-10 17:39:48 +00001176 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1177 .addMBB(TBB)
1178 .addReg(CondReg);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001179
Dan Gohman2e644382016-05-10 17:39:48 +00001180 finishCondBranch(Br->getParent(), TBB, FBB);
1181 return true;
1182}
1183
1184bool WebAssemblyFastISel::selectRet(const Instruction *I) {
1185 if (!FuncInfo.CanLowerReturn)
1186 return false;
1187
1188 const ReturnInst *Ret = cast<ReturnInst>(I);
1189
1190 if (Ret->getNumOperands() == 0) {
1191 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1192 TII.get(WebAssembly::RETURN_VOID));
1193 return true;
1194 }
1195
1196 Value *RV = Ret->getOperand(0);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001197 if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
1198 return false;
1199
Dan Gohman2e644382016-05-10 17:39:48 +00001200 unsigned Opc;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001201 switch (getSimpleType(RV->getType())) {
1202 case MVT::i1: case MVT::i8:
1203 case MVT::i16: case MVT::i32:
1204 Opc = WebAssembly::RETURN_I32;
Dan Gohman2e644382016-05-10 17:39:48 +00001205 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001206 case MVT::i64:
1207 Opc = WebAssembly::RETURN_I64;
1208 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001209 case MVT::f32:
1210 Opc = WebAssembly::RETURN_F32;
1211 break;
1212 case MVT::f64:
1213 Opc = WebAssembly::RETURN_F64;
1214 break;
1215 case MVT::v16i8:
1216 Opc = WebAssembly::RETURN_v16i8;
1217 break;
1218 case MVT::v8i16:
1219 Opc = WebAssembly::RETURN_v8i16;
1220 break;
1221 case MVT::v4i32:
1222 Opc = WebAssembly::RETURN_v4i32;
1223 break;
1224 case MVT::v4f32:
1225 Opc = WebAssembly::RETURN_v4f32;
1226 break;
Dan Gohman2e644382016-05-10 17:39:48 +00001227 default: return false;
1228 }
1229
Dan Gohman33e694a2016-05-12 04:19:09 +00001230 unsigned Reg;
1231 if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
1232 Reg = getRegForSignedValue(RV);
1233 else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
1234 Reg = getRegForUnsignedValue(RV);
1235 else
1236 Reg = getRegForValue(RV);
1237
Derek Schuff732636d2016-08-04 18:01:52 +00001238 if (Reg == 0)
1239 return false;
1240
Dan Gohman2e644382016-05-10 17:39:48 +00001241 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg);
1242 return true;
1243}
1244
1245bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
1246 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1247 TII.get(WebAssembly::UNREACHABLE));
1248 return true;
1249}
1250
1251bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
1252 switch (I->getOpcode()) {
Dan Gohman33e694a2016-05-12 04:19:09 +00001253 case Instruction::Call:
1254 if (selectCall(I))
1255 return true;
1256 break;
1257 case Instruction::Select: return selectSelect(I);
1258 case Instruction::Trunc: return selectTrunc(I);
Dan Gohman3a5ce732016-05-11 16:32:42 +00001259 case Instruction::ZExt: return selectZExt(I);
1260 case Instruction::SExt: return selectSExt(I);
1261 case Instruction::ICmp: return selectICmp(I);
1262 case Instruction::FCmp: return selectFCmp(I);
Dan Gohman2e644382016-05-10 17:39:48 +00001263 case Instruction::BitCast: return selectBitCast(I);
1264 case Instruction::Load: return selectLoad(I);
1265 case Instruction::Store: return selectStore(I);
1266 case Instruction::Br: return selectBr(I);
1267 case Instruction::Ret: return selectRet(I);
1268 case Instruction::Unreachable: return selectUnreachable(I);
1269 default: break;
Dan Gohman7b634842015-08-24 18:44:37 +00001270 }
1271
1272 // Fall back to target-independent instruction selection.
1273 return selectOperator(I, I->getOpcode());
1274}
1275
1276FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,
1277 const TargetLibraryInfo *LibInfo) {
1278 return new WebAssemblyFastISel(FuncInfo, LibInfo);
1279}