LLVM  4.0.0
WebAssemblyFastISel.cpp
Go to the documentation of this file.
1 //===-- WebAssemblyFastISel.cpp - WebAssembly FastISel implementation -----===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// \brief This file defines the WebAssembly-specific support for the FastISel
12 /// class. Some of the target-specific code is generated by tablegen in the file
13 /// WebAssemblyGenFastISel.inc, which is #included here.
14 ///
15 /// TODO: kill flags
16 ///
17 //===----------------------------------------------------------------------===//
18 
19 #include "WebAssembly.h"
22 #include "WebAssemblySubtarget.h"
25 #include "llvm/CodeGen/FastISel.h"
31 #include "llvm/IR/DataLayout.h"
32 #include "llvm/IR/DerivedTypes.h"
33 #include "llvm/IR/Function.h"
35 #include "llvm/IR/GlobalAlias.h"
36 #include "llvm/IR/GlobalVariable.h"
37 #include "llvm/IR/Instructions.h"
38 #include "llvm/IR/IntrinsicInst.h"
39 #include "llvm/IR/Operator.h"
40 using namespace llvm;
41 
42 #define DEBUG_TYPE "wasm-fastisel"
43 
44 namespace {
45 
46 class WebAssemblyFastISel final : public FastISel {
47  // All possible address modes.
48  class Address {
49  public:
50  typedef enum { RegBase, FrameIndexBase } BaseKind;
51 
52  private:
53  BaseKind Kind;
54  union {
55  unsigned Reg;
56  int FI;
57  } Base;
58 
59  int64_t Offset;
60 
61  const GlobalValue *GV;
62 
63  public:
64  // Innocuous defaults for our address.
65  Address() : Kind(RegBase), Offset(0), GV(0) { Base.Reg = 0; }
66  void setKind(BaseKind K) { Kind = K; }
67  BaseKind getKind() const { return Kind; }
68  bool isRegBase() const { return Kind == RegBase; }
69  bool isFIBase() const { return Kind == FrameIndexBase; }
70  void setReg(unsigned Reg) {
71  assert(isRegBase() && "Invalid base register access!");
72  Base.Reg = Reg;
73  }
74  unsigned getReg() const {
75  assert(isRegBase() && "Invalid base register access!");
76  return Base.Reg;
77  }
78  void setFI(unsigned FI) {
79  assert(isFIBase() && "Invalid base frame index access!");
80  Base.FI = FI;
81  }
82  unsigned getFI() const {
83  assert(isFIBase() && "Invalid base frame index access!");
84  return Base.FI;
85  }
86 
87  void setOffset(int64_t Offset_) {
88  assert(Offset_ >= 0 && "Offsets must be non-negative");
89  Offset = Offset_;
90  }
91  int64_t getOffset() const { return Offset; }
92  void setGlobalValue(const GlobalValue *G) { GV = G; }
93  const GlobalValue *getGlobalValue() const { return GV; }
94  };
95 
96  /// Keep a pointer to the WebAssemblySubtarget around so that we can make the
97  /// right decision when generating code for different targets.
98  const WebAssemblySubtarget *Subtarget;
100 
101 private:
102  // Utility helper routines
103  MVT::SimpleValueType getSimpleType(Type *Ty) {
104  EVT VT = TLI.getValueType(DL, Ty, /*HandleUnknown=*/true);
105  return VT.isSimple() ? VT.getSimpleVT().SimpleTy :
107  }
108  MVT::SimpleValueType getLegalType(MVT::SimpleValueType VT) {
109  switch (VT) {
110  case MVT::i1:
111  case MVT::i8:
112  case MVT::i16:
113  return MVT::i32;
114  case MVT::i32:
115  case MVT::i64:
116  case MVT::f32:
117  case MVT::f64:
118  return VT;
119  case MVT::v16i8:
120  case MVT::v8i16:
121  case MVT::v4i32:
122  case MVT::v4f32:
123  if (Subtarget->hasSIMD128())
124  return VT;
125  break;
126  default:
127  break;
128  }
130  }
131  bool computeAddress(const Value *Obj, Address &Addr);
132  void materializeLoadStoreOperands(Address &Addr);
133  void addLoadStoreOperands(const Address &Addr, const MachineInstrBuilder &MIB,
134  MachineMemOperand *MMO);
135  unsigned maskI1Value(unsigned Reg, const Value *V);
136  unsigned getRegForI1Value(const Value *V, bool &Not);
137  unsigned zeroExtendToI32(unsigned Reg, const Value *V,
138  MVT::SimpleValueType From);
139  unsigned signExtendToI32(unsigned Reg, const Value *V,
140  MVT::SimpleValueType From);
141  unsigned zeroExtend(unsigned Reg, const Value *V,
144  unsigned signExtend(unsigned Reg, const Value *V,
147  unsigned getRegForUnsignedValue(const Value *V);
148  unsigned getRegForSignedValue(const Value *V);
149  unsigned getRegForPromotedValue(const Value *V, bool IsSigned);
150  unsigned notValue(unsigned Reg);
151  unsigned copyValue(unsigned Reg);
152 
153  // Backend specific FastISel code.
154  unsigned fastMaterializeAlloca(const AllocaInst *AI) override;
155  unsigned fastMaterializeConstant(const Constant *C) override;
156  bool fastLowerArguments() override;
157 
158  // Selection routines.
159  bool selectCall(const Instruction *I);
160  bool selectSelect(const Instruction *I);
161  bool selectTrunc(const Instruction *I);
162  bool selectZExt(const Instruction *I);
163  bool selectSExt(const Instruction *I);
164  bool selectICmp(const Instruction *I);
165  bool selectFCmp(const Instruction *I);
166  bool selectBitCast(const Instruction *I);
167  bool selectLoad(const Instruction *I);
168  bool selectStore(const Instruction *I);
169  bool selectBr(const Instruction *I);
170  bool selectRet(const Instruction *I);
171  bool selectUnreachable(const Instruction *I);
172 
173 public:
174  // Backend specific FastISel code.
175  WebAssemblyFastISel(FunctionLoweringInfo &FuncInfo,
176  const TargetLibraryInfo *LibInfo)
177  : FastISel(FuncInfo, LibInfo, /*SkipTargetIndependentISel=*/true) {
178  Subtarget = &FuncInfo.MF->getSubtarget<WebAssemblySubtarget>();
179  Context = &FuncInfo.Fn->getContext();
180  }
181 
182  bool fastSelectInstruction(const Instruction *I) override;
183 
184 #include "WebAssemblyGenFastISel.inc"
185 };
186 
187 } // end anonymous namespace
188 
189 bool WebAssemblyFastISel::computeAddress(const Value *Obj, Address &Addr) {
190 
191  const User *U = nullptr;
192  unsigned Opcode = Instruction::UserOp1;
193  if (const Instruction *I = dyn_cast<Instruction>(Obj)) {
194  // Don't walk into other basic blocks unless the object is an alloca from
195  // another block, otherwise it may not have a virtual register assigned.
196  if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) ||
197  FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) {
198  Opcode = I->getOpcode();
199  U = I;
200  }
201  } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) {
202  Opcode = C->getOpcode();
203  U = C;
204  }
205 
206  if (auto *Ty = dyn_cast<PointerType>(Obj->getType()))
207  if (Ty->getAddressSpace() > 255)
208  // Fast instruction selection doesn't support the special
209  // address spaces.
210  return false;
211 
212  if (const GlobalValue *GV = dyn_cast<GlobalValue>(Obj)) {
213  if (Addr.getGlobalValue())
214  return false;
215  Addr.setGlobalValue(GV);
216  return true;
217  }
218 
219  switch (Opcode) {
220  default:
221  break;
222  case Instruction::BitCast: {
223  // Look through bitcasts.
224  return computeAddress(U->getOperand(0), Addr);
225  }
226  case Instruction::IntToPtr: {
227  // Look past no-op inttoptrs.
228  if (TLI.getValueType(DL, U->getOperand(0)->getType()) ==
229  TLI.getPointerTy(DL))
230  return computeAddress(U->getOperand(0), Addr);
231  break;
232  }
233  case Instruction::PtrToInt: {
234  // Look past no-op ptrtoints.
235  if (TLI.getValueType(DL, U->getType()) == TLI.getPointerTy(DL))
236  return computeAddress(U->getOperand(0), Addr);
237  break;
238  }
239  case Instruction::GetElementPtr: {
240  Address SavedAddr = Addr;
241  uint64_t TmpOffset = Addr.getOffset();
242  // Non-inbounds geps can wrap; wasm's offsets can't.
243  if (!cast<GEPOperator>(U)->isInBounds())
244  goto unsupported_gep;
245  // Iterate through the GEP folding the constants into offsets where
246  // we can.
247  for (gep_type_iterator GTI = gep_type_begin(U), E = gep_type_end(U);
248  GTI != E; ++GTI) {
249  const Value *Op = GTI.getOperand();
250  if (StructType *STy = GTI.getStructTypeOrNull()) {
251  const StructLayout *SL = DL.getStructLayout(STy);
252  unsigned Idx = cast<ConstantInt>(Op)->getZExtValue();
253  TmpOffset += SL->getElementOffset(Idx);
254  } else {
255  uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType());
256  for (;;) {
257  if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
258  // Constant-offset addressing.
259  TmpOffset += CI->getSExtValue() * S;
260  break;
261  }
262  if (S == 1 && Addr.isRegBase() && Addr.getReg() == 0) {
263  // An unscaled add of a register. Set it as the new base.
264  Addr.setReg(getRegForValue(Op));
265  break;
266  }
267  if (canFoldAddIntoGEP(U, Op)) {
268  // A compatible add with a constant operand. Fold the constant.
269  ConstantInt *CI =
270  cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1));
271  TmpOffset += CI->getSExtValue() * S;
272  // Iterate on the other operand.
273  Op = cast<AddOperator>(Op)->getOperand(0);
274  continue;
275  }
276  // Unsupported
277  goto unsupported_gep;
278  }
279  }
280  }
281  // Don't fold in negative offsets.
282  if (int64_t(TmpOffset) >= 0) {
283  // Try to grab the base operand now.
284  Addr.setOffset(TmpOffset);
285  if (computeAddress(U->getOperand(0), Addr))
286  return true;
287  }
288  // We failed, restore everything and try the other options.
289  Addr = SavedAddr;
290  unsupported_gep:
291  break;
292  }
293  case Instruction::Alloca: {
294  const AllocaInst *AI = cast<AllocaInst>(Obj);
296  FuncInfo.StaticAllocaMap.find(AI);
297  if (SI != FuncInfo.StaticAllocaMap.end()) {
298  Addr.setKind(Address::FrameIndexBase);
299  Addr.setFI(SI->second);
300  return true;
301  }
302  break;
303  }
304  case Instruction::Add: {
305  // Adds of constants are common and easy enough.
306  const Value *LHS = U->getOperand(0);
307  const Value *RHS = U->getOperand(1);
308 
309  if (isa<ConstantInt>(LHS))
310  std::swap(LHS, RHS);
311 
312  if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
313  uint64_t TmpOffset = Addr.getOffset() + CI->getSExtValue();
314  if (int64_t(TmpOffset) >= 0) {
315  Addr.setOffset(TmpOffset);
316  return computeAddress(LHS, Addr);
317  }
318  }
319 
320  Address Backup = Addr;
321  if (computeAddress(LHS, Addr) && computeAddress(RHS, Addr))
322  return true;
323  Addr = Backup;
324 
325  break;
326  }
327  case Instruction::Sub: {
328  // Subs of constants are common and easy enough.
329  const Value *LHS = U->getOperand(0);
330  const Value *RHS = U->getOperand(1);
331 
332  if (const ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) {
333  int64_t TmpOffset = Addr.getOffset() - CI->getSExtValue();
334  if (TmpOffset >= 0) {
335  Addr.setOffset(TmpOffset);
336  return computeAddress(LHS, Addr);
337  }
338  }
339  break;
340  }
341  }
342  Addr.setReg(getRegForValue(Obj));
343  return Addr.getReg() != 0;
344 }
345 
346 void WebAssemblyFastISel::materializeLoadStoreOperands(Address &Addr) {
347  if (Addr.isRegBase()) {
348  unsigned Reg = Addr.getReg();
349  if (Reg == 0) {
350  Reg = createResultReg(Subtarget->hasAddr64() ?
351  &WebAssembly::I64RegClass :
352  &WebAssembly::I32RegClass);
353  unsigned Opc = Subtarget->hasAddr64() ?
354  WebAssembly::CONST_I64 :
355  WebAssembly::CONST_I32;
356  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), Reg)
357  .addImm(0);
358  Addr.setReg(Reg);
359  }
360  }
361 }
362 
363 void WebAssemblyFastISel::addLoadStoreOperands(const Address &Addr,
364  const MachineInstrBuilder &MIB,
365  MachineMemOperand *MMO) {
366  // Set the alignment operand (this is rewritten in SetP2AlignOperands).
367  // TODO: Disable SetP2AlignOperands for FastISel and just do it here.
368  MIB.addImm(0);
369 
370  if (const GlobalValue *GV = Addr.getGlobalValue())
371  MIB.addGlobalAddress(GV, Addr.getOffset());
372  else
373  MIB.addImm(Addr.getOffset());
374 
375  if (Addr.isRegBase())
376  MIB.addReg(Addr.getReg());
377  else
378  MIB.addFrameIndex(Addr.getFI());
379 
380  MIB.addMemOperand(MMO);
381 }
382 
383 unsigned WebAssemblyFastISel::maskI1Value(unsigned Reg, const Value *V) {
384  return zeroExtendToI32(Reg, V, MVT::i1);
385 }
386 
387 unsigned WebAssemblyFastISel::getRegForI1Value(const Value *V, bool &Not) {
388  if (const ICmpInst *ICmp = dyn_cast<ICmpInst>(V))
389  if (const ConstantInt *C = dyn_cast<ConstantInt>(ICmp->getOperand(1)))
390  if (ICmp->isEquality() && C->isZero() && C->getType()->isIntegerTy(32)) {
391  Not = ICmp->isTrueWhenEqual();
392  return getRegForValue(ICmp->getOperand(0));
393  }
394 
395  if (BinaryOperator::isNot(V)) {
396  Not = true;
397  return getRegForValue(BinaryOperator::getNotArgument(V));
398  }
399 
400  Not = false;
401  return maskI1Value(getRegForValue(V), V);
402 }
403 
404 unsigned WebAssemblyFastISel::zeroExtendToI32(unsigned Reg, const Value *V,
405  MVT::SimpleValueType From) {
406  if (Reg == 0)
407  return 0;
408 
409  switch (From) {
410  case MVT::i1:
411  // If the value is naturally an i1, we don't need to mask it.
412  // TODO: Recursively examine selects, phis, and, or, xor, constants.
413  if (From == MVT::i1 && V != nullptr) {
414  if (isa<CmpInst>(V) ||
415  (isa<Argument>(V) && cast<Argument>(V)->hasZExtAttr()))
416  return copyValue(Reg);
417  }
418  case MVT::i8:
419  case MVT::i16:
420  break;
421  case MVT::i32:
422  return copyValue(Reg);
423  default:
424  return 0;
425  }
426 
427  unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
428  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
429  TII.get(WebAssembly::CONST_I32), Imm)
430  .addImm(~(~uint64_t(0) << MVT(From).getSizeInBits()));
431 
432  unsigned Result = createResultReg(&WebAssembly::I32RegClass);
433  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
434  TII.get(WebAssembly::AND_I32), Result)
435  .addReg(Reg)
436  .addReg(Imm);
437 
438  return Result;
439 }
440 
441 unsigned WebAssemblyFastISel::signExtendToI32(unsigned Reg, const Value *V,
442  MVT::SimpleValueType From) {
443  if (Reg == 0)
444  return 0;
445 
446  switch (From) {
447  case MVT::i1:
448  case MVT::i8:
449  case MVT::i16:
450  break;
451  case MVT::i32:
452  return copyValue(Reg);
453  default:
454  return 0;
455  }
456 
457  unsigned Imm = createResultReg(&WebAssembly::I32RegClass);
458  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
459  TII.get(WebAssembly::CONST_I32), Imm)
460  .addImm(32 - MVT(From).getSizeInBits());
461 
462  unsigned Left = createResultReg(&WebAssembly::I32RegClass);
463  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
464  TII.get(WebAssembly::SHL_I32), Left)
465  .addReg(Reg)
466  .addReg(Imm);
467 
468  unsigned Right = createResultReg(&WebAssembly::I32RegClass);
469  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
470  TII.get(WebAssembly::SHR_S_I32), Right)
471  .addReg(Left)
472  .addReg(Imm);
473 
474  return Right;
475 }
476 
477 unsigned WebAssemblyFastISel::zeroExtend(unsigned Reg, const Value *V,
480  if (To == MVT::i64) {
481  if (From == MVT::i64)
482  return copyValue(Reg);
483 
484  Reg = zeroExtendToI32(Reg, V, From);
485 
486  unsigned Result = createResultReg(&WebAssembly::I64RegClass);
487  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
488  TII.get(WebAssembly::I64_EXTEND_U_I32), Result)
489  .addReg(Reg);
490  return Result;
491  }
492 
493  return zeroExtendToI32(Reg, V, From);
494 }
495 
496 unsigned WebAssemblyFastISel::signExtend(unsigned Reg, const Value *V,
499  if (To == MVT::i64) {
500  if (From == MVT::i64)
501  return copyValue(Reg);
502 
503  Reg = signExtendToI32(Reg, V, From);
504 
505  unsigned Result = createResultReg(&WebAssembly::I64RegClass);
506  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
507  TII.get(WebAssembly::I64_EXTEND_S_I32), Result)
508  .addReg(Reg);
509  return Result;
510  }
511 
512  return signExtendToI32(Reg, V, From);
513 }
514 
515 unsigned WebAssemblyFastISel::getRegForUnsignedValue(const Value *V) {
516  MVT::SimpleValueType From = getSimpleType(V->getType());
517  MVT::SimpleValueType To = getLegalType(From);
518  return zeroExtend(getRegForValue(V), V, From, To);
519 }
520 
521 unsigned WebAssemblyFastISel::getRegForSignedValue(const Value *V) {
522  MVT::SimpleValueType From = getSimpleType(V->getType());
523  MVT::SimpleValueType To = getLegalType(From);
524  return zeroExtend(getRegForValue(V), V, From, To);
525 }
526 
527 unsigned WebAssemblyFastISel::getRegForPromotedValue(const Value *V,
528  bool IsSigned) {
529  return IsSigned ? getRegForSignedValue(V) :
530  getRegForUnsignedValue(V);
531 }
532 
533 unsigned WebAssemblyFastISel::notValue(unsigned Reg) {
534  assert(MRI.getRegClass(Reg) == &WebAssembly::I32RegClass);
535 
536  unsigned NotReg = createResultReg(&WebAssembly::I32RegClass);
537  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
538  TII.get(WebAssembly::EQZ_I32), NotReg)
539  .addReg(Reg);
540  return NotReg;
541 }
542 
543 unsigned WebAssemblyFastISel::copyValue(unsigned Reg) {
544  unsigned ResultReg = createResultReg(MRI.getRegClass(Reg));
545  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
546  TII.get(WebAssembly::COPY), ResultReg)
547  .addReg(Reg);
548  return ResultReg;
549 }
550 
551 unsigned WebAssemblyFastISel::fastMaterializeAlloca(const AllocaInst *AI) {
553  FuncInfo.StaticAllocaMap.find(AI);
554 
555  if (SI != FuncInfo.StaticAllocaMap.end()) {
556  unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ?
557  &WebAssembly::I64RegClass :
558  &WebAssembly::I32RegClass);
559  unsigned Opc = Subtarget->hasAddr64() ?
560  WebAssembly::COPY_I64 :
561  WebAssembly::COPY_I32;
562  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
563  .addFrameIndex(SI->second);
564  return ResultReg;
565  }
566 
567  return 0;
568 }
569 
570 unsigned WebAssemblyFastISel::fastMaterializeConstant(const Constant *C) {
571  if (const GlobalValue *GV = dyn_cast<GlobalValue>(C)) {
572  unsigned ResultReg = createResultReg(Subtarget->hasAddr64() ?
573  &WebAssembly::I64RegClass :
574  &WebAssembly::I32RegClass);
575  unsigned Opc = Subtarget->hasAddr64() ?
576  WebAssembly::CONST_I64 :
577  WebAssembly::CONST_I32;
578  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
579  .addGlobalAddress(GV);
580  return ResultReg;
581  }
582 
583  // Let target-independent code handle it.
584  return 0;
585 }
586 
587 bool WebAssemblyFastISel::fastLowerArguments() {
588  if (!FuncInfo.CanLowerReturn)
589  return false;
590 
591  const Function *F = FuncInfo.Fn;
592  if (F->isVarArg())
593  return false;
594 
595  unsigned i = 0;
596  for (auto const &Arg : F->args()) {
597  const AttributeSet &Attrs = F->getAttributes();
598  if (Attrs.hasAttribute(i+1, Attribute::ByVal) ||
599  Attrs.hasAttribute(i+1, Attribute::SwiftSelf) ||
600  Attrs.hasAttribute(i+1, Attribute::SwiftError) ||
601  Attrs.hasAttribute(i+1, Attribute::InAlloca) ||
602  Attrs.hasAttribute(i+1, Attribute::Nest))
603  return false;
604 
605  Type *ArgTy = Arg.getType();
606  if (ArgTy->isStructTy() || ArgTy->isArrayTy())
607  return false;
608  if (!Subtarget->hasSIMD128() && ArgTy->isVectorTy())
609  return false;
610 
611  unsigned Opc;
612  const TargetRegisterClass *RC;
613  switch (getSimpleType(ArgTy)) {
614  case MVT::i1:
615  case MVT::i8:
616  case MVT::i16:
617  case MVT::i32:
618  Opc = WebAssembly::ARGUMENT_I32;
619  RC = &WebAssembly::I32RegClass;
620  break;
621  case MVT::i64:
622  Opc = WebAssembly::ARGUMENT_I64;
623  RC = &WebAssembly::I64RegClass;
624  break;
625  case MVT::f32:
626  Opc = WebAssembly::ARGUMENT_F32;
627  RC = &WebAssembly::F32RegClass;
628  break;
629  case MVT::f64:
630  Opc = WebAssembly::ARGUMENT_F64;
631  RC = &WebAssembly::F64RegClass;
632  break;
633  case MVT::v16i8:
634  Opc = WebAssembly::ARGUMENT_v16i8;
635  RC = &WebAssembly::V128RegClass;
636  break;
637  case MVT::v8i16:
638  Opc = WebAssembly::ARGUMENT_v8i16;
639  RC = &WebAssembly::V128RegClass;
640  break;
641  case MVT::v4i32:
642  Opc = WebAssembly::ARGUMENT_v4i32;
643  RC = &WebAssembly::V128RegClass;
644  break;
645  case MVT::v4f32:
646  Opc = WebAssembly::ARGUMENT_v4f32;
647  RC = &WebAssembly::V128RegClass;
648  break;
649  default:
650  return false;
651  }
652  unsigned ResultReg = createResultReg(RC);
653  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
654  .addImm(i);
655  updateValueMap(&Arg, ResultReg);
656 
657  ++i;
658  }
659 
660  MRI.addLiveIn(WebAssembly::ARGUMENTS);
661 
662  auto *MFI = MF->getInfo<WebAssemblyFunctionInfo>();
663  for (auto const &Arg : F->args())
664  MFI->addParam(getLegalType(getSimpleType(Arg.getType())));
665 
666  if (!F->getReturnType()->isVoidTy())
667  MFI->addResult(getLegalType(getSimpleType(F->getReturnType())));
668 
669  return true;
670 }
671 
672 bool WebAssemblyFastISel::selectCall(const Instruction *I) {
673  const CallInst *Call = cast<CallInst>(I);
674 
675  if (Call->isMustTailCall() || Call->isInlineAsm() ||
676  Call->getFunctionType()->isVarArg())
677  return false;
678 
679  Function *Func = Call->getCalledFunction();
680  if (Func && Func->isIntrinsic())
681  return false;
682 
683  FunctionType *FuncTy = Call->getFunctionType();
684  unsigned Opc;
685  bool IsDirect = Func != nullptr;
686  bool IsVoid = FuncTy->getReturnType()->isVoidTy();
687  unsigned ResultReg;
688  if (IsVoid) {
689  Opc = IsDirect ? WebAssembly::CALL_VOID : WebAssembly::PCALL_INDIRECT_VOID;
690  } else {
691  if (!Subtarget->hasSIMD128() && Call->getType()->isVectorTy())
692  return false;
693 
694  MVT::SimpleValueType RetTy = getSimpleType(Call->getType());
695  switch (RetTy) {
696  case MVT::i1:
697  case MVT::i8:
698  case MVT::i16:
699  case MVT::i32:
700  Opc = IsDirect ? WebAssembly::CALL_I32 : WebAssembly::PCALL_INDIRECT_I32;
701  ResultReg = createResultReg(&WebAssembly::I32RegClass);
702  break;
703  case MVT::i64:
704  Opc = IsDirect ? WebAssembly::CALL_I64 : WebAssembly::PCALL_INDIRECT_I64;
705  ResultReg = createResultReg(&WebAssembly::I64RegClass);
706  break;
707  case MVT::f32:
708  Opc = IsDirect ? WebAssembly::CALL_F32 : WebAssembly::PCALL_INDIRECT_F32;
709  ResultReg = createResultReg(&WebAssembly::F32RegClass);
710  break;
711  case MVT::f64:
712  Opc = IsDirect ? WebAssembly::CALL_F64 : WebAssembly::PCALL_INDIRECT_F64;
713  ResultReg = createResultReg(&WebAssembly::F64RegClass);
714  break;
715  case MVT::v16i8:
716  Opc =
717  IsDirect ? WebAssembly::CALL_v16i8 : WebAssembly::PCALL_INDIRECT_v16i8;
718  ResultReg = createResultReg(&WebAssembly::V128RegClass);
719  break;
720  case MVT::v8i16:
721  Opc =
722  IsDirect ? WebAssembly::CALL_v8i16 : WebAssembly::PCALL_INDIRECT_v8i16;
723  ResultReg = createResultReg(&WebAssembly::V128RegClass);
724  break;
725  case MVT::v4i32:
726  Opc =
727  IsDirect ? WebAssembly::CALL_v4i32 : WebAssembly::PCALL_INDIRECT_v4i32;
728  ResultReg = createResultReg(&WebAssembly::V128RegClass);
729  break;
730  case MVT::v4f32:
731  Opc =
732  IsDirect ? WebAssembly::CALL_v4f32 : WebAssembly::PCALL_INDIRECT_v4f32;
733  ResultReg = createResultReg(&WebAssembly::V128RegClass);
734  break;
735  default:
736  return false;
737  }
738  }
739 
741  for (unsigned i = 0, e = Call->getNumArgOperands(); i < e; ++i) {
742  Value *V = Call->getArgOperand(i);
743  MVT::SimpleValueType ArgTy = getSimpleType(V->getType());
744  if (ArgTy == MVT::INVALID_SIMPLE_VALUE_TYPE)
745  return false;
746 
747  const AttributeSet &Attrs = Call->getAttributes();
748  if (Attrs.hasAttribute(i+1, Attribute::ByVal) ||
749  Attrs.hasAttribute(i+1, Attribute::SwiftSelf) ||
750  Attrs.hasAttribute(i+1, Attribute::SwiftError) ||
751  Attrs.hasAttribute(i+1, Attribute::InAlloca) ||
752  Attrs.hasAttribute(i+1, Attribute::Nest))
753  return false;
754 
755  unsigned Reg;
756 
757  if (Attrs.hasAttribute(i+1, Attribute::SExt))
758  Reg = getRegForSignedValue(V);
759  else if (Attrs.hasAttribute(i+1, Attribute::ZExt))
760  Reg = getRegForUnsignedValue(V);
761  else
762  Reg = getRegForValue(V);
763 
764  if (Reg == 0)
765  return false;
766 
767  Args.push_back(Reg);
768  }
769 
770  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
771 
772  if (!IsVoid)
773  MIB.addReg(ResultReg, RegState::Define);
774 
775  if (IsDirect)
776  MIB.addGlobalAddress(Func);
777  else
778  MIB.addReg(getRegForValue(Call->getCalledValue()));
779 
780  for (unsigned ArgReg : Args)
781  MIB.addReg(ArgReg);
782 
783  if (!IsVoid)
784  updateValueMap(Call, ResultReg);
785  return true;
786 }
787 
788 bool WebAssemblyFastISel::selectSelect(const Instruction *I) {
789  const SelectInst *Select = cast<SelectInst>(I);
790 
791  bool Not;
792  unsigned CondReg = getRegForI1Value(Select->getCondition(), Not);
793  if (CondReg == 0)
794  return false;
795 
796  unsigned TrueReg = getRegForValue(Select->getTrueValue());
797  if (TrueReg == 0)
798  return false;
799 
800  unsigned FalseReg = getRegForValue(Select->getFalseValue());
801  if (FalseReg == 0)
802  return false;
803 
804  if (Not)
805  std::swap(TrueReg, FalseReg);
806 
807  unsigned Opc;
808  const TargetRegisterClass *RC;
809  switch (getSimpleType(Select->getType())) {
810  case MVT::i1:
811  case MVT::i8:
812  case MVT::i16:
813  case MVT::i32:
814  Opc = WebAssembly::SELECT_I32;
815  RC = &WebAssembly::I32RegClass;
816  break;
817  case MVT::i64:
818  Opc = WebAssembly::SELECT_I64;
819  RC = &WebAssembly::I64RegClass;
820  break;
821  case MVT::f32:
822  Opc = WebAssembly::SELECT_F32;
823  RC = &WebAssembly::F32RegClass;
824  break;
825  case MVT::f64:
826  Opc = WebAssembly::SELECT_F64;
827  RC = &WebAssembly::F64RegClass;
828  break;
829  default:
830  return false;
831  }
832 
833  unsigned ResultReg = createResultReg(RC);
834  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
835  .addReg(TrueReg)
836  .addReg(FalseReg)
837  .addReg(CondReg);
838 
839  updateValueMap(Select, ResultReg);
840  return true;
841 }
842 
843 bool WebAssemblyFastISel::selectTrunc(const Instruction *I) {
844  const TruncInst *Trunc = cast<TruncInst>(I);
845 
846  unsigned Reg = getRegForValue(Trunc->getOperand(0));
847  if (Reg == 0)
848  return false;
849 
850  if (Trunc->getOperand(0)->getType()->isIntegerTy(64)) {
851  unsigned Result = createResultReg(&WebAssembly::I32RegClass);
852  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
853  TII.get(WebAssembly::I32_WRAP_I64), Result)
854  .addReg(Reg);
855  Reg = Result;
856  }
857 
858  updateValueMap(Trunc, Reg);
859  return true;
860 }
861 
862 bool WebAssemblyFastISel::selectZExt(const Instruction *I) {
863  const ZExtInst *ZExt = cast<ZExtInst>(I);
864 
865  const Value *Op = ZExt->getOperand(0);
866  MVT::SimpleValueType From = getSimpleType(Op->getType());
867  MVT::SimpleValueType To = getLegalType(getSimpleType(ZExt->getType()));
868  unsigned Reg = zeroExtend(getRegForValue(Op), Op, From, To);
869  if (Reg == 0)
870  return false;
871 
872  updateValueMap(ZExt, Reg);
873  return true;
874 }
875 
876 bool WebAssemblyFastISel::selectSExt(const Instruction *I) {
877  const SExtInst *SExt = cast<SExtInst>(I);
878 
879  const Value *Op = SExt->getOperand(0);
880  MVT::SimpleValueType From = getSimpleType(Op->getType());
881  MVT::SimpleValueType To = getLegalType(getSimpleType(SExt->getType()));
882  unsigned Reg = signExtend(getRegForValue(Op), Op, From, To);
883  if (Reg == 0)
884  return false;
885 
886  updateValueMap(SExt, Reg);
887  return true;
888 }
889 
890 bool WebAssemblyFastISel::selectICmp(const Instruction *I) {
891  const ICmpInst *ICmp = cast<ICmpInst>(I);
892 
893  bool I32 = getSimpleType(ICmp->getOperand(0)->getType()) != MVT::i64;
894  unsigned Opc;
895  bool isSigned = false;
896  switch (ICmp->getPredicate()) {
897  case ICmpInst::ICMP_EQ:
898  Opc = I32 ? WebAssembly::EQ_I32 : WebAssembly::EQ_I64;
899  break;
900  case ICmpInst::ICMP_NE:
901  Opc = I32 ? WebAssembly::NE_I32 : WebAssembly::NE_I64;
902  break;
903  case ICmpInst::ICMP_UGT:
904  Opc = I32 ? WebAssembly::GT_U_I32 : WebAssembly::GT_U_I64;
905  break;
906  case ICmpInst::ICMP_UGE:
907  Opc = I32 ? WebAssembly::GE_U_I32 : WebAssembly::GE_U_I64;
908  break;
909  case ICmpInst::ICMP_ULT:
910  Opc = I32 ? WebAssembly::LT_U_I32 : WebAssembly::LT_U_I64;
911  break;
912  case ICmpInst::ICMP_ULE:
913  Opc = I32 ? WebAssembly::LE_U_I32 : WebAssembly::LE_U_I64;
914  break;
915  case ICmpInst::ICMP_SGT:
916  Opc = I32 ? WebAssembly::GT_S_I32 : WebAssembly::GT_S_I64;
917  isSigned = true;
918  break;
919  case ICmpInst::ICMP_SGE:
920  Opc = I32 ? WebAssembly::GE_S_I32 : WebAssembly::GE_S_I64;
921  isSigned = true;
922  break;
923  case ICmpInst::ICMP_SLT:
924  Opc = I32 ? WebAssembly::LT_S_I32 : WebAssembly::LT_S_I64;
925  isSigned = true;
926  break;
927  case ICmpInst::ICMP_SLE:
928  Opc = I32 ? WebAssembly::LE_S_I32 : WebAssembly::LE_S_I64;
929  isSigned = true;
930  break;
931  default: return false;
932  }
933 
934  unsigned LHS = getRegForPromotedValue(ICmp->getOperand(0), isSigned);
935  if (LHS == 0)
936  return false;
937 
938  unsigned RHS = getRegForPromotedValue(ICmp->getOperand(1), isSigned);
939  if (RHS == 0)
940  return false;
941 
942  unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
943  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
944  .addReg(LHS)
945  .addReg(RHS);
946  updateValueMap(ICmp, ResultReg);
947  return true;
948 }
949 
950 bool WebAssemblyFastISel::selectFCmp(const Instruction *I) {
951  const FCmpInst *FCmp = cast<FCmpInst>(I);
952 
953  unsigned LHS = getRegForValue(FCmp->getOperand(0));
954  if (LHS == 0)
955  return false;
956 
957  unsigned RHS = getRegForValue(FCmp->getOperand(1));
958  if (RHS == 0)
959  return false;
960 
961  bool F32 = getSimpleType(FCmp->getOperand(0)->getType()) != MVT::f64;
962  unsigned Opc;
963  bool Not = false;
964  switch (FCmp->getPredicate()) {
965  case FCmpInst::FCMP_OEQ:
966  Opc = F32 ? WebAssembly::EQ_F32 : WebAssembly::EQ_F64;
967  break;
968  case FCmpInst::FCMP_UNE:
969  Opc = F32 ? WebAssembly::NE_F32 : WebAssembly::NE_F64;
970  break;
971  case FCmpInst::FCMP_OGT:
972  Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
973  break;
974  case FCmpInst::FCMP_OGE:
975  Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
976  break;
977  case FCmpInst::FCMP_OLT:
978  Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
979  break;
980  case FCmpInst::FCMP_OLE:
981  Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
982  break;
983  case FCmpInst::FCMP_UGT:
984  Opc = F32 ? WebAssembly::LE_F32 : WebAssembly::LE_F64;
985  Not = true;
986  break;
987  case FCmpInst::FCMP_UGE:
988  Opc = F32 ? WebAssembly::LT_F32 : WebAssembly::LT_F64;
989  Not = true;
990  break;
991  case FCmpInst::FCMP_ULT:
992  Opc = F32 ? WebAssembly::GE_F32 : WebAssembly::GE_F64;
993  Not = true;
994  break;
995  case FCmpInst::FCMP_ULE:
996  Opc = F32 ? WebAssembly::GT_F32 : WebAssembly::GT_F64;
997  Not = true;
998  break;
999  default:
1000  return false;
1001  }
1002 
1003  unsigned ResultReg = createResultReg(&WebAssembly::I32RegClass);
1004  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
1005  .addReg(LHS)
1006  .addReg(RHS);
1007 
1008  if (Not)
1009  ResultReg = notValue(ResultReg);
1010 
1011  updateValueMap(FCmp, ResultReg);
1012  return true;
1013 }
1014 
1015 bool WebAssemblyFastISel::selectBitCast(const Instruction *I) {
1016  // Target-independent code can handle this, except it doesn't set the dead
1017  // flag on the ARGUMENTS clobber, so we have to do that manually in order
1018  // to satisfy code that expects this of isBitcast() instructions.
1019  EVT VT = TLI.getValueType(DL, I->getOperand(0)->getType());
1020  EVT RetVT = TLI.getValueType(DL, I->getType());
1021  if (!VT.isSimple() || !RetVT.isSimple())
1022  return false;
1023 
1024  if (VT == RetVT) {
1025  // No-op bitcast.
1026  updateValueMap(I, getRegForValue(I->getOperand(0)));
1027  return true;
1028  }
1029 
1030  unsigned Reg = fastEmit_ISD_BITCAST_r(VT.getSimpleVT(), RetVT.getSimpleVT(),
1031  getRegForValue(I->getOperand(0)),
1032  I->getOperand(0)->hasOneUse());
1033  if (!Reg)
1034  return false;
1035  MachineBasicBlock::iterator Iter = FuncInfo.InsertPt;
1036  --Iter;
1037  assert(Iter->isBitcast());
1038  Iter->setPhysRegsDeadExcept(ArrayRef<unsigned>(), TRI);
1039  updateValueMap(I, Reg);
1040  return true;
1041 }
1042 
1043 bool WebAssemblyFastISel::selectLoad(const Instruction *I) {
1044  const LoadInst *Load = cast<LoadInst>(I);
1045  if (Load->isAtomic())
1046  return false;
1047  if (!Subtarget->hasSIMD128() && Load->getType()->isVectorTy())
1048  return false;
1049 
1050  Address Addr;
1051  if (!computeAddress(Load->getPointerOperand(), Addr))
1052  return false;
1053 
1054  // TODO: Fold a following sign-/zero-extend into the load instruction.
1055 
1056  unsigned Opc;
1057  const TargetRegisterClass *RC;
1058  switch (getSimpleType(Load->getType())) {
1059  case MVT::i1:
1060  case MVT::i8:
1061  Opc = WebAssembly::LOAD8_U_I32;
1062  RC = &WebAssembly::I32RegClass;
1063  break;
1064  case MVT::i16:
1065  Opc = WebAssembly::LOAD16_U_I32;
1066  RC = &WebAssembly::I32RegClass;
1067  break;
1068  case MVT::i32:
1069  Opc = WebAssembly::LOAD_I32;
1070  RC = &WebAssembly::I32RegClass;
1071  break;
1072  case MVT::i64:
1073  Opc = WebAssembly::LOAD_I64;
1074  RC = &WebAssembly::I64RegClass;
1075  break;
1076  case MVT::f32:
1077  Opc = WebAssembly::LOAD_F32;
1078  RC = &WebAssembly::F32RegClass;
1079  break;
1080  case MVT::f64:
1081  Opc = WebAssembly::LOAD_F64;
1082  RC = &WebAssembly::F64RegClass;
1083  break;
1084  default:
1085  return false;
1086  }
1087 
1088  materializeLoadStoreOperands(Addr);
1089 
1090  unsigned ResultReg = createResultReg(RC);
1091  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc),
1092  ResultReg);
1093 
1094  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Load));
1095 
1096  updateValueMap(Load, ResultReg);
1097  return true;
1098 }
1099 
1100 bool WebAssemblyFastISel::selectStore(const Instruction *I) {
1101  const StoreInst *Store = cast<StoreInst>(I);
1102  if (Store->isAtomic())
1103  return false;
1104  if (!Subtarget->hasSIMD128() &&
1105  Store->getValueOperand()->getType()->isVectorTy())
1106  return false;
1107 
1108  Address Addr;
1109  if (!computeAddress(Store->getPointerOperand(), Addr))
1110  return false;
1111 
1112  unsigned Opc;
1113  bool VTIsi1 = false;
1114  switch (getSimpleType(Store->getValueOperand()->getType())) {
1115  case MVT::i1:
1116  VTIsi1 = true;
1117  case MVT::i8:
1118  Opc = WebAssembly::STORE8_I32;
1119  break;
1120  case MVT::i16:
1121  Opc = WebAssembly::STORE16_I32;
1122  break;
1123  case MVT::i32:
1124  Opc = WebAssembly::STORE_I32;
1125  break;
1126  case MVT::i64:
1127  Opc = WebAssembly::STORE_I64;
1128  break;
1129  case MVT::f32:
1130  Opc = WebAssembly::STORE_F32;
1131  break;
1132  case MVT::f64:
1133  Opc = WebAssembly::STORE_F64;
1134  break;
1135  default: return false;
1136  }
1137 
1138  materializeLoadStoreOperands(Addr);
1139 
1140  unsigned ValueReg = getRegForValue(Store->getValueOperand());
1141  if (ValueReg == 0)
1142  return false;
1143  if (VTIsi1)
1144  ValueReg = maskI1Value(ValueReg, Store->getValueOperand());
1145 
1146  auto MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc));
1147 
1148  addLoadStoreOperands(Addr, MIB, createMachineMemOperandFor(Store));
1149 
1150  MIB.addReg(ValueReg);
1151  return true;
1152 }
1153 
1154 bool WebAssemblyFastISel::selectBr(const Instruction *I) {
1155  const BranchInst *Br = cast<BranchInst>(I);
1156  if (Br->isUnconditional()) {
1157  MachineBasicBlock *MSucc = FuncInfo.MBBMap[Br->getSuccessor(0)];
1158  fastEmitBranch(MSucc, Br->getDebugLoc());
1159  return true;
1160  }
1161 
1162  MachineBasicBlock *TBB = FuncInfo.MBBMap[Br->getSuccessor(0)];
1163  MachineBasicBlock *FBB = FuncInfo.MBBMap[Br->getSuccessor(1)];
1164 
1165  bool Not;
1166  unsigned CondReg = getRegForI1Value(Br->getCondition(), Not);
1167  if (CondReg == 0)
1168  return false;
1169 
1170  unsigned Opc = WebAssembly::BR_IF;
1171  if (Not)
1172  Opc = WebAssembly::BR_UNLESS;
1173 
1174  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
1175  .addMBB(TBB)
1176  .addReg(CondReg);
1177 
1178  finishCondBranch(Br->getParent(), TBB, FBB);
1179  return true;
1180 }
1181 
1182 bool WebAssemblyFastISel::selectRet(const Instruction *I) {
1183  if (!FuncInfo.CanLowerReturn)
1184  return false;
1185 
1186  const ReturnInst *Ret = cast<ReturnInst>(I);
1187 
1188  if (Ret->getNumOperands() == 0) {
1189  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1190  TII.get(WebAssembly::RETURN_VOID));
1191  return true;
1192  }
1193 
1194  Value *RV = Ret->getOperand(0);
1195  if (!Subtarget->hasSIMD128() && RV->getType()->isVectorTy())
1196  return false;
1197 
1198  unsigned Opc;
1199  switch (getSimpleType(RV->getType())) {
1200  case MVT::i1: case MVT::i8:
1201  case MVT::i16: case MVT::i32:
1202  Opc = WebAssembly::RETURN_I32;
1203  break;
1204  case MVT::i64:
1205  Opc = WebAssembly::RETURN_I64;
1206  break;
1207  case MVT::f32:
1208  Opc = WebAssembly::RETURN_F32;
1209  break;
1210  case MVT::f64:
1211  Opc = WebAssembly::RETURN_F64;
1212  break;
1213  case MVT::v16i8:
1214  Opc = WebAssembly::RETURN_v16i8;
1215  break;
1216  case MVT::v8i16:
1217  Opc = WebAssembly::RETURN_v8i16;
1218  break;
1219  case MVT::v4i32:
1220  Opc = WebAssembly::RETURN_v4i32;
1221  break;
1222  case MVT::v4f32:
1223  Opc = WebAssembly::RETURN_v4f32;
1224  break;
1225  default: return false;
1226  }
1227 
1228  unsigned Reg;
1229  if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::SExt))
1230  Reg = getRegForSignedValue(RV);
1231  else if (FuncInfo.Fn->getAttributes().hasAttribute(0, Attribute::ZExt))
1232  Reg = getRegForUnsignedValue(RV);
1233  else
1234  Reg = getRegForValue(RV);
1235 
1236  if (Reg == 0)
1237  return false;
1238 
1239  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)).addReg(Reg);
1240  return true;
1241 }
1242 
1243 bool WebAssemblyFastISel::selectUnreachable(const Instruction *I) {
1244  BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc,
1245  TII.get(WebAssembly::UNREACHABLE));
1246  return true;
1247 }
1248 
1249 bool WebAssemblyFastISel::fastSelectInstruction(const Instruction *I) {
1250  switch (I->getOpcode()) {
1251  case Instruction::Call:
1252  if (selectCall(I))
1253  return true;
1254  break;
1255  case Instruction::Select: return selectSelect(I);
1256  case Instruction::Trunc: return selectTrunc(I);
1257  case Instruction::ZExt: return selectZExt(I);
1258  case Instruction::SExt: return selectSExt(I);
1259  case Instruction::ICmp: return selectICmp(I);
1260  case Instruction::FCmp: return selectFCmp(I);
1261  case Instruction::BitCast: return selectBitCast(I);
1262  case Instruction::Load: return selectLoad(I);
1263  case Instruction::Store: return selectStore(I);
1264  case Instruction::Br: return selectBr(I);
1265  case Instruction::Ret: return selectRet(I);
1266  case Instruction::Unreachable: return selectUnreachable(I);
1267  default: break;
1268  }
1269 
1270  // Fall back to target-independent instruction selection.
1271  return selectOperator(I, I->getOpcode());
1272 }
1273 
1275  const TargetLibraryInfo *LibInfo) {
1276  return new WebAssemblyFastISel(FuncInfo, LibInfo);
1277 }
AttributeSet getAttributes() const
Return the parameter attributes for this call.
Return a value (possibly void), from a function.
Value * getValueOperand()
Definition: Instructions.h:391
const Value * getCalledValue() const
Get a pointer to the function that is invoked by this instruction.
void push_back(const T &Elt)
Definition: SmallVector.h:211
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:226
LLVMContext & Context
size_t i
This class represents zero extension of integer types.
unsigned getNumOperands() const
Definition: User.h:167
This class represents a function call, abstracting a target machine's calling convention.
bool isIntrinsic() const
isIntrinsic - Returns true if the function's name starts with "llvm.".
Definition: Function.h:151
gep_type_iterator gep_type_end(const User *GEP)
unsigned less or equal
Definition: InstrTypes.h:906
unsigned less than
Definition: InstrTypes.h:905
0 1 0 0 True if ordered and less than
Definition: InstrTypes.h:886
unsigned getSizeInBits() const
1 1 1 0 True if unordered or not equal
Definition: InstrTypes.h:896
Type * getReturnType() const
Returns the type of the ret val.
Definition: Function.cpp:238
This class represents a sign extension of integer types.
An instruction for reading from memory.
Definition: Instructions.h:164
bool hasAttribute(unsigned Index, Attribute::AttrKind Kind) const
Return true if the attribute exists at the given index.
Definition: Attributes.cpp:994
This file contains the entry points for global functions defined in the LLVM WebAssembly back-end...
APInt Not(const APInt &APIVal)
Bitwise complement function.
Definition: APInt.h:1957
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:496
bool isUnconditional() const
A description of a memory reference used in the backend.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
This class represents the LLVM 'select' instruction.
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:199
unsigned getNumArgOperands() const
Return the number of call arguments.
Reg
All possible values of the reg field in the ModR/M byte.
0 1 0 1 True if ordered and less than or equal
Definition: InstrTypes.h:887
SimpleValueType SimpleTy
bool isMustTailCall() const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
This is a fast-path instruction selection class that generates poor code and doesn't support illegal ...
Definition: FastISel.h:31
Class to represent function types.
Definition: DerivedTypes.h:102
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:873
This file declares the WebAssembly-specific subclass of TargetMachine.
#define F(x, y, z)
Definition: MD5.cpp:51
This instruction compares its operands according to the predicate given to the constructor.
BasicBlock * getSuccessor(unsigned i) const
An instruction for storing to memory.
Definition: Instructions.h:300
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
bool isArrayTy() const
True if this is an instance of ArrayType.
Definition: Type.h:210
This class represents a truncation of integer types.
bool isAtomic() const
Return true if this instruction has an AtomicOrdering of unordered or higher.
static const Value * getNotArgument(const Value *BinOp)
static GCRegistry::Add< CoreCLRGC > E("coreclr","CoreCLR-compatible GC")
uint64_t getElementOffset(unsigned Idx) const
Definition: DataLayout.h:517
MachineInstrBuilder BuildMI(MachineFunction &MF, const DebugLoc &DL, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
unsigned const MachineRegisterInfo * MRI
MVT - Machine Value Type.
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:48
Conditional or Unconditional Branch instruction.
bool isVectorTy() const
True if this is an instance of VectorType.
Definition: Type.h:219
static unsigned getSizeInBits(unsigned Reg, const MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI)
Get the size in bits of Reg.
This is an important base class in LLVM.
Definition: Constant.h:42
const Value * getCondition() const
This file provides WebAssembly-specific target descriptions.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
Definition: Instruction.h:259
uint32_t Offset
This instruction compares its operands according to the predicate given to the constructor.
Value * getOperand(unsigned i) const
Definition: User.h:145
Value * getPointerOperand()
Definition: Instructions.h:270
static bool isNot(const Value *V)
Predicate getPredicate() const
Return the predicate for this instruction.
Definition: InstrTypes.h:960
EVT - Extended Value Type.
Definition: ValueTypes.h:31
const Value * getTrueValue() const
1 1 0 1 True if unordered, less than, or equal
Definition: InstrTypes.h:895
signed greater than
Definition: InstrTypes.h:907
FunctionType * getFunctionType() const
0 0 1 0 True if ordered and greater than
Definition: InstrTypes.h:884
This file declares the WebAssembly-specific subclass of TargetSubtarget.
This is the shared class of boolean and integer constants.
Definition: Constants.h:88
1 1 0 0 True if unordered or less than
Definition: InstrTypes.h:894
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:230
Provides information about what library functions are available for the current target.
const DataFlowGraph & G
Definition: RDFGraph.cpp:206
signed less than
Definition: InstrTypes.h:909
Function * getCalledFunction() const
Return the function called, or null if this is an indirect function invocation.
const MachineInstrBuilder & addFrameIndex(int Idx) const
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition: BitVector.h:586
AttributeSet getAttributes() const
Return the attribute list for this Function.
Definition: Function.h:176
Value * getArgOperand(unsigned i) const
getArgOperand/setArgOperand - Return/set the i-th call argument.
signed less or equal
Definition: InstrTypes.h:910
static unsigned getReg(const void *D, unsigned RC, unsigned RegNo)
bool isIntegerTy() const
True if this is an instance of IntegerType.
Definition: Type.h:195
This file defines the FastISel class.
bool isInlineAsm() const
Check if this call is an inline asm statement.
const MachineInstrBuilder & addGlobalAddress(const GlobalValue *GV, int64_t Offset=0, unsigned char TargetFlags=0) const
bool isStructTy() const
True if this is an instance of StructType.
Definition: Type.h:207
This class is derived from MachineFunctionInfo and contains private WebAssembly-specific information ...
Value * getCondition() const
unsigned greater or equal
Definition: InstrTypes.h:904
const MachineInstrBuilder & addMemOperand(MachineMemOperand *MMO) const
#define I(x, y, z)
Definition: MD5.cpp:54
bool hasOneUse() const
Return true if there is exactly one user of this value.
Definition: Value.h:383
FunctionLoweringInfo - This contains information that is global to a function that is used when lower...
This file declares WebAssembly-specific per-machine-function information.
iterator find(const KeyT &Val)
Definition: DenseMap.h:127
1 0 1 0 True if unordered or greater than
Definition: InstrTypes.h:892
bool isVarArg() const
Definition: DerivedTypes.h:122
const unsigned Kind
Type * getReturnType() const
Definition: DerivedTypes.h:123
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
bool isSimple() const
isSimple - Test if the given EVT is simple (as opposed to being extended).
Definition: ValueTypes.h:107
0 0 0 1 True if ordered and equal
Definition: InstrTypes.h:883
LLVM Value Representation.
Definition: Value.h:71
1 0 1 1 True if unordered, greater than, or equal
Definition: InstrTypes.h:893
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Definition: Instruction.h:111
const Value * getFalseValue() const
unsigned greater than
Definition: InstrTypes.h:903
int64_t getSExtValue() const
Return the constant as a 64-bit integer value after it has been sign extended as appropriate for the ...
Definition: Constants.h:162
0 0 1 1 True if ordered and greater than or equal
Definition: InstrTypes.h:885
const MachineInstrBuilder & addReg(unsigned RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
Definition: Function.cpp:234
Value * getPointerOperand()
Definition: Instructions.h:394
const BasicBlock * getParent() const
Definition: Instruction.h:62
MVT getSimpleVT() const
getSimpleVT - Return the SimpleValueType held in the specified simple EVT.
Definition: ValueTypes.h:226
iterator_range< arg_iterator > args()
Definition: Function.h:568
signed greater or equal
Definition: InstrTypes.h:908
bool isVoidTy() const
Return true if this is 'void'.
Definition: Type.h:139
an instruction to allocate memory on the stack
Definition: Instructions.h:60
gep_type_iterator gep_type_begin(const User *GEP)