LLVM  9.0.0svn
WebAssemblyFastISel.cpp
Go to the documentation of this file.
1 //===-- WebAssemblyFastISel.cpp - WebAssembly FastISel implementation -----===//
2 //
3 // 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
6 //
7 //===----------------------------------------------------------------------===//
8 ///
9 /// \file
10 /// This file defines the WebAssembly-specific support for the FastISel
11 /// class. Some of the target-specific code is generated by tablegen in the file
12 /// WebAssemblyGenFastISel.inc, which is #included here.
13 ///
14 /// TODO: kill flags
15 ///
16 //===----------------------------------------------------------------------===//
17 
19 #include "WebAssembly.h"
21 #include "WebAssemblySubtarget.h"
24 #include "llvm/CodeGen/FastISel.h"
30 #include "llvm/IR/DataLayout.h"
31 #include "llvm/IR/DerivedTypes.h"
32 #include "llvm/IR/Function.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"
39 #include "llvm/IR/PatternMatch.h"
40 
41 using namespace llvm;
42 using namespace PatternMatch;
43 
44 #define DEBUG_TYPE "wasm-fastisel"
45 
46 namespace {
47 
48 class WebAssemblyFastISel final : public FastISel {
49  // All possible address modes.
50  class Address {
51  public:
52  using BaseKind = enum { RegBase, FrameIndexBase };
53 
54  private:
55  BaseKind Kind = RegBase;
56  union {
57  unsigned Reg;
58  int FI;
59  } Base;
60 
61  int64_t Offset = 0;
62 
63  const GlobalValue *GV = nullptr;
64 
65  public:
66  // Innocuous defaults for our address.
67  Address() { Base.Reg = 0; }
68  void setKind(BaseKind K) {
69  assert(!isSet() && "Can't change kind with non-zero base");
70  Kind = K;
71  }
72  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!");
77  assert(Base.Reg == 0 && "Overwriting non-zero register");
78  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!");
86  assert(Base.FI == 0 && "Overwriting non-zero frame index");
87  Base.FI = FI;
88  }
89  unsigned getFI() const {
90  assert(isFIBase() && "Invalid base frame index access!");
91  return Base.FI;
92  }
93 
94  void setOffset(int64_t NewOffset) {
95  assert(NewOffset >= 0 && "Offsets must be non-negative");
96  Offset = NewOffset;
97  }
98  int64_t getOffset() const { return Offset; }
99  void setGlobalValue(const GlobalValue *G) { GV = G; }
100  const GlobalValue *getGlobalValue() const { return GV; }
101  bool isSet() const {
102  if (isRegBase()) {
103  return Base.Reg != 0;
104  } else {
105  return Base.FI != 0;
106  }
107  }
108  };
109 
110  /// 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;
114 
115 private:
116  // Utility helper routines
117  MVT::SimpleValueType getSimpleType(Type *Ty) {
118  EVT VT = TLI.getValueType(DL, Ty, /*HandleUnknown=*/true);
119  return VT.isSimple() ? VT.getSimpleVT().SimpleTy
121  }
122  MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
123  switch (VT) {
124  case MVT::i1:
125  case MVT::i8:
126  case MVT::i16:
127  return MVT::i32;
128  case MVT::i32:
129  case MVT::i64:
130  case MVT::f32:
131  case MVT::f64:
132  case MVT::ExceptRef:
133  return VT;
134  case MVT::f16:
135  return MVT::f32;
136  case MVT::v16i8:
137  case MVT::v8i16:
138  case MVT::v4i32:
139  case MVT::v4f32:
140  if (Subtarget->hasSIMD128())
141  return VT;
142  break;
143  case MVT::v2i64:
144  case MVT::v2f64:
145  if (Subtarget->hasUnimplementedSIMD128())
146  return VT;
147  break;
148  default:
149  break;
150  }
152  }
153  bool computeAddress(const Value *Obj, Address &Addr);
154  bool materializeLoadStoreOperands(Address &Addr);
155  void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
156  MachineMemOperand *MMO);
157  unsigned maskI1Value(unsigned Reg, const Value *V);
158  unsigned getRegForI1Value(const Value *V, bool &Not);
159  unsigned zeroExtendToI32(unsigned Reg, const Value *V,
161  unsigned signExtendToI32(unsigned Reg, const Value *V,
162  MVT::SimpleValueType From);
163  unsigned zeroExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
165  unsigned signExtend(unsigned Reg, const Value *V, MVT::SimpleValueType From,
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);
171  unsigned copyValue(unsigned Reg);
172 
173  // Backend specific FastISel code.
174  unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
175  unsigned fastMaterializeConstant(const Constant *C) override;
176  bool fastLowerArguments() override;
177 
178  // Selection routines.
179  bool selectCall(const Instruction *I);
180  bool selectSelect(const Instruction *I);
181  bool selectTrunc(const Instruction *I);
182  bool selectZExt(const Instruction *I);
183  bool selectSExt(const Instruction *I);
184  bool selectICmp(const Instruction *I);
185  bool selectFCmp(const Instruction *I);
186  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 
193 public:
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 
209 bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {
210 
211  const User *U = nullptr;
212  unsigned Opcode = Instruction::UserOp1;
213  if (const auto *I = dyn_cast<Instruction>(Obj)) {
214  // 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  }
221  } else if (const auto *C = dyn_cast<ConstantExpr>(Obj)) {
222  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 
232  if (const auto *GV = dyn_cast<GlobalValue>(Obj)) {
233  if (Addr.getGlobalValue())
234  return false;
235  Addr.setGlobalValue(GV);
236  return true;
237  }
238 
239  switch (Opcode) {
240  default:
241  break;
242  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();
262  // Non-inbounds geps can wrap; wasm's offsets can't.
263  if (!cast<GEPOperator>(U)->isInBounds())
264  goto unsupported_gep;
265  // Iterate through the GEP folding the constants into offsets where
266  // we can.
267  for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
268  GTI != E; ++GTI) {
269  const Value *Op = GTI.getOperand();
270  if (StructType *STy = GTI.getStructTypeOrNull()) {
271  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 (;;) {
277  if (const auto *CI = dyn_cast<ConstantInt>(Op)) {
278  // Constant-offset addressing.
279  TmpOffset += CI->getSExtValue() * S;
280  break;
281  }
282  if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
283  // An unscaled add of a register. Set it as the new base.
284  unsigned Reg = getRegForValue(Op);
285  if (Reg == 0)
286  return false;
287  Addr.setReg(Reg);
288  break;
289  }
290  if (canFoldAddIntoGEP(U, Op)) {
291  // A compatible add with a constant operand. Fold the constant.
292  auto *CI = cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
293  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  }
303  // 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  }
310  // We failed, restore everything and try the other options.
311  Addr = SavedAddr;
312  unsupported_gep:
313  break;
314  }
315  case Instruction::Alloca: {
316  const auto *AI = cast<AllocaInst>(Obj);
318  FuncInfo.StaticAllocaMap.find(AI);
319  if (SI != FuncInfo.StaticAllocaMap.end()) {
320  if (Addr.isSet()) {
321  return false;
322  }
323  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 
337  if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
338  uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
339  if (int64_t(TmpOffset) >= 0) {
340  Addr.setOffset(TmpOffset);
341  return computeAddress(LHS, Addr);
342  }
343  }
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 
357  if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
358  int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
359  if (TmpOffset >= 0) {
360  Addr.setOffset(TmpOffset);
361  return computeAddress(LHS, Addr);
362  }
363  }
364  break;
365  }
366  }
367  if (Addr.isSet()) {
368  return false;
369  }
370  unsigned Reg = getRegForValue(Obj);
371  if (Reg == 0)
372  return false;
373  Addr.setReg(Reg);
374  return Addr.getReg() != 0;
375 }
376 
377 bool WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
378  if (Addr.isRegBase()) {
379  unsigned Reg = Addr.getReg();
380  if (Reg == 0) {
381  const GlobalValue *GV = Addr.getGlobalValue();
382  if (GV && TLI.isPositionIndependent())
383  return false;
384  Reg = createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
385  : &WebAssembly::I32RegClass);
386  unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
387  : WebAssembly::CONST_I32;
388  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
389  .addImm(0);
390  Addr.setReg(Reg);
391  }
392  }
393  return true;
394 }
395 
396 void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
397  const MachineInstrBuilder &MIB,
398  MachineMemOperand *MMO) {
399  // 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 
403  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 
413  MIB.addMemOperand(MMO);
414 }
415 
416 unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
417  return zeroExtendToI32(Reg, V, MVT::i1);
418 }
419 
420 unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
421  if (const auto *ICmp = dyn_cast<ICmpInst>(V))
422  if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
423  if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
424  Not = ICmp->isTrueWhenEqual();
425  return getRegForValue(ICmp->getOperand(0));
426  }
427 
428  Value *NotV;
429  if (match(V, m_Not(m_Value(NotV))) && V->getType()->isIntegerTy(32)) {
430  Not = true;
431  return getRegForValue(NotV);
432  }
433 
434  Not = false;
435  unsigned Reg = getRegForValue(V);
436  if (Reg == 0)
437  return 0;
438  return maskI1Value(Reg, V);
439 }
440 
441 unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
443  if (Reg == 0)
444  return 0;
445 
446  switch (From) {
447  case MVT::i1:
448  // 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);
453  break;
454  case MVT::i8:
455  case MVT::i16:
456  break;
457  case MVT::i32:
458  return copyValue(Reg);
459  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)
466  .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
467 
468  unsigned Result = createResultReg(&WebAssembly::I32RegClass);
469  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
470  TII.get(WebAssembly::AND_I32), Result)
471  .addReg(Reg)
472  .addReg(Imm);
473 
474  return Result;
475 }
476 
477 unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
479  if (Reg == 0)
480  return 0;
481 
482  switch (From) {
483  case MVT::i1:
484  case MVT::i8:
485  case MVT::i16:
486  break;
487  case MVT::i32:
488  return copyValue(Reg);
489  default:
490  return 0;
491  }
492 
493  unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
494  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
495  TII.get(WebAssembly::CONST_I32), Imm)
496  .addImm(32 - MVT(From).getSizeInBits());
497 
498  unsigned Left = createResultReg(&WebAssembly::I32RegClass);
499  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
500  TII.get(WebAssembly::SHL_I32), Left)
501  .addReg(Reg)
502  .addReg(Imm);
503 
504  unsigned Right = createResultReg(&WebAssembly::I32RegClass);
505  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
506  TII.get(WebAssembly::SHR_S_I32), Right)
507  .addReg(Left)
508  .addReg(Imm);
509 
510  return Right;
511 }
512 
513 unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
516  if (To == MVT::i64) {
517  if (From == MVT::i64)
518  return copyValue(Reg);
519 
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 
529  return zeroExtendToI32(Reg, V, From);
530 }
531 
532 unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
535  if (To == MVT::i64) {
536  if (From == MVT::i64)
537  return copyValue(Reg);
538 
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 
548  return signExtendToI32(Reg, V, From);
549 }
550 
551 unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
552  MVT::SimpleValueType From = getSimpleType(V->getType());
553  MVT::SimpleValueType To = getLegalType(From);
554  unsigned VReg = getRegForValue(V);
555  if (VReg == 0)
556  return 0;
557  return zeroExtend(VReg, V, From, To);
558 }
559 
560 unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
561  MVT::SimpleValueType From = getSimpleType(V->getType());
562  MVT::SimpleValueType To = getLegalType(From);
563  unsigned VReg = getRegForValue(V);
564  if (VReg == 0)
565  return 0;
566  return signExtend(VReg, V, From, To);
567 }
568 
569 unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
570  bool IsSigned) {
571  return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
572 }
573 
574 unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
575  assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
576 
577  unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
578  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
579  TII.get(WebAssembly::EQZ_I32), NotReg)
580  .addReg(Reg);
581  return NotReg;
582 }
583 
584 unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
585  unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
586  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
587  ResultReg)
588  .addReg(Reg);
589  return ResultReg;
590 }
591 
592 unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
594  FuncInfo.StaticAllocaMap.find(AI);
595 
596  if (SI != FuncInfo.StaticAllocaMap.end()) {
597  unsigned ResultReg =
598  createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
599  : &WebAssembly::I32RegClass);
600  unsigned Opc =
601  Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
602  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
603  .addFrameIndex(SI->second);
604  return ResultReg;
605  }
606 
607  return 0;
608 }
609 
610 unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
611  if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
612  if (TLI.isPositionIndependent())
613  return 0;
614  unsigned ResultReg =
615  createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
616  : &WebAssembly::I32RegClass);
617  unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
618  : WebAssembly::CONST_I32;
619  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
620  .addGlobalAddress(GV);
621  return ResultReg;
622  }
623 
624  // Let target-independent code handle it.
625  return 0;
626 }
627 
628 bool WebAssemblyFastISel::fastLowerArguments() {
629  if (!FuncInfo.CanLowerReturn)
630  return false;
631 
632  const Function *F = FuncInfo.Fn;
633  if (F->isVarArg())
634  return false;
635 
636  unsigned I = 0;
637  for (auto const &Arg : F->args()) {
638  const AttributeList &Attrs = F->getAttributes();
639  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))
644  return false;
645 
646  Type *ArgTy = Arg.getType();
647  if (ArgTy->isStructTy() || ArgTy->isArrayTy())
648  return false;
649  if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
650  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:
659  Opc = WebAssembly::ARGUMENT_i32;
660  RC = &WebAssembly::I32RegClass;
661  break;
662  case MVT::i64:
663  Opc = WebAssembly::ARGUMENT_i64;
664  RC = &WebAssembly::I64RegClass;
665  break;
666  case MVT::f32:
667  Opc = WebAssembly::ARGUMENT_f32;
668  RC = &WebAssembly::F32RegClass;
669  break;
670  case MVT::f64:
671  Opc = WebAssembly::ARGUMENT_f64;
672  RC = &WebAssembly::F64RegClass;
673  break;
674  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;
686  case MVT::v2i64:
687  Opc = WebAssembly::ARGUMENT_v2i64;
688  RC = &WebAssembly::V128RegClass;
689  break;
690  case MVT::v4f32:
691  Opc = WebAssembly::ARGUMENT_v4f32;
692  RC = &WebAssembly::V128RegClass;
693  break;
694  case MVT::v2f64:
695  Opc = WebAssembly::ARGUMENT_v2f64;
696  RC = &WebAssembly::V128RegClass;
697  break;
698  case MVT::ExceptRef:
699  Opc = WebAssembly::ARGUMENT_ExceptRef;
700  RC = &WebAssembly::EXCEPT_REFRegClass;
701  break;
702  default:
703  return false;
704  }
705  unsigned ResultReg = createResultReg(RC);
706  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
707  .addImm(I);
708  updateValueMap(&Arg, ResultReg);
709 
710  ++I;
711  }
712 
713  MRI.addLiveIn(WebAssembly::ARGUMENTS);
714 
715  auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
716  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  }
724 
725  if (!F->getReturnType()->isVoidTy()) {
726  MVT::SimpleValueType RetTy =
727  getLegalType(getSimpleType(F->getReturnType()));
728  if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
729  MFI->clearParamsAndResults();
730  return false;
731  }
732  MFI->addResult(RetTy);
733  }
734 
735  return true;
736 }
737 
738 bool WebAssemblyFastISel::selectCall(const Instruction *I) {
739  const auto *Call = cast<CallInst>(I);
740 
741  if (Call->isMustTailCall() || Call->isInlineAsm() ||
742  Call->getFunctionType()->isVarArg())
743  return false;
744 
745  Function *Func = Call->getCalledFunction();
746  if (Func && Func->isIntrinsic())
747  return false;
748 
749  bool IsDirect = Func != nullptr;
750  if (!IsDirect && isa<ConstantExpr>(Call->getCalledValue()))
751  return false;
752 
753  FunctionType *FuncTy = Call->getFunctionType();
754  unsigned Opc;
755  bool IsVoid = FuncTy->getReturnType()->isVoidTy();
756  unsigned ResultReg;
757  if (IsVoid) {
758  Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
759  } else {
760  if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
761  return false;
762 
763  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:
769  Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::PCALL_INDIRECT_I32;
770  ResultReg = createResultReg(&WebAssembly::I32RegClass);
771  break;
772  case MVT::i64:
773  Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::PCALL_INDIRECT_I64;
774  ResultReg = createResultReg(&WebAssembly::I64RegClass);
775  break;
776  case MVT::f32:
777  Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::PCALL_INDIRECT_F32;
778  ResultReg = createResultReg(&WebAssembly::F32RegClass);
779  break;
780  case MVT::f64:
781  Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::PCALL_INDIRECT_F64;
782  ResultReg = createResultReg(&WebAssembly::F64RegClass);
783  break;
784  case MVT::v16i8:
785  Opc = IsDirect ? WebAssembly::CALL_v16i8
786  : WebAssembly::PCALL_INDIRECT_v16i8;
787  ResultReg = createResultReg(&WebAssembly::V128RegClass);
788  break;
789  case MVT::v8i16:
790  Opc = IsDirect ? WebAssembly::CALL_v8i16
791  : WebAssembly::PCALL_INDIRECT_v8i16;
792  ResultReg = createResultReg(&WebAssembly::V128RegClass);
793  break;
794  case MVT::v4i32:
795  Opc = IsDirect ? WebAssembly::CALL_v4i32
796  : WebAssembly::PCALL_INDIRECT_v4i32;
797  ResultReg = createResultReg(&WebAssembly::V128RegClass);
798  break;
799  case MVT::v2i64:
800  Opc = IsDirect ? WebAssembly::CALL_v2i64
801  : WebAssembly::PCALL_INDIRECT_v2i64;
802  ResultReg = createResultReg(&WebAssembly::V128RegClass);
803  break;
804  case MVT::v4f32:
805  Opc = IsDirect ? WebAssembly::CALL_v4f32
806  : WebAssembly::PCALL_INDIRECT_v4f32;
807  ResultReg = createResultReg(&WebAssembly::V128RegClass);
808  break;
809  case MVT::v2f64:
810  Opc = IsDirect ? WebAssembly::CALL_v2f64
811  : WebAssembly::PCALL_INDIRECT_v2f64;
812  ResultReg = createResultReg(&WebAssembly::V128RegClass);
813  break;
814  case MVT::ExceptRef:
815  Opc = IsDirect ? WebAssembly::CALL_EXCEPT_REF
816  : WebAssembly::PCALL_INDIRECT_EXCEPT_REF;
817  ResultReg = createResultReg(&WebAssembly::EXCEPT_REFRegClass);
818  break;
819  default:
820  return false;
821  }
822  }
823 
825  for (unsigned I = 0, E = Call->getNumArgOperands(); I < E; ++I) {
826  Value *V = Call->getArgOperand(I);
827  MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
828  if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
829  return false;
830 
831  const AttributeList &Attrs = Call->getAttributes();
832  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))
837  return false;
838 
839  unsigned Reg;
840 
841  if (Attrs.hasParamAttribute(I, Attribute::SExt))
842  Reg = getRegForSignedValue(V);
843  else if (Attrs.hasParamAttribute(I, Attribute::ZExt))
844  Reg = getRegForUnsignedValue(V);
845  else
846  Reg = getRegForValue(V);
847 
848  if (Reg == 0)
849  return false;
850 
851  Args.push_back(Reg);
852  }
853 
854  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
855 
856  if (!IsVoid)
857  MIB.addReg(ResultReg, RegState::Define);
858 
859  if (IsDirect)
860  MIB.addGlobalAddress(Func);
861  else {
862  unsigned Reg = getRegForValue(Call->getCalledValue());
863  if (Reg == 0)
864  return false;
865  MIB.addReg(Reg);
866  }
867 
868  for (unsigned ArgReg : Args)
869  MIB.addReg(ArgReg);
870 
871  if (!IsVoid)
872  updateValueMap(Call, ResultReg);
873  return true;
874 }
875 
876 bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
877  const auto *Select = cast<SelectInst>(I);
878 
879  bool Not;
880  unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
881  if (CondReg == 0)
882  return false;
883 
884  unsigned TrueReg = getRegForValue(Select->getTrueValue());
885  if (TrueReg == 0)
886  return false;
887 
888  unsigned FalseReg = getRegForValue(Select->getFalseValue());
889  if (FalseReg == 0)
890  return false;
891 
892  if (Not)
893  std::swap(TrueReg, FalseReg);
894 
895  unsigned Opc;
896  const TargetRegisterClass *RC;
897  switch (getSimpleType(Select->getType())) {
898  case MVT::i1:
899  case MVT::i8:
900  case MVT::i16:
901  case MVT::i32:
902  Opc = WebAssembly::SELECT_I32;
903  RC = &WebAssembly::I32RegClass;
904  break;
905  case MVT::i64:
906  Opc = WebAssembly::SELECT_I64;
907  RC = &WebAssembly::I64RegClass;
908  break;
909  case MVT::f32:
910  Opc = WebAssembly::SELECT_F32;
911  RC = &WebAssembly::F32RegClass;
912  break;
913  case MVT::f64:
914  Opc = WebAssembly::SELECT_F64;
915  RC = &WebAssembly::F64RegClass;
916  break;
917  case MVT::ExceptRef:
918  Opc = WebAssembly::SELECT_EXCEPT_REF;
919  RC = &WebAssembly::EXCEPT_REFRegClass;
920  break;
921  default:
922  return false;
923  }
924 
925  unsigned ResultReg = createResultReg(RC);
926  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
927  .addReg(TrueReg)
928  .addReg(FalseReg)
929  .addReg(CondReg);
930 
931  updateValueMap(Select, ResultReg);
932  return true;
933 }
934 
935 bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
936  const auto *Trunc = cast<TruncInst>(I);
937 
938  unsigned Reg = getRegForValue(Trunc->getOperand(0));
939  if (Reg == 0)
940  return false;
941 
942  if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
943  unsigned Result = createResultReg(&WebAssembly::I32RegClass);
944  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
945  TII.get(WebAssembly::I32_WRAP_I64), Result)
946  .addReg(Reg);
947  Reg = Result;
948  }
949 
950  updateValueMap(Trunc, Reg);
951  return true;
952 }
953 
954 bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
955  const auto *ZExt = cast<ZExtInst>(I);
956 
957  const Value *Op = ZExt->getOperand(0);
958  MVT::SimpleValueType From = getSimpleType(Op->getType());
959  MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
960  unsigned In = getRegForValue(Op);
961  if (In == 0)
962  return false;
963  unsigned Reg = zeroExtend(In, Op, From, To);
964  if (Reg == 0)
965  return false;
966 
967  updateValueMap(ZExt, Reg);
968  return true;
969 }
970 
971 bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
972  const auto *SExt = cast<SExtInst>(I);
973 
974  const Value *Op = SExt->getOperand(0);
975  MVT::SimpleValueType From = getSimpleType(Op->getType());
976  MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
977  unsigned In = getRegForValue(Op);
978  if (In == 0)
979  return false;
980  unsigned Reg = signExtend(In, Op, From, To);
981  if (Reg == 0)
982  return false;
983 
984  updateValueMap(SExt, Reg);
985  return true;
986 }
987 
988 bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
989  const auto *ICmp = cast<ICmpInst>(I);
990 
991  bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
992  unsigned Opc;
993  bool IsSigned = false;
994  switch (ICmp->getPredicate()) {
995  case ICmpInst::ICMP_EQ:
996  Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
997  break;
998  case ICmpInst::ICMP_NE:
999  Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1000  break;
1001  case ICmpInst::ICMP_UGT:
1002  Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1003  break;
1004  case ICmpInst::ICMP_UGE:
1005  Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1006  break;
1007  case ICmpInst::ICMP_ULT:
1008  Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1009  break;
1010  case ICmpInst::ICMP_ULE:
1011  Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1012  break;
1013  case ICmpInst::ICMP_SGT:
1014  Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1015  IsSigned = true;
1016  break;
1017  case ICmpInst::ICMP_SGE:
1018  Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1019  IsSigned = true;
1020  break;
1021  case ICmpInst::ICMP_SLT:
1022  Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1023  IsSigned = true;
1024  break;
1025  case ICmpInst::ICMP_SLE:
1026  Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1027  IsSigned = true;
1028  break;
1029  default:
1030  return false;
1031  }
1032 
1033  unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
1034  if (LHS == 0)
1035  return false;
1036 
1037  unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
1038  if (RHS == 0)
1039  return false;
1040 
1041  unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1042  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1043  .addReg(LHS)
1044  .addReg(RHS);
1045  updateValueMap(ICmp, ResultReg);
1046  return true;
1047 }
1048 
1049 bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
1050  const auto *FCmp = cast<FCmpInst>(I);
1051 
1052  unsigned LHS = getRegForValue(FCmp->getOperand(0));
1053  if (LHS == 0)
1054  return false;
1055 
1056  unsigned RHS = getRegForValue(FCmp->getOperand(1));
1057  if (RHS == 0)
1058  return false;
1059 
1060  bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1061  unsigned Opc;
1062  bool Not = false;
1063  switch (FCmp->getPredicate()) {
1064  case FCmpInst::FCMP_OEQ:
1065  Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1066  break;
1067  case FCmpInst::FCMP_UNE:
1068  Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1069  break;
1070  case FCmpInst::FCMP_OGT:
1071  Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1072  break;
1073  case FCmpInst::FCMP_OGE:
1074  Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1075  break;
1076  case FCmpInst::FCMP_OLT:
1077  Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1078  break;
1079  case FCmpInst::FCMP_OLE:
1080  Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1081  break;
1082  case FCmpInst::FCMP_UGT:
1083  Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1084  Not = true;
1085  break;
1086  case FCmpInst::FCMP_UGE:
1087  Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1088  Not = true;
1089  break;
1090  case FCmpInst::FCMP_ULT:
1091  Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1092  Not = true;
1093  break;
1094  case FCmpInst::FCMP_ULE:
1095  Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1096  Not = true;
1097  break;
1098  default:
1099  return false;
1100  }
1101 
1102  unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1103  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1104  .addReg(LHS)
1105  .addReg(RHS);
1106 
1107  if (Not)
1108  ResultReg = notValue(ResultReg);
1109 
1110  updateValueMap(FCmp, ResultReg);
1111  return true;
1112 }
1113 
1114 bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
1115  // Target-independent code can handle this, except it doesn't set the dead
1116  // flag on the ARGUMENTS clobber, so we have to do that manually in order
1117  // to satisfy code that expects this of isBitcast() instructions.
1118  EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
1119  EVT RetVT = TLI.getValueType(DL, I->getType());
1120  if (!VT.isSimple() || !RetVT.isSimple())
1121  return false;
1122 
1123  unsigned In = getRegForValue(I->getOperand(0));
1124  if (In == 0)
1125  return false;
1126 
1127  if (VT == RetVT) {
1128  // No-op bitcast.
1129  updateValueMap(I, In);
1130  return true;
1131  }
1132 
1133  unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
1134  In, I->getOperand(0)->hasOneUse());
1135  if (!Reg)
1136  return false;
1137  MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
1138  --Iter;
1139  assert(Iter->isBitcast());
1140  Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI);
1141  updateValueMap(I, Reg);
1142  return true;
1143 }
1144 
1145 bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
1146  const auto *Load = cast<LoadInst>(I);
1147  if (Load->isAtomic())
1148  return false;
1149  if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
1150  return false;
1151 
1152  Address Addr;
1153  if (!computeAddress(Load->getPointerOperand(), Addr))
1154  return false;
1155 
1156  // TODO: Fold a following sign-/zero-extend into the load instruction.
1157 
1158  unsigned Opc;
1159  const TargetRegisterClass *RC;
1160  switch (getSimpleType(Load->getType())) {
1161  case MVT::i1:
1162  case MVT::i8:
1163  Opc = WebAssembly::LOAD8_U_I32;
1164  RC = &WebAssembly::I32RegClass;
1165  break;
1166  case MVT::i16:
1167  Opc = WebAssembly::LOAD16_U_I32;
1168  RC = &WebAssembly::I32RegClass;
1169  break;
1170  case MVT::i32:
1171  Opc = WebAssembly::LOAD_I32;
1172  RC = &WebAssembly::I32RegClass;
1173  break;
1174  case MVT::i64:
1175  Opc = WebAssembly::LOAD_I64;
1176  RC = &WebAssembly::I64RegClass;
1177  break;
1178  case MVT::f32:
1179  Opc = WebAssembly::LOAD_F32;
1180  RC = &WebAssembly::F32RegClass;
1181  break;
1182  case MVT::f64:
1183  Opc = WebAssembly::LOAD_F64;
1184  RC = &WebAssembly::F64RegClass;
1185  break;
1186  default:
1187  return false;
1188  }
1189 
1190  if (!materializeLoadStoreOperands(Addr))
1191  return false;
1192 
1193  unsigned ResultReg = createResultReg(RC);
1194  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
1195  ResultReg);
1196 
1197  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1198 
1199  updateValueMap(Load, ResultReg);
1200  return true;
1201 }
1202 
1203 bool WebAssemblyFastISel::selectStore(const Instruction *I) {
1204  const auto *Store = cast<StoreInst>(I);
1205  if (Store->isAtomic())
1206  return false;
1207  if (!Subtarget->hasSIMD128() &&
1208  Store->getValueOperand()->getType()->isVectorTy())
1209  return false;
1210 
1211  Address Addr;
1212  if (!computeAddress(Store->getPointerOperand(), Addr))
1213  return false;
1214 
1215  unsigned Opc;
1216  bool VTIsi1 = false;
1217  switch (getSimpleType(Store->getValueOperand()->getType())) {
1218  case MVT::i1:
1219  VTIsi1 = true;
1221  case MVT::i8:
1222  Opc = WebAssembly::STORE8_I32;
1223  break;
1224  case MVT::i16:
1225  Opc = WebAssembly::STORE16_I32;
1226  break;
1227  case MVT::i32:
1228  Opc = WebAssembly::STORE_I32;
1229  break;
1230  case MVT::i64:
1231  Opc = WebAssembly::STORE_I64;
1232  break;
1233  case MVT::f32:
1234  Opc = WebAssembly::STORE_F32;
1235  break;
1236  case MVT::f64:
1237  Opc = WebAssembly::STORE_F64;
1238  break;
1239  default:
1240  return false;
1241  }
1242 
1243  if (!materializeLoadStoreOperands(Addr))
1244  return false;
1245 
1246  unsigned ValueReg = getRegForValue(Store->getValueOperand());
1247  if (ValueReg == 0)
1248  return false;
1249  if (VTIsi1)
1250  ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
1251 
1252  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
1253 
1254  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1255 
1256  MIB.addReg(ValueReg);
1257  return true;
1258 }
1259 
1260 bool WebAssemblyFastISel::selectBr(const Instruction *I) {
1261  const auto *Br = cast<BranchInst>(I);
1262  if (Br->isUnconditional()) {
1263  MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
1264  fastEmitBranch(MSucc, Br->getDebugLoc());
1265  return true;
1266  }
1267 
1268  MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
1269  MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
1270 
1271  bool Not;
1272  unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
1273  if (CondReg == 0)
1274  return false;
1275 
1276  unsigned Opc = WebAssembly::BR_IF;
1277  if (Not)
1278  Opc = WebAssembly::BR_UNLESS;
1279 
1280  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1281  .addMBB(TBB)
1282  .addReg(CondReg);
1283 
1284  finishCondBranch(Br->getParent(), TBB, FBB);
1285  return true;
1286 }
1287 
1288 bool WebAssemblyFastISel::selectRet(const Instruction *I) {
1289  if (!FuncInfo.CanLowerReturn)
1290  return false;
1291 
1292  const auto *Ret = cast<ReturnInst>(I);
1293 
1294  if (Ret->getNumOperands() == 0) {
1295  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1296  TII.get(WebAssembly::RETURN_VOID));
1297  return true;
1298  }
1299 
1300  Value *RV = Ret->getOperand(0);
1301  if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
1302  return false;
1303 
1304  unsigned Opc;
1305  switch (getSimpleType(RV->getType())) {
1306  case MVT::i1:
1307  case MVT::i8:
1308  case MVT::i16:
1309  case MVT::i32:
1310  Opc = WebAssembly::RETURN_I32;
1311  break;
1312  case MVT::i64:
1313  Opc = WebAssembly::RETURN_I64;
1314  break;
1315  case MVT::f32:
1316  Opc = WebAssembly::RETURN_F32;
1317  break;
1318  case MVT::f64:
1319  Opc = WebAssembly::RETURN_F64;
1320  break;
1321  case MVT::v16i8:
1322  Opc = WebAssembly::RETURN_v16i8;
1323  break;
1324  case MVT::v8i16:
1325  Opc = WebAssembly::RETURN_v8i16;
1326  break;
1327  case MVT::v4i32:
1328  Opc = WebAssembly::RETURN_v4i32;
1329  break;
1330  case MVT::v2i64:
1331  Opc = WebAssembly::RETURN_v2i64;
1332  break;
1333  case MVT::v4f32:
1334  Opc = WebAssembly::RETURN_v4f32;
1335  break;
1336  case MVT::v2f64:
1337  Opc = WebAssembly::RETURN_v2f64;
1338  break;
1339  case MVT::ExceptRef:
1340  Opc = WebAssembly::RETURN_EXCEPT_REF;
1341  break;
1342  default:
1343  return false;
1344  }
1345 
1346  unsigned Reg;
1347  if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
1348  Reg = getRegForSignedValue(RV);
1349  else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
1350  Reg = getRegForUnsignedValue(RV);
1351  else
1352  Reg = getRegForValue(RV);
1353 
1354  if (Reg == 0)
1355  return false;
1356 
1357  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg);
1358  return true;
1359 }
1360 
1361 bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
1362  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1363  TII.get(WebAssembly::UNREACHABLE));
1364  return true;
1365 }
1366 
1367 bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
1368  switch (I->getOpcode()) {
1369  case Instruction::Call:
1370  if (selectCall(I))
1371  return true;
1372  break;
1373  case Instruction::Select:
1374  return selectSelect(I);
1375  case Instruction::Trunc:
1376  return selectTrunc(I);
1377  case Instruction::ZExt:
1378  return selectZExt(I);
1379  case Instruction::SExt:
1380  return selectSExt(I);
1381  case Instruction::ICmp:
1382  return selectICmp(I);
1383  case Instruction::FCmp:
1384  return selectFCmp(I);
1385  case Instruction::BitCast:
1386  return selectBitCast(I);
1387  case Instruction::Load:
1388  return selectLoad(I);
1389  case Instruction::Store:
1390  return selectStore(I);
1391  case Instruction::Br:
1392  return selectBr(I);
1393  case Instruction::Ret:
1394  return selectRet(I);
1395  case Instruction::Unreachable:
1396  return selectUnreachable(I);
1397  default:
1398  break;
1399  }
1400 
1401  // Fall back to target-independent instruction selection.
1402  return selectOperator(I, I->getOpcode());
1403 }
1404 
1406  const TargetLibraryInfo *LibInfo) {
1407  return new WebAssemblyFastISel(FuncInfo, LibInfo);
1408 }
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Definition: Function.h:176
uint64_t CallInst * C
bool isIntrinsic() const
isIntrinsic - Returns true if the function&#39;s name starts with "llvm.".
Definition: Function.h:198
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
Definition: PatternMatch.h:70
LLVMContext & Context
This class represents lattice values for constants.
Definition: AllocatorList.h:23
void push_back(const T &Elt)
Definition: SmallVector.h:211
unsigned Reg
MVT getSimpleVT() const
Return the SimpleValueType held in the specified simple EVT.
Definition: ValueTypes.h:252
gep_type_iterator gep_type_end(const User *GEP)
unsigned less or equal
Definition: InstrTypes.h:672
unsigned less than
Definition: InstrTypes.h:671
0 1 0 0 True if ordered and less than
Definition: InstrTypes.h:652
1 1 1 0 True if unordered or not equal
Definition: InstrTypes.h:662
unsigned const TargetRegisterInfo * TRI
F(f)
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
bool isVectorTy() const
True if this is an instance of VectorType.
Definition: Type.h:229
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
bool match(Val *V, const Pattern &P)
Definition: PatternMatch.h:47
FastISel * createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo)
Used to lazily calculate structure layout information for a target machine, based on the DataLayout s...
Definition: DataLayout.h:554
A description of a memory reference used in the backend.
This file declares the MachineConstantPool class which is an abstract constant pool to keep track of ...
const HexagonInstrInfo * TII
Class to represent struct types.
Definition: DerivedTypes.h:232
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:196
0 1 0 1 True if ordered and less than or equal
Definition: InstrTypes.h:653
SimpleValueType SimpleTy
unsigned getSizeInBits() const
This is a fast-path instruction selection class that generates poor code and doesn&#39;t support illegal ...
Definition: FastISel.h:66
Class to represent function types.
Definition: DerivedTypes.h:102
This file declares the WebAssembly-specific subclass of TargetMachine.
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:244
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Definition: Instruction.h:125
AttributeList getAttributes() const
Return the attribute list for this Function.
Definition: Function.h:223
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
constexpr char Attrs[]
Key for Kernel::Metadata::mAttrs.
Value * getOperand(unsigned i) const
Definition: User.h:169
bool isVoidTy() const
Return true if this is &#39;void&#39;.
Definition: Type.h:140
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
Type * getReturnType() const
Returns the type of the ret val.
Definition: Function.h:168
unsigned const MachineRegisterInfo * MRI
Machine Value Type.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
The instances of the Type class are immutable: once they are created, they are never changed...
Definition: Type.h:45
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:64
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This is an important base class in LLVM.
Definition: Constant.h:41
This file provides WebAssembly-specific target descriptions.
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
const MachineInstrBuilder & addFrameIndex(int Idx) const
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:192
Extended Value Type.
Definition: ValueTypes.h:33
1 1 0 1 True if unordered, less than, or equal
Definition: InstrTypes.h:661
signed greater than
Definition: InstrTypes.h:673
0 0 1 0 True if ordered and greater than
Definition: InstrTypes.h:650
This file declares the WebAssembly-specific subclass of TargetSubtarget.
bool hasParamAttribute(unsigned ArgNo, Attribute::AttrKind Kind) const
Equivalent to hasAttribute(ArgNo + FirstArgIndex, Kind).
This is the shared class of boolean and integer constants.
Definition: Constants.h:83
BlockVerifier::State From
1 1 0 0 True if unordered or less than
Definition: InstrTypes.h:660
Provides information about what library functions are available for the current target.
const DataFlowGraph & G
Definition: RDFGraph.cpp:202
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
signed less than
Definition: InstrTypes.h:675
Type * getReturnType() const
Definition: DerivedTypes.h:123
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:940
signed less or equal
Definition: InstrTypes.h:676
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
This file defines the FastISel class.
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
uint64_t getElementOffset(unsigned Idx) const
Definition: DataLayout.h:576
unsigned greater or equal
Definition: InstrTypes.h:670
#define I(x, y, z)
Definition: MD5.cpp:58
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
This file declares WebAssembly-specific per-machine-function information.
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
1 0 1 0 True if unordered or greater than
Definition: InstrTypes.h:658
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
0 0 0 1 True if ordered and equal
Definition: InstrTypes.h:649
LLVM Value Representation.
Definition: Value.h:72
unsigned getSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
1 0 1 1 True if unordered, greater than, or equal
Definition: InstrTypes.h:659
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:250
bool hasOneUse() const
Return true if there is exactly one user of this value.
Definition: Value.h:412
unsigned greater than
Definition: InstrTypes.h:669
bool isSimple() const
Test if the given EVT is simple (as opposed to being extended).
Definition: ValueTypes.h:125
0 0 1 1 True if ordered and greater than or equal
Definition: InstrTypes.h:651
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
BinaryOp_match< ValTy, cst_pred_ty< is_all_ones >, Instruction::Xor, true > m_Not(const ValTy &V)
Matches a &#39;Not&#39; as &#39;xor V, -1&#39; or &#39;xor -1, V&#39;.
iterator_range< arg_iterator > args()
Definition: Function.h:691
bool isStructTy() const
True if this is an instance of StructType.
Definition: Type.h:217
signed greater or equal
Definition: InstrTypes.h:674
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition: Type.h:220
an instruction to allocate memory on the stack
Definition: Instructions.h:59
gep_type_iterator gep_type_begin(const User *GEP)