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