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