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