blob: 2d9aae7a698c90f4e3976c904d671b6cd45f4a09 [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 Clegg492f7522019-03-26 19:46:15 +0000154 bool 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) {
210
211 const User *U = nullptr;
212 unsigned Opcode = Instruction::UserOp1;
Heejin Ahn18c56a02019-02-04 19:13:39 +0000213 if (const auto *I = dyn_cast<Instruction>(Obj)) {
Dan Gohman2e644382016-05-10 17:39:48 +0000214 // Don't walk into other basic blocks unless the object is an alloca from
215 // another block, otherwise it may not have a virtual register assigned.
216 if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
217 FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
218 Opcode = I->getOpcode();
219 U = I;
220 }
Heejin Ahn18c56a02019-02-04 19:13:39 +0000221 } else if (const auto *C = dyn_cast<ConstantExpr>(Obj)) {
Dan Gohman2e644382016-05-10 17:39:48 +0000222 Opcode = C->getOpcode();
223 U = C;
224 }
225
226 if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
227 if (Ty->getAddressSpace() > 255)
228 // Fast instruction selection doesn't support the special
229 // address spaces.
230 return false;
231
Heejin Ahn18c56a02019-02-04 19:13:39 +0000232 if (const auto *GV = dyn_cast<GlobalValue>(Obj)) {
Dan Gohman2e644382016-05-10 17:39:48 +0000233 if (Addr.getGlobalValue())
234 return false;
235 Addr.setGlobalValue(GV);
236 return true;
237 }
238
239 switch (Opcode) {
Dan Gohman7b634842015-08-24 18:44:37 +0000240 default:
241 break;
Dan Gohman2e644382016-05-10 17:39:48 +0000242 case Instruction::BitCast: {
243 // Look through bitcasts.
244 return computeAddress(U->getOperand(0), Addr);
245 }
246 case Instruction::IntToPtr: {
247 // Look past no-op inttoptrs.
248 if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
249 TLI.getPointerTy(DL))
250 return computeAddress(U->getOperand(0), Addr);
251 break;
252 }
253 case Instruction::PtrToInt: {
254 // Look past no-op ptrtoints.
255 if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
256 return computeAddress(U->getOperand(0), Addr);
257 break;
258 }
259 case Instruction::GetElementPtr: {
260 Address SavedAddr = Addr;
261 uint64_t TmpOffset = Addr.getOffset();
Dan Gohman728926a2016-12-22 15:15:10 +0000262 // Non-inbounds geps can wrap; wasm's offsets can't.
263 if (!cast<GEPOperator>(U)->isInBounds())
264 goto unsupported_gep;
Dan Gohman2e644382016-05-10 17:39:48 +0000265 // Iterate through the GEP folding the constants into offsets where
266 // we can.
Dan Gohman33e694a2016-05-12 04:19:09 +0000267 for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
Dan Gohman2e644382016-05-10 17:39:48 +0000268 GTI != E; ++GTI) {
269 const Value *Op = GTI.getOperand();
Peter Collingbourneab85225b2016-12-02 02:24:42 +0000270 if (StructType *STy = GTI.getStructTypeOrNull()) {
Dan Gohman2e644382016-05-10 17:39:48 +0000271 const StructLayout *SL = DL.getStructLayout(STy);
272 unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
273 TmpOffset += SL->getElementOffset(Idx);
274 } else {
275 uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
276 for (;;) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000277 if (const auto *CI = dyn_cast<ConstantInt>(Op)) {
Dan Gohman2e644382016-05-10 17:39:48 +0000278 // Constant-offset addressing.
279 TmpOffset += CI->getSExtValue() * S;
280 break;
281 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000282 if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
283 // An unscaled add of a register. Set it as the new base.
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000284 unsigned Reg = getRegForValue(Op);
285 if (Reg == 0)
286 return false;
287 Addr.setReg(Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000288 break;
289 }
Dan Gohman2e644382016-05-10 17:39:48 +0000290 if (canFoldAddIntoGEP(U, Op)) {
291 // A compatible add with a constant operand. Fold the constant.
Heejin Ahn18c56a02019-02-04 19:13:39 +0000292 auto *CI = cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
Dan Gohman2e644382016-05-10 17:39:48 +0000293 TmpOffset += CI->getSExtValue() * S;
294 // Iterate on the other operand.
295 Op = cast<AddOperator>(Op)->getOperand(0);
296 continue;
297 }
298 // Unsupported
299 goto unsupported_gep;
300 }
301 }
302 }
Dan Gohman728926a2016-12-22 15:15:10 +0000303 // Don't fold in negative offsets.
304 if (int64_t(TmpOffset) >= 0) {
305 // Try to grab the base operand now.
306 Addr.setOffset(TmpOffset);
307 if (computeAddress(U->getOperand(0), Addr))
308 return true;
309 }
Dan Gohman2e644382016-05-10 17:39:48 +0000310 // We failed, restore everything and try the other options.
311 Addr = SavedAddr;
312 unsupported_gep:
313 break;
314 }
315 case Instruction::Alloca: {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000316 const auto *AI = cast<AllocaInst>(Obj);
Dan Gohman2e644382016-05-10 17:39:48 +0000317 DenseMap<const AllocaInst *, int>::iterator SI =
318 FuncInfo.StaticAllocaMap.find(AI);
319 if (SI != FuncInfo.StaticAllocaMap.end()) {
Jacob Gravellea31ec612017-06-22 21:26:08 +0000320 if (Addr.isSet()) {
321 return false;
322 }
Dan Gohman2e644382016-05-10 17:39:48 +0000323 Addr.setKind(Address::FrameIndexBase);
324 Addr.setFI(SI->second);
325 return true;
326 }
327 break;
328 }
329 case Instruction::Add: {
330 // Adds of constants are common and easy enough.
331 const Value *LHS = U->getOperand(0);
332 const Value *RHS = U->getOperand(1);
333
334 if (isa<ConstantInt>(LHS))
335 std::swap(LHS, RHS);
336
Heejin Ahn18c56a02019-02-04 19:13:39 +0000337 if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
Dan Gohman728926a2016-12-22 15:15:10 +0000338 uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
339 if (int64_t(TmpOffset) >= 0) {
340 Addr.setOffset(TmpOffset);
341 return computeAddress(LHS, Addr);
342 }
Dan Gohman2e644382016-05-10 17:39:48 +0000343 }
344
345 Address Backup = Addr;
346 if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
347 return true;
348 Addr = Backup;
349
350 break;
351 }
352 case Instruction::Sub: {
353 // Subs of constants are common and easy enough.
354 const Value *LHS = U->getOperand(0);
355 const Value *RHS = U->getOperand(1);
356
Heejin Ahn18c56a02019-02-04 19:13:39 +0000357 if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
Dan Gohman728926a2016-12-22 15:15:10 +0000358 int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
359 if (TmpOffset >= 0) {
360 Addr.setOffset(TmpOffset);
361 return computeAddress(LHS, Addr);
362 }
Dan Gohman2e644382016-05-10 17:39:48 +0000363 }
364 break;
365 }
366 }
Jacob Gravellea31ec612017-06-22 21:26:08 +0000367 if (Addr.isSet()) {
368 return false;
369 }
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000370 unsigned Reg = getRegForValue(Obj);
371 if (Reg == 0)
372 return false;
373 Addr.setReg(Reg);
Dan Gohman2e644382016-05-10 17:39:48 +0000374 return Addr.getReg() != 0;
375}
376
Sam Clegg492f7522019-03-26 19:46:15 +0000377bool WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
Dan Gohman2e644382016-05-10 17:39:48 +0000378 if (Addr.isRegBase()) {
379 unsigned Reg = Addr.getReg();
380 if (Reg == 0) {
Sam Clegg492f7522019-03-26 19:46:15 +0000381 const GlobalValue *GV = Addr.getGlobalValue();
382 if (GV && TLI.isPositionIndependent())
383 return false;
Heejin Ahnf208f632018-09-05 01:27:38 +0000384 Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
385 : &WebAssembly::I32RegClass);
386 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
387 : WebAssembly::CONST_I32;
Dan Gohman2e644382016-05-10 17:39:48 +0000388 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000389 .addImm(0);
Dan Gohman2e644382016-05-10 17:39:48 +0000390 Addr.setReg(Reg);
391 }
392 }
Sam Clegg492f7522019-03-26 19:46:15 +0000393 return true;
Dan Gohman2e644382016-05-10 17:39:48 +0000394}
395
396void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
397 const MachineInstrBuilder &MIB,
398 MachineMemOperand *MMO) {
Dan Gohman48abaa92016-10-25 00:17:11 +0000399 // Set the alignment operand (this is rewritten in SetP2AlignOperands).
400 // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
401 MIB.addImm(0);
402
Dan Gohman2e644382016-05-10 17:39:48 +0000403 if (const GlobalValue *GV = Addr.getGlobalValue())
404 MIB.addGlobalAddress(GV, Addr.getOffset());
405 else
406 MIB.addImm(Addr.getOffset());
407
408 if (Addr.isRegBase())
409 MIB.addReg(Addr.getReg());
410 else
411 MIB.addFrameIndex(Addr.getFI());
412
Dan Gohman2e644382016-05-10 17:39:48 +0000413 MIB.addMemOperand(MMO);
414}
415
Dan Gohman3a5ce732016-05-11 16:32:42 +0000416unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
417 return zeroExtendToI32(Reg, V, MVT::i1);
Dan Gohman2e644382016-05-10 17:39:48 +0000418}
419
Dan Gohman33e694a2016-05-12 04:19:09 +0000420unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000421 if (const auto *ICmp = dyn_cast<ICmpInst>(V))
Dan Gohman33e694a2016-05-12 04:19:09 +0000422 if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
423 if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
424 Not = ICmp->isTrueWhenEqual();
425 return getRegForValue(ICmp->getOperand(0));
426 }
427
Sanjay Patel47a52a02018-10-23 16:05:09 +0000428 Value *NotV;
429 if (match(V, m_Not(m_Value(NotV))) && V->getType()->isIntegerTy(32)) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000430 Not = true;
Sanjay Patel47a52a02018-10-23 16:05:09 +0000431 return getRegForValue(NotV);
Dan Gohman33e694a2016-05-12 04:19:09 +0000432 }
433
434 Not = false;
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000435 unsigned Reg = getRegForValue(V);
436 if (Reg == 0)
437 return 0;
438 return maskI1Value(Reg, V);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000439}
440
441unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
442 MVT::SimpleValueType From) {
Derek Schuff732636d2016-08-04 18:01:52 +0000443 if (Reg == 0)
444 return 0;
445
Dan Gohman3a5ce732016-05-11 16:32:42 +0000446 switch (From) {
447 case MVT::i1:
Thomas Lively2a47e032019-01-14 22:03:43 +0000448 // If the value is naturally an i1, we don't need to mask it. We only know
449 // if a value is naturally an i1 if it is definitely lowered by FastISel,
450 // not a DAG ISel fallback.
451 if (V != nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr())
452 return copyValue(Reg);
Reid Kleckner4dc0b1a2018-11-01 19:54:45 +0000453 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000454 case MVT::i8:
455 case MVT::i16:
Dan Gohman3a5ce732016-05-11 16:32:42 +0000456 break;
457 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000458 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000459 default:
460 return 0;
461 }
462
463 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
464 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
465 TII.get(WebAssembly::CONST_I32), Imm)
Heejin Ahnf208f632018-09-05 01:27:38 +0000466 .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
Dan Gohman3a5ce732016-05-11 16:32:42 +0000467
468 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
469 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
470 TII.get(WebAssembly::AND_I32), Result)
Heejin Ahnf208f632018-09-05 01:27:38 +0000471 .addReg(Reg)
472 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000473
474 return Result;
475}
476
477unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
478 MVT::SimpleValueType From) {
Derek Schuff732636d2016-08-04 18:01:52 +0000479 if (Reg == 0)
480 return 0;
481
Dan Gohman3a5ce732016-05-11 16:32:42 +0000482 switch (From) {
483 case MVT::i1:
484 case MVT::i8:
485 case MVT::i16:
486 break;
487 case MVT::i32:
Dan Gohman33e694a2016-05-12 04:19:09 +0000488 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000489 default:
Dan Gohman33e694a2016-05-12 04:19:09 +0000490 return 0;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000491 }
492
493 unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
494 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
495 TII.get(WebAssembly::CONST_I32), Imm)
Heejin Ahnf208f632018-09-05 01:27:38 +0000496 .addImm(32 - MVT(From).getSizeInBits());
Dan Gohman3a5ce732016-05-11 16:32:42 +0000497
498 unsigned Left = createResultReg(&WebAssembly::I32RegClass);
499 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
500 TII.get(WebAssembly::SHL_I32), Left)
Heejin Ahnf208f632018-09-05 01:27:38 +0000501 .addReg(Reg)
502 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000503
504 unsigned Right = createResultReg(&WebAssembly::I32RegClass);
505 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
506 TII.get(WebAssembly::SHR_S_I32), Right)
Heejin Ahnf208f632018-09-05 01:27:38 +0000507 .addReg(Left)
508 .addReg(Imm);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000509
510 return Right;
511}
512
513unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
514 MVT::SimpleValueType From,
515 MVT::SimpleValueType To) {
516 if (To == MVT::i64) {
517 if (From == MVT::i64)
Dan Gohman33e694a2016-05-12 04:19:09 +0000518 return copyValue(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000519
520 Reg = zeroExtendToI32(Reg, V, From);
521
522 unsigned Result = createResultReg(&WebAssembly::I64RegClass);
523 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
524 TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
525 .addReg(Reg);
526 return Result;
527 }
528
Dan Gohman3a5ce732016-05-11 16:32:42 +0000529 return zeroExtendToI32(Reg, V, From);
530}
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
Dan Gohman3a5ce732016-05-11 16:32:42 +0000548 return signExtendToI32(Reg, V, From);
549}
550
551unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
552 MVT::SimpleValueType From = getSimpleType(V->getType());
553 MVT::SimpleValueType To = getLegalType(From);
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000554 unsigned VReg = getRegForValue(V);
555 if (VReg == 0)
556 return 0;
557 return zeroExtend(VReg, V, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000558}
559
560unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
561 MVT::SimpleValueType From = getSimpleType(V->getType());
562 MVT::SimpleValueType To = getLegalType(From);
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000563 unsigned VReg = getRegForValue(V);
564 if (VReg == 0)
565 return 0;
566 return signExtend(VReg, V, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000567}
568
569unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
570 bool IsSigned) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000571 return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000572}
573
574unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
Dan Gohman33e694a2016-05-12 04:19:09 +0000575 assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
576
Dan Gohman3a5ce732016-05-11 16:32:42 +0000577 unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
578 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
579 TII.get(WebAssembly::EQZ_I32), NotReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000580 .addReg(Reg);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000581 return NotReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000582}
583
Dan Gohman33e694a2016-05-12 04:19:09 +0000584unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
585 unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
Heejin Ahnf208f632018-09-05 01:27:38 +0000586 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
587 ResultReg)
588 .addReg(Reg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000589 return ResultReg;
590}
591
Dan Gohman2e644382016-05-10 17:39:48 +0000592unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
593 DenseMap<const AllocaInst *, int>::iterator SI =
594 FuncInfo.StaticAllocaMap.find(AI);
595
596 if (SI != FuncInfo.StaticAllocaMap.end()) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000597 unsigned ResultReg =
598 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
599 : &WebAssembly::I32RegClass);
600 unsigned Opc =
601 Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
Dan Gohman2e644382016-05-10 17:39:48 +0000602 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
603 .addFrameIndex(SI->second);
604 return ResultReg;
605 }
606
607 return 0;
608}
609
610unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
Sam Clegg492f7522019-03-26 19:46:15 +0000611 if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
612 if (TLI.isPositionIndependent())
613 return 0;
Heejin Ahnf208f632018-09-05 01:27:38 +0000614 unsigned ResultReg =
615 createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
616 : &WebAssembly::I32RegClass);
617 unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
618 : WebAssembly::CONST_I32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000619 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000620 .addGlobalAddress(GV);
Dan Gohman33e694a2016-05-12 04:19:09 +0000621 return ResultReg;
Dan Gohman2e644382016-05-10 17:39:48 +0000622 }
623
624 // Let target-independent code handle it.
625 return 0;
626}
627
Dan Gohman33e694a2016-05-12 04:19:09 +0000628bool WebAssemblyFastISel::fastLowerArguments() {
629 if (!FuncInfo.CanLowerReturn)
630 return false;
631
632 const Function *F = FuncInfo.Fn;
633 if (F->isVarArg())
634 return false;
635
Heejin Ahn18c56a02019-02-04 19:13:39 +0000636 unsigned I = 0;
Dan Gohman33e694a2016-05-12 04:19:09 +0000637 for (auto const &Arg : F->args()) {
Reid Klecknerb5180542017-03-21 16:57:19 +0000638 const AttributeList &Attrs = F->getAttributes();
Heejin Ahn18c56a02019-02-04 19:13:39 +0000639 if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
640 Attrs.hasParamAttribute(I, Attribute::SwiftSelf) ||
641 Attrs.hasParamAttribute(I, Attribute::SwiftError) ||
642 Attrs.hasParamAttribute(I, Attribute::InAlloca) ||
643 Attrs.hasParamAttribute(I, Attribute::Nest))
Dan Gohman33e694a2016-05-12 04:19:09 +0000644 return false;
645
646 Type *ArgTy = Arg.getType();
Derek Schuff39bf39f2016-08-02 23:16:09 +0000647 if (ArgTy->isStructTy() || ArgTy->isArrayTy())
648 return false;
649 if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
Dan Gohman33e694a2016-05-12 04:19:09 +0000650 return false;
651
652 unsigned Opc;
653 const TargetRegisterClass *RC;
654 switch (getSimpleType(ArgTy)) {
655 case MVT::i1:
656 case MVT::i8:
657 case MVT::i16:
658 case MVT::i32:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000659 Opc = WebAssembly::ARGUMENT_i32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000660 RC = &WebAssembly::I32RegClass;
661 break;
662 case MVT::i64:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000663 Opc = WebAssembly::ARGUMENT_i64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000664 RC = &WebAssembly::I64RegClass;
665 break;
666 case MVT::f32:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000667 Opc = WebAssembly::ARGUMENT_f32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000668 RC = &WebAssembly::F32RegClass;
669 break;
670 case MVT::f64:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000671 Opc = WebAssembly::ARGUMENT_f64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000672 RC = &WebAssembly::F64RegClass;
673 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000674 case MVT::v16i8:
675 Opc = WebAssembly::ARGUMENT_v16i8;
676 RC = &WebAssembly::V128RegClass;
677 break;
678 case MVT::v8i16:
679 Opc = WebAssembly::ARGUMENT_v8i16;
680 RC = &WebAssembly::V128RegClass;
681 break;
682 case MVT::v4i32:
683 Opc = WebAssembly::ARGUMENT_v4i32;
684 RC = &WebAssembly::V128RegClass;
685 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000686 case MVT::v2i64:
687 Opc = WebAssembly::ARGUMENT_v2i64;
688 RC = &WebAssembly::V128RegClass;
689 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000690 case MVT::v4f32:
691 Opc = WebAssembly::ARGUMENT_v4f32;
692 RC = &WebAssembly::V128RegClass;
693 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000694 case MVT::v2f64:
695 Opc = WebAssembly::ARGUMENT_v2f64;
696 RC = &WebAssembly::V128RegClass;
697 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000698 case MVT::ExceptRef:
Thomas Lively0ff82ac2018-10-13 07:09:10 +0000699 Opc = WebAssembly::ARGUMENT_ExceptRef;
Heejin Ahn0de58722018-03-08 04:05:37 +0000700 RC = &WebAssembly::EXCEPT_REFRegClass;
701 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000702 default:
703 return false;
704 }
705 unsigned ResultReg = createResultReg(RC);
706 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahn18c56a02019-02-04 19:13:39 +0000707 .addImm(I);
Dan Gohman33e694a2016-05-12 04:19:09 +0000708 updateValueMap(&Arg, ResultReg);
709
Heejin Ahn18c56a02019-02-04 19:13:39 +0000710 ++I;
Dan Gohman33e694a2016-05-12 04:19:09 +0000711 }
712
713 MRI.addLiveIn(WebAssembly::ARGUMENTS);
714
715 auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
Dan Gohmanb8184822018-05-22 04:58:36 +0000716 for (auto const &Arg : F->args()) {
717 MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType()));
718 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
719 MFI->clearParamsAndResults();
720 return false;
721 }
722 MFI->addParam(ArgTy);
723 }
Dan Gohman33e694a2016-05-12 04:19:09 +0000724
Dan Gohman4576dc02018-04-17 20:46:42 +0000725 if (!F->getReturnType()->isVoidTy()) {
Heejin Ahnf208f632018-09-05 01:27:38 +0000726 MVT::SimpleValueType RetTy =
727 getLegalType(getSimpleType(F->getReturnType()));
Dan Gohmanb8184822018-05-22 04:58:36 +0000728 if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
729 MFI->clearParamsAndResults();
Dan Gohman4576dc02018-04-17 20:46:42 +0000730 return false;
Dan Gohmanb8184822018-05-22 04:58:36 +0000731 }
732 MFI->addResult(RetTy);
Dan Gohman4576dc02018-04-17 20:46:42 +0000733 }
Dan Gohman6055fba2017-01-09 23:09:38 +0000734
Dan Gohman33e694a2016-05-12 04:19:09 +0000735 return true;
736}
737
738bool WebAssemblyFastISel::selectCall(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000739 const auto *Call = cast<CallInst>(I);
Dan Gohman33e694a2016-05-12 04:19:09 +0000740
741 if (Call->isMustTailCall() || Call->isInlineAsm() ||
742 Call->getFunctionType()->isVarArg())
743 return false;
744
745 Function *Func = Call->getCalledFunction();
746 if (Func && Func->isIntrinsic())
747 return false;
748
Jacob Gravelle690b76e2017-08-24 19:53:44 +0000749 bool IsDirect = Func != nullptr;
750 if (!IsDirect && isa<ConstantExpr>(Call->getCalledValue()))
751 return false;
752
Dan Gohman33e694a2016-05-12 04:19:09 +0000753 FunctionType *FuncTy = Call->getFunctionType();
754 unsigned Opc;
Dan Gohman33e694a2016-05-12 04:19:09 +0000755 bool IsVoid = FuncTy->getReturnType()->isVoidTy();
756 unsigned ResultReg;
757 if (IsVoid) {
Derek Schuff6f697832016-10-21 16:38:07 +0000758 Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
Dan Gohman33e694a2016-05-12 04:19:09 +0000759 } else {
Derek Schuff39bf39f2016-08-02 23:16:09 +0000760 if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
761 return false;
762
Dan Gohman33e694a2016-05-12 04:19:09 +0000763 MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
764 switch (RetTy) {
765 case MVT::i1:
766 case MVT::i8:
767 case MVT::i16:
768 case MVT::i32:
Derek Schuff6f697832016-10-21 16:38:07 +0000769 Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::PCALL_INDIRECT_I32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000770 ResultReg = createResultReg(&WebAssembly::I32RegClass);
771 break;
772 case MVT::i64:
Derek Schuff6f697832016-10-21 16:38:07 +0000773 Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::PCALL_INDIRECT_I64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000774 ResultReg = createResultReg(&WebAssembly::I64RegClass);
775 break;
776 case MVT::f32:
Derek Schuff6f697832016-10-21 16:38:07 +0000777 Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::PCALL_INDIRECT_F32;
Dan Gohman33e694a2016-05-12 04:19:09 +0000778 ResultReg = createResultReg(&WebAssembly::F32RegClass);
779 break;
780 case MVT::f64:
Derek Schuff6f697832016-10-21 16:38:07 +0000781 Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::PCALL_INDIRECT_F64;
Dan Gohman33e694a2016-05-12 04:19:09 +0000782 ResultReg = createResultReg(&WebAssembly::F64RegClass);
783 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000784 case MVT::v16i8:
Heejin Ahnf208f632018-09-05 01:27:38 +0000785 Opc = IsDirect ? WebAssembly::CALL_v16i8
786 : WebAssembly::PCALL_INDIRECT_v16i8;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000787 ResultReg = createResultReg(&WebAssembly::V128RegClass);
788 break;
789 case MVT::v8i16:
Heejin Ahnf208f632018-09-05 01:27:38 +0000790 Opc = IsDirect ? WebAssembly::CALL_v8i16
791 : WebAssembly::PCALL_INDIRECT_v8i16;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000792 ResultReg = createResultReg(&WebAssembly::V128RegClass);
793 break;
794 case MVT::v4i32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000795 Opc = IsDirect ? WebAssembly::CALL_v4i32
796 : WebAssembly::PCALL_INDIRECT_v4i32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000797 ResultReg = createResultReg(&WebAssembly::V128RegClass);
798 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000799 case MVT::v2i64:
Heejin Ahnf208f632018-09-05 01:27:38 +0000800 Opc = IsDirect ? WebAssembly::CALL_v2i64
801 : WebAssembly::PCALL_INDIRECT_v2i64;
Derek Schuff51ed1312018-08-07 21:24:01 +0000802 ResultReg = createResultReg(&WebAssembly::V128RegClass);
803 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000804 case MVT::v4f32:
Heejin Ahnf208f632018-09-05 01:27:38 +0000805 Opc = IsDirect ? WebAssembly::CALL_v4f32
806 : WebAssembly::PCALL_INDIRECT_v4f32;
Derek Schuff39bf39f2016-08-02 23:16:09 +0000807 ResultReg = createResultReg(&WebAssembly::V128RegClass);
808 break;
Derek Schuff51ed1312018-08-07 21:24:01 +0000809 case MVT::v2f64:
Heejin Ahnf208f632018-09-05 01:27:38 +0000810 Opc = IsDirect ? WebAssembly::CALL_v2f64
811 : WebAssembly::PCALL_INDIRECT_v2f64;
Derek Schuff51ed1312018-08-07 21:24:01 +0000812 ResultReg = createResultReg(&WebAssembly::V128RegClass);
813 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000814 case MVT::ExceptRef:
815 Opc = IsDirect ? WebAssembly::CALL_EXCEPT_REF
816 : WebAssembly::PCALL_INDIRECT_EXCEPT_REF;
817 ResultReg = createResultReg(&WebAssembly::EXCEPT_REFRegClass);
818 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000819 default:
820 return false;
821 }
822 }
823
824 SmallVector<unsigned, 8> Args;
Heejin Ahn18c56a02019-02-04 19:13:39 +0000825 for (unsigned I = 0, E = Call->getNumArgOperands(); I < E; ++I) {
826 Value *V = Call->getArgOperand(I);
Dan Gohman33e694a2016-05-12 04:19:09 +0000827 MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
828 if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
829 return false;
830
Reid Klecknerb5180542017-03-21 16:57:19 +0000831 const AttributeList &Attrs = Call->getAttributes();
Heejin Ahn18c56a02019-02-04 19:13:39 +0000832 if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
833 Attrs.hasParamAttribute(I, Attribute::SwiftSelf) ||
834 Attrs.hasParamAttribute(I, Attribute::SwiftError) ||
835 Attrs.hasParamAttribute(I, Attribute::InAlloca) ||
836 Attrs.hasParamAttribute(I, Attribute::Nest))
Dan Gohman33e694a2016-05-12 04:19:09 +0000837 return false;
838
839 unsigned Reg;
840
Heejin Ahn18c56a02019-02-04 19:13:39 +0000841 if (Attrs.hasParamAttribute(I, Attribute::SExt))
Dan Gohman33e694a2016-05-12 04:19:09 +0000842 Reg = getRegForSignedValue(V);
Heejin Ahn18c56a02019-02-04 19:13:39 +0000843 else if (Attrs.hasParamAttribute(I, Attribute::ZExt))
Dan Gohman33e694a2016-05-12 04:19:09 +0000844 Reg = getRegForUnsignedValue(V);
845 else
846 Reg = getRegForValue(V);
847
848 if (Reg == 0)
849 return false;
850
851 Args.push_back(Reg);
852 }
853
Sam Clegga2725272019-04-19 22:43:32 +0000854 unsigned CalleeReg = 0;
855 if (!IsDirect) {
856 CalleeReg = getRegForValue(Call->getCalledValue());
857 if (!CalleeReg)
858 return false;
859 }
860
Dan Gohman33e694a2016-05-12 04:19:09 +0000861 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
862
863 if (!IsVoid)
864 MIB.addReg(ResultReg, RegState::Define);
865
866 if (IsDirect)
867 MIB.addGlobalAddress(Func);
Sam Clegga2725272019-04-19 22:43:32 +0000868 else
869 MIB.addReg(CalleeReg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000870
871 for (unsigned ArgReg : Args)
872 MIB.addReg(ArgReg);
873
874 if (!IsVoid)
875 updateValueMap(Call, ResultReg);
876 return true;
877}
878
879bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000880 const auto *Select = cast<SelectInst>(I);
Dan Gohman33e694a2016-05-12 04:19:09 +0000881
882 bool Not;
Heejin Ahnf208f632018-09-05 01:27:38 +0000883 unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
Dan Gohman33e694a2016-05-12 04:19:09 +0000884 if (CondReg == 0)
885 return false;
886
Heejin Ahnf208f632018-09-05 01:27:38 +0000887 unsigned TrueReg = getRegForValue(Select->getTrueValue());
Dan Gohman33e694a2016-05-12 04:19:09 +0000888 if (TrueReg == 0)
889 return false;
890
891 unsigned FalseReg = getRegForValue(Select->getFalseValue());
892 if (FalseReg == 0)
893 return false;
894
895 if (Not)
896 std::swap(TrueReg, FalseReg);
897
898 unsigned Opc;
899 const TargetRegisterClass *RC;
900 switch (getSimpleType(Select->getType())) {
901 case MVT::i1:
902 case MVT::i8:
903 case MVT::i16:
904 case MVT::i32:
905 Opc = WebAssembly::SELECT_I32;
906 RC = &WebAssembly::I32RegClass;
907 break;
908 case MVT::i64:
909 Opc = WebAssembly::SELECT_I64;
910 RC = &WebAssembly::I64RegClass;
911 break;
912 case MVT::f32:
913 Opc = WebAssembly::SELECT_F32;
914 RC = &WebAssembly::F32RegClass;
915 break;
916 case MVT::f64:
917 Opc = WebAssembly::SELECT_F64;
918 RC = &WebAssembly::F64RegClass;
919 break;
Heejin Ahn0de58722018-03-08 04:05:37 +0000920 case MVT::ExceptRef:
921 Opc = WebAssembly::SELECT_EXCEPT_REF;
922 RC = &WebAssembly::EXCEPT_REFRegClass;
923 break;
Dan Gohman33e694a2016-05-12 04:19:09 +0000924 default:
925 return false;
926 }
927
928 unsigned ResultReg = createResultReg(RC);
929 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
Heejin Ahnf208f632018-09-05 01:27:38 +0000930 .addReg(TrueReg)
931 .addReg(FalseReg)
932 .addReg(CondReg);
Dan Gohman33e694a2016-05-12 04:19:09 +0000933
934 updateValueMap(Select, ResultReg);
935 return true;
936}
937
938bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000939 const auto *Trunc = cast<TruncInst>(I);
Dan Gohman33e694a2016-05-12 04:19:09 +0000940
941 unsigned Reg = getRegForValue(Trunc->getOperand(0));
942 if (Reg == 0)
943 return false;
944
945 if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
946 unsigned Result = createResultReg(&WebAssembly::I32RegClass);
947 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
948 TII.get(WebAssembly::I32_WRAP_I64), Result)
949 .addReg(Reg);
950 Reg = Result;
951 }
952
953 updateValueMap(Trunc, Reg);
954 return true;
955}
956
Dan Gohman3a5ce732016-05-11 16:32:42 +0000957bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000958 const auto *ZExt = cast<ZExtInst>(I);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000959
Dan Gohman33e694a2016-05-12 04:19:09 +0000960 const Value *Op = ZExt->getOperand(0);
961 MVT::SimpleValueType From = getSimpleType(Op->getType());
962 MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000963 unsigned In = getRegForValue(Op);
964 if (In == 0)
965 return false;
966 unsigned Reg = zeroExtend(In, Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000967 if (Reg == 0)
968 return false;
969
970 updateValueMap(ZExt, Reg);
971 return true;
972}
973
974bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000975 const auto *SExt = cast<SExtInst>(I);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000976
Dan Gohman33e694a2016-05-12 04:19:09 +0000977 const Value *Op = SExt->getOperand(0);
978 MVT::SimpleValueType From = getSimpleType(Op->getType());
979 MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
Dan Gohman3ff73cf2017-11-28 05:36:42 +0000980 unsigned In = getRegForValue(Op);
981 if (In == 0)
982 return false;
983 unsigned Reg = signExtend(In, Op, From, To);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000984 if (Reg == 0)
985 return false;
986
987 updateValueMap(SExt, Reg);
988 return true;
989}
990
991bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +0000992 const auto *ICmp = cast<ICmpInst>(I);
Dan Gohman3a5ce732016-05-11 16:32:42 +0000993
994 bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
995 unsigned Opc;
Heejin Ahn18c56a02019-02-04 19:13:39 +0000996 bool IsSigned = false;
Dan Gohman3a5ce732016-05-11 16:32:42 +0000997 switch (ICmp->getPredicate()) {
998 case ICmpInst::ICMP_EQ:
999 Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
1000 break;
1001 case ICmpInst::ICMP_NE:
1002 Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1003 break;
1004 case ICmpInst::ICMP_UGT:
1005 Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1006 break;
1007 case ICmpInst::ICMP_UGE:
1008 Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1009 break;
1010 case ICmpInst::ICMP_ULT:
1011 Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1012 break;
1013 case ICmpInst::ICMP_ULE:
1014 Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1015 break;
1016 case ICmpInst::ICMP_SGT:
1017 Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
Heejin Ahn18c56a02019-02-04 19:13:39 +00001018 IsSigned = true;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001019 break;
1020 case ICmpInst::ICMP_SGE:
1021 Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
Heejin Ahn18c56a02019-02-04 19:13:39 +00001022 IsSigned = true;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001023 break;
1024 case ICmpInst::ICMP_SLT:
1025 Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
Heejin Ahn18c56a02019-02-04 19:13:39 +00001026 IsSigned = true;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001027 break;
1028 case ICmpInst::ICMP_SLE:
1029 Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
Heejin Ahn18c56a02019-02-04 19:13:39 +00001030 IsSigned = true;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001031 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001032 default:
1033 return false;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001034 }
1035
Heejin Ahn18c56a02019-02-04 19:13:39 +00001036 unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
Dan Gohman3a5ce732016-05-11 16:32:42 +00001037 if (LHS == 0)
1038 return false;
1039
Heejin Ahn18c56a02019-02-04 19:13:39 +00001040 unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
Dan Gohman3a5ce732016-05-11 16:32:42 +00001041 if (RHS == 0)
1042 return false;
1043
1044 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1045 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1046 .addReg(LHS)
1047 .addReg(RHS);
1048 updateValueMap(ICmp, ResultReg);
1049 return true;
1050}
1051
1052bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +00001053 const auto *FCmp = cast<FCmpInst>(I);
Dan Gohman3a5ce732016-05-11 16:32:42 +00001054
1055 unsigned LHS = getRegForValue(FCmp->getOperand(0));
1056 if (LHS == 0)
1057 return false;
1058
1059 unsigned RHS = getRegForValue(FCmp->getOperand(1));
1060 if (RHS == 0)
1061 return false;
1062
1063 bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1064 unsigned Opc;
1065 bool Not = false;
1066 switch (FCmp->getPredicate()) {
1067 case FCmpInst::FCMP_OEQ:
1068 Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1069 break;
1070 case FCmpInst::FCMP_UNE:
1071 Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1072 break;
1073 case FCmpInst::FCMP_OGT:
1074 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1075 break;
1076 case FCmpInst::FCMP_OGE:
1077 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1078 break;
1079 case FCmpInst::FCMP_OLT:
1080 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1081 break;
1082 case FCmpInst::FCMP_OLE:
1083 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1084 break;
1085 case FCmpInst::FCMP_UGT:
1086 Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1087 Not = true;
1088 break;
1089 case FCmpInst::FCMP_UGE:
1090 Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1091 Not = true;
1092 break;
1093 case FCmpInst::FCMP_ULT:
1094 Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1095 Not = true;
1096 break;
1097 case FCmpInst::FCMP_ULE:
1098 Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1099 Not = true;
1100 break;
1101 default:
1102 return false;
1103 }
1104
1105 unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1106 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1107 .addReg(LHS)
1108 .addReg(RHS);
1109
1110 if (Not)
1111 ResultReg = notValue(ResultReg);
1112
1113 updateValueMap(FCmp, ResultReg);
1114 return true;
1115}
1116
Dan Gohman2e644382016-05-10 17:39:48 +00001117bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
1118 // Target-independent code can handle this, except it doesn't set the dead
1119 // flag on the ARGUMENTS clobber, so we have to do that manually in order
1120 // to satisfy code that expects this of isBitcast() instructions.
1121 EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
1122 EVT RetVT = TLI.getValueType(DL, I->getType());
1123 if (!VT.isSimple() || !RetVT.isSimple())
1124 return false;
Dan Gohman33e694a2016-05-12 04:19:09 +00001125
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001126 unsigned In = getRegForValue(I->getOperand(0));
1127 if (In == 0)
1128 return false;
1129
Dan Gohman33e694a2016-05-12 04:19:09 +00001130 if (VT == RetVT) {
1131 // No-op bitcast.
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001132 updateValueMap(I, In);
Dan Gohman33e694a2016-05-12 04:19:09 +00001133 return true;
1134 }
1135
Dan Gohman2e644382016-05-10 17:39:48 +00001136 unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
Dan Gohman3ff73cf2017-11-28 05:36:42 +00001137 In, I->getOperand(0)->hasOneUse());
Dan Gohman2e644382016-05-10 17:39:48 +00001138 if (!Reg)
1139 return false;
1140 MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
1141 --Iter;
1142 assert(Iter->isBitcast());
1143 Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI);
1144 updateValueMap(I, Reg);
1145 return true;
1146}
1147
1148bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +00001149 const auto *Load = cast<LoadInst>(I);
Dan Gohman2e644382016-05-10 17:39:48 +00001150 if (Load->isAtomic())
1151 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001152 if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
1153 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001154
1155 Address Addr;
1156 if (!computeAddress(Load->getPointerOperand(), Addr))
1157 return false;
1158
1159 // TODO: Fold a following sign-/zero-extend into the load instruction.
1160
1161 unsigned Opc;
1162 const TargetRegisterClass *RC;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001163 switch (getSimpleType(Load->getType())) {
1164 case MVT::i1:
1165 case MVT::i8:
1166 Opc = WebAssembly::LOAD8_U_I32;
1167 RC = &WebAssembly::I32RegClass;
Dan Gohman2e644382016-05-10 17:39:48 +00001168 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001169 case MVT::i16:
1170 Opc = WebAssembly::LOAD16_U_I32;
1171 RC = &WebAssembly::I32RegClass;
1172 break;
1173 case MVT::i32:
1174 Opc = WebAssembly::LOAD_I32;
1175 RC = &WebAssembly::I32RegClass;
1176 break;
1177 case MVT::i64:
1178 Opc = WebAssembly::LOAD_I64;
1179 RC = &WebAssembly::I64RegClass;
1180 break;
1181 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001182 Opc = WebAssembly::LOAD_F32;
1183 RC = &WebAssembly::F32RegClass;
1184 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001185 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001186 Opc = WebAssembly::LOAD_F64;
1187 RC = &WebAssembly::F64RegClass;
1188 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001189 default:
1190 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001191 }
1192
Sam Clegg492f7522019-03-26 19:46:15 +00001193 if (!materializeLoadStoreOperands(Addr))
1194 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001195
1196 unsigned ResultReg = createResultReg(RC);
1197 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
1198 ResultReg);
1199
1200 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1201
1202 updateValueMap(Load, ResultReg);
1203 return true;
1204}
1205
1206bool WebAssemblyFastISel::selectStore(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +00001207 const auto *Store = cast<StoreInst>(I);
Dan Gohman2e644382016-05-10 17:39:48 +00001208 if (Store->isAtomic())
1209 return false;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001210 if (!Subtarget->hasSIMD128() &&
1211 Store->getValueOperand()->getType()->isVectorTy())
1212 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001213
1214 Address Addr;
1215 if (!computeAddress(Store->getPointerOperand(), Addr))
1216 return false;
1217
1218 unsigned Opc;
Dan Gohman2e644382016-05-10 17:39:48 +00001219 bool VTIsi1 = false;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001220 switch (getSimpleType(Store->getValueOperand()->getType())) {
1221 case MVT::i1:
1222 VTIsi1 = true;
Dan Gohman861bec22018-02-09 22:59:01 +00001223 LLVM_FALLTHROUGH;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001224 case MVT::i8:
1225 Opc = WebAssembly::STORE8_I32;
Dan Gohman2e644382016-05-10 17:39:48 +00001226 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001227 case MVT::i16:
1228 Opc = WebAssembly::STORE16_I32;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001229 break;
1230 case MVT::i32:
1231 Opc = WebAssembly::STORE_I32;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001232 break;
1233 case MVT::i64:
1234 Opc = WebAssembly::STORE_I64;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001235 break;
1236 case MVT::f32:
Dan Gohman2e644382016-05-10 17:39:48 +00001237 Opc = WebAssembly::STORE_F32;
Dan Gohman2e644382016-05-10 17:39:48 +00001238 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001239 case MVT::f64:
Dan Gohman2e644382016-05-10 17:39:48 +00001240 Opc = WebAssembly::STORE_F64;
Dan Gohman2e644382016-05-10 17:39:48 +00001241 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001242 default:
1243 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001244 }
1245
Sam Clegg492f7522019-03-26 19:46:15 +00001246 if (!materializeLoadStoreOperands(Addr))
1247 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001248
1249 unsigned ValueReg = getRegForValue(Store->getValueOperand());
Derek Schuff732636d2016-08-04 18:01:52 +00001250 if (ValueReg == 0)
1251 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001252 if (VTIsi1)
Dan Gohman3a5ce732016-05-11 16:32:42 +00001253 ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
Dan Gohman2e644382016-05-10 17:39:48 +00001254
Dan Gohman7f1bdb22016-10-06 22:08:28 +00001255 auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
Dan Gohman2e644382016-05-10 17:39:48 +00001256
1257 addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1258
1259 MIB.addReg(ValueReg);
1260 return true;
1261}
1262
1263bool WebAssemblyFastISel::selectBr(const Instruction *I) {
Heejin Ahn18c56a02019-02-04 19:13:39 +00001264 const auto *Br = cast<BranchInst>(I);
Dan Gohman2e644382016-05-10 17:39:48 +00001265 if (Br->isUnconditional()) {
1266 MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
1267 fastEmitBranch(MSucc, Br->getDebugLoc());
1268 return true;
1269 }
1270
1271 MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
1272 MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
1273
Dan Gohman33e694a2016-05-12 04:19:09 +00001274 bool Not;
1275 unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
Derek Schuff732636d2016-08-04 18:01:52 +00001276 if (CondReg == 0)
1277 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001278
Dan Gohman33e694a2016-05-12 04:19:09 +00001279 unsigned Opc = WebAssembly::BR_IF;
1280 if (Not)
1281 Opc = WebAssembly::BR_UNLESS;
1282
Dan Gohman2e644382016-05-10 17:39:48 +00001283 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1284 .addMBB(TBB)
1285 .addReg(CondReg);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001286
Dan Gohman2e644382016-05-10 17:39:48 +00001287 finishCondBranch(Br->getParent(), TBB, FBB);
1288 return true;
1289}
1290
1291bool WebAssemblyFastISel::selectRet(const Instruction *I) {
1292 if (!FuncInfo.CanLowerReturn)
1293 return false;
1294
Heejin Ahn18c56a02019-02-04 19:13:39 +00001295 const auto *Ret = cast<ReturnInst>(I);
Dan Gohman2e644382016-05-10 17:39:48 +00001296
1297 if (Ret->getNumOperands() == 0) {
1298 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1299 TII.get(WebAssembly::RETURN_VOID));
1300 return true;
1301 }
1302
1303 Value *RV = Ret->getOperand(0);
Derek Schuff39bf39f2016-08-02 23:16:09 +00001304 if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
1305 return false;
1306
Dan Gohman2e644382016-05-10 17:39:48 +00001307 unsigned Opc;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001308 switch (getSimpleType(RV->getType())) {
Heejin Ahnf208f632018-09-05 01:27:38 +00001309 case MVT::i1:
1310 case MVT::i8:
1311 case MVT::i16:
1312 case MVT::i32:
Dan Gohman3a5ce732016-05-11 16:32:42 +00001313 Opc = WebAssembly::RETURN_I32;
Dan Gohman2e644382016-05-10 17:39:48 +00001314 break;
Dan Gohman3a5ce732016-05-11 16:32:42 +00001315 case MVT::i64:
1316 Opc = WebAssembly::RETURN_I64;
1317 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001318 case MVT::f32:
1319 Opc = WebAssembly::RETURN_F32;
1320 break;
1321 case MVT::f64:
1322 Opc = WebAssembly::RETURN_F64;
1323 break;
1324 case MVT::v16i8:
1325 Opc = WebAssembly::RETURN_v16i8;
1326 break;
1327 case MVT::v8i16:
1328 Opc = WebAssembly::RETURN_v8i16;
1329 break;
1330 case MVT::v4i32:
1331 Opc = WebAssembly::RETURN_v4i32;
1332 break;
Derek Schuff51ed1312018-08-07 21:24:01 +00001333 case MVT::v2i64:
1334 Opc = WebAssembly::RETURN_v2i64;
1335 break;
Derek Schuff39bf39f2016-08-02 23:16:09 +00001336 case MVT::v4f32:
1337 Opc = WebAssembly::RETURN_v4f32;
1338 break;
Derek Schuff51ed1312018-08-07 21:24:01 +00001339 case MVT::v2f64:
1340 Opc = WebAssembly::RETURN_v2f64;
1341 break;
Heejin Ahn0de58722018-03-08 04:05:37 +00001342 case MVT::ExceptRef:
1343 Opc = WebAssembly::RETURN_EXCEPT_REF;
1344 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001345 default:
1346 return false;
Dan Gohman2e644382016-05-10 17:39:48 +00001347 }
1348
Dan Gohman33e694a2016-05-12 04:19:09 +00001349 unsigned Reg;
1350 if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
1351 Reg = getRegForSignedValue(RV);
1352 else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
1353 Reg = getRegForUnsignedValue(RV);
1354 else
1355 Reg = getRegForValue(RV);
1356
Derek Schuff732636d2016-08-04 18:01:52 +00001357 if (Reg == 0)
1358 return false;
1359
Dan Gohman2e644382016-05-10 17:39:48 +00001360 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg);
1361 return true;
1362}
1363
1364bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
1365 BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1366 TII.get(WebAssembly::UNREACHABLE));
1367 return true;
1368}
1369
1370bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
1371 switch (I->getOpcode()) {
Dan Gohman33e694a2016-05-12 04:19:09 +00001372 case Instruction::Call:
1373 if (selectCall(I))
1374 return true;
1375 break;
Heejin Ahnf208f632018-09-05 01:27:38 +00001376 case Instruction::Select:
1377 return selectSelect(I);
1378 case Instruction::Trunc:
1379 return selectTrunc(I);
1380 case Instruction::ZExt:
1381 return selectZExt(I);
1382 case Instruction::SExt:
1383 return selectSExt(I);
1384 case Instruction::ICmp:
1385 return selectICmp(I);
1386 case Instruction::FCmp:
1387 return selectFCmp(I);
1388 case Instruction::BitCast:
1389 return selectBitCast(I);
1390 case Instruction::Load:
1391 return selectLoad(I);
1392 case Instruction::Store:
1393 return selectStore(I);
1394 case Instruction::Br:
1395 return selectBr(I);
1396 case Instruction::Ret:
1397 return selectRet(I);
1398 case Instruction::Unreachable:
1399 return selectUnreachable(I);
1400 default:
1401 break;
Dan Gohman7b634842015-08-24 18:44:37 +00001402 }
1403
1404 // Fall back to target-independent instruction selection.
1405 return selectOperator(I, I->getOpcode());
1406}
1407
1408FastISel *WebAssembly::createFastISel(FunctionLoweringInfo &FuncInfo,
1409 const TargetLibraryInfo *LibInfo) {
1410 return new WebAssemblyFastISel(FuncInfo, LibInfo);
1411}