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