LLVM  10.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, /*AllowUnknown=*/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::exnref:
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  void 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  const User *U = nullptr;
211  unsigned Opcode = Instruction::UserOp1;
212  if (const auto *I = dyn_cast<Instruction>(Obj)) {
213  // Don't walk into other basic blocks unless the object is an alloca from
214  // another block, otherwise it may not have a virtual register assigned.
215  if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
216  FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
217  Opcode = I->getOpcode();
218  U = I;
219  }
220  } else if (const auto *C = dyn_cast<ConstantExpr>(Obj)) {
221  Opcode = C->getOpcode();
222  U = C;
223  }
224 
225  if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
226  if (Ty->getAddressSpace() > 255)
227  // Fast instruction selection doesn't support the special
228  // address spaces.
229  return false;
230 
231  if (const auto *GV = dyn_cast<GlobalValue>(Obj)) {
232  if (TLI.isPositionIndependent())
233  return false;
234  if (Addr.getGlobalValue())
235  return false;
236  if (GV->isThreadLocal())
237  return false;
238  Addr.setGlobalValue(GV);
239  return true;
240  }
241 
242  switch (Opcode) {
243  default:
244  break;
245  case Instruction::BitCast: {
246  // Look through bitcasts.
247  return computeAddress(U->getOperand(0), Addr);
248  }
249  case Instruction::IntToPtr: {
250  // Look past no-op inttoptrs.
251  if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
252  TLI.getPointerTy(DL))
253  return computeAddress(U->getOperand(0), Addr);
254  break;
255  }
256  case Instruction::PtrToInt: {
257  // Look past no-op ptrtoints.
258  if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
259  return computeAddress(U->getOperand(0), Addr);
260  break;
261  }
262  case Instruction::GetElementPtr: {
263  Address SavedAddr = Addr;
264  uint64_t TmpOffset = Addr.getOffset();
265  // Non-inbounds geps can wrap; wasm's offsets can't.
266  if (!cast<GEPOperator>(U)->isInBounds())
267  goto unsupported_gep;
268  // Iterate through the GEP folding the constants into offsets where
269  // we can.
270  for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
271  GTI != E; ++GTI) {
272  const Value *Op = GTI.getOperand();
273  if (StructType *STy = GTI.getStructTypeOrNull()) {
274  const StructLayout *SL = DL.getStructLayout(STy);
275  unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
276  TmpOffset += SL->getElementOffset(Idx);
277  } else {
278  uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
279  for (;;) {
280  if (const auto *CI = dyn_cast<ConstantInt>(Op)) {
281  // Constant-offset addressing.
282  TmpOffset += CI->getSExtValue() * S;
283  break;
284  }
285  if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
286  // An unscaled add of a register. Set it as the new base.
287  unsigned Reg = getRegForValue(Op);
288  if (Reg == 0)
289  return false;
290  Addr.setReg(Reg);
291  break;
292  }
293  if (canFoldAddIntoGEP(U, Op)) {
294  // A compatible add with a constant operand. Fold the constant.
295  auto *CI = cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
296  TmpOffset += CI->getSExtValue() * S;
297  // Iterate on the other operand.
298  Op = cast<AddOperator>(Op)->getOperand(0);
299  continue;
300  }
301  // Unsupported
302  goto unsupported_gep;
303  }
304  }
305  }
306  // Don't fold in negative offsets.
307  if (int64_t(TmpOffset) >= 0) {
308  // Try to grab the base operand now.
309  Addr.setOffset(TmpOffset);
310  if (computeAddress(U->getOperand(0), Addr))
311  return true;
312  }
313  // We failed, restore everything and try the other options.
314  Addr = SavedAddr;
315  unsupported_gep:
316  break;
317  }
318  case Instruction::Alloca: {
319  const auto *AI = cast<AllocaInst>(Obj);
321  FuncInfo.StaticAllocaMap.find(AI);
322  if (SI != FuncInfo.StaticAllocaMap.end()) {
323  if (Addr.isSet()) {
324  return false;
325  }
326  Addr.setKind(Address::FrameIndexBase);
327  Addr.setFI(SI->second);
328  return true;
329  }
330  break;
331  }
332  case Instruction::Add: {
333  // Adds of constants are common and easy enough.
334  const Value *LHS = U->getOperand(0);
335  const Value *RHS = U->getOperand(1);
336 
337  if (isa<ConstantInt>(LHS))
338  std::swap(LHS, RHS);
339 
340  if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
341  uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
342  if (int64_t(TmpOffset) >= 0) {
343  Addr.setOffset(TmpOffset);
344  return computeAddress(LHS, Addr);
345  }
346  }
347 
348  Address Backup = Addr;
349  if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
350  return true;
351  Addr = Backup;
352 
353  break;
354  }
355  case Instruction::Sub: {
356  // Subs of constants are common and easy enough.
357  const Value *LHS = U->getOperand(0);
358  const Value *RHS = U->getOperand(1);
359 
360  if (const auto *CI = dyn_cast<ConstantInt>(RHS)) {
361  int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
362  if (TmpOffset >= 0) {
363  Addr.setOffset(TmpOffset);
364  return computeAddress(LHS, Addr);
365  }
366  }
367  break;
368  }
369  }
370  if (Addr.isSet()) {
371  return false;
372  }
373  unsigned Reg = getRegForValue(Obj);
374  if (Reg == 0)
375  return false;
376  Addr.setReg(Reg);
377  return Addr.getReg() != 0;
378 }
379 
380 void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
381  if (Addr.isRegBase()) {
382  unsigned Reg = Addr.getReg();
383  if (Reg == 0) {
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 }
394 
395 void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
396  const MachineInstrBuilder &MIB,
397  MachineMemOperand *MMO) {
398  // Set the alignment operand (this is rewritten in SetP2AlignOperands).
399  // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
400  MIB.addImm(0);
401 
402  if (const GlobalValue *GV = Addr.getGlobalValue())
403  MIB.addGlobalAddress(GV, Addr.getOffset());
404  else
405  MIB.addImm(Addr.getOffset());
406 
407  if (Addr.isRegBase())
408  MIB.addReg(Addr.getReg());
409  else
410  MIB.addFrameIndex(Addr.getFI());
411 
412  MIB.addMemOperand(MMO);
413 }
414 
415 unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
416  return zeroExtendToI32(Reg, V, MVT::i1);
417 }
418 
419 unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
420  if (const auto *ICmp = dyn_cast<ICmpInst>(V))
421  if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
422  if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
423  Not = ICmp->isTrueWhenEqual();
424  return getRegForValue(ICmp->getOperand(0));
425  }
426 
427  Value *NotV;
428  if (match(V, m_Not(m_Value(NotV))) && V->getType()->isIntegerTy(32)) {
429  Not = true;
430  return getRegForValue(NotV);
431  }
432 
433  Not = false;
434  unsigned Reg = getRegForValue(V);
435  if (Reg == 0)
436  return 0;
437  return maskI1Value(Reg, V);
438 }
439 
440 unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
442  if (Reg == 0)
443  return 0;
444 
445  switch (From) {
446  case MVT::i1:
447  // If the value is naturally an i1, we don't need to mask it. We only know
448  // if a value is naturally an i1 if it is definitely lowered by FastISel,
449  // not a DAG ISel fallback.
450  if (V != nullptr && isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr())
451  return copyValue(Reg);
452  break;
453  case MVT::i8:
454  case MVT::i16:
455  break;
456  case MVT::i32:
457  return copyValue(Reg);
458  default:
459  return 0;
460  }
461 
462  unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
463  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
464  TII.get(WebAssembly::CONST_I32), Imm)
465  .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
466 
467  unsigned Result = createResultReg(&WebAssembly::I32RegClass);
468  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
469  TII.get(WebAssembly::AND_I32), Result)
470  .addReg(Reg)
471  .addReg(Imm);
472 
473  return Result;
474 }
475 
476 unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
478  if (Reg == 0)
479  return 0;
480 
481  switch (From) {
482  case MVT::i1:
483  case MVT::i8:
484  case MVT::i16:
485  break;
486  case MVT::i32:
487  return copyValue(Reg);
488  default:
489  return 0;
490  }
491 
492  unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
493  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
494  TII.get(WebAssembly::CONST_I32), Imm)
495  .addImm(32 - MVT(From).getSizeInBits());
496 
497  unsigned Left = createResultReg(&WebAssembly::I32RegClass);
498  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
499  TII.get(WebAssembly::SHL_I32), Left)
500  .addReg(Reg)
501  .addReg(Imm);
502 
503  unsigned Right = createResultReg(&WebAssembly::I32RegClass);
504  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
505  TII.get(WebAssembly::SHR_S_I32), Right)
506  .addReg(Left)
507  .addReg(Imm);
508 
509  return Right;
510 }
511 
512 unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
515  if (To == MVT::i64) {
516  if (From == MVT::i64)
517  return copyValue(Reg);
518 
519  Reg = zeroExtendToI32(Reg, V, From);
520 
521  unsigned Result = createResultReg(&WebAssembly::I64RegClass);
522  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
523  TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
524  .addReg(Reg);
525  return Result;
526  }
527 
528  if (To == MVT::i32)
529  return zeroExtendToI32(Reg, V, From);
530 
531  return 0;
532 }
533 
534 unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
537  if (To == MVT::i64) {
538  if (From == MVT::i64)
539  return copyValue(Reg);
540 
541  Reg = signExtendToI32(Reg, V, From);
542 
543  unsigned Result = createResultReg(&WebAssembly::I64RegClass);
544  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
545  TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
546  .addReg(Reg);
547  return Result;
548  }
549 
550  if (To == MVT::i32)
551  return signExtendToI32(Reg, V, From);
552 
553  return 0;
554 }
555 
556 unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
557  MVT::SimpleValueType From = getSimpleType(V->getType());
558  MVT::SimpleValueType To = getLegalType(From);
559  unsigned VReg = getRegForValue(V);
560  if (VReg == 0)
561  return 0;
562  return zeroExtend(VReg, V, From, To);
563 }
564 
565 unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
566  MVT::SimpleValueType From = getSimpleType(V->getType());
567  MVT::SimpleValueType To = getLegalType(From);
568  unsigned VReg = getRegForValue(V);
569  if (VReg == 0)
570  return 0;
571  return signExtend(VReg, V, From, To);
572 }
573 
574 unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
575  bool IsSigned) {
576  return IsSigned ? getRegForSignedValue(V) : getRegForUnsignedValue(V);
577 }
578 
579 unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
580  assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
581 
582  unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
583  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
584  TII.get(WebAssembly::EQZ_I32), NotReg)
585  .addReg(Reg);
586  return NotReg;
587 }
588 
589 unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
590  unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
591  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(WebAssembly::COPY),
592  ResultReg)
593  .addReg(Reg);
594  return ResultReg;
595 }
596 
597 unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
599  FuncInfo.StaticAllocaMap.find(AI);
600 
601  if (SI != FuncInfo.StaticAllocaMap.end()) {
602  unsigned ResultReg =
603  createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
604  : &WebAssembly::I32RegClass);
605  unsigned Opc =
606  Subtarget->hasAddr64() ? WebAssembly::COPY_I64 : WebAssembly::COPY_I32;
607  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
608  .addFrameIndex(SI->second);
609  return ResultReg;
610  }
611 
612  return 0;
613 }
614 
615 unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
616  if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
617  if (TLI.isPositionIndependent())
618  return 0;
619  if (GV->isThreadLocal())
620  return 0;
621  unsigned ResultReg =
622  createResultReg(Subtarget->hasAddr64() ? &WebAssembly::I64RegClass
623  : &WebAssembly::I32RegClass);
624  unsigned Opc = Subtarget->hasAddr64() ? WebAssembly::CONST_I64
625  : WebAssembly::CONST_I32;
626  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
627  .addGlobalAddress(GV);
628  return ResultReg;
629  }
630 
631  // Let target-independent code handle it.
632  return 0;
633 }
634 
635 bool WebAssemblyFastISel::fastLowerArguments() {
636  if (!FuncInfo.CanLowerReturn)
637  return false;
638 
639  const Function *F = FuncInfo.Fn;
640  if (F->isVarArg())
641  return false;
642 
643  unsigned I = 0;
644  for (auto const &Arg : F->args()) {
645  const AttributeList &Attrs = F->getAttributes();
646  if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
647  Attrs.hasParamAttribute(I, Attribute::SwiftSelf) ||
648  Attrs.hasParamAttribute(I, Attribute::SwiftError) ||
649  Attrs.hasParamAttribute(I, Attribute::InAlloca) ||
650  Attrs.hasParamAttribute(I, Attribute::Nest))
651  return false;
652 
653  Type *ArgTy = Arg.getType();
654  if (ArgTy->isStructTy() || ArgTy->isArrayTy())
655  return false;
656  if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
657  return false;
658 
659  unsigned Opc;
660  const TargetRegisterClass *RC;
661  switch (getSimpleType(ArgTy)) {
662  case MVT::i1:
663  case MVT::i8:
664  case MVT::i16:
665  case MVT::i32:
666  Opc = WebAssembly::ARGUMENT_i32;
667  RC = &WebAssembly::I32RegClass;
668  break;
669  case MVT::i64:
670  Opc = WebAssembly::ARGUMENT_i64;
671  RC = &WebAssembly::I64RegClass;
672  break;
673  case MVT::f32:
674  Opc = WebAssembly::ARGUMENT_f32;
675  RC = &WebAssembly::F32RegClass;
676  break;
677  case MVT::f64:
678  Opc = WebAssembly::ARGUMENT_f64;
679  RC = &WebAssembly::F64RegClass;
680  break;
681  case MVT::v16i8:
682  Opc = WebAssembly::ARGUMENT_v16i8;
683  RC = &WebAssembly::V128RegClass;
684  break;
685  case MVT::v8i16:
686  Opc = WebAssembly::ARGUMENT_v8i16;
687  RC = &WebAssembly::V128RegClass;
688  break;
689  case MVT::v4i32:
690  Opc = WebAssembly::ARGUMENT_v4i32;
691  RC = &WebAssembly::V128RegClass;
692  break;
693  case MVT::v2i64:
694  Opc = WebAssembly::ARGUMENT_v2i64;
695  RC = &WebAssembly::V128RegClass;
696  break;
697  case MVT::v4f32:
698  Opc = WebAssembly::ARGUMENT_v4f32;
699  RC = &WebAssembly::V128RegClass;
700  break;
701  case MVT::v2f64:
702  Opc = WebAssembly::ARGUMENT_v2f64;
703  RC = &WebAssembly::V128RegClass;
704  break;
705  case MVT::exnref:
706  Opc = WebAssembly::ARGUMENT_exnref;
707  RC = &WebAssembly::EXNREFRegClass;
708  break;
709  default:
710  return false;
711  }
712  unsigned ResultReg = createResultReg(RC);
713  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
714  .addImm(I);
715  updateValueMap(&Arg, ResultReg);
716 
717  ++I;
718  }
719 
720  MRI.addLiveIn(WebAssembly::ARGUMENTS);
721 
722  auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
723  for (auto const &Arg : F->args()) {
724  MVT::SimpleValueType ArgTy = getLegalType(getSimpleType(Arg.getType()));
725  if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
726  MFI->clearParamsAndResults();
727  return false;
728  }
729  MFI->addParam(ArgTy);
730  }
731 
732  if (!F->getReturnType()->isVoidTy()) {
733  MVT::SimpleValueType RetTy =
734  getLegalType(getSimpleType(F->getReturnType()));
735  if (RetTy == MVT::INVALID_SIMPLE_VALUE_TYPE) {
736  MFI->clearParamsAndResults();
737  return false;
738  }
739  MFI->addResult(RetTy);
740  }
741 
742  return true;
743 }
744 
745 bool WebAssemblyFastISel::selectCall(const Instruction *I) {
746  const auto *Call = cast<CallInst>(I);
747 
748  // TODO: Support tail calls in FastISel
749  if (Call->isMustTailCall() || Call->isInlineAsm() ||
750  Call->getFunctionType()->isVarArg())
751  return false;
752 
753  Function *Func = Call->getCalledFunction();
754  if (Func && Func->isIntrinsic())
755  return false;
756 
757  bool IsDirect = Func != nullptr;
758  if (!IsDirect && isa<ConstantExpr>(Call->getCalledValue()))
759  return false;
760 
761  FunctionType *FuncTy = Call->getFunctionType();
762  unsigned Opc;
763  bool IsVoid = FuncTy->getReturnType()->isVoidTy();
764  unsigned ResultReg;
765  if (IsVoid) {
766  Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
767  } else {
768  if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
769  return false;
770 
771  MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
772  switch (RetTy) {
773  case MVT::i1:
774  case MVT::i8:
775  case MVT::i16:
776  case MVT::i32:
777  Opc = IsDirect ? WebAssembly::CALL_i32 : WebAssembly::PCALL_INDIRECT_i32;
778  ResultReg = createResultReg(&WebAssembly::I32RegClass);
779  break;
780  case MVT::i64:
781  Opc = IsDirect ? WebAssembly::CALL_i64 : WebAssembly::PCALL_INDIRECT_i64;
782  ResultReg = createResultReg(&WebAssembly::I64RegClass);
783  break;
784  case MVT::f32:
785  Opc = IsDirect ? WebAssembly::CALL_f32 : WebAssembly::PCALL_INDIRECT_f32;
786  ResultReg = createResultReg(&WebAssembly::F32RegClass);
787  break;
788  case MVT::f64:
789  Opc = IsDirect ? WebAssembly::CALL_f64 : WebAssembly::PCALL_INDIRECT_f64;
790  ResultReg = createResultReg(&WebAssembly::F64RegClass);
791  break;
792  case MVT::v16i8:
793  Opc = IsDirect ? WebAssembly::CALL_v16i8
794  : WebAssembly::PCALL_INDIRECT_v16i8;
795  ResultReg = createResultReg(&WebAssembly::V128RegClass);
796  break;
797  case MVT::v8i16:
798  Opc = IsDirect ? WebAssembly::CALL_v8i16
799  : WebAssembly::PCALL_INDIRECT_v8i16;
800  ResultReg = createResultReg(&WebAssembly::V128RegClass);
801  break;
802  case MVT::v4i32:
803  Opc = IsDirect ? WebAssembly::CALL_v4i32
804  : WebAssembly::PCALL_INDIRECT_v4i32;
805  ResultReg = createResultReg(&WebAssembly::V128RegClass);
806  break;
807  case MVT::v2i64:
808  Opc = IsDirect ? WebAssembly::CALL_v2i64
809  : WebAssembly::PCALL_INDIRECT_v2i64;
810  ResultReg = createResultReg(&WebAssembly::V128RegClass);
811  break;
812  case MVT::v4f32:
813  Opc = IsDirect ? WebAssembly::CALL_v4f32
814  : WebAssembly::PCALL_INDIRECT_v4f32;
815  ResultReg = createResultReg(&WebAssembly::V128RegClass);
816  break;
817  case MVT::v2f64:
818  Opc = IsDirect ? WebAssembly::CALL_v2f64
819  : WebAssembly::PCALL_INDIRECT_v2f64;
820  ResultReg = createResultReg(&WebAssembly::V128RegClass);
821  break;
822  case MVT::exnref:
823  Opc = IsDirect ? WebAssembly::CALL_exnref
824  : WebAssembly::PCALL_INDIRECT_exnref;
825  ResultReg = createResultReg(&WebAssembly::EXNREFRegClass);
826  break;
827  default:
828  return false;
829  }
830  }
831 
833  for (unsigned I = 0, E = Call->getNumArgOperands(); I < E; ++I) {
834  Value *V = Call->getArgOperand(I);
835  MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
836  if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
837  return false;
838 
839  const AttributeList &Attrs = Call->getAttributes();
840  if (Attrs.hasParamAttribute(I, Attribute::ByVal) ||
841  Attrs.hasParamAttribute(I, Attribute::SwiftSelf) ||
842  Attrs.hasParamAttribute(I, Attribute::SwiftError) ||
843  Attrs.hasParamAttribute(I, Attribute::InAlloca) ||
844  Attrs.hasParamAttribute(I, Attribute::Nest))
845  return false;
846 
847  unsigned Reg;
848 
849  if (Attrs.hasParamAttribute(I, Attribute::SExt))
850  Reg = getRegForSignedValue(V);
851  else if (Attrs.hasParamAttribute(I, Attribute::ZExt))
852  Reg = getRegForUnsignedValue(V);
853  else
854  Reg = getRegForValue(V);
855 
856  if (Reg == 0)
857  return false;
858 
859  Args.push_back(Reg);
860  }
861 
862  unsigned CalleeReg = 0;
863  if (!IsDirect) {
864  CalleeReg = getRegForValue(Call->getCalledValue());
865  if (!CalleeReg)
866  return false;
867  }
868 
869  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
870 
871  if (!IsVoid)
872  MIB.addReg(ResultReg, RegState::Define);
873 
874  if (IsDirect)
875  MIB.addGlobalAddress(Func);
876  else
877  MIB.addReg(CalleeReg);
878 
879  for (unsigned ArgReg : Args)
880  MIB.addReg(ArgReg);
881 
882  if (!IsVoid)
883  updateValueMap(Call, ResultReg);
884  return true;
885 }
886 
887 bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
888  const auto *Select = cast<SelectInst>(I);
889 
890  bool Not;
891  unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
892  if (CondReg == 0)
893  return false;
894 
895  unsigned TrueReg = getRegForValue(Select->getTrueValue());
896  if (TrueReg == 0)
897  return false;
898 
899  unsigned FalseReg = getRegForValue(Select->getFalseValue());
900  if (FalseReg == 0)
901  return false;
902 
903  if (Not)
904  std::swap(TrueReg, FalseReg);
905 
906  unsigned Opc;
907  const TargetRegisterClass *RC;
908  switch (getSimpleType(Select->getType())) {
909  case MVT::i1:
910  case MVT::i8:
911  case MVT::i16:
912  case MVT::i32:
913  Opc = WebAssembly::SELECT_I32;
914  RC = &WebAssembly::I32RegClass;
915  break;
916  case MVT::i64:
917  Opc = WebAssembly::SELECT_I64;
918  RC = &WebAssembly::I64RegClass;
919  break;
920  case MVT::f32:
921  Opc = WebAssembly::SELECT_F32;
922  RC = &WebAssembly::F32RegClass;
923  break;
924  case MVT::f64:
925  Opc = WebAssembly::SELECT_F64;
926  RC = &WebAssembly::F64RegClass;
927  break;
928  case MVT::exnref:
929  Opc = WebAssembly::SELECT_EXNREF;
930  RC = &WebAssembly::EXNREFRegClass;
931  break;
932  default:
933  return false;
934  }
935 
936  unsigned ResultReg = createResultReg(RC);
937  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
938  .addReg(TrueReg)
939  .addReg(FalseReg)
940  .addReg(CondReg);
941 
942  updateValueMap(Select, ResultReg);
943  return true;
944 }
945 
946 bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
947  const auto *Trunc = cast<TruncInst>(I);
948 
949  unsigned Reg = getRegForValue(Trunc->getOperand(0));
950  if (Reg == 0)
951  return false;
952 
953  if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
954  unsigned Result = createResultReg(&WebAssembly::I32RegClass);
955  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
956  TII.get(WebAssembly::I32_WRAP_I64), Result)
957  .addReg(Reg);
958  Reg = Result;
959  }
960 
961  updateValueMap(Trunc, Reg);
962  return true;
963 }
964 
965 bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
966  const auto *ZExt = cast<ZExtInst>(I);
967 
968  const Value *Op = ZExt->getOperand(0);
969  MVT::SimpleValueType From = getSimpleType(Op->getType());
970  MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
971  unsigned In = getRegForValue(Op);
972  if (In == 0)
973  return false;
974  unsigned Reg = zeroExtend(In, Op, From, To);
975  if (Reg == 0)
976  return false;
977 
978  updateValueMap(ZExt, Reg);
979  return true;
980 }
981 
982 bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
983  const auto *SExt = cast<SExtInst>(I);
984 
985  const Value *Op = SExt->getOperand(0);
986  MVT::SimpleValueType From = getSimpleType(Op->getType());
987  MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
988  unsigned In = getRegForValue(Op);
989  if (In == 0)
990  return false;
991  unsigned Reg = signExtend(In, Op, From, To);
992  if (Reg == 0)
993  return false;
994 
995  updateValueMap(SExt, Reg);
996  return true;
997 }
998 
999 bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
1000  const auto *ICmp = cast<ICmpInst>(I);
1001 
1002  bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
1003  unsigned Opc;
1004  bool IsSigned = false;
1005  switch (ICmp->getPredicate()) {
1006  case ICmpInst::ICMP_EQ:
1007  Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
1008  break;
1009  case ICmpInst::ICMP_NE:
1010  Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
1011  break;
1012  case ICmpInst::ICMP_UGT:
1013  Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
1014  break;
1015  case ICmpInst::ICMP_UGE:
1016  Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
1017  break;
1018  case ICmpInst::ICMP_ULT:
1019  Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
1020  break;
1021  case ICmpInst::ICMP_ULE:
1022  Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
1023  break;
1024  case ICmpInst::ICMP_SGT:
1025  Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
1026  IsSigned = true;
1027  break;
1028  case ICmpInst::ICMP_SGE:
1029  Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
1030  IsSigned = true;
1031  break;
1032  case ICmpInst::ICMP_SLT:
1033  Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
1034  IsSigned = true;
1035  break;
1036  case ICmpInst::ICMP_SLE:
1037  Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
1038  IsSigned = true;
1039  break;
1040  default:
1041  return false;
1042  }
1043 
1044  unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), IsSigned);
1045  if (LHS == 0)
1046  return false;
1047 
1048  unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), IsSigned);
1049  if (RHS == 0)
1050  return false;
1051 
1052  unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1053  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1054  .addReg(LHS)
1055  .addReg(RHS);
1056  updateValueMap(ICmp, ResultReg);
1057  return true;
1058 }
1059 
1060 bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
1061  const auto *FCmp = cast<FCmpInst>(I);
1062 
1063  unsigned LHS = getRegForValue(FCmp->getOperand(0));
1064  if (LHS == 0)
1065  return false;
1066 
1067  unsigned RHS = getRegForValue(FCmp->getOperand(1));
1068  if (RHS == 0)
1069  return false;
1070 
1071  bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
1072  unsigned Opc;
1073  bool Not = false;
1074  switch (FCmp->getPredicate()) {
1075  case FCmpInst::FCMP_OEQ:
1076  Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
1077  break;
1078  case FCmpInst::FCMP_UNE:
1079  Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
1080  break;
1081  case FCmpInst::FCMP_OGT:
1082  Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1083  break;
1084  case FCmpInst::FCMP_OGE:
1085  Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1086  break;
1087  case FCmpInst::FCMP_OLT:
1088  Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1089  break;
1090  case FCmpInst::FCMP_OLE:
1091  Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1092  break;
1093  case FCmpInst::FCMP_UGT:
1094  Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
1095  Not = true;
1096  break;
1097  case FCmpInst::FCMP_UGE:
1098  Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
1099  Not = true;
1100  break;
1101  case FCmpInst::FCMP_ULT:
1102  Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
1103  Not = true;
1104  break;
1105  case FCmpInst::FCMP_ULE:
1106  Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
1107  Not = true;
1108  break;
1109  default:
1110  return false;
1111  }
1112 
1113  unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1114  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1115  .addReg(LHS)
1116  .addReg(RHS);
1117 
1118  if (Not)
1119  ResultReg = notValue(ResultReg);
1120 
1121  updateValueMap(FCmp, ResultReg);
1122  return true;
1123 }
1124 
1125 bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
1126  // Target-independent code can handle this, except it doesn't set the dead
1127  // flag on the ARGUMENTS clobber, so we have to do that manually in order
1128  // to satisfy code that expects this of isBitcast() instructions.
1129  EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
1130  EVT RetVT = TLI.getValueType(DL, I->getType());
1131  if (!VT.isSimple() || !RetVT.isSimple())
1132  return false;
1133 
1134  unsigned In = getRegForValue(I->getOperand(0));
1135  if (In == 0)
1136  return false;
1137 
1138  if (VT == RetVT) {
1139  // No-op bitcast.
1140  updateValueMap(I, In);
1141  return true;
1142  }
1143 
1144  Register Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
1145  In, I->getOperand(0)->hasOneUse());
1146  if (!Reg)
1147  return false;
1148  MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
1149  --Iter;
1150  assert(Iter->isBitcast());
1151  Iter->setPhysRegsDeadExcept(ArrayRef<Register>(), TRI);
1152  updateValueMap(I, Reg);
1153  return true;
1154 }
1155 
1156 bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
1157  const auto *Load = cast<LoadInst>(I);
1158  if (Load->isAtomic())
1159  return false;
1160  if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
1161  return false;
1162 
1163  Address Addr;
1164  if (!computeAddress(Load->getPointerOperand(), Addr))
1165  return false;
1166 
1167  // TODO: Fold a following sign-/zero-extend into the load instruction.
1168 
1169  unsigned Opc;
1170  const TargetRegisterClass *RC;
1171  switch (getSimpleType(Load->getType())) {
1172  case MVT::i1:
1173  case MVT::i8:
1174  Opc = WebAssembly::LOAD8_U_I32;
1175  RC = &WebAssembly::I32RegClass;
1176  break;
1177  case MVT::i16:
1178  Opc = WebAssembly::LOAD16_U_I32;
1179  RC = &WebAssembly::I32RegClass;
1180  break;
1181  case MVT::i32:
1182  Opc = WebAssembly::LOAD_I32;
1183  RC = &WebAssembly::I32RegClass;
1184  break;
1185  case MVT::i64:
1186  Opc = WebAssembly::LOAD_I64;
1187  RC = &WebAssembly::I64RegClass;
1188  break;
1189  case MVT::f32:
1190  Opc = WebAssembly::LOAD_F32;
1191  RC = &WebAssembly::F32RegClass;
1192  break;
1193  case MVT::f64:
1194  Opc = WebAssembly::LOAD_F64;
1195  RC = &WebAssembly::F64RegClass;
1196  break;
1197  default:
1198  return false;
1199  }
1200 
1201  materializeLoadStoreOperands(Addr);
1202 
1203  unsigned ResultReg = createResultReg(RC);
1204  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
1205  ResultReg);
1206 
1207  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1208 
1209  updateValueMap(Load, ResultReg);
1210  return true;
1211 }
1212 
1213 bool WebAssemblyFastISel::selectStore(const Instruction *I) {
1214  const auto *Store = cast<StoreInst>(I);
1215  if (Store->isAtomic())
1216  return false;
1217  if (!Subtarget->hasSIMD128() &&
1218  Store->getValueOperand()->getType()->isVectorTy())
1219  return false;
1220 
1221  Address Addr;
1222  if (!computeAddress(Store->getPointerOperand(), Addr))
1223  return false;
1224 
1225  unsigned Opc;
1226  bool VTIsi1 = false;
1227  switch (getSimpleType(Store->getValueOperand()->getType())) {
1228  case MVT::i1:
1229  VTIsi1 = true;
1231  case MVT::i8:
1232  Opc = WebAssembly::STORE8_I32;
1233  break;
1234  case MVT::i16:
1235  Opc = WebAssembly::STORE16_I32;
1236  break;
1237  case MVT::i32:
1238  Opc = WebAssembly::STORE_I32;
1239  break;
1240  case MVT::i64:
1241  Opc = WebAssembly::STORE_I64;
1242  break;
1243  case MVT::f32:
1244  Opc = WebAssembly::STORE_F32;
1245  break;
1246  case MVT::f64:
1247  Opc = WebAssembly::STORE_F64;
1248  break;
1249  default:
1250  return false;
1251  }
1252 
1253  materializeLoadStoreOperands(Addr);
1254 
1255  unsigned ValueReg = getRegForValue(Store->getValueOperand());
1256  if (ValueReg == 0)
1257  return false;
1258  if (VTIsi1)
1259  ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
1260 
1261  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
1262 
1263  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1264 
1265  MIB.addReg(ValueReg);
1266  return true;
1267 }
1268 
1269 bool WebAssemblyFastISel::selectBr(const Instruction *I) {
1270  const auto *Br = cast<BranchInst>(I);
1271  if (Br->isUnconditional()) {
1272  MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
1273  fastEmitBranch(MSucc, Br->getDebugLoc());
1274  return true;
1275  }
1276 
1277  MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
1278  MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
1279 
1280  bool Not;
1281  unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
1282  if (CondReg == 0)
1283  return false;
1284 
1285  unsigned Opc = WebAssembly::BR_IF;
1286  if (Not)
1287  Opc = WebAssembly::BR_UNLESS;
1288 
1289  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1290  .addMBB(TBB)
1291  .addReg(CondReg);
1292 
1293  finishCondBranch(Br->getParent(), TBB, FBB);
1294  return true;
1295 }
1296 
1297 bool WebAssemblyFastISel::selectRet(const Instruction *I) {
1298  if (!FuncInfo.CanLowerReturn)
1299  return false;
1300 
1301  const auto *Ret = cast<ReturnInst>(I);
1302 
1303  if (Ret->getNumOperands() == 0) {
1304  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1305  TII.get(WebAssembly::RETURN));
1306  return true;
1307  }
1308 
1309  // TODO: support multiple return in FastISel
1310  if (Ret->getNumOperands() > 1)
1311  return false;
1312 
1313  Value *RV = Ret->getOperand(0);
1314  if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
1315  return false;
1316 
1317  switch (getSimpleType(RV->getType())) {
1318  case MVT::i1:
1319  case MVT::i8:
1320  case MVT::i16:
1321  case MVT::i32:
1322  case MVT::i64:
1323  case MVT::f32:
1324  case MVT::f64:
1325  case MVT::v16i8:
1326  case MVT::v8i16:
1327  case MVT::v4i32:
1328  case MVT::v2i64:
1329  case MVT::v4f32:
1330  case MVT::v2f64:
1331  case MVT::exnref:
1332  break;
1333  default:
1334  return false;
1335  }
1336 
1337  unsigned Reg;
1338  if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
1339  Reg = getRegForSignedValue(RV);
1340  else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
1341  Reg = getRegForUnsignedValue(RV);
1342  else
1343  Reg = getRegForValue(RV);
1344 
1345  if (Reg == 0)
1346  return false;
1347 
1348  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1349  TII.get(WebAssembly::RETURN))
1350  .addReg(Reg);
1351  return true;
1352 }
1353 
1354 bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
1355  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1356  TII.get(WebAssembly::UNREACHABLE));
1357  return true;
1358 }
1359 
1360 bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
1361  switch (I->getOpcode()) {
1362  case Instruction::Call:
1363  if (selectCall(I))
1364  return true;
1365  break;
1366  case Instruction::Select:
1367  return selectSelect(I);
1368  case Instruction::Trunc:
1369  return selectTrunc(I);
1370  case Instruction::ZExt:
1371  return selectZExt(I);
1372  case Instruction::SExt:
1373  return selectSExt(I);
1374  case Instruction::ICmp:
1375  return selectICmp(I);
1376  case Instruction::FCmp:
1377  return selectFCmp(I);
1378  case Instruction::BitCast:
1379  return selectBitCast(I);
1380  case Instruction::Load:
1381  return selectLoad(I);
1382  case Instruction::Store:
1383  return selectStore(I);
1384  case Instruction::Br:
1385  return selectBr(I);
1386  case Instruction::Ret:
1387  return selectRet(I);
1388  case Instruction::Unreachable:
1389  return selectUnreachable(I);
1390  default:
1391  break;
1392  }
1393 
1394  // Fall back to target-independent instruction selection.
1395  return selectOperator(I, I->getOpcode());
1396 }
1397 
1399  const TargetLibraryInfo *LibInfo) {
1400  return new WebAssemblyFastISel(FuncInfo, LibInfo);
1401 }
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
unsigned getSizeInBits(Register Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI) const
Get the size in bits of Reg.
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:758
unsigned less than
Definition: InstrTypes.h:757
0 1 0 0 True if ordered and less than
Definition: InstrTypes.h:738
1 1 1 0 True if unordered or not equal
Definition: InstrTypes.h:748
unsigned const TargetRegisterInfo * TRI
F(f)
bool isVectorTy() const
True if this is an instance of VectorType.
Definition: Type.h:230
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:585
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:238
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:197
0 1 0 1 True if ordered and less than or equal
Definition: InstrTypes.h:739
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:108
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:246
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned TargetFlags=0) const
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:32
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:141
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:46
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:205
Extended Value Type.
Definition: ValueTypes.h:33
1 1 0 1 True if unordered, less than, or equal
Definition: InstrTypes.h:747
signed greater than
Definition: InstrTypes.h:759
0 0 1 0 True if ordered and greater than
Definition: InstrTypes.h:736
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:746
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:761
Type * getReturnType() const
Definition: DerivedTypes.h:129
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:762
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:607
unsigned greater or equal
Definition: InstrTypes.h:756
#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.
1 0 1 0 True if unordered or greater than
Definition: InstrTypes.h:744
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
0 0 0 1 True if ordered and equal
Definition: InstrTypes.h:735
LLVM Value Representation.
Definition: Value.h:74
1 0 1 1 True if unordered, greater than, or equal
Definition: InstrTypes.h:745
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:273
bool hasOneUse() const
Return true if there is exactly one user of this value.
Definition: Value.h:433
unsigned greater than
Definition: InstrTypes.h:755
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:737
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
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:724
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
bool isStructTy() const
True if this is an instance of StructType.
Definition: Type.h:218
signed greater or equal
Definition: InstrTypes.h:760
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition: Type.h:221
an instruction to allocate memory on the stack
Definition: Instructions.h:59
gep_type_iterator gep_type_begin(const User *GEP)