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