blob: b4786e5518f95519167b7d601aaf99710fce7ace [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
87 void setOffset(int64_t Offset_) { Offset = Offset_; }
88 int64_t getOffset() const { return Offset; }
89 void setGlobalValue(const GlobalValue *G) { GV = G; }
90 const GlobalValue *getGlobalValue() const { return GV; }
91 };
92
Dan Gohman7b634842015-08-24 18:44:37 +000093 /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
94 /// right decision when generating code for different targets.
95 const WebAssemblySubtarget *Subtarget;
96 LLVMContext *Context;
97
Dan Gohman7b634842015-08-24 18:44:37 +000098private:
Dan Gohman2e644382016-05-10 17:39:48 +000099 // Utility helper routines
Dan Gohman3a5ce732016-05-11 16:32:42 +0000100 MVT::SimpleValueType getSimpleType(Type *Ty) {
101 EVT VT = TLI.getValueType(DL, Ty, /*HandleUnknown=*/true);
102 return VT.isSimple() ? VT.getSimpleVT().SimpleTy :
103 MVT::INVALID_SIMPLE_VALUE_TYPE;
104 }
105 MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
106 switch (VT) {
107 case MVT::i1:
108 case MVT::i8:
109 case MVT::i16:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000110 return MVT::i32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000111 case MVT::i32:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000112 case MVT::i64:
Dan Gohman33e694a2016-05-12 04:19:09 +0000113 case MVT::f32:
114 case MVT::f64:
115 return VT;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000116 case MVT::v16i8:
117 case MVT::v8i16:
118 case MVT::v4i32:
119 case MVT::v4f32:
120 if (Subtarget->hasSIMD128())
121 return VT;
122 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000123 default:
124 break;
125 }
126 return MVT::INVALID_SIMPLE_VALUE_TYPE;
127 }
Dan Gohman2e644382016-05-10 17:39:48 +0000128 bool computeAddress(const Value *Obj, Address &Addr);
129 void materializeLoadStoreOperands(Address &Addr);
130 void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
131 MachineMemOperand *MMO);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000132 unsigned maskI1Value(unsigned Reg, const Value *V);
Dan Gohman33e694a2016-05-12 04:19:09 +0000133 unsigned getRegForI1Value(const Value *V, bool &Not);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000134 unsigned zeroExtendToI32(unsigned Reg, const Value *V,
135 MVT::SimpleValueType From);
136 unsigned signExtendToI32(unsigned Reg, const Value *V,
137 MVT::SimpleValueType From);
138 unsigned zeroExtend(unsigned Reg, const Value *V,
139 MVT::SimpleValueType From,
140 MVT::SimpleValueType To);
141 unsigned signExtend(unsigned Reg, const Value *V,
142 MVT::SimpleValueType From,
143 MVT::SimpleValueType To);
144 unsigned getRegForUnsignedValue(const Value *V);
145 unsigned getRegForSignedValue(const Value *V);
146 unsigned getRegForPromotedValue(const Value *V, bool IsSigned);
147 unsigned notValue(unsigned Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000148 unsigned copyValue(unsigned Reg);
Dan Gohman2e644382016-05-10 17:39:48 +0000149
150 // Backend specific FastISel code.
151 unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
152 unsigned fastMaterializeConstant(const Constant *C) override;
Dan Gohman33e694a2016-05-12 04:19:09 +0000153 bool fastLowerArguments() override;
Dan Gohman2e644382016-05-10 17:39:48 +0000154
155 // Selection routines.
Dan Gohman33e694a2016-05-12 04:19:09 +0000156 bool selectCall(const Instruction *I);
157 bool selectSelect(const Instruction *I);
158 bool selectTrunc(const Instruction *I);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000159 bool selectZExt(const Instruction *I);
160 bool selectSExt(const Instruction *I);
161 bool selectICmp(const Instruction *I);
162 bool selectFCmp(const Instruction *I);
Dan Gohman2e644382016-05-10 17:39:48 +0000163 bool selectBitCast(const Instruction *I);
164 bool selectLoad(const Instruction *I);
165 bool selectStore(const Instruction *I);
166 bool selectBr(const Instruction *I);
167 bool selectRet(const Instruction *I);
168 bool selectUnreachable(const Instruction *I);
169
Dan Gohman7b634842015-08-24 18:44:37 +0000170public:
171 // Backend specific FastISel code.
172 WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo,
173 const TargetLibraryInfo *LibInfo)
174 : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
175 Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>();
176 Context = &FuncInfo.Fn->getContext();
177 }
178
179 bool fastSelectInstruction(const Instruction *I) override;
180
181#include "WebAssemblyGenFastISel.inc"
182};
183
184} // end anonymous namespace
185
Dan Gohman2e644382016-05-10 17:39:48 +0000186bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {
187
188 const User *U = nullptr;
189 unsigned Opcode = Instruction::UserOp1;
190 if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
191 // Don't walk into other basic blocks unless the object is an alloca from
192 // another block, otherwise it may not have a virtual register assigned.
193 if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
194 FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
195 Opcode = I->getOpcode();
196 U = I;
197 }
198 } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
199 Opcode = C->getOpcode();
200 U = C;
201 }
202
203 if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
204 if (Ty->getAddressSpace() > 255)
205 // Fast instruction selection doesn't support the special
206 // address spaces.
207 return false;
208
209 if (const GlobalValue *GV = dyn_cast<GlobalValue>(Obj)) {
210 if (Addr.getGlobalValue())
211 return false;
212 Addr.setGlobalValue(GV);
213 return true;
214 }
215
216 switch (Opcode) {
Dan Gohman7b634842015-08-24 18:44:37 +0000217 default:
218 break;
Dan Gohman2e644382016-05-10 17:39:48 +0000219 case Instruction::BitCast: {
220 // Look through bitcasts.
221 return computeAddress(U->getOperand(0), Addr);
222 }
223 case Instruction::IntToPtr: {
224 // Look past no-op inttoptrs.
225 if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
226 TLI.getPointerTy(DL))
227 return computeAddress(U->getOperand(0), Addr);
228 break;
229 }
230 case Instruction::PtrToInt: {
231 // Look past no-op ptrtoints.
232 if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
233 return computeAddress(U->getOperand(0), Addr);
234 break;
235 }
236 case Instruction::GetElementPtr: {
237 Address SavedAddr = Addr;
238 uint64_t TmpOffset = Addr.getOffset();
239 // Iterate through the GEP folding the constants into offsets where
240 // we can.
Dan Gohman33e694a2016-05-12 04:19:09 +0000241 for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
Dan Gohman2e644382016-05-10 17:39:48 +0000242 GTI != E; ++GTI) {
243 const Value *Op = GTI.getOperand();
244 if (StructType *STy = dyn_cast<StructType>(*GTI)) {
245 const StructLayout *SL = DL.getStructLayout(STy);
246 unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
247 TmpOffset += SL->getElementOffset(Idx);
248 } else {
249 uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
250 for (;;) {
251 if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
252 // Constant-offset addressing.
253 TmpOffset += CI->getSExtValue() * S;
254 break;
255 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000256 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
257 // An unscaled add of a register. Set it as the new base.
258 Addr.setReg(getRegForValue(Op));
259 break;
260 }
Dan Gohman2e644382016-05-10 17:39:48 +0000261 if (canFoldAddIntoGEP(U, Op)) {
262 // A compatible add with a constant operand. Fold the constant.
263 ConstantInt *CI =
264 cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
265 TmpOffset += CI->getSExtValue() * S;
266 // Iterate on the other operand.
267 Op = cast<AddOperator>(Op)->getOperand(0);
268 continue;
269 }
270 // Unsupported
271 goto unsupported_gep;
272 }
273 }
274 }
275 // Try to grab the base operand now.
276 Addr.setOffset(TmpOffset);
277 if (computeAddress(U->getOperand(0), Addr))
278 return true;
279 // We failed, restore everything and try the other options.
280 Addr = SavedAddr;
281 unsupported_gep:
282 break;
283 }
284 case Instruction::Alloca: {
285 const AllocaInst *AI = cast<AllocaInst>(Obj);
286 DenseMap<const AllocaInst *, int>::iterator SI =
287 FuncInfo.StaticAllocaMap.find(AI);
288 if (SI != FuncInfo.StaticAllocaMap.end()) {
289 Addr.setKind(Address::FrameIndexBase);
290 Addr.setFI(SI->second);
291 return true;
292 }
293 break;
294 }
295 case Instruction::Add: {
296 // Adds of constants are common and easy enough.
297 const Value *LHS = U->getOperand(0);
298 const Value *RHS = U->getOperand(1);
299
300 if (isa<ConstantInt>(LHS))
301 std::swap(LHS, RHS);
302
303 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
304 Addr.setOffset(Addr.getOffset() + CI->getSExtValue());
305 return computeAddress(LHS, Addr);
306 }
307
308 Address Backup = Addr;
309 if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
310 return true;
311 Addr = Backup;
312
313 break;
314 }
315 case Instruction::Sub: {
316 // Subs of constants are common and easy enough.
317 const Value *LHS = U->getOperand(0);
318 const Value *RHS = U->getOperand(1);
319
320 if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
321 Addr.setOffset(Addr.getOffset() - CI->getSExtValue());
322 return computeAddress(LHS, Addr);
323 }
324 break;
325 }
326 }
327 Addr.setReg(getRegForValue(Obj));
328 return Addr.getReg() != 0;
329}
330
331void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
332 if (Addr.isRegBase()) {
333 unsigned Reg = Addr.getReg();
334 if (Reg == 0) {
335 Reg = createResultReg(Subtarget->hasAddr64() ?
336 &WebAssembly::I64RegClass :
337 &WebAssembly::I32RegClass);
338 unsigned Opc = Subtarget->hasAddr64() ?
339 WebAssembly::CONST_I64 :
340 WebAssembly::CONST_I32;
341 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
342 .addImm(0);
343 Addr.setReg(Reg);
344 }
345 }
346}
347
348void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
349 const MachineInstrBuilder &MIB,
350 MachineMemOperand *MMO) {
351 if (const GlobalValue *GV = Addr.getGlobalValue())
352 MIB.addGlobalAddress(GV, Addr.getOffset());
353 else
354 MIB.addImm(Addr.getOffset());
355
356 if (Addr.isRegBase())
357 MIB.addReg(Addr.getReg());
358 else
359 MIB.addFrameIndex(Addr.getFI());
360
361 // Set the alignment operand (this is rewritten in SetP2AlignOperands).
362 // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
363 MIB.addImm(0);
364
365 MIB.addMemOperand(MMO);
366}
367
Dan Gohman3a5ce732016-05-11 16:32:42 +0000368unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
369 return zeroExtendToI32(Reg, V, MVT::i1);
Dan Gohman2e644382016-05-10 17:39:48 +0000370}
371
Dan Gohman33e694a2016-05-12 04:19:09 +0000372unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
373 if (const ICmpInst *ICmp = dyn_cast<ICmpInst>(V))
374 if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
375 if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
376 Not = ICmp->isTrueWhenEqual();
377 return getRegForValue(ICmp->getOperand(0));
378 }
379
380 if (BinaryOperator::isNot(V)) {
381 Not = true;
382 return getRegForValue(BinaryOperator::getNotArgument(V));
383 }
384
385 Not = false;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000386 return maskI1Value(getRegForValue(V), V);
387}
388
389unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
390 MVT::SimpleValueType From) {
391 switch (From) {
392 case MVT::i1:
393 // If the value is naturally an i1, we don't need to mask it.
394 // TODO: Recursively examine selects, phis, and, or, xor, constants.
Dan Gohman33e694a2016-05-12 04:19:09 +0000395 if (From == MVT::i1 && V != nullptr) {
396 if (isa<CmpInst>(V) ||
397 (isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr()))
398 return copyValue(Reg);
399 }
400 case MVT::i8:
401 case MVT::i16:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000402 break;
403 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000404 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000405 default:
406 return 0;
407 }
408
409 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
410 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
411 TII.get(WebAssembly::CONST_I32), Imm)
412 .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
413
414 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
415 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
416 TII.get(WebAssembly::AND_I32), Result)
417 .addReg(Reg)
418 .addReg(Imm);
419
420 return Result;
421}
422
423unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
424 MVT::SimpleValueType From) {
425 switch (From) {
426 case MVT::i1:
427 case MVT::i8:
428 case MVT::i16:
429 break;
430 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000431 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000432 default:
Dan Gohman33e694a2016-05-12 04:19:09 +0000433 return 0;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000434 }
435
436 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
437 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
438 TII.get(WebAssembly::CONST_I32), Imm)
439 .addImm(32 - MVT(From).getSizeInBits());
440
441 unsigned Left = createResultReg(&WebAssembly::I32RegClass);
442 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
443 TII.get(WebAssembly::SHL_I32), Left)
444 .addReg(Reg)
445 .addReg(Imm);
446
447 unsigned Right = createResultReg(&WebAssembly::I32RegClass);
448 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
449 TII.get(WebAssembly::SHR_S_I32), Right)
450 .addReg(Left)
451 .addReg(Imm);
452
453 return Right;
454}
455
456unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
457 MVT::SimpleValueType From,
458 MVT::SimpleValueType To) {
459 if (To == MVT::i64) {
460 if (From == MVT::i64)
Dan Gohman33e694a2016-05-12 04:19:09 +0000461 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000462
463 Reg = zeroExtendToI32(Reg, V, From);
464
465 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
466 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
467 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
468 .addReg(Reg);
469 return Result;
470 }
471
Dan Gohman3a5ce732016-05-11 16:32:42 +0000472 return zeroExtendToI32(Reg, V, From);
473}
474
475unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
476 MVT::SimpleValueType From,
477 MVT::SimpleValueType To) {
478 if (To == MVT::i64) {
479 if (From == MVT::i64)
Dan Gohman33e694a2016-05-12 04:19:09 +0000480 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000481
482 Reg = signExtendToI32(Reg, V, From);
483
484 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
485 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
486 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
487 .addReg(Reg);
488 return Result;
489 }
490
Dan Gohman3a5ce732016-05-11 16:32:42 +0000491 return signExtendToI32(Reg, V, From);
492}
493
494unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
495 MVT::SimpleValueType From = getSimpleType(V->getType());
496 MVT::SimpleValueType To = getLegalType(From);
497 return zeroExtend(getRegForValue(V), V, From, To);
498}
499
500unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
501 MVT::SimpleValueType From = getSimpleType(V->getType());
502 MVT::SimpleValueType To = getLegalType(From);
503 return zeroExtend(getRegForValue(V), V, From, To);
504}
505
506unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
507 bool IsSigned) {
508 return IsSigned ? getRegForSignedValue(V) :
509 getRegForUnsignedValue(V);
510}
511
512unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000513 assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
514
Dan Gohman3a5ce732016-05-11 16:32:42 +0000515 unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
516 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
517 TII.get(WebAssembly::EQZ_I32), NotReg)
518 .addReg(Reg);
519 return NotReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000520}
521
Dan Gohman33e694a2016-05-12 04:19:09 +0000522unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
523 unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
524 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
525 TII.get(WebAssembly::COPY), ResultReg)
526 .addReg(Reg);
527 return ResultReg;
528}
529
Dan Gohman2e644382016-05-10 17:39:48 +0000530unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
531 DenseMap<const AllocaInst *, int>::iterator SI =
532 FuncInfo.StaticAllocaMap.find(AI);
533
534 if (SI != FuncInfo.StaticAllocaMap.end()) {
535 unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ?
536 &WebAssembly::I64RegClass :
537 &WebAssembly::I32RegClass);
538 unsigned Opc = Subtarget->hasAddr64() ?
539 WebAssembly::COPY_LOCAL_I64 :
540 WebAssembly::COPY_LOCAL_I32;
541 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
542 .addFrameIndex(SI->second);
543 return ResultReg;
544 }
545
546 return 0;
547}
548
549unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
550 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000551 unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ?
552 &WebAssembly::I64RegClass :
553 &WebAssembly::I32RegClass);
Dan Gohman2e644382016-05-10 17:39:48 +0000554 unsigned Opc = Subtarget->hasAddr64() ?
555 WebAssembly::CONST_I64 :
556 WebAssembly::CONST_I32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000557 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Dan Gohman2e644382016-05-10 17:39:48 +0000558 .addGlobalAddress(GV);
Dan Gohman33e694a2016-05-12 04:19:09 +0000559 return ResultReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000560 }
561
562 // Let target-independent code handle it.
563 return 0;
564}
565
Dan Gohman33e694a2016-05-12 04:19:09 +0000566bool WebAssemblyFastISel::fastLowerArguments() {
567 if (!FuncInfo.CanLowerReturn)
568 return false;
569
570 const Function *F = FuncInfo.Fn;
571 if (F->isVarArg())
572 return false;
573
574 unsigned i = 0;
575 for (auto const &Arg : F->args()) {
576 const AttributeSet &Attrs = F->getAttributes();
577 if (Attrs.hasAttribute(i+1, Attribute::ByVal) ||
578 Attrs.hasAttribute(i+1, Attribute::SwiftSelf) ||
579 Attrs.hasAttribute(i+1, Attribute::SwiftError) ||
580 Attrs.hasAttribute(i+1, Attribute::InAlloca) ||
581 Attrs.hasAttribute(i+1, Attribute::Nest))
582 return false;
583
584 Type *ArgTy = Arg.getType();
Derek Schuff39bf39f2016-08-02 23:16:09 +0000585 if (ArgTy->isStructTy() || ArgTy->isArrayTy())
586 return false;
587 if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
Dan Gohman33e694a2016-05-12 04:19:09 +0000588 return false;
589
590 unsigned Opc;
591 const TargetRegisterClass *RC;
592 switch (getSimpleType(ArgTy)) {
593 case MVT::i1:
594 case MVT::i8:
595 case MVT::i16:
596 case MVT::i32:
597 Opc = WebAssembly::ARGUMENT_I32;
598 RC = &WebAssembly::I32RegClass;
599 break;
600 case MVT::i64:
601 Opc = WebAssembly::ARGUMENT_I64;
602 RC = &WebAssembly::I64RegClass;
603 break;
604 case MVT::f32:
605 Opc = WebAssembly::ARGUMENT_F32;
606 RC = &WebAssembly::F32RegClass;
607 break;
608 case MVT::f64:
609 Opc = WebAssembly::ARGUMENT_F64;
610 RC = &WebAssembly::F64RegClass;
611 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000612 case MVT::v16i8:
613 Opc = WebAssembly::ARGUMENT_v16i8;
614 RC = &WebAssembly::V128RegClass;
615 break;
616 case MVT::v8i16:
617 Opc = WebAssembly::ARGUMENT_v8i16;
618 RC = &WebAssembly::V128RegClass;
619 break;
620 case MVT::v4i32:
621 Opc = WebAssembly::ARGUMENT_v4i32;
622 RC = &WebAssembly::V128RegClass;
623 break;
624 case MVT::v4f32:
625 Opc = WebAssembly::ARGUMENT_v4f32;
626 RC = &WebAssembly::V128RegClass;
627 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000628 default:
629 return false;
630 }
631 unsigned ResultReg = createResultReg(RC);
632 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
633 .addImm(i);
634 updateValueMap(&Arg, ResultReg);
635
636 ++i;
637 }
638
639 MRI.addLiveIn(WebAssembly::ARGUMENTS);
640
641 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
642 for (auto const &Arg : F->args())
643 MFI->addParam(getLegalType(getSimpleType(Arg.getType())));
644
645 return true;
646}
647
648bool WebAssemblyFastISel::selectCall(const Instruction *I) {
649 const CallInst *Call = cast<CallInst>(I);
650
651 if (Call->isMustTailCall() || Call->isInlineAsm() ||
652 Call->getFunctionType()->isVarArg())
653 return false;
654
655 Function *Func = Call->getCalledFunction();
656 if (Func && Func->isIntrinsic())
657 return false;
658
659 FunctionType *FuncTy = Call->getFunctionType();
660 unsigned Opc;
661 bool IsDirect = Func != nullptr;
662 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
663 unsigned ResultReg;
664 if (IsVoid) {
665 Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::CALL_INDIRECT_VOID;
666 } else {
Derek Schuff39bf39f2016-08-02 23:16:09 +0000667 if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
668 return false;
669
Dan Gohman33e694a2016-05-12 04:19:09 +0000670 MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
671 switch (RetTy) {
672 case MVT::i1:
673 case MVT::i8:
674 case MVT::i16:
675 case MVT::i32:
676 Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::CALL_INDIRECT_I32;
677 ResultReg = createResultReg(&WebAssembly::I32RegClass);
678 break;
679 case MVT::i64:
680 Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::CALL_INDIRECT_I64;
681 ResultReg = createResultReg(&WebAssembly::I64RegClass);
682 break;
683 case MVT::f32:
684 Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::CALL_INDIRECT_F32;
685 ResultReg = createResultReg(&WebAssembly::F32RegClass);
686 break;
687 case MVT::f64:
688 Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::CALL_INDIRECT_F64;
689 ResultReg = createResultReg(&WebAssembly::F64RegClass);
690 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000691 case MVT::v16i8:
692 Opc =
693 IsDirect ? WebAssembly::CALL_v16i8 : WebAssembly::CALL_INDIRECT_v16i8;
694 ResultReg = createResultReg(&WebAssembly::V128RegClass);
695 break;
696 case MVT::v8i16:
697 Opc =
698 IsDirect ? WebAssembly::CALL_v8i16 : WebAssembly::CALL_INDIRECT_v8i16;
699 ResultReg = createResultReg(&WebAssembly::V128RegClass);
700 break;
701 case MVT::v4i32:
702 Opc =
703 IsDirect ? WebAssembly::CALL_v4i32 : WebAssembly::CALL_INDIRECT_v4i32;
704 ResultReg = createResultReg(&WebAssembly::V128RegClass);
705 break;
706 case MVT::v4f32:
707 Opc =
708 IsDirect ? WebAssembly::CALL_v4f32 : WebAssembly::CALL_INDIRECT_v4f32;
709 ResultReg = createResultReg(&WebAssembly::V128RegClass);
710 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000711 default:
712 return false;
713 }
714 }
715
716 SmallVector<unsigned, 8> Args;
717 for (unsigned i = 0, e = Call->getNumArgOperands(); i < e; ++i) {
718 Value *V = Call->getArgOperand(i);
719 MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
720 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
721 return false;
722
723 const AttributeSet &Attrs = Call->getAttributes();
724 if (Attrs.hasAttribute(i+1, Attribute::ByVal) ||
725 Attrs.hasAttribute(i+1, Attribute::SwiftSelf) ||
726 Attrs.hasAttribute(i+1, Attribute::SwiftError) ||
727 Attrs.hasAttribute(i+1, Attribute::InAlloca) ||
728 Attrs.hasAttribute(i+1, Attribute::Nest))
729 return false;
730
731 unsigned Reg;
732
733 if (Attrs.hasAttribute(i+1, Attribute::SExt))
734 Reg = getRegForSignedValue(V);
735 else if (Attrs.hasAttribute(i+1, Attribute::ZExt))
736 Reg = getRegForUnsignedValue(V);
737 else
738 Reg = getRegForValue(V);
739
740 if (Reg == 0)
741 return false;
742
743 Args.push_back(Reg);
744 }
745
746 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
747
748 if (!IsVoid)
749 MIB.addReg(ResultReg, RegState::Define);
750
751 if (IsDirect)
752 MIB.addGlobalAddress(Func);
753 else
754 MIB.addReg(getRegForValue(Call->getCalledValue()));
755
756 for (unsigned ArgReg : Args)
757 MIB.addReg(ArgReg);
758
759 if (!IsVoid)
760 updateValueMap(Call, ResultReg);
761 return true;
762}
763
764bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
765 const SelectInst *Select = cast<SelectInst>(I);
766
767 bool Not;
768 unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
769 if (CondReg == 0)
770 return false;
771
772 unsigned TrueReg = getRegForValue(Select->getTrueValue());
773 if (TrueReg == 0)
774 return false;
775
776 unsigned FalseReg = getRegForValue(Select->getFalseValue());
777 if (FalseReg == 0)
778 return false;
779
780 if (Not)
781 std::swap(TrueReg, FalseReg);
782
783 unsigned Opc;
784 const TargetRegisterClass *RC;
785 switch (getSimpleType(Select->getType())) {
786 case MVT::i1:
787 case MVT::i8:
788 case MVT::i16:
789 case MVT::i32:
790 Opc = WebAssembly::SELECT_I32;
791 RC = &WebAssembly::I32RegClass;
792 break;
793 case MVT::i64:
794 Opc = WebAssembly::SELECT_I64;
795 RC = &WebAssembly::I64RegClass;
796 break;
797 case MVT::f32:
798 Opc = WebAssembly::SELECT_F32;
799 RC = &WebAssembly::F32RegClass;
800 break;
801 case MVT::f64:
802 Opc = WebAssembly::SELECT_F64;
803 RC = &WebAssembly::F64RegClass;
804 break;
805 default:
806 return false;
807 }
808
809 unsigned ResultReg = createResultReg(RC);
810 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
811 .addReg(TrueReg)
812 .addReg(FalseReg)
813 .addReg(CondReg);
814
815 updateValueMap(Select, ResultReg);
816 return true;
817}
818
819bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
820 const TruncInst *Trunc = cast<TruncInst>(I);
821
822 unsigned Reg = getRegForValue(Trunc->getOperand(0));
823 if (Reg == 0)
824 return false;
825
826 if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
827 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
828 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
829 TII.get(WebAssembly::I32_WRAP_I64), Result)
830 .addReg(Reg);
831 Reg = Result;
832 }
833
834 updateValueMap(Trunc, Reg);
835 return true;
836}
837
Dan Gohman3a5ce732016-05-11 16:32:42 +0000838bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
839 const ZExtInst *ZExt = cast<ZExtInst>(I);
840
Dan Gohman33e694a2016-05-12 04:19:09 +0000841 const Value *Op = ZExt->getOperand(0);
842 MVT::SimpleValueType From = getSimpleType(Op->getType());
843 MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
844 unsigned Reg = zeroExtend(getRegForValue(Op), Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000845 if (Reg == 0)
846 return false;
847
848 updateValueMap(ZExt, Reg);
849 return true;
850}
851
852bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
853 const SExtInst *SExt = cast<SExtInst>(I);
854
Dan Gohman33e694a2016-05-12 04:19:09 +0000855 const Value *Op = SExt->getOperand(0);
856 MVT::SimpleValueType From = getSimpleType(Op->getType());
857 MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
858 unsigned Reg = signExtend(getRegForValue(Op), Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000859 if (Reg == 0)
860 return false;
861
862 updateValueMap(SExt, Reg);
863 return true;
864}
865
866bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
867 const ICmpInst *ICmp = cast<ICmpInst>(I);
868
869 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
870 unsigned Opc;
871 bool isSigned = false;
872 switch (ICmp->getPredicate()) {
873 case ICmpInst::ICMP_EQ:
874 Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
875 break;
876 case ICmpInst::ICMP_NE:
877 Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
878 break;
879 case ICmpInst::ICMP_UGT:
880 Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
881 break;
882 case ICmpInst::ICMP_UGE:
883 Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
884 break;
885 case ICmpInst::ICMP_ULT:
886 Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
887 break;
888 case ICmpInst::ICMP_ULE:
889 Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
890 break;
891 case ICmpInst::ICMP_SGT:
892 Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
893 isSigned = true;
894 break;
895 case ICmpInst::ICMP_SGE:
896 Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
897 isSigned = true;
898 break;
899 case ICmpInst::ICMP_SLT:
900 Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
901 isSigned = true;
902 break;
903 case ICmpInst::ICMP_SLE:
904 Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
905 isSigned = true;
906 break;
907 default: return false;
908 }
909
910 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), isSigned);
911 if (LHS == 0)
912 return false;
913
914 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), isSigned);
915 if (RHS == 0)
916 return false;
917
918 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
919 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
920 .addReg(LHS)
921 .addReg(RHS);
922 updateValueMap(ICmp, ResultReg);
923 return true;
924}
925
926bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
927 const FCmpInst *FCmp = cast<FCmpInst>(I);
928
929 unsigned LHS = getRegForValue(FCmp->getOperand(0));
930 if (LHS == 0)
931 return false;
932
933 unsigned RHS = getRegForValue(FCmp->getOperand(1));
934 if (RHS == 0)
935 return false;
936
937 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
938 unsigned Opc;
939 bool Not = false;
940 switch (FCmp->getPredicate()) {
941 case FCmpInst::FCMP_OEQ:
942 Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
943 break;
944 case FCmpInst::FCMP_UNE:
945 Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
946 break;
947 case FCmpInst::FCMP_OGT:
948 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
949 break;
950 case FCmpInst::FCMP_OGE:
951 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
952 break;
953 case FCmpInst::FCMP_OLT:
954 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
955 break;
956 case FCmpInst::FCMP_OLE:
957 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
958 break;
959 case FCmpInst::FCMP_UGT:
960 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
961 Not = true;
962 break;
963 case FCmpInst::FCMP_UGE:
964 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
965 Not = true;
966 break;
967 case FCmpInst::FCMP_ULT:
968 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
969 Not = true;
970 break;
971 case FCmpInst::FCMP_ULE:
972 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
973 Not = true;
974 break;
975 default:
976 return false;
977 }
978
979 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
980 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
981 .addReg(LHS)
982 .addReg(RHS);
983
984 if (Not)
985 ResultReg = notValue(ResultReg);
986
987 updateValueMap(FCmp, ResultReg);
988 return true;
989}
990
Dan Gohman2e644382016-05-10 17:39:48 +0000991bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
992 // Target-independent code can handle this, except it doesn't set the dead
993 // flag on the ARGUMENTS clobber, so we have to do that manually in order
994 // to satisfy code that expects this of isBitcast() instructions.
995 EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
996 EVT RetVT = TLI.getValueType(DL, I->getType());
997 if (!VT.isSimple() || !RetVT.isSimple())
998 return false;
Dan Gohman33e694a2016-05-12 04:19:09 +0000999
1000 if (VT == RetVT) {
1001 // No-op bitcast.
1002 updateValueMap(I, getRegForValue(I->getOperand(0)));
1003 return true;
1004 }
1005
Dan Gohman2e644382016-05-10 17:39:48 +00001006 unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
1007 getRegForValue(I->getOperand(0)),
1008 I->getOperand(0)->hasOneUse());
1009 if (!Reg)
1010 return false;
1011 MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
1012 --Iter;
1013 assert(Iter->isBitcast());
1014 Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI);
1015 updateValueMap(I, Reg);
1016 return true;
1017}
1018
1019bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
1020 const LoadInst *Load = cast<LoadInst>(I);
1021 if (Load->isAtomic())
1022 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001023 if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
1024 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001025
1026 Address Addr;
1027 if (!computeAddress(Load->getPointerOperand(), Addr))
1028 return false;
1029
1030 // TODO: Fold a following sign-/zero-extend into the load instruction.
1031
1032 unsigned Opc;
1033 const TargetRegisterClass *RC;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001034 switch (getSimpleType(Load->getType())) {
1035 case MVT::i1:
1036 case MVT::i8:
1037 Opc = WebAssembly::LOAD8_U_I32;
1038 RC = &WebAssembly::I32RegClass;
Dan Gohman2e644382016-05-10 17:39:48 +00001039 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001040 case MVT::i16:
1041 Opc = WebAssembly::LOAD16_U_I32;
1042 RC = &WebAssembly::I32RegClass;
1043 break;
1044 case MVT::i32:
1045 Opc = WebAssembly::LOAD_I32;
1046 RC = &WebAssembly::I32RegClass;
1047 break;
1048 case MVT::i64:
1049 Opc = WebAssembly::LOAD_I64;
1050 RC = &WebAssembly::I64RegClass;
1051 break;
1052 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001053 Opc = WebAssembly::LOAD_F32;
1054 RC = &WebAssembly::F32RegClass;
1055 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001056 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001057 Opc = WebAssembly::LOAD_F64;
1058 RC = &WebAssembly::F64RegClass;
1059 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001060 default:
1061 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001062 }
1063
1064 materializeLoadStoreOperands(Addr);
1065
1066 unsigned ResultReg = createResultReg(RC);
1067 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
1068 ResultReg);
1069
1070 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1071
1072 updateValueMap(Load, ResultReg);
1073 return true;
1074}
1075
1076bool WebAssemblyFastISel::selectStore(const Instruction *I) {
1077 const StoreInst *Store = cast<StoreInst>(I);
1078 if (Store->isAtomic())
1079 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001080 if (!Subtarget->hasSIMD128() &&
1081 Store->getValueOperand()->getType()->isVectorTy())
1082 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001083
1084 Address Addr;
1085 if (!computeAddress(Store->getPointerOperand(), Addr))
1086 return false;
1087
1088 unsigned Opc;
1089 const TargetRegisterClass *RC;
1090 bool VTIsi1 = false;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001091 switch (getSimpleType(Store->getValueOperand()->getType())) {
1092 case MVT::i1:
1093 VTIsi1 = true;
1094 case MVT::i8:
1095 Opc = WebAssembly::STORE8_I32;
1096 RC = &WebAssembly::I32RegClass;
Dan Gohman2e644382016-05-10 17:39:48 +00001097 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001098 case MVT::i16:
1099 Opc = WebAssembly::STORE16_I32;
1100 RC = &WebAssembly::I32RegClass;
1101 break;
1102 case MVT::i32:
1103 Opc = WebAssembly::STORE_I32;
1104 RC = &WebAssembly::I32RegClass;
1105 break;
1106 case MVT::i64:
1107 Opc = WebAssembly::STORE_I64;
1108 RC = &WebAssembly::I64RegClass;
1109 break;
1110 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001111 Opc = WebAssembly::STORE_F32;
1112 RC = &WebAssembly::F32RegClass;
1113 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001114 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001115 Opc = WebAssembly::STORE_F64;
1116 RC = &WebAssembly::F64RegClass;
1117 break;
1118 default: return false;
1119 }
1120
1121 materializeLoadStoreOperands(Addr);
1122
1123 unsigned ValueReg = getRegForValue(Store->getValueOperand());
1124 if (VTIsi1)
Dan Gohman3a5ce732016-05-11 16:32:42 +00001125 ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
Dan Gohman2e644382016-05-10 17:39:48 +00001126
1127 unsigned ResultReg = createResultReg(RC);
1128 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
1129 ResultReg);
1130
1131 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1132
1133 MIB.addReg(ValueReg);
1134 return true;
1135}
1136
1137bool WebAssemblyFastISel::selectBr(const Instruction *I) {
1138 const BranchInst *Br = cast<BranchInst>(I);
1139 if (Br->isUnconditional()) {
1140 MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
1141 fastEmitBranch(MSucc, Br->getDebugLoc());
1142 return true;
1143 }
1144
1145 MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
1146 MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
1147
Dan Gohman33e694a2016-05-12 04:19:09 +00001148 bool Not;
1149 unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
Dan Gohman2e644382016-05-10 17:39:48 +00001150
Dan Gohman33e694a2016-05-12 04:19:09 +00001151 unsigned Opc = WebAssembly::BR_IF;
1152 if (Not)
1153 Opc = WebAssembly::BR_UNLESS;
1154
Dan Gohman2e644382016-05-10 17:39:48 +00001155 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1156 .addMBB(TBB)
1157 .addReg(CondReg);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001158
Dan Gohman2e644382016-05-10 17:39:48 +00001159 finishCondBranch(Br->getParent(), TBB, FBB);
1160 return true;
1161}
1162
1163bool WebAssemblyFastISel::selectRet(const Instruction *I) {
1164 if (!FuncInfo.CanLowerReturn)
1165 return false;
1166
1167 const ReturnInst *Ret = cast<ReturnInst>(I);
1168
1169 if (Ret->getNumOperands() == 0) {
1170 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1171 TII.get(WebAssembly::RETURN_VOID));
1172 return true;
1173 }
1174
1175 Value *RV = Ret->getOperand(0);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001176 if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
1177 return false;
1178
Dan Gohman2e644382016-05-10 17:39:48 +00001179 unsigned Opc;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001180 switch (getSimpleType(RV->getType())) {
1181 case MVT::i1: case MVT::i8:
1182 case MVT::i16: case MVT::i32:
1183 Opc = WebAssembly::RETURN_I32;
Dan Gohman2e644382016-05-10 17:39:48 +00001184 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001185 case MVT::i64:
1186 Opc = WebAssembly::RETURN_I64;
1187 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001188 case MVT::f32:
1189 Opc = WebAssembly::RETURN_F32;
1190 break;
1191 case MVT::f64:
1192 Opc = WebAssembly::RETURN_F64;
1193 break;
1194 case MVT::v16i8:
1195 Opc = WebAssembly::RETURN_v16i8;
1196 break;
1197 case MVT::v8i16:
1198 Opc = WebAssembly::RETURN_v8i16;
1199 break;
1200 case MVT::v4i32:
1201 Opc = WebAssembly::RETURN_v4i32;
1202 break;
1203 case MVT::v4f32:
1204 Opc = WebAssembly::RETURN_v4f32;
1205 break;
Dan Gohman2e644382016-05-10 17:39:48 +00001206 default: return false;
1207 }
1208
Dan Gohman33e694a2016-05-12 04:19:09 +00001209 unsigned Reg;
1210 if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
1211 Reg = getRegForSignedValue(RV);
1212 else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
1213 Reg = getRegForUnsignedValue(RV);
1214 else
1215 Reg = getRegForValue(RV);
1216
Dan Gohman2e644382016-05-10 17:39:48 +00001217 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg);
1218 return true;
1219}
1220
1221bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
1222 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1223 TII.get(WebAssembly::UNREACHABLE));
1224 return true;
1225}
1226
1227bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
1228 switch (I->getOpcode()) {
Dan Gohman33e694a2016-05-12 04:19:09 +00001229 case Instruction::Call:
1230 if (selectCall(I))
1231 return true;
1232 break;
1233 case Instruction::Select: return selectSelect(I);
1234 case Instruction::Trunc: return selectTrunc(I);
Dan Gohman3a5ce732016-05-11 16:32:42 +00001235 case Instruction::ZExt: return selectZExt(I);
1236 case Instruction::SExt: return selectSExt(I);
1237 case Instruction::ICmp: return selectICmp(I);
1238 case Instruction::FCmp: return selectFCmp(I);
Dan Gohman2e644382016-05-10 17:39:48 +00001239 case Instruction::BitCast: return selectBitCast(I);
1240 case Instruction::Load: return selectLoad(I);
1241 case Instruction::Store: return selectStore(I);
1242 case Instruction::Br: return selectBr(I);
1243 case Instruction::Ret: return selectRet(I);
1244 case Instruction::Unreachable: return selectUnreachable(I);
1245 default: break;
Dan Gohman7b634842015-08-24 18:44:37 +00001246 }
1247
1248 // Fall back to target-independent instruction selection.
1249 return selectOperator(I, I->getOpcode());
1250}
1251
1252FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,
1253 const TargetLibraryInfo *LibInfo) {
1254 return new WebAssemblyFastISel(FuncInfo, LibInfo);
1255}