blob: 39c682dc7ca7dab83540e819fd05d6894f4ac39c [file] [log] [blame]
Dan Gohman7b634842015-08-24 18:44:37 +00001//===-- WebAssemblyFastISel.cpp - WebAssembly FastISel implementation -----===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Dan Gohman7b634842015-08-24 18:44:37 +00006//
7//===----------------------------------------------------------------------===//
8///
9/// \file
Adrian Prantl5f8f34e42018-05-01 15:54:18 +000010/// This file defines the WebAssembly-specific support for the FastISel
Dan Gohman7b634842015-08-24 18:44:37 +000011/// class. Some of the target-specific code is generated by tablegen in the file
12/// WebAssemblyGenFastISel.inc, which is #included here.
13///
Dan Gohman33e694a2016-05-12 04:19:09 +000014/// TODO: kill flags
15///
Dan Gohman7b634842015-08-24 18:44:37 +000016//===----------------------------------------------------------------------===//
17
Dan Gohman7b634842015-08-24 18:44:37 +000018#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "WebAssembly.h"
Dan Gohman33e694a2016-05-12 04:19:09 +000020#include "WebAssemblyMachineFunctionInfo.h"
Dan Gohman7b634842015-08-24 18:44:37 +000021#include "WebAssemblySubtarget.h"
22#include "WebAssemblyTargetMachine.h"
23#include "llvm/Analysis/BranchProbabilityInfo.h"
24#include "llvm/CodeGen/FastISel.h"
25#include "llvm/CodeGen/FunctionLoweringInfo.h"
26#include "llvm/CodeGen/MachineConstantPool.h"
27#include "llvm/CodeGen/MachineFrameInfo.h"
28#include "llvm/CodeGen/MachineInstrBuilder.h"
29#include "llvm/CodeGen/MachineRegisterInfo.h"
30#include "llvm/IR/DataLayout.h"
31#include "llvm/IR/DerivedTypes.h"
32#include "llvm/IR/Function.h"
33#include "llvm/IR/GetElementPtrTypeIterator.h"
34#include "llvm/IR/GlobalAlias.h"
35#include "llvm/IR/GlobalVariable.h"
36#include "llvm/IR/Instructions.h"
37#include "llvm/IR/IntrinsicInst.h"
38#include "llvm/IR/Operator.h"
Sanjay Patel47a52a02018-10-23 16:05:09 +000039#include "llvm/IR/PatternMatch.h"
40
Dan Gohman7b634842015-08-24 18:44:37 +000041using namespace llvm;
Sanjay Patel47a52a02018-10-23 16:05:09 +000042using namespace PatternMatch;
Dan Gohman7b634842015-08-24 18:44:37 +000043
44#define DEBUG_TYPE "wasm-fastisel"
45
46namespace {
47
48class WebAssemblyFastISel final : public FastISel {
Dan Gohman2e644382016-05-10 17:39:48 +000049 // All possible address modes.
50 class Address {
51 public:
Heejin Ahn18c56a02019-02-04 19:13:39 +000052 using BaseKind = enum { RegBase, FrameIndexBase };
Dan Gohman2e644382016-05-10 17:39:48 +000053
54 private:
Heejin Ahn18c56a02019-02-04 19:13:39 +000055 BaseKind Kind = RegBase;
Dan Gohman2e644382016-05-10 17:39:48 +000056 union {
57 unsigned Reg;
58 int FI;
59 } Base;
60
Heejin Ahn18c56a02019-02-04 19:13:39 +000061 int64_t Offset = 0;
Dan Gohman2e644382016-05-10 17:39:48 +000062
Heejin Ahn18c56a02019-02-04 19:13:39 +000063 const GlobalValue *GV = nullptr;
Dan Gohman2e644382016-05-10 17:39:48 +000064
65 public:
66 // Innocuous defaults for our address.
Heejin Ahn18c56a02019-02-04 19:13:39 +000067 Address() { Base.Reg = 0; }
Jacob Gravellea31ec612017-06-22 21:26:08 +000068 void setKind(BaseKind K) {
69 assert(!isSet() && "Can't change kind with non-zero base");
70 Kind = K;
71 }
Dan Gohman2e644382016-05-10 17:39:48 +000072 BaseKind getKind() const { return Kind; }
73 bool isRegBase() const { return Kind == RegBase; }
74 bool isFIBase() const { return Kind == FrameIndexBase; }
75 void setReg(unsigned Reg) {
76 assert(isRegBase() && "Invalid base register access!");
Jacob Gravellea31ec612017-06-22 21:26:08 +000077 assert(Base.Reg == 0 && "Overwriting non-zero register");
Dan Gohman2e644382016-05-10 17:39:48 +000078 Base.Reg = Reg;
79 }
80 unsigned getReg() const {
81 assert(isRegBase() && "Invalid base register access!");
82 return Base.Reg;
83 }
84 void setFI(unsigned FI) {
85 assert(isFIBase() && "Invalid base frame index access!");
Jacob Gravellea31ec612017-06-22 21:26:08 +000086 assert(Base.FI == 0 && "Overwriting non-zero frame index");
Dan Gohman2e644382016-05-10 17:39:48 +000087 Base.FI = FI;
88 }
89 unsigned getFI() const {
90 assert(isFIBase() && "Invalid base frame index access!");
91 return Base.FI;
92 }
93
Heejin Ahn18c56a02019-02-04 19:13:39 +000094 void setOffset(int64_t NewOffset) {
95 assert(NewOffset >= 0 && "Offsets must be non-negative");
96 Offset = NewOffset;
Dan Gohman728926a2016-12-22 15:15:10 +000097 }
Dan Gohman2e644382016-05-10 17:39:48 +000098 int64_t getOffset() const { return Offset; }
99 void setGlobalValue(const GlobalValue *G) { GV = G; }
100 const GlobalValue *getGlobalValue() const { return GV; }
Jacob Gravellea31ec612017-06-22 21:26:08 +0000101 bool isSet() const {
102 if (isRegBase()) {
103 return Base.Reg != 0;
104 } else {
105 return Base.FI != 0;
106 }
107 }
Dan Gohman2e644382016-05-10 17:39:48 +0000108 };
109
Dan Gohman7b634842015-08-24 18:44:37 +0000110 /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
111 /// right decision when generating code for different targets.
112 const WebAssemblySubtarget *Subtarget;
113 LLVMContext *Context;
114
Dan Gohman7b634842015-08-24 18:44:37 +0000115private:
Dan Gohman2e644382016-05-10 17:39:48 +0000116 // Utility helper routines
Dan Gohman3a5ce732016-05-11 16:32:42 +0000117 MVT::SimpleValueType getSimpleType(Type *Ty) {
118 EVT VT = TLI.getValueType(DL, Ty, /*HandleUnknown=*/true);
Heejin Ahnf208f632018-09-05 01:27:38 +0000119 return VT.isSimple() ? VT.getSimpleVT().SimpleTy
120 : MVT::INVALID_SIMPLE_VALUE_TYPE;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000121 }
122 MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
123 switch (VT) {
124 case MVT::i1:
125 case MVT::i8:
126 case MVT::i16:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000127 return MVT::i32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000128 case MVT::i32:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000129 case MVT::i64:
Dan Gohman33e694a2016-05-12 04:19:09 +0000130 case MVT::f32:
131 case MVT::f64:
Heejin Ahn0de58722018-03-08 04:05:37 +0000132 case MVT::ExceptRef:
Dan Gohman33e694a2016-05-12 04:19:09 +0000133 return VT;
Dan Gohman6999c4f2017-02-24 21:05:35 +0000134 case MVT::f16:
135 return MVT::f32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000136 case MVT::v16i8:
137 case MVT::v8i16:
138 case MVT::v4i32:
139 case MVT::v4f32:
140 if (Subtarget->hasSIMD128())
141 return VT;
142 break;
Thomas Livelyb6dac892018-12-21 06:58:15 +0000143 case MVT::v2i64:
144 case MVT::v2f64:
Thomas Lively64a39a12019-01-10 22:32:11 +0000145 if (Subtarget->hasUnimplementedSIMD128())
Thomas Livelyb6dac892018-12-21 06:58:15 +0000146 return VT;
147 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000148 default:
149 break;
150 }
151 return MVT::INVALID_SIMPLE_VALUE_TYPE;
152 }
Dan Gohman2e644382016-05-10 17:39:48 +0000153 bool computeAddress(const Value *Obj, Address &Addr);
Sam Clegg9da81422019-04-23 03:43:26 +0000154 void materializeLoadStoreOperands(Address &Addr);
Dan Gohman2e644382016-05-10 17:39:48 +0000155 void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
156 MachineMemOperand *MMO);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000157 unsigned maskI1Value(unsigned Reg, const Value *V);
Dan Gohman33e694a2016-05-12 04:19:09 +0000158 unsigned getRegForI1Value(const Value *V, bool &Not);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000159 unsigned zeroExtendToI32(unsigned Reg, const Value *V,
160 MVT::SimpleValueType From);
161 unsigned signExtendToI32(unsigned Reg, const Value *V,
162 MVT::SimpleValueType From);
Heejin Ahnf208f632018-09-05 01:27:38 +0000163 unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
Dan Gohman3a5ce732016-05-11 16:32:42 +0000164 MVT::SimpleValueType To);
Heejin Ahnf208f632018-09-05 01:27:38 +0000165 unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
Dan Gohman3a5ce732016-05-11 16:32:42 +0000166 MVT::SimpleValueType To);
167 unsigned getRegForUnsignedValue(const Value *V);
168 unsigned getRegForSignedValue(const Value *V);
169 unsigned getRegForPromotedValue(const Value *V, bool IsSigned);
170 unsigned notValue(unsigned Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000171 unsigned copyValue(unsigned Reg);
Dan Gohman2e644382016-05-10 17:39:48 +0000172
173 // Backend specific FastISel code.
174 unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
175 unsigned fastMaterializeConstant(const Constant *C) override;
Dan Gohman33e694a2016-05-12 04:19:09 +0000176 bool fastLowerArguments() override;
Dan Gohman2e644382016-05-10 17:39:48 +0000177
178 // Selection routines.
Dan Gohman33e694a2016-05-12 04:19:09 +0000179 bool selectCall(const Instruction *I);
180 bool selectSelect(const Instruction *I);
181 bool selectTrunc(const Instruction *I);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000182 bool selectZExt(const Instruction *I);
183 bool selectSExt(const Instruction *I);
184 bool selectICmp(const Instruction *I);
185 bool selectFCmp(const Instruction *I);
Dan Gohman2e644382016-05-10 17:39:48 +0000186 bool selectBitCast(const Instruction *I);
187 bool selectLoad(const Instruction *I);
188 bool selectStore(const Instruction *I);
189 bool selectBr(const Instruction *I);
190 bool selectRet(const Instruction *I);
191 bool selectUnreachable(const Instruction *I);
192
Dan Gohman7b634842015-08-24 18:44:37 +0000193public:
194 // Backend specific FastISel code.
195 WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo,
196 const TargetLibraryInfo *LibInfo)
197 : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
198 Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>();
199 Context = &FuncInfo.Fn->getContext();
200 }
201
202 bool fastSelectInstruction(const Instruction *I) override;
203
204#include "WebAssemblyGenFastISel.inc"
205};
206
207} // end anonymous namespace
208
Dan Gohman2e644382016-05-10 17:39:48 +0000209bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {
Dan Gohman2e644382016-05-10 17:39:48 +0000210 const User *U = nullptr;
211 unsigned Opcode = Instruction::UserOp1;
Heejin Ahn18c56a02019-02-04 19:13:39 +0000212 if (const auto *I = dyn_cast<Instruction>(Obj)) {
Dan Gohman2e644382016-05-10 17:39:48 +0000213 // Don't walk into other basic blocks unless the object is an alloca from
214 // another block, otherwise it may not have a virtual register assigned.
215 if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
216 FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
217 Opcode = I->getOpcode();
218 U = I;
219 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000220 } else if (const auto *C = dyn_cast<ConstantExpr>(Obj)) {
Dan Gohman2e644382016-05-10 17:39:48 +0000221 Opcode = C->getOpcode();
222 U = C;
223 }
224
225 if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
226 if (Ty->getAddressSpace() > 255)
227 // Fast instruction selection doesn't support the special
228 // address spaces.
229 return false;
230
Heejin Ahn18c56a02019-02-04 19:13:39 +0000231 if (const auto *GV = dyn_cast<GlobalValue>(Obj)) {
Sam Clegg9da81422019-04-23 03:43:26 +0000232 if (TLI.isPositionIndependent())
233 return false;
Dan Gohman2e644382016-05-10 17:39:48 +0000234 if (Addr.getGlobalValue())
235 return false;
236 Addr.setGlobalValue(GV);
237 return true;
238 }
239
240 switch (Opcode) {
Dan Gohman7b634842015-08-24 18:44:37 +0000241 default:
242 break;
Dan Gohman2e644382016-05-10 17:39:48 +0000243 case Instruction::BitCast: {
244 // Look through bitcasts.
245 return computeAddress(U->getOperand(0), Addr);
246 }
247 case Instruction::IntToPtr: {
248 // Look past no-op inttoptrs.
249 if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
250 TLI.getPointerTy(DL))
251 return computeAddress(U->getOperand(0), Addr);
252 break;
253 }
254 case Instruction::PtrToInt: {
255 // Look past no-op ptrtoints.
256 if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
257 return computeAddress(U->getOperand(0), Addr);
258 break;
259 }
260 case Instruction::GetElementPtr: {
261 Address SavedAddr = Addr;
262 uint64_t TmpOffset = Addr.getOffset();
Dan Gohman728926a2016-12-22 15:15:10 +0000263 // Non-inbounds geps can wrap; wasm's offsets can't.
264 if (!cast<GEPOperator>(U)->isInBounds())
265 goto unsupported_gep;
Dan Gohman2e644382016-05-10 17:39:48 +0000266 // Iterate through the GEP folding the constants into offsets where
267 // we can.
Dan Gohman33e694a2016-05-12 04:19:09 +0000268 for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
Dan Gohman2e644382016-05-10 17:39:48 +0000269 GTI != E; ++GTI) {
270 const Value *Op = GTI.getOperand();
Peter Collingbourneab85225b2016-12-02 02:24:42 +0000271 if (StructType *STy = GTI.getStructTypeOrNull()) {
Dan Gohman2e644382016-05-10 17:39:48 +0000272 const StructLayout *SL = DL.getStructLayout(STy);
273 unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
274 TmpOffset += SL->getElementOffset(Idx);
275 } else {
276 uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
277 for (;;) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000278 if (const auto *CI = dyn_cast<ConstantInt>(Op)) {
Dan Gohman2e644382016-05-10 17:39:48 +0000279 // Constant-offset addressing.
280 TmpOffset += CI->getSExtValue() * S;
281 break;
282 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000283 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
284 // An unscaled add of a register. Set it as the new base.
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000285 unsigned Reg = getRegForValue(Op);
286 if (Reg == 0)
287 return false;
288 Addr.setReg(Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000289 break;
290 }
Dan Gohman2e644382016-05-10 17:39:48 +0000291 if (canFoldAddIntoGEP(U, Op)) {
292 // A compatible add with a constant operand. Fold the constant.
Heejin Ahn18c56a02019-02-04 19:13:39 +0000293 auto *CI = cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
Dan Gohman2e644382016-05-10 17:39:48 +0000294 TmpOffset += CI->getSExtValue() * S;
295 // Iterate on the other operand.
296 Op = cast<AddOperator>(Op)->getOperand(0);
297 continue;
298 }
299 // Unsupported
300 goto unsupported_gep;
301 }
302 }
303 }
Dan Gohman728926a2016-12-22 15:15:10 +0000304 // Don't fold in negative offsets.
305 if (int64_t(TmpOffset) >= 0) {
306 // Try to grab the base operand now.
307 Addr.setOffset(TmpOffset);
308 if (computeAddress(U->getOperand(0), Addr))
309 return true;
310 }
Dan Gohman2e644382016-05-10 17:39:48 +0000311 // We failed, restore everything and try the other options.
312 Addr = SavedAddr;
313 unsupported_gep:
314 break;
315 }
316 case Instruction::Alloca: {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000317 const auto *AI = cast<AllocaInst>(Obj);
Dan Gohman2e644382016-05-10 17:39:48 +0000318 DenseMap<const AllocaInst *, int>::iterator SI =
319 FuncInfo.StaticAllocaMap.find(AI);
320 if (SI != FuncInfo.StaticAllocaMap.end()) {
Jacob Gravellea31ec612017-06-22 21:26:08 +0000321 if (Addr.isSet()) {
322 return false;
323 }
Dan Gohman2e644382016-05-10 17:39:48 +0000324 Addr.setKind(Address::FrameIndexBase);
325 Addr.setFI(SI->second);
326 return true;
327 }
328 break;
329 }
330 case Instruction::Add: {
331 // Adds of constants are common and easy enough.
332 const Value *LHS = U->getOperand(0);
333 const Value *RHS = U->getOperand(1);
334
335 if (isa<ConstantInt>(LHS))
336 std::swap(LHS, RHS);
337
Heejin Ahn18c56a02019-02-04 19:13:39 +0000338 if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
Dan Gohman728926a2016-12-22 15:15:10 +0000339 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
340 if (int64_t(TmpOffset) >= 0) {
341 Addr.setOffset(TmpOffset);
342 return computeAddress(LHS, Addr);
343 }
Dan Gohman2e644382016-05-10 17:39:48 +0000344 }
345
346 Address Backup = Addr;
347 if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
348 return true;
349 Addr = Backup;
350
351 break;
352 }
353 case Instruction::Sub: {
354 // Subs of constants are common and easy enough.
355 const Value *LHS = U->getOperand(0);
356 const Value *RHS = U->getOperand(1);
357
Heejin Ahn18c56a02019-02-04 19:13:39 +0000358 if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
Dan Gohman728926a2016-12-22 15:15:10 +0000359 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
360 if (TmpOffset >= 0) {
361 Addr.setOffset(TmpOffset);
362 return computeAddress(LHS, Addr);
363 }
Dan Gohman2e644382016-05-10 17:39:48 +0000364 }
365 break;
366 }
367 }
Jacob Gravellea31ec612017-06-22 21:26:08 +0000368 if (Addr.isSet()) {
369 return false;
370 }
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000371 unsigned Reg = getRegForValue(Obj);
372 if (Reg == 0)
373 return false;
374 Addr.setReg(Reg);
Dan Gohman2e644382016-05-10 17:39:48 +0000375 return Addr.getReg() != 0;
376}
377
Sam Clegg9da81422019-04-23 03:43:26 +0000378void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
Dan Gohman2e644382016-05-10 17:39:48 +0000379 if (Addr.isRegBase()) {
380 unsigned Reg = Addr.getReg();
381 if (Reg == 0) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000382 Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
383 : &WebAssembly::I32RegClass);
384 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
385 : WebAssembly::CONST_I32;
Dan Gohman2e644382016-05-10 17:39:48 +0000386 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000387 .addImm(0);
Dan Gohman2e644382016-05-10 17:39:48 +0000388 Addr.setReg(Reg);
389 }
390 }
391}
392
393void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
394 const MachineInstrBuilder &MIB,
395 MachineMemOperand *MMO) {
Dan Gohman48abaa92016-10-25 00:17:11 +0000396 // Set the alignment operand (this is rewritten in SetP2AlignOperands).
397 // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
398 MIB.addImm(0);
399
Dan Gohman2e644382016-05-10 17:39:48 +0000400 if (const GlobalValue *GV = Addr.getGlobalValue())
401 MIB.addGlobalAddress(GV, Addr.getOffset());
402 else
403 MIB.addImm(Addr.getOffset());
404
405 if (Addr.isRegBase())
406 MIB.addReg(Addr.getReg());
407 else
408 MIB.addFrameIndex(Addr.getFI());
409
Dan Gohman2e644382016-05-10 17:39:48 +0000410 MIB.addMemOperand(MMO);
411}
412
Dan Gohman3a5ce732016-05-11 16:32:42 +0000413unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
414 return zeroExtendToI32(Reg, V, MVT::i1);
Dan Gohman2e644382016-05-10 17:39:48 +0000415}
416
Dan Gohman33e694a2016-05-12 04:19:09 +0000417unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000418 if (const auto *ICmp = dyn_cast<ICmpInst>(V))
Dan Gohman33e694a2016-05-12 04:19:09 +0000419 if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
420 if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
421 Not = ICmp->isTrueWhenEqual();
422 return getRegForValue(ICmp->getOperand(0));
423 }
424
Sanjay Patel47a52a02018-10-23 16:05:09 +0000425 Value *NotV;
426 if (match(V, m_Not(m_Value(NotV))) && V->getType()->isIntegerTy(32)) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000427 Not = true;
Sanjay Patel47a52a02018-10-23 16:05:09 +0000428 return getRegForValue(NotV);
Dan Gohman33e694a2016-05-12 04:19:09 +0000429 }
430
431 Not = false;
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000432 unsigned Reg = getRegForValue(V);
433 if (Reg == 0)
434 return 0;
435 return maskI1Value(Reg, V);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000436}
437
438unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
439 MVT::SimpleValueType From) {
Derek Schuff732636d2016-08-04 18:01:52 +0000440 if (Reg == 0)
441 return 0;
442
Dan Gohman3a5ce732016-05-11 16:32:42 +0000443 switch (From) {
444 case MVT::i1:
Thomas Lively2a47e032019-01-14 22:03:43 +0000445 // If the value is naturally an i1, we don't need to mask it. We only know
446 // if a value is naturally an i1 if it is definitely lowered by FastISel,
447 // not a DAG ISel fallback.
448 if (V != nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr())
449 return copyValue(Reg);
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000450 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000451 case MVT::i8:
452 case MVT::i16:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000453 break;
454 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000455 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000456 default:
457 return 0;
458 }
459
460 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
461 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
462 TII.get(WebAssembly::CONST_I32), Imm)
Heejin Ahnf208f632018-09-05 01:27:38 +0000463 .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
Dan Gohman3a5ce732016-05-11 16:32:42 +0000464
465 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
466 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
467 TII.get(WebAssembly::AND_I32), Result)
Heejin Ahnf208f632018-09-05 01:27:38 +0000468 .addReg(Reg)
469 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000470
471 return Result;
472}
473
474unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
475 MVT::SimpleValueType From) {
Derek Schuff732636d2016-08-04 18:01:52 +0000476 if (Reg == 0)
477 return 0;
478
Dan Gohman3a5ce732016-05-11 16:32:42 +0000479 switch (From) {
480 case MVT::i1:
481 case MVT::i8:
482 case MVT::i16:
483 break;
484 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000485 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000486 default:
Dan Gohman33e694a2016-05-12 04:19:09 +0000487 return 0;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000488 }
489
490 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
491 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
492 TII.get(WebAssembly::CONST_I32), Imm)
Heejin Ahnf208f632018-09-05 01:27:38 +0000493 .addImm(32 - MVT(From).getSizeInBits());
Dan Gohman3a5ce732016-05-11 16:32:42 +0000494
495 unsigned Left = createResultReg(&WebAssembly::I32RegClass);
496 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
497 TII.get(WebAssembly::SHL_I32), Left)
Heejin Ahnf208f632018-09-05 01:27:38 +0000498 .addReg(Reg)
499 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000500
501 unsigned Right = createResultReg(&WebAssembly::I32RegClass);
502 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
503 TII.get(WebAssembly::SHR_S_I32), Right)
Heejin Ahnf208f632018-09-05 01:27:38 +0000504 .addReg(Left)
505 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000506
507 return Right;
508}
509
510unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
511 MVT::SimpleValueType From,
512 MVT::SimpleValueType To) {
513 if (To == MVT::i64) {
514 if (From == MVT::i64)
Dan Gohman33e694a2016-05-12 04:19:09 +0000515 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000516
517 Reg = zeroExtendToI32(Reg, V, From);
518
519 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
520 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
521 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
522 .addReg(Reg);
523 return Result;
524 }
525
Nikita Popov323dc632019-05-13 19:40:18 +0000526 if (To == MVT::i32)
527 return zeroExtendToI32(Reg, V, From);
528
529 return 0;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000530}
531
532unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
533 MVT::SimpleValueType From,
534 MVT::SimpleValueType To) {
535 if (To == MVT::i64) {
536 if (From == MVT::i64)
Dan Gohman33e694a2016-05-12 04:19:09 +0000537 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000538
539 Reg = signExtendToI32(Reg, V, From);
540
541 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
542 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
543 TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
544 .addReg(Reg);
545 return Result;
546 }
547
Nikita Popov323dc632019-05-13 19:40:18 +0000548 if (To == MVT::i32)
549 return signExtendToI32(Reg, V, From);
550
551 return 0;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000552}
553
554unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
555 MVT::SimpleValueType From = getSimpleType(V->getType());
556 MVT::SimpleValueType To = getLegalType(From);
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000557 unsigned VReg = getRegForValue(V);
558 if (VReg == 0)
559 return 0;
560 return zeroExtend(VReg, V, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000561}
562
563unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
564 MVT::SimpleValueType From = getSimpleType(V->getType());
565 MVT::SimpleValueType To = getLegalType(From);
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000566 unsigned VReg = getRegForValue(V);
567 if (VReg == 0)
568 return 0;
569 return signExtend(VReg, V, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000570}
571
572unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
573 bool IsSigned) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000574 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000575}
576
577unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000578 assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
579
Dan Gohman3a5ce732016-05-11 16:32:42 +0000580 unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
581 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
582 TII.get(WebAssembly::EQZ_I32), NotReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000583 .addReg(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000584 return NotReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000585}
586
Dan Gohman33e694a2016-05-12 04:19:09 +0000587unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
588 unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
Heejin Ahnf208f632018-09-05 01:27:38 +0000589 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
590 ResultReg)
591 .addReg(Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000592 return ResultReg;
593}
594
Dan Gohman2e644382016-05-10 17:39:48 +0000595unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
596 DenseMap<const AllocaInst *, int>::iterator SI =
597 FuncInfo.StaticAllocaMap.find(AI);
598
599 if (SI != FuncInfo.StaticAllocaMap.end()) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000600 unsigned ResultReg =
601 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
602 : &WebAssembly::I32RegClass);
603 unsigned Opc =
604 Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
Dan Gohman2e644382016-05-10 17:39:48 +0000605 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
606 .addFrameIndex(SI->second);
607 return ResultReg;
608 }
609
610 return 0;
611}
612
613unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
Sam Clegg492f7522019-03-26 19:46:15 +0000614 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
615 if (TLI.isPositionIndependent())
616 return 0;
Heejin Ahnf208f632018-09-05 01:27:38 +0000617 unsigned ResultReg =
618 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
619 : &WebAssembly::I32RegClass);
620 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
621 : WebAssembly::CONST_I32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000622 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000623 .addGlobalAddress(GV);
Dan Gohman33e694a2016-05-12 04:19:09 +0000624 return ResultReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000625 }
626
627 // Let target-independent code handle it.
628 return 0;
629}
630
Dan Gohman33e694a2016-05-12 04:19:09 +0000631bool WebAssemblyFastISel::fastLowerArguments() {
632 if (!FuncInfo.CanLowerReturn)
633 return false;
634
635 const Function *F = FuncInfo.Fn;
636 if (F->isVarArg())
637 return false;
638
Heejin Ahn18c56a02019-02-04 19:13:39 +0000639 unsigned I = 0;
Dan Gohman33e694a2016-05-12 04:19:09 +0000640 for (auto const &Arg : F->args()) {
Reid Klecknerb5180542017-03-21 16:57:19 +0000641 const AttributeList &Attrs = F->getAttributes();
Heejin Ahn18c56a02019-02-04 19:13:39 +0000642 if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
643 Attrs.hasParamAttribute(I, Attribute::SwiftSelf) ||
644 Attrs.hasParamAttribute(I, Attribute::SwiftError) ||
645 Attrs.hasParamAttribute(I, Attribute::InAlloca) ||
646 Attrs.hasParamAttribute(I, Attribute::Nest))
Dan Gohman33e694a2016-05-12 04:19:09 +0000647 return false;
648
649 Type *ArgTy = Arg.getType();
Derek Schuff39bf39f2016-08-02 23:16:09 +0000650 if (ArgTy->isStructTy() || ArgTy->isArrayTy())
651 return false;
652 if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
Dan Gohman33e694a2016-05-12 04:19:09 +0000653 return false;
654
655 unsigned Opc;
656 const TargetRegisterClass *RC;
657 switch (getSimpleType(ArgTy)) {
658 case MVT::i1:
659 case MVT::i8:
660 case MVT::i16:
661 case MVT::i32:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000662 Opc = WebAssembly::ARGUMENT_i32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000663 RC = &WebAssembly::I32RegClass;
664 break;
665 case MVT::i64:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000666 Opc = WebAssembly::ARGUMENT_i64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000667 RC = &WebAssembly::I64RegClass;
668 break;
669 case MVT::f32:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000670 Opc = WebAssembly::ARGUMENT_f32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000671 RC = &WebAssembly::F32RegClass;
672 break;
673 case MVT::f64:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000674 Opc = WebAssembly::ARGUMENT_f64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000675 RC = &WebAssembly::F64RegClass;
676 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000677 case MVT::v16i8:
678 Opc = WebAssembly::ARGUMENT_v16i8;
679 RC = &WebAssembly::V128RegClass;
680 break;
681 case MVT::v8i16:
682 Opc = WebAssembly::ARGUMENT_v8i16;
683 RC = &WebAssembly::V128RegClass;
684 break;
685 case MVT::v4i32:
686 Opc = WebAssembly::ARGUMENT_v4i32;
687 RC = &WebAssembly::V128RegClass;
688 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000689 case MVT::v2i64:
690 Opc = WebAssembly::ARGUMENT_v2i64;
691 RC = &WebAssembly::V128RegClass;
692 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000693 case MVT::v4f32:
694 Opc = WebAssembly::ARGUMENT_v4f32;
695 RC = &WebAssembly::V128RegClass;
696 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000697 case MVT::v2f64:
698 Opc = WebAssembly::ARGUMENT_v2f64;
699 RC = &WebAssembly::V128RegClass;
700 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000701 case MVT::ExceptRef:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000702 Opc = WebAssembly::ARGUMENT_ExceptRef;
Heejin Ahn0de58722018-03-08 04:05:37 +0000703 RC = &WebAssembly::EXCEPT_REFRegClass;
704 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000705 default:
706 return false;
707 }
708 unsigned ResultReg = createResultReg(RC);
709 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahn18c56a02019-02-04 19:13:39 +0000710 .addImm(I);
Dan Gohman33e694a2016-05-12 04:19:09 +0000711 updateValueMap(&Arg, ResultReg);
712
Heejin Ahn18c56a02019-02-04 19:13:39 +0000713 ++I;
Dan Gohman33e694a2016-05-12 04:19:09 +0000714 }
715
716 MRI.addLiveIn(WebAssembly::ARGUMENTS);
717
718 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
Dan Gohmanb8184822018-05-22 04:58:36 +0000719 for (auto const &Arg : F->args()) {
720 MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType()));
721 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
722 MFI->clearParamsAndResults();
723 return false;
724 }
725 MFI->addParam(ArgTy);
726 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000727
Dan Gohman4576dc02018-04-17 20:46:42 +0000728 if (!F->getReturnType()->isVoidTy()) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000729 MVT::SimpleValueType RetTy =
730 getLegalType(getSimpleType(F->getReturnType()));
Dan Gohmanb8184822018-05-22 04:58:36 +0000731 if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
732 MFI->clearParamsAndResults();
Dan Gohman4576dc02018-04-17 20:46:42 +0000733 return false;
Dan Gohmanb8184822018-05-22 04:58:36 +0000734 }
735 MFI->addResult(RetTy);
Dan Gohman4576dc02018-04-17 20:46:42 +0000736 }
Dan Gohman6055fba2017-01-09 23:09:38 +0000737
Dan Gohman33e694a2016-05-12 04:19:09 +0000738 return true;
739}
740
741bool WebAssemblyFastISel::selectCall(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000742 const auto *Call = cast<CallInst>(I);
Dan Gohman33e694a2016-05-12 04:19:09 +0000743
744 if (Call->isMustTailCall() || Call->isInlineAsm() ||
745 Call->getFunctionType()->isVarArg())
746 return false;
747
748 Function *Func = Call->getCalledFunction();
749 if (Func && Func->isIntrinsic())
750 return false;
751
Jacob Gravelle690b76e2017-08-24 19:53:44 +0000752 bool IsDirect = Func != nullptr;
753 if (!IsDirect && isa<ConstantExpr>(Call->getCalledValue()))
754 return false;
755
Dan Gohman33e694a2016-05-12 04:19:09 +0000756 FunctionType *FuncTy = Call->getFunctionType();
757 unsigned Opc;
Dan Gohman33e694a2016-05-12 04:19:09 +0000758 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
759 unsigned ResultReg;
760 if (IsVoid) {
Derek Schuff6f697832016-10-21 16:38:07 +0000761 Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
Dan Gohman33e694a2016-05-12 04:19:09 +0000762 } else {
Derek Schuff39bf39f2016-08-02 23:16:09 +0000763 if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
764 return false;
765
Dan Gohman33e694a2016-05-12 04:19:09 +0000766 MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
767 switch (RetTy) {
768 case MVT::i1:
769 case MVT::i8:
770 case MVT::i16:
771 case MVT::i32:
Derek Schuff6f697832016-10-21 16:38:07 +0000772 Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::PCALL_INDIRECT_I32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000773 ResultReg = createResultReg(&WebAssembly::I32RegClass);
774 break;
775 case MVT::i64:
Derek Schuff6f697832016-10-21 16:38:07 +0000776 Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::PCALL_INDIRECT_I64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000777 ResultReg = createResultReg(&WebAssembly::I64RegClass);
778 break;
779 case MVT::f32:
Derek Schuff6f697832016-10-21 16:38:07 +0000780 Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::PCALL_INDIRECT_F32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000781 ResultReg = createResultReg(&WebAssembly::F32RegClass);
782 break;
783 case MVT::f64:
Derek Schuff6f697832016-10-21 16:38:07 +0000784 Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::PCALL_INDIRECT_F64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000785 ResultReg = createResultReg(&WebAssembly::F64RegClass);
786 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000787 case MVT::v16i8:
Heejin Ahnf208f632018-09-05 01:27:38 +0000788 Opc = IsDirect ? WebAssembly::CALL_v16i8
789 : WebAssembly::PCALL_INDIRECT_v16i8;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000790 ResultReg = createResultReg(&WebAssembly::V128RegClass);
791 break;
792 case MVT::v8i16:
Heejin Ahnf208f632018-09-05 01:27:38 +0000793 Opc = IsDirect ? WebAssembly::CALL_v8i16
794 : WebAssembly::PCALL_INDIRECT_v8i16;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000795 ResultReg = createResultReg(&WebAssembly::V128RegClass);
796 break;
797 case MVT::v4i32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000798 Opc = IsDirect ? WebAssembly::CALL_v4i32
799 : WebAssembly::PCALL_INDIRECT_v4i32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000800 ResultReg = createResultReg(&WebAssembly::V128RegClass);
801 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000802 case MVT::v2i64:
Heejin Ahnf208f632018-09-05 01:27:38 +0000803 Opc = IsDirect ? WebAssembly::CALL_v2i64
804 : WebAssembly::PCALL_INDIRECT_v2i64;
Derek Schuff51ed1312018-08-07 21:24:01 +0000805 ResultReg = createResultReg(&WebAssembly::V128RegClass);
806 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000807 case MVT::v4f32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000808 Opc = IsDirect ? WebAssembly::CALL_v4f32
809 : WebAssembly::PCALL_INDIRECT_v4f32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000810 ResultReg = createResultReg(&WebAssembly::V128RegClass);
811 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000812 case MVT::v2f64:
Heejin Ahnf208f632018-09-05 01:27:38 +0000813 Opc = IsDirect ? WebAssembly::CALL_v2f64
814 : WebAssembly::PCALL_INDIRECT_v2f64;
Derek Schuff51ed1312018-08-07 21:24:01 +0000815 ResultReg = createResultReg(&WebAssembly::V128RegClass);
816 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000817 case MVT::ExceptRef:
818 Opc = IsDirect ? WebAssembly::CALL_EXCEPT_REF
819 : WebAssembly::PCALL_INDIRECT_EXCEPT_REF;
820 ResultReg = createResultReg(&WebAssembly::EXCEPT_REFRegClass);
821 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000822 default:
823 return false;
824 }
825 }
826
827 SmallVector<unsigned, 8> Args;
Heejin Ahn18c56a02019-02-04 19:13:39 +0000828 for (unsigned I = 0, E = Call->getNumArgOperands(); I < E; ++I) {
829 Value *V = Call->getArgOperand(I);
Dan Gohman33e694a2016-05-12 04:19:09 +0000830 MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
831 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
832 return false;
833
Reid Klecknerb5180542017-03-21 16:57:19 +0000834 const AttributeList &Attrs = Call->getAttributes();
Heejin Ahn18c56a02019-02-04 19:13:39 +0000835 if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
836 Attrs.hasParamAttribute(I, Attribute::SwiftSelf) ||
837 Attrs.hasParamAttribute(I, Attribute::SwiftError) ||
838 Attrs.hasParamAttribute(I, Attribute::InAlloca) ||
839 Attrs.hasParamAttribute(I, Attribute::Nest))
Dan Gohman33e694a2016-05-12 04:19:09 +0000840 return false;
841
842 unsigned Reg;
843
Heejin Ahn18c56a02019-02-04 19:13:39 +0000844 if (Attrs.hasParamAttribute(I, Attribute::SExt))
Dan Gohman33e694a2016-05-12 04:19:09 +0000845 Reg = getRegForSignedValue(V);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000846 else if (Attrs.hasParamAttribute(I, Attribute::ZExt))
Dan Gohman33e694a2016-05-12 04:19:09 +0000847 Reg = getRegForUnsignedValue(V);
848 else
849 Reg = getRegForValue(V);
850
851 if (Reg == 0)
852 return false;
853
854 Args.push_back(Reg);
855 }
856
Sam Clegga2725272019-04-19 22:43:32 +0000857 unsigned CalleeReg = 0;
858 if (!IsDirect) {
859 CalleeReg = getRegForValue(Call->getCalledValue());
860 if (!CalleeReg)
861 return false;
862 }
863
Dan Gohman33e694a2016-05-12 04:19:09 +0000864 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
865
866 if (!IsVoid)
867 MIB.addReg(ResultReg, RegState::Define);
868
869 if (IsDirect)
870 MIB.addGlobalAddress(Func);
Sam Clegga2725272019-04-19 22:43:32 +0000871 else
872 MIB.addReg(CalleeReg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000873
874 for (unsigned ArgReg : Args)
875 MIB.addReg(ArgReg);
876
877 if (!IsVoid)
878 updateValueMap(Call, ResultReg);
879 return true;
880}
881
882bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000883 const auto *Select = cast<SelectInst>(I);
Dan Gohman33e694a2016-05-12 04:19:09 +0000884
885 bool Not;
Heejin Ahnf208f632018-09-05 01:27:38 +0000886 unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
Dan Gohman33e694a2016-05-12 04:19:09 +0000887 if (CondReg == 0)
888 return false;
889
Heejin Ahnf208f632018-09-05 01:27:38 +0000890 unsigned TrueReg = getRegForValue(Select->getTrueValue());
Dan Gohman33e694a2016-05-12 04:19:09 +0000891 if (TrueReg == 0)
892 return false;
893
894 unsigned FalseReg = getRegForValue(Select->getFalseValue());
895 if (FalseReg == 0)
896 return false;
897
898 if (Not)
899 std::swap(TrueReg, FalseReg);
900
901 unsigned Opc;
902 const TargetRegisterClass *RC;
903 switch (getSimpleType(Select->getType())) {
904 case MVT::i1:
905 case MVT::i8:
906 case MVT::i16:
907 case MVT::i32:
908 Opc = WebAssembly::SELECT_I32;
909 RC = &WebAssembly::I32RegClass;
910 break;
911 case MVT::i64:
912 Opc = WebAssembly::SELECT_I64;
913 RC = &WebAssembly::I64RegClass;
914 break;
915 case MVT::f32:
916 Opc = WebAssembly::SELECT_F32;
917 RC = &WebAssembly::F32RegClass;
918 break;
919 case MVT::f64:
920 Opc = WebAssembly::SELECT_F64;
921 RC = &WebAssembly::F64RegClass;
922 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000923 case MVT::ExceptRef:
924 Opc = WebAssembly::SELECT_EXCEPT_REF;
925 RC = &WebAssembly::EXCEPT_REFRegClass;
926 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000927 default:
928 return false;
929 }
930
931 unsigned ResultReg = createResultReg(RC);
932 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000933 .addReg(TrueReg)
934 .addReg(FalseReg)
935 .addReg(CondReg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000936
937 updateValueMap(Select, ResultReg);
938 return true;
939}
940
941bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000942 const auto *Trunc = cast<TruncInst>(I);
Dan Gohman33e694a2016-05-12 04:19:09 +0000943
944 unsigned Reg = getRegForValue(Trunc->getOperand(0));
945 if (Reg == 0)
946 return false;
947
948 if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
949 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
950 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
951 TII.get(WebAssembly::I32_WRAP_I64), Result)
952 .addReg(Reg);
953 Reg = Result;
954 }
955
956 updateValueMap(Trunc, Reg);
957 return true;
958}
959
Dan Gohman3a5ce732016-05-11 16:32:42 +0000960bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000961 const auto *ZExt = cast<ZExtInst>(I);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000962
Dan Gohman33e694a2016-05-12 04:19:09 +0000963 const Value *Op = ZExt->getOperand(0);
964 MVT::SimpleValueType From = getSimpleType(Op->getType());
965 MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000966 unsigned In = getRegForValue(Op);
967 if (In == 0)
968 return false;
969 unsigned Reg = zeroExtend(In, Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000970 if (Reg == 0)
971 return false;
972
973 updateValueMap(ZExt, Reg);
974 return true;
975}
976
977bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000978 const auto *SExt = cast<SExtInst>(I);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000979
Dan Gohman33e694a2016-05-12 04:19:09 +0000980 const Value *Op = SExt->getOperand(0);
981 MVT::SimpleValueType From = getSimpleType(Op->getType());
982 MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000983 unsigned In = getRegForValue(Op);
984 if (In == 0)
985 return false;
986 unsigned Reg = signExtend(In, Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000987 if (Reg == 0)
988 return false;
989
990 updateValueMap(SExt, Reg);
991 return true;
992}
993
994bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000995 const auto *ICmp = cast<ICmpInst>(I);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000996
997 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
998 unsigned Opc;
Heejin Ahn18c56a02019-02-04 19:13:39 +0000999 bool IsSigned = false;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001000 switch (ICmp->getPredicate()) {
1001 case ICmpInst::ICMP_EQ:
1002 Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
1003 break;
1004 case ICmpInst::ICMP_NE:
1005 Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1006 break;
1007 case ICmpInst::ICMP_UGT:
1008 Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1009 break;
1010 case ICmpInst::ICMP_UGE:
1011 Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1012 break;
1013 case ICmpInst::ICMP_ULT:
1014 Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1015 break;
1016 case ICmpInst::ICMP_ULE:
1017 Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1018 break;
1019 case ICmpInst::ICMP_SGT:
1020 Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
Heejin Ahn18c56a02019-02-04 19:13:39 +00001021 IsSigned = true;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001022 break;
1023 case ICmpInst::ICMP_SGE:
1024 Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
Heejin Ahn18c56a02019-02-04 19:13:39 +00001025 IsSigned = true;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001026 break;
1027 case ICmpInst::ICMP_SLT:
1028 Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
Heejin Ahn18c56a02019-02-04 19:13:39 +00001029 IsSigned = true;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001030 break;
1031 case ICmpInst::ICMP_SLE:
1032 Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
Heejin Ahn18c56a02019-02-04 19:13:39 +00001033 IsSigned = true;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001034 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001035 default:
1036 return false;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001037 }
1038
Heejin Ahn18c56a02019-02-04 19:13:39 +00001039 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
Dan Gohman3a5ce732016-05-11 16:32:42 +00001040 if (LHS == 0)
1041 return false;
1042
Heejin Ahn18c56a02019-02-04 19:13:39 +00001043 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
Dan Gohman3a5ce732016-05-11 16:32:42 +00001044 if (RHS == 0)
1045 return false;
1046
1047 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1048 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1049 .addReg(LHS)
1050 .addReg(RHS);
1051 updateValueMap(ICmp, ResultReg);
1052 return true;
1053}
1054
1055bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +00001056 const auto *FCmp = cast<FCmpInst>(I);
Dan Gohman3a5ce732016-05-11 16:32:42 +00001057
1058 unsigned LHS = getRegForValue(FCmp->getOperand(0));
1059 if (LHS == 0)
1060 return false;
1061
1062 unsigned RHS = getRegForValue(FCmp->getOperand(1));
1063 if (RHS == 0)
1064 return false;
1065
1066 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1067 unsigned Opc;
1068 bool Not = false;
1069 switch (FCmp->getPredicate()) {
1070 case FCmpInst::FCMP_OEQ:
1071 Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1072 break;
1073 case FCmpInst::FCMP_UNE:
1074 Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1075 break;
1076 case FCmpInst::FCMP_OGT:
1077 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1078 break;
1079 case FCmpInst::FCMP_OGE:
1080 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1081 break;
1082 case FCmpInst::FCMP_OLT:
1083 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1084 break;
1085 case FCmpInst::FCMP_OLE:
1086 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1087 break;
1088 case FCmpInst::FCMP_UGT:
1089 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1090 Not = true;
1091 break;
1092 case FCmpInst::FCMP_UGE:
1093 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1094 Not = true;
1095 break;
1096 case FCmpInst::FCMP_ULT:
1097 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1098 Not = true;
1099 break;
1100 case FCmpInst::FCMP_ULE:
1101 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1102 Not = true;
1103 break;
1104 default:
1105 return false;
1106 }
1107
1108 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1109 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1110 .addReg(LHS)
1111 .addReg(RHS);
1112
1113 if (Not)
1114 ResultReg = notValue(ResultReg);
1115
1116 updateValueMap(FCmp, ResultReg);
1117 return true;
1118}
1119
Dan Gohman2e644382016-05-10 17:39:48 +00001120bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
1121 // Target-independent code can handle this, except it doesn't set the dead
1122 // flag on the ARGUMENTS clobber, so we have to do that manually in order
1123 // to satisfy code that expects this of isBitcast() instructions.
1124 EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
1125 EVT RetVT = TLI.getValueType(DL, I->getType());
1126 if (!VT.isSimple() || !RetVT.isSimple())
1127 return false;
Dan Gohman33e694a2016-05-12 04:19:09 +00001128
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001129 unsigned In = getRegForValue(I->getOperand(0));
1130 if (In == 0)
1131 return false;
1132
Dan Gohman33e694a2016-05-12 04:19:09 +00001133 if (VT == RetVT) {
1134 // No-op bitcast.
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001135 updateValueMap(I, In);
Dan Gohman33e694a2016-05-12 04:19:09 +00001136 return true;
1137 }
1138
Dan Gohman2e644382016-05-10 17:39:48 +00001139 unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001140 In, I->getOperand(0)->hasOneUse());
Dan Gohman2e644382016-05-10 17:39:48 +00001141 if (!Reg)
1142 return false;
1143 MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
1144 --Iter;
1145 assert(Iter->isBitcast());
1146 Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI);
1147 updateValueMap(I, Reg);
1148 return true;
1149}
1150
1151bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +00001152 const auto *Load = cast<LoadInst>(I);
Dan Gohman2e644382016-05-10 17:39:48 +00001153 if (Load->isAtomic())
1154 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001155 if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
1156 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001157
1158 Address Addr;
1159 if (!computeAddress(Load->getPointerOperand(), Addr))
1160 return false;
1161
1162 // TODO: Fold a following sign-/zero-extend into the load instruction.
1163
1164 unsigned Opc;
1165 const TargetRegisterClass *RC;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001166 switch (getSimpleType(Load->getType())) {
1167 case MVT::i1:
1168 case MVT::i8:
1169 Opc = WebAssembly::LOAD8_U_I32;
1170 RC = &WebAssembly::I32RegClass;
Dan Gohman2e644382016-05-10 17:39:48 +00001171 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001172 case MVT::i16:
1173 Opc = WebAssembly::LOAD16_U_I32;
1174 RC = &WebAssembly::I32RegClass;
1175 break;
1176 case MVT::i32:
1177 Opc = WebAssembly::LOAD_I32;
1178 RC = &WebAssembly::I32RegClass;
1179 break;
1180 case MVT::i64:
1181 Opc = WebAssembly::LOAD_I64;
1182 RC = &WebAssembly::I64RegClass;
1183 break;
1184 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001185 Opc = WebAssembly::LOAD_F32;
1186 RC = &WebAssembly::F32RegClass;
1187 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001188 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001189 Opc = WebAssembly::LOAD_F64;
1190 RC = &WebAssembly::F64RegClass;
1191 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001192 default:
1193 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001194 }
1195
Sam Clegg9da81422019-04-23 03:43:26 +00001196 materializeLoadStoreOperands(Addr);
Dan Gohman2e644382016-05-10 17:39:48 +00001197
1198 unsigned ResultReg = createResultReg(RC);
1199 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
1200 ResultReg);
1201
1202 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1203
1204 updateValueMap(Load, ResultReg);
1205 return true;
1206}
1207
1208bool WebAssemblyFastISel::selectStore(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +00001209 const auto *Store = cast<StoreInst>(I);
Dan Gohman2e644382016-05-10 17:39:48 +00001210 if (Store->isAtomic())
1211 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001212 if (!Subtarget->hasSIMD128() &&
1213 Store->getValueOperand()->getType()->isVectorTy())
1214 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001215
1216 Address Addr;
1217 if (!computeAddress(Store->getPointerOperand(), Addr))
1218 return false;
1219
1220 unsigned Opc;
Dan Gohman2e644382016-05-10 17:39:48 +00001221 bool VTIsi1 = false;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001222 switch (getSimpleType(Store->getValueOperand()->getType())) {
1223 case MVT::i1:
1224 VTIsi1 = true;
Dan Gohman861bec22018-02-09 22:59:01 +00001225 LLVM_FALLTHROUGH;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001226 case MVT::i8:
1227 Opc = WebAssembly::STORE8_I32;
Dan Gohman2e644382016-05-10 17:39:48 +00001228 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001229 case MVT::i16:
1230 Opc = WebAssembly::STORE16_I32;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001231 break;
1232 case MVT::i32:
1233 Opc = WebAssembly::STORE_I32;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001234 break;
1235 case MVT::i64:
1236 Opc = WebAssembly::STORE_I64;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001237 break;
1238 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001239 Opc = WebAssembly::STORE_F32;
Dan Gohman2e644382016-05-10 17:39:48 +00001240 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001241 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001242 Opc = WebAssembly::STORE_F64;
Dan Gohman2e644382016-05-10 17:39:48 +00001243 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001244 default:
1245 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001246 }
1247
Sam Clegg9da81422019-04-23 03:43:26 +00001248 materializeLoadStoreOperands(Addr);
Dan Gohman2e644382016-05-10 17:39:48 +00001249
1250 unsigned ValueReg = getRegForValue(Store->getValueOperand());
Derek Schuff732636d2016-08-04 18:01:52 +00001251 if (ValueReg == 0)
1252 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001253 if (VTIsi1)
Dan Gohman3a5ce732016-05-11 16:32:42 +00001254 ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
Dan Gohman2e644382016-05-10 17:39:48 +00001255
Dan Gohman7f1bdb22016-10-06 22:08:28 +00001256 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
Dan Gohman2e644382016-05-10 17:39:48 +00001257
1258 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1259
1260 MIB.addReg(ValueReg);
1261 return true;
1262}
1263
1264bool WebAssemblyFastISel::selectBr(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +00001265 const auto *Br = cast<BranchInst>(I);
Dan Gohman2e644382016-05-10 17:39:48 +00001266 if (Br->isUnconditional()) {
1267 MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
1268 fastEmitBranch(MSucc, Br->getDebugLoc());
1269 return true;
1270 }
1271
1272 MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
1273 MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
1274
Dan Gohman33e694a2016-05-12 04:19:09 +00001275 bool Not;
1276 unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
Derek Schuff732636d2016-08-04 18:01:52 +00001277 if (CondReg == 0)
1278 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001279
Dan Gohman33e694a2016-05-12 04:19:09 +00001280 unsigned Opc = WebAssembly::BR_IF;
1281 if (Not)
1282 Opc = WebAssembly::BR_UNLESS;
1283
Dan Gohman2e644382016-05-10 17:39:48 +00001284 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1285 .addMBB(TBB)
1286 .addReg(CondReg);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001287
Dan Gohman2e644382016-05-10 17:39:48 +00001288 finishCondBranch(Br->getParent(), TBB, FBB);
1289 return true;
1290}
1291
1292bool WebAssemblyFastISel::selectRet(const Instruction *I) {
1293 if (!FuncInfo.CanLowerReturn)
1294 return false;
1295
Heejin Ahn18c56a02019-02-04 19:13:39 +00001296 const auto *Ret = cast<ReturnInst>(I);
Dan Gohman2e644382016-05-10 17:39:48 +00001297
1298 if (Ret->getNumOperands() == 0) {
1299 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1300 TII.get(WebAssembly::RETURN_VOID));
1301 return true;
1302 }
1303
1304 Value *RV = Ret->getOperand(0);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001305 if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
1306 return false;
1307
Dan Gohman2e644382016-05-10 17:39:48 +00001308 unsigned Opc;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001309 switch (getSimpleType(RV->getType())) {
Heejin Ahnf208f632018-09-05 01:27:38 +00001310 case MVT::i1:
1311 case MVT::i8:
1312 case MVT::i16:
1313 case MVT::i32:
Dan Gohman3a5ce732016-05-11 16:32:42 +00001314 Opc = WebAssembly::RETURN_I32;
Dan Gohman2e644382016-05-10 17:39:48 +00001315 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001316 case MVT::i64:
1317 Opc = WebAssembly::RETURN_I64;
1318 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001319 case MVT::f32:
1320 Opc = WebAssembly::RETURN_F32;
1321 break;
1322 case MVT::f64:
1323 Opc = WebAssembly::RETURN_F64;
1324 break;
1325 case MVT::v16i8:
1326 Opc = WebAssembly::RETURN_v16i8;
1327 break;
1328 case MVT::v8i16:
1329 Opc = WebAssembly::RETURN_v8i16;
1330 break;
1331 case MVT::v4i32:
1332 Opc = WebAssembly::RETURN_v4i32;
1333 break;
Derek Schuff51ed1312018-08-07 21:24:01 +00001334 case MVT::v2i64:
1335 Opc = WebAssembly::RETURN_v2i64;
1336 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001337 case MVT::v4f32:
1338 Opc = WebAssembly::RETURN_v4f32;
1339 break;
Derek Schuff51ed1312018-08-07 21:24:01 +00001340 case MVT::v2f64:
1341 Opc = WebAssembly::RETURN_v2f64;
1342 break;
Heejin Ahn0de58722018-03-08 04:05:37 +00001343 case MVT::ExceptRef:
1344 Opc = WebAssembly::RETURN_EXCEPT_REF;
1345 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001346 default:
1347 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001348 }
1349
Dan Gohman33e694a2016-05-12 04:19:09 +00001350 unsigned Reg;
1351 if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
1352 Reg = getRegForSignedValue(RV);
1353 else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
1354 Reg = getRegForUnsignedValue(RV);
1355 else
1356 Reg = getRegForValue(RV);
1357
Derek Schuff732636d2016-08-04 18:01:52 +00001358 if (Reg == 0)
1359 return false;
1360
Dan Gohman2e644382016-05-10 17:39:48 +00001361 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg);
1362 return true;
1363}
1364
1365bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
1366 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1367 TII.get(WebAssembly::UNREACHABLE));
1368 return true;
1369}
1370
1371bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
1372 switch (I->getOpcode()) {
Dan Gohman33e694a2016-05-12 04:19:09 +00001373 case Instruction::Call:
1374 if (selectCall(I))
1375 return true;
1376 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001377 case Instruction::Select:
1378 return selectSelect(I);
1379 case Instruction::Trunc:
1380 return selectTrunc(I);
1381 case Instruction::ZExt:
1382 return selectZExt(I);
1383 case Instruction::SExt:
1384 return selectSExt(I);
1385 case Instruction::ICmp:
1386 return selectICmp(I);
1387 case Instruction::FCmp:
1388 return selectFCmp(I);
1389 case Instruction::BitCast:
1390 return selectBitCast(I);
1391 case Instruction::Load:
1392 return selectLoad(I);
1393 case Instruction::Store:
1394 return selectStore(I);
1395 case Instruction::Br:
1396 return selectBr(I);
1397 case Instruction::Ret:
1398 return selectRet(I);
1399 case Instruction::Unreachable:
1400 return selectUnreachable(I);
1401 default:
1402 break;
Dan Gohman7b634842015-08-24 18:44:37 +00001403 }
1404
1405 // Fall back to target-independent instruction selection.
1406 return selectOperator(I, I->getOpcode());
1407}
1408
1409FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,
1410 const TargetLibraryInfo *LibInfo) {
1411 return new WebAssemblyFastISel(FuncInfo, LibInfo);
1412}